Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Security Solution] New Side nav integrating links config #132210

Merged
merged 34 commits into from
May 20, 2022
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
b8b145e
Update navigation landing pages to use appLinks config
machadoum May 11, 2022
cda1850
align app links changes
semd May 13, 2022
1449681
merge main
semd May 13, 2022
8df2b1b
link configs refactor to use updater$
semd May 13, 2022
59e5d1c
merge
semd May 13, 2022
b18c4c4
navigation panel categories
semd May 16, 2022
7e5895b
test and type fixes
semd May 16, 2022
d50dd4b
[CI] Auto-commit changed files from 'node scripts/precommit_hook.js -…
kibanamachine May 16, 2022
01a3fa2
types changes
semd May 16, 2022
66fb386
Merge branch '130023_security_side_nav_config' of https:/…
semd May 16, 2022
e1f6a98
shared style change moved to a separate PR
semd May 16, 2022
d2b71de
use old deep links
semd May 16, 2022
ce8e988
Merge remote-tracking branch 'upstream/main' into 130023_security_sid…
semd May 16, 2022
320fce7
minor changes after ux meeting
semd May 17, 2022
cccf46f
conflicts solved
semd May 17, 2022
66a7713
add links filtering
semd May 17, 2022
5222d41
remove duplicated categories
semd May 17, 2022
50d715a
temporary increase of plugin size limit
semd May 17, 2022
f00c0ad
swap management links order
semd May 17, 2022
dbd28f6
improve performance closing nav panel
semd May 17, 2022
448477d
test updated
semd May 17, 2022
e1fe85b
host isolation page filterd and some improvements
semd May 18, 2022
a77c93b
remove async from plugin start
semd May 18, 2022
ac944aa
move links register from start to mount
semd May 18, 2022
c49f731
restore size limits
semd May 18, 2022
3a9ce56
merge main
semd May 18, 2022
d94f2ea
Merge remote-tracking branch 'elastic/main' into 130023_security_side…
machadoum May 19, 2022
ed4cda9
Fix use_show_timeline unit tests
machadoum May 19, 2022
b6e260e
reverted changes where we moved the navigation registration to the co…
YulNaumenko May 19, 2022
2f6a658
Merge branch '130023_security_side_nav_config' of https:/…
YulNaumenko May 19, 2022
41ab96e
Merge branch 'main' into 130023_security_side_nav_config
YulNaumenko May 19, 2022
0f3da0e
[CI] Auto-commit changed files from 'node scripts/eslint --no-cache -…
kibanamachine May 19, 2022
8436ec4
Fix HostIsolationExceptions link visibility
machadoum May 20, 2022
c255354
Fix manageOldSiemRoutes been called before deepLinks initialization
machadoum May 20, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import { i18n } from '@kbn/i18n';
import { get } from 'lodash';
import { LicenseType } from '@kbn/licensing-plugin/common/types';
import { getCasesDeepLinks } from '@kbn/cases-plugin/public';
import { AppDeepLink, AppNavLinkStatus, Capabilities } from '@kbn/core/public';
import { AppDeepLink, AppNavLinkStatus, AppUpdater, Capabilities } from '@kbn/core/public';
import { Subject } from 'rxjs';
import { SecurityPageName } from '../types';
import {
OVERVIEW,
Expand Down Expand Up @@ -63,6 +64,8 @@ import {
RULES_CREATE_PATH,
} from '../../../common/constants';
import { ExperimentalFeatures } from '../../../common/experimental_features';
import { subscribeAppLinks } from '../../common/links';
import { AppLinkItems } from '../../common/links/types';

const FEATURE = {
general: `${SERVER_APP_ID}.show`,
Expand Down Expand Up @@ -553,3 +556,37 @@ export function isPremiumLicense(licenseType?: LicenseType): boolean {
licenseType === 'trial'
);
}

/**
* New deep links code starts here.
* All the code above will be removed once the appLinks migration is over.
* The code below manages the new implementation using the unified appLinks.
*/

const formatDeepLinks = (appLinks: AppLinkItems): AppDeepLink[] =>
appLinks.map((appLink) => ({
id: appLink.id,
path: appLink.path,
title: appLink.title,
navLinkStatus: appLink.globalNavEnabled ? AppNavLinkStatus.visible : AppNavLinkStatus.hidden,
searchable: !appLink.globalSearchDisabled,
...(appLink.globalSearchKeywords != null ? { keywords: appLink.globalSearchKeywords } : {}),
...(appLink.globalNavOrder != null ? { order: appLink.globalNavOrder } : {}),
...(appLink.links && appLink.links?.length
? {
deepLinks: formatDeepLinks(appLink.links),
}
: {}),
}));

/**
* Registers any change in appLinks to be updated in app deepLinks
*/
export const registerDeepLinksUpdater = (appUpdater$: Subject<AppUpdater>) => {
subscribeAppLinks((appLinks) => {
appUpdater$.next(() => ({
navLinkStatus: AppNavLinkStatus.hidden, // needed to prevent main security link to switch to visible after update
deepLinks: formatDeepLinks(appLinks),
}));
});
};
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { gutterTimeline } from '../../../common/lib/helpers';
import { useKibana } from '../../../common/lib/kibana';
import { useShowPagesWithEmptyView } from '../../../common/utils/empty_view/use_show_pages_with_empty_view';
import { useIsPolicySettingsBarVisible } from '../../../management/pages/policy/view/policy_hooks';
import { useIsGroupedNavigationEnabled } from '../../../common/components/navigation/helpers';

const NO_DATA_PAGE_MAX_WIDTH = 950;

Expand All @@ -44,8 +45,7 @@ const NO_DATA_PAGE_TEMPLATE_PROPS = {
*/
const StyledKibanaPageTemplate = styled(KibanaPageTemplate)<{
$isShowingTimelineOverlay?: boolean;
$isTimelineBottomBarVisible?: boolean;
$isPolicySettingsVisible?: boolean;
$addBottomPadding?: boolean;
}>`
.${BOTTOM_BAR_CLASSNAME} {
animation: 'none !important'; // disable the default bottom bar slide animation
Expand All @@ -63,19 +63,8 @@ const StyledKibanaPageTemplate = styled(KibanaPageTemplate)<{
}

// If the bottom bar is visible add padding to the navigation
${({ $isTimelineBottomBarVisible }) =>
$isTimelineBottomBarVisible &&
`
@media (min-width: 768px) {
.kbnPageTemplateSolutionNav {
padding-bottom: ${gutterTimeline};
}
}
`}

// If the policy settings bottom bar is visible add padding to the navigation
${({ $isPolicySettingsVisible }) =>
$isPolicySettingsVisible &&
${({ $addBottomPadding }) =>
$addBottomPadding &&
`
@media (min-width: 768px) {
.kbnPageTemplateSolutionNav {
Expand All @@ -98,6 +87,9 @@ export const SecuritySolutionTemplateWrapper: React.FC<SecuritySolutionPageWrapp
const { show: isShowingTimelineOverlay } = useDeepEqualSelector((state) =>
getTimelineShowStatus(state, TimelineId.active)
);
const isGroupedNavEnabled = useIsGroupedNavigationEnabled();
const addBottomPadding =
isTimelineBottomBarVisible || isPolicySettingsVisible || isGroupedNavEnabled;

const userHasSecuritySolutionVisible = useKibana().services.application.capabilities.siem.show;
const showEmptyState = useShowPagesWithEmptyView();
Expand All @@ -117,9 +109,8 @@ export const SecuritySolutionTemplateWrapper: React.FC<SecuritySolutionPageWrapp
*/
return (
<StyledKibanaPageTemplate
$isTimelineBottomBarVisible={isTimelineBottomBarVisible}
$addBottomPadding={addBottomPadding}
$isShowingTimelineOverlay={isShowingTimelineOverlay}
$isPolicySettingsVisible={isPolicySettingsVisible}
bottomBarProps={SecuritySolutionBottomBarProps}
bottomBar={
userHasSecuritySolutionVisible && <SecuritySolutionBottomBar onAppLeave={onAppLeave} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export const HOSTS = i18n.translate('xpack.securitySolution.navigation.hosts', {
});

export const GETTING_STARTED = i18n.translate('xpack.securitySolution.navigation.gettingStarted', {
defaultMessage: 'Getting started',
defaultMessage: 'Get started',
});

export const THREAT_HUNTING = i18n.translate('xpack.securitySolution.navigation.threatHunting', {
Expand Down
12 changes: 7 additions & 5 deletions x-pack/plugins/security_solution/public/cases/links.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
*/

import { getCasesDeepLinks } from '@kbn/cases-plugin/public';
import { CASES_PATH, SecurityPageName } from '../../common/constants';
import { FEATURE, LinkItem } from '../common/links/types';
import { CASES_FEATURE_ID, CASES_PATH, SecurityPageName } from '../../common/constants';
import { LinkItem } from '../common/links/types';

export const getCasesLinkItems = (): LinkItem => {
const casesLinks = getCasesDeepLinks<LinkItem>({
Expand All @@ -16,15 +16,17 @@ export const getCasesLinkItems = (): LinkItem => {
[SecurityPageName.case]: {
globalNavEnabled: true,
globalNavOrder: 9006,
features: [FEATURE.casesRead],
capabilities: [`${CASES_FEATURE_ID}.read_cases`],
},
[SecurityPageName.caseConfigure]: {
features: [FEATURE.casesCrud],
capabilities: [`${CASES_FEATURE_ID}.crud_cases`],
licenseType: 'gold',
sideNavDisabled: true,
hideTimeline: true,
},
[SecurityPageName.caseCreate]: {
features: [FEATURE.casesCrud],
capabilities: [`${CASES_FEATURE_ID}.crud_cases`],
sideNavDisabled: true,
hideTimeline: true,
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@

import { renderHook } from '@testing-library/react-hooks';
import { SecurityPageName } from '../../../app/types';
import { NavLinkItem } from '../../links/types';
import { AppLinkItems } from '../../links';
import { TestProviders } from '../../mock';
import { useAppNavLinks, useAppRootNavLink } from './nav_links';
import { NavLinkItem } from './types';

const mockNavLinks = [
const mockNavLinks: AppLinkItems = [
{
description: 'description',
id: SecurityPageName.administration,
Expand All @@ -22,6 +23,10 @@ const mockNavLinks = [
links: [],
path: '/path_2',
title: 'title 2',
sideNavDisabled: true,
landingIcon: 'someicon',
landingImage: 'someimage',
skipUrlState: true,
},
],
path: '/path',
Expand All @@ -30,7 +35,7 @@ const mockNavLinks = [
];

jest.mock('../../links', () => ({
getNavLinkItems: () => mockNavLinks,
useAppLinks: () => mockNavLinks,
}));

const renderUseAppNavLinks = () =>
Expand All @@ -44,11 +49,47 @@ const renderUseAppRootNavLink = (id: SecurityPageName) =>
describe('useAppNavLinks', () => {
it('should return all nav links', () => {
const { result } = renderUseAppNavLinks();
expect(result.current).toEqual(mockNavLinks);
expect(result.current).toMatchInlineSnapshot(`
Array [
Object {
"description": "description",
"id": "administration",
"links": Array [
Object {
"description": "description 2",
"disabled": true,
"icon": "someicon",
"id": "endpoints",
"image": "someimage",
"skipUrlState": true,
"title": "title 2",
},
],
"title": "title",
},
]
`);
});

it('should return a root nav links', () => {
const { result } = renderUseAppRootNavLink(SecurityPageName.administration);
expect(result.current).toEqual(mockNavLinks[0]);
expect(result.current).toMatchInlineSnapshot(`
Object {
"description": "description",
"id": "administration",
"links": Array [
Object {
"description": "description 2",
"disabled": true,
"icon": "someicon",
"id": "endpoints",
"image": "someimage",
"skipUrlState": true,
"title": "title 2",
},
],
"title": "title",
}
`);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,35 @@
* 2.0.
*/

import { useKibana } from '../../lib/kibana';
import { useEnableExperimental } from '../../hooks/use_experimental_features';
import { useLicense } from '../../hooks/use_license';
import { getNavLinkItems } from '../../links';
import { useMemo } from 'react';
import { useAppLinks } from '../../links';
import type { SecurityPageName } from '../../../app/types';
import type { NavLinkItem } from '../../links/types';
import { NavLinkItem } from './types';
import { AppLinkItems } from '../../links/types';

export const useAppNavLinks = (): NavLinkItem[] => {
const license = useLicense();
const enableExperimental = useEnableExperimental();
const capabilities = useKibana().services.application.capabilities;

return getNavLinkItems({ enableExperimental, license, capabilities });
const appLinks = useAppLinks();
const navLinks = useMemo(() => formatNavLinkItems(appLinks), [appLinks]);
return navLinks;
};

export const useAppRootNavLink = (linkId: SecurityPageName): NavLinkItem | undefined => {
return useAppNavLinks().find(({ id }) => id === linkId);
};

const formatNavLinkItems = (appLinks: AppLinkItems): NavLinkItem[] =>
appLinks.map((link) => ({
id: link.id,
title: link.title,
...(link.categories != null ? { categories: link.categories } : {}),
...(link.description != null ? { description: link.description } : {}),
...(link.sideNavDisabled === true ? { disabled: true } : {}),
...(link.landingIcon != null ? { icon: link.landingIcon } : {}),
...(link.landingImage != null ? { image: link.landingImage } : {}),
...(link.skipUrlState != null ? { skipUrlState: link.skipUrlState } : {}),
...(link.links && link.links.length
? {
links: formatNavLinkItems(link.links),
}
: {}),
}));
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* 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 React, { SVGProps } from 'react';

export const EuiIconLaunch: React.FC<SVGProps<SVGSVGElement>> = ({ ...props }) => (
<svg
xmlns="http://www.w3.org/2000/svg"
width={16}
height={16}
fill="none"
viewBox="0 0 16 16"
{...props}
>
<path d="M14.5 1.5L15 1.5L15 0.999999L14.5 0.999999L14.5 1.5ZM2.50018 7L2.15128 6.64186C1.98519 6.80366 1.95214 7.05842 2.07144 7.25725L2.50018 7ZM8.99958 13.5L8.74229 13.9287C8.93901 14.0468 9.19083 14.0158 9.35308 13.8536L8.99958 13.5ZM4.00018 9.5L3.57144 9.75725C3.59247 9.7923 3.61772 9.82465 3.64663 9.85355L4.00018 9.5ZM6.50018 12L6.14663 12.3536C6.17552 12.3824 6.20785 12.4077 6.24289 12.4287L6.50018 12ZM10.7526 8.71583L11.1263 9.04802L10.7526 8.71583ZM10.5 9.3802L10 9.3802L10.5 9.3802ZM7.28418 5.24741L7.61636 5.62111L7.28418 5.24741ZM6.61982 5.5L6.61982 6L6.61982 5.5ZM10.5 11.5857L11 11.5857L10.5 11.5857ZM10.207 12.2929L10.5605 12.6465L10.207 12.2929ZM14.5 2.599L15 2.599L14.5 2.599ZM13.401 1.5L13.401 0.999999L13.401 1.5ZM13.401 2L14.5 2L14.5 0.999999L13.401 0.999999L13.401 2ZM14 1.5L14 2.599L15 2.599L15 1.5L14 1.5ZM7.61636 5.62111L10.4114 3.13666L9.74701 2.38925L6.952 4.8737L7.61636 5.62111ZM4.44648 6L6.61982 6L6.61981 5L4.44648 5L4.44648 6ZM2.84909 7.35814L4.09758 6.14186L3.39977 5.42557L2.15128 6.64186L2.84909 7.35814ZM12.8634 5.58864L10.3789 8.38365L11.1263 9.04802L13.6108 6.253L12.8634 5.58864ZM10 9.3802L10 11.5857L11 11.5857L11 9.3802L10 9.3802ZM9.85352 11.9393L8.64608 13.1464L9.35308 13.8536L10.5605 12.6465L9.85352 11.9393ZM6.85374 11.6464L4.35374 9.14645L3.64663 9.85355L6.14663 12.3536L6.85374 11.6464ZM4.42893 9.24275L2.92893 6.74275L2.07144 7.25725L3.57144 9.75725L4.42893 9.24275ZM9.25687 13.0713L6.75748 11.5713L6.24289 12.4287L8.74229 13.9287L9.25687 13.0713ZM10.3789 8.38365C10.1348 8.65823 10 9.01283 10 9.3802L11 9.3802C11 9.25774 11.045 9.13954 11.1263 9.04802L10.3789 8.38365ZM4.44648 5C4.05544 5 3.67986 5.1527 3.39977 5.42557L4.09758 6.14186C4.19094 6.0509 4.31614 6 4.44648 6L4.44648 5ZM6.952 4.8737C6.86047 4.95506 6.74227 5 6.61981 5L6.61982 6C6.98719 6 7.34178 5.86518 7.61636 5.62111L6.952 4.8737ZM10 11.5857C10 11.7183 9.94731 11.8455 9.85352 11.9393L10.5605 12.6465C10.8419 12.3652 11 11.9836 11 11.5857L10 11.5857ZM14 2.599C14 3.70112 13.5956 4.76491 12.8634 5.58864L13.6108 6.253C14.5057 5.24622 15 3.94603 15 2.599L14 2.599ZM13.401 0.999999C12.054 0.999999 10.7538 1.49433 9.74701 2.38925L10.4114 3.13666C11.2351 2.40445 12.2989 2 13.401 2L13.401 0.999999Z" />
<path d="M2.5 10.5L1.5 12.5V14.5H3.5L5.5 13.5" strokeLinecap="round" strokeLinejoin="round" />
<path d="M1 14.1667L2.5 10.5L5.5 13.5L1.83333 15H1V14.1667Z" />
<circle cx="10" cy="6" r="1" />
<path d="M5.5 10.5L8 8" strokeLinecap="round" strokeLinejoin="round" />
</svg>
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* 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.
*/

export { SecuritySideNav } from './security_side_nav';
Loading