Skip to content

Commit

Permalink
Add breadcrumbs to CSP UI (elastic#84)
Browse files Browse the repository at this point in the history
  • Loading branch information
ari-aviran authored and orouz committed Jan 13, 2022
1 parent 0f67fb6 commit 26fe2fe
Show file tree
Hide file tree
Showing 15 changed files with 122 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import React from 'react';
import { I18nProvider } from '@kbn/i18n-react';
import { Router, Redirect, Switch, Route } from 'react-router-dom';
import { QueryClient, QueryClientProvider } from 'react-query';
import { CSP_DASHBOARD_PATH } from '../common/navigation/constants';
import { routes } from './routes';
import { UnknownRoute } from '../components/unknown_route';
import { CSP_DASHBOARD_PATH } from '../common/constants';
import { KibanaContextProvider } from '../../../../../src/plugins/kibana_react/public';
import type { AppMountParameters, CoreStart } from '../../../../../src/core/public';
import type { CspStart } from '../types';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
* 2.0.
*/
import { RouteProps } from 'react-router-dom';
import { CSP_DASHBOARD_PATH, CSP_FINDINGS_PATH } from '../common/navigation/constants';
import * as pages from '../pages';
import { CSP_FINDINGS_PATH, CSP_DASHBOARD_PATH } from '../common/constants';

export const routes: readonly RouteProps[] = [
{ path: CSP_FINDINGS_PATH, component: pages.Findings },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,3 @@ import { euiPaletteForStatus } from '@elastic/eui';
const [success, warning, danger] = euiPaletteForStatus(3);

export const statusColors = { success, warning, danger };

export const CSP_ROOT_PATH = '/csp';
export const CSP_FINDINGS_PATH = '/findings';
export const CSP_DASHBOARD_PATH = '/dashboard';
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import * as TEXT from './translations';
import type { CspNavigationItem } from './types';

export const CSP_FINDINGS_PATH = '/findings';
export const CSP_DASHBOARD_PATH = '/dashboard';

type NavigableScreens = 'dashboard' | 'findings';

export const allNavigationItems: Record<NavigableScreens, CspNavigationItem> = {
dashboard: { name: TEXT.DASHBOARD, path: CSP_DASHBOARD_PATH },
findings: { name: TEXT.FINDINGS, path: CSP_FINDINGS_PATH },
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { i18n } from '@kbn/i18n';

export const CLOUD_POSTURE = i18n.translate('xpack.csp.navigation.cloudPosture', {
defaultMessage: 'Cloud Posture',
});

export const FINDINGS = i18n.translate('xpack.csp.navigation.findings', {
defaultMessage: 'Findings',
});

export const DASHBOARD = i18n.translate('xpack.csp.navigation.dashboard', {
defaultMessage: 'Dashboard',
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@
* 2.0.
*/

import { CSP_FINDINGS_PATH, CSP_DASHBOARD_PATH } from '../common/constants';

export const navigationLinks = [
{ name: 'Dashboard', path: CSP_DASHBOARD_PATH },
{ name: 'Findings', path: CSP_FINDINGS_PATH },
] as const;
export interface CspNavigationItem {
name: string;
path: string;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import type { ChromeBreadcrumb, CoreStart } from 'kibana/public';
import { useEffect } from 'react';
import { useKibana } from '../../../../../../src/plugins/kibana_react/public';
import { PLUGIN_ID } from '../../../common';
import type { CspNavigationItem } from './types';
import { CLOUD_POSTURE } from './translations';

export const useCspBreadcrumbs = (breadcrumbs: CspNavigationItem[]) => {
const {
services: {
chrome: { setBreadcrumbs },
application: { getUrlForApp },
},
} = useKibana<CoreStart>();

useEffect(() => {
const cspPath = getUrlForApp(PLUGIN_ID);
const additionalBreadCrumbs: ChromeBreadcrumb[] = breadcrumbs.map((breadcrumb) => ({
text: breadcrumb.name,
path: breadcrumb.path.startsWith('/')
? `${cspPath}${breadcrumb.path}`
: `${cspPath}/${breadcrumb.path}`,
}));

setBreadcrumbs([
{
text: CLOUD_POSTURE,
href: cspPath,
},
...additionalBreadCrumbs,
]);
}, [getUrlForApp, setBreadcrumbs, breadcrumbs]);
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@
*/

import { useHistory } from 'react-router-dom';
import { CSP_FINDINGS_PATH } from './constants';

export const useNavigateToCSPFindings = () => {
const history = useHistory();

return {
navigate: (query: string) =>
history.push({
pathname: '/findings',
pathname: CSP_FINDINGS_PATH,
search: new URLSearchParams([['query', query]].filter((p) => !!p[1])).toString(),
}),
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,22 @@ import {
KibanaPageTemplate,
KibanaPageTemplateProps,
} from '../../../../../src/plugins/kibana_react/public';
import { navigationLinks } from '../application/navigation';
import { CLOUD_SECURITY_POSTURE } from '../../common/translations';
import { allNavigationItems } from '../common/navigation/constants';
import { CLOUD_SECURITY_POSTURE } from '../common/translations';

const activeItemStyle = { fontWeight: 700 };

const navItems: NonNullable<KibanaPageTemplateProps['solutionNav']>['items'] = navigationLinks.map(
(route) => ({
id: route.name,
...route,
renderItem: () => (
<NavLink to={route.path} activeStyle={activeItemStyle}>
{route.name}
</NavLink>
),
})
);
const navItems: NonNullable<KibanaPageTemplateProps['solutionNav']>['items'] = Object.values(
allNavigationItems
).map((route) => ({
id: route.path,
...route,
renderItem: () => (
<NavLink to={route.path} activeStyle={activeItemStyle}>
{route.name}
</NavLink>
),
}));

const defaultProps: KibanaPageTemplateProps = {
solutionNav: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import React from 'react';
import { Chart, Datum, Partition, PartitionLayout, Settings } from '@elastic/charts';
import { EuiText } from '@elastic/eui';
import { useNavigateToCSPFindings } from '../../../common/hooks/use_navigate_to_csp_findings';
import { useNavigateToCSPFindings } from '../../../common/navigation/use_navigate_to_csp_findings';
import type { BenchmarkStats } from '../../../../common/types';
import { statusColors } from '../../../common/constants';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import React from 'react';
import { Axis, BarSeries, Chart, Settings } from '@elastic/charts';
import { euiPaletteForStatus } from '@elastic/eui';
import { useNavigateToCSPFindings } from '../../../common/hooks/use_navigate_to_csp_findings';
import { useNavigateToCSPFindings } from '../../../common/navigation/use_navigate_to_csp_findings';
import { CloudPostureStats } from '../../../../common/types';

export function sortAscending<T>(getter: (x: T) => number | string) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

import React from 'react';
import { EuiSpacer, EuiTitle } from '@elastic/eui';
import { allNavigationItems } from '../../common/navigation/constants';
import { useCspBreadcrumbs } from '../../common/navigation/use_csp_breadcrumbs';
import { SummarySection } from './dashboard_sections/summary_section';
import { BenchmarksSection } from './dashboard_sections/benchmarks_section';
import { useCloudPostureStatsApi } from '../../common/api';
Expand Down Expand Up @@ -34,12 +36,16 @@ const CompliancePage = () => {
);
};

export const ComplianceDashboard = () => (
<CspPageTemplate
pageHeader={{
pageTitle: 'Compliance',
}}
>
<CompliancePage />
</CspPageTemplate>
);
export const ComplianceDashboard = () => {
useCspBreadcrumbs([allNavigationItems.dashboard]);

return (
<CspPageTemplate
pageHeader={{
pageTitle: 'Compliance',
}}
>
<CompliancePage />
</CspPageTemplate>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import React from 'react';
import { EuiEmptyPrompt, EuiLoadingSpinner } from '@elastic/eui';
import type { EuiPageHeaderProps } from '@elastic/eui';
import { allNavigationItems } from '../../common/navigation/constants';
import { useCspBreadcrumbs } from '../../common/navigation/use_csp_breadcrumbs';
import { FindingsTableContainer } from './findings_container';
import { CspPageTemplate } from '../../components/page_template';
import { useKubebeatDataView } from './utils';
Expand All @@ -18,6 +20,7 @@ const pageHeader: EuiPageHeaderProps = {

export const Findings = () => {
const dataView = useKubebeatDataView();
useCspBreadcrumbs([allNavigationItems.findings]);

return (
<CspPageTemplate pageHeader={pageHeader}>
Expand Down
4 changes: 2 additions & 2 deletions x-pack/plugins/cloud_security_posture/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@
import type { AppMountParameters, CoreSetup, CoreStart, Plugin } from '../../../../src/core/public';
import type { CspSetup, CspStart, CspPluginSetup, CspPluginStart } from './types';
import { AppNavLinkStatus, AppStatus } from '../../../../src/core/public';
import { PLUGIN_NAME } from '../common';
import { PLUGIN_NAME, PLUGIN_ID } from '../common';

export class CspPlugin implements Plugin<CspSetup, CspStart, CspPluginSetup, CspPluginStart> {
public setup(core: CoreSetup<CspPluginStart, CspStart>, plugins: CspPluginSetup): CspSetup {
// Register an application into the side navigation menu

core.application.register({
id: 'csp',
id: PLUGIN_ID,
title: PLUGIN_NAME,
status: AppStatus.accessible,
navLinkStatus: AppNavLinkStatus.hidden,
Expand Down

0 comments on commit 26fe2fe

Please sign in to comment.