Skip to content

Commit 613509d

Browse files
authored
Improve home screen for limited-access users (#77665)
1 parent 5a31dce commit 613509d

File tree

19 files changed

+287
-32
lines changed

19 files changed

+287
-32
lines changed

src/plugins/home/public/application/components/__snapshots__/home.test.js.snap

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/plugins/home/public/application/components/home.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,10 @@ export class Home extends Component {
163163
</EuiFlexItem>
164164

165165
{stackManagement ? (
166-
<EuiFlexItem className="homHeader__actionItem">
166+
<EuiFlexItem
167+
className="homHeader__actionItem"
168+
data-test-subj="homManagementActionItem"
169+
>
167170
<EuiButtonEmpty
168171
onClick={createAppNavigationHandler(stackManagement.path)}
169172
iconType="gear"

src/plugins/home/public/application/components/manage_data/__snapshots__/manage_data.test.tsx.snap

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/plugins/home/public/application/components/manage_data/manage_data.test.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,4 +88,9 @@ describe('ManageData', () => {
8888
);
8989
expect(component).toMatchSnapshot();
9090
});
91+
92+
test('render empty without any features', () => {
93+
const component = shallowWithIntl(<ManageData addBasePath={addBasePathMock} features={[]} />);
94+
expect(component).toMatchSnapshot();
95+
});
9196
});

src/plugins/home/public/application/components/manage_data/manage_data.tsx

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -36,31 +36,37 @@ export const ManageData: FC<Props> = ({ addBasePath, features }) => (
3636
<>
3737
{features.length > 1 && <EuiHorizontalRule margin="xl" aria-hidden="true" />}
3838

39-
<section className="homDataManage" aria-labelledby="homDataManage__title">
40-
<EuiTitle size="s">
41-
<h2 id="homDataManage__title">
42-
<FormattedMessage id="home.manageData.sectionTitle" defaultMessage="Manage your data" />
43-
</h2>
44-
</EuiTitle>
39+
{features.length > 0 && (
40+
<section
41+
className="homDataManage"
42+
aria-labelledby="homDataManage__title"
43+
data-test-subj="homDataManage"
44+
>
45+
<EuiTitle size="s">
46+
<h2 id="homDataManage__title">
47+
<FormattedMessage id="home.manageData.sectionTitle" defaultMessage="Manage your data" />
48+
</h2>
49+
</EuiTitle>
4550

46-
<EuiSpacer size="m" />
51+
<EuiSpacer size="m" />
4752

48-
<EuiFlexGroup className="homDataManage__content">
49-
{features.map((feature) => (
50-
<EuiFlexItem key={feature.id}>
51-
<Synopsis
52-
id={feature.id}
53-
onClick={createAppNavigationHandler(feature.path)}
54-
description={feature.description}
55-
iconType={feature.icon}
56-
title={feature.title}
57-
url={addBasePath(feature.path)}
58-
wrapInPanel
59-
/>
60-
</EuiFlexItem>
61-
))}
62-
</EuiFlexGroup>
63-
</section>
53+
<EuiFlexGroup className="homDataManage__content">
54+
{features.map((feature) => (
55+
<EuiFlexItem key={feature.id}>
56+
<Synopsis
57+
id={feature.id}
58+
onClick={createAppNavigationHandler(feature.path)}
59+
description={feature.description}
60+
iconType={feature.icon}
61+
title={feature.title}
62+
url={addBasePath(feature.path)}
63+
wrapInPanel
64+
/>
65+
</EuiFlexItem>
66+
))}
67+
</EuiFlexGroup>
68+
</section>
69+
)}
6470
</>
6571
);
6672

src/plugins/home/public/application/components/solutions_section/__snapshots__/solution_panel.test.tsx.snap

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/plugins/home/public/application/components/solutions_section/solution_panel.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ interface Props {
5353
export const SolutionPanel: FC<Props> = ({ addBasePath, solution }) => (
5454
<EuiFlexItem
5555
key={solution.id}
56+
data-test-subj={`homSolutionPanel homSolutionPanel_${solution.id}`}
5657
className={`${
5758
solution.id === 'kibana' ? 'homSolutions__group homSolutions__group--single' : ''
5859
} homSolutions__item`}

src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.test.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,40 @@ describe('FeatureCatalogueRegistry', () => {
8888
expect(service.get()).toEqual([]);
8989
});
9090
});
91+
92+
describe('visibility filtering', () => {
93+
test('retains items with no "visible" callback', () => {
94+
const service = new FeatureCatalogueRegistry();
95+
service.setup().register(DASHBOARD_FEATURE);
96+
const capabilities = { catalogue: {} } as any;
97+
service.start({ capabilities });
98+
expect(service.get()).toEqual([DASHBOARD_FEATURE]);
99+
});
100+
101+
test('retains items with a "visible" callback which returns "true"', () => {
102+
const service = new FeatureCatalogueRegistry();
103+
const feature = {
104+
...DASHBOARD_FEATURE,
105+
visible: () => true,
106+
};
107+
service.setup().register(feature);
108+
const capabilities = { catalogue: {} } as any;
109+
service.start({ capabilities });
110+
expect(service.get()).toEqual([feature]);
111+
});
112+
113+
test('removes items with a "visible" callback which returns "false"', () => {
114+
const service = new FeatureCatalogueRegistry();
115+
const feature = {
116+
...DASHBOARD_FEATURE,
117+
visible: () => false,
118+
};
119+
service.setup().register(feature);
120+
const capabilities = { catalogue: {} } as any;
121+
service.start({ capabilities });
122+
expect(service.get()).toEqual([]);
123+
});
124+
});
91125
});
92126

93127
describe('title sorting', () => {

src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ export interface FeatureCatalogueEntry {
4545
readonly showOnHomePage: boolean;
4646
/** An ordinal used to sort features relative to one another for display on the home page */
4747
readonly order?: number;
48+
/** Optional function to control visibility of this feature. */
49+
readonly visible?: () => boolean;
4850
}
4951

5052
/** @public */
@@ -103,7 +105,10 @@ export class FeatureCatalogueRegistry {
103105
}
104106
const capabilities = this.capabilities;
105107
return [...this.features.values()]
106-
.filter((entry) => capabilities.catalogue[entry.id] !== false)
108+
.filter(
109+
(entry) =>
110+
capabilities.catalogue[entry.id] !== false && (entry.visible ? entry.visible() : true)
111+
)
107112
.sort(compareByKey('title'));
108113
}
109114

src/plugins/management/public/plugin.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ export class ManagementPlugin implements Plugin<ManagementSetup, ManagementStart
4747

4848
private readonly appUpdater = new BehaviorSubject<AppUpdater>(() => ({}));
4949

50+
private hasAnyEnabledApps = true;
51+
5052
constructor(private initializerContext: PluginInitializerContext) {}
5153

5254
public setup(core: CoreSetup, { home }: ManagementSetupDependencies) {
@@ -65,6 +67,7 @@ export class ManagementPlugin implements Plugin<ManagementSetup, ManagementStart
6567
path: '/app/management',
6668
showOnHomePage: false,
6769
category: FeatureCatalogueCategory.ADMIN,
70+
visible: () => this.hasAnyEnabledApps,
6871
});
6972
}
7073

@@ -96,11 +99,11 @@ export class ManagementPlugin implements Plugin<ManagementSetup, ManagementStart
9699

97100
public start(core: CoreStart) {
98101
this.managementSections.start({ capabilities: core.application.capabilities });
99-
const hasAnyEnabledApps = getSectionsServiceStartPrivate()
102+
this.hasAnyEnabledApps = getSectionsServiceStartPrivate()
100103
.getSectionsEnabled()
101104
.some((section) => section.getAppsEnabled().length > 0);
102105

103-
if (!hasAnyEnabledApps) {
106+
if (!this.hasAnyEnabledApps) {
104107
this.appUpdater.next(() => {
105108
return {
106109
status: AppStatus.inaccessible,

0 commit comments

Comments
 (0)