Skip to content

Commit

Permalink
Update navigation landing pages to use appLinks config
Browse files Browse the repository at this point in the history
  • Loading branch information
machadoum committed May 11, 2022
1 parent 4ef0f1e commit 208e065
Show file tree
Hide file tree
Showing 24 changed files with 207 additions and 251 deletions.
6 changes: 3 additions & 3 deletions x-pack/plugins/security_solution/public/app/translations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export const USERS = i18n.translate('xpack.securitySolution.navigation.users', {
});

export const RULES = i18n.translate('xpack.securitySolution.navigation.rules', {
defaultMessage: 'Rules',
defaultMessage: 'SIEM rules',
});

export const EXCEPTIONS = i18n.translate('xpack.securitySolution.navigation.exceptions', {
Expand Down Expand Up @@ -71,7 +71,7 @@ export const ENDPOINTS = i18n.translate('xpack.securitySolution.search.administr
export const POLICIES = i18n.translate(
'xpack.securitySolution.navigation.administration.policies',
{
defaultMessage: 'Policies',
defaultMessage: 'Endpoint policies',
}
);
export const TRUSTED_APPLICATIONS = i18n.translate(
Expand All @@ -90,7 +90,7 @@ export const EVENT_FILTERS = i18n.translate(
export const HOST_ISOLATION_EXCEPTIONS = i18n.translate(
'xpack.securitySolution.search.administration.hostIsolationExceptions',
{
defaultMessage: 'Host isolation exceptions',
defaultMessage: 'Host isolation IP exceptions',
}
);
export const DETECT = i18n.translate('xpack.securitySolution.navigation.detect', {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,16 @@ import {

const allowedExperimentalValues = getExperimentalAllowedValues();

export const useIsExperimentalFeatureEnabled = (feature: keyof ExperimentalFeatures): boolean =>
useSelector(({ app: { enableExperimental } }: State) => {
if (!enableExperimental || !(feature in enableExperimental)) {
throw new Error(
`Invalid enable value ${feature}. Allowed values are: ${allowedExperimentalValues.join(
', '
)}`
);
}
return enableExperimental[feature];
});
export const useIsExperimentalFeatureEnabled = (feature: keyof ExperimentalFeatures): boolean => {
const enableExperimental = useEnableExperimental();

if (!enableExperimental || !(feature in enableExperimental)) {
throw new Error(
`Invalid enable value ${feature}. Allowed values are: ${allowedExperimentalValues.join(', ')}`
);
}
return enableExperimental[feature];
};

export const useEnableExperimental = (): ExperimentalFeatures =>
useSelector(({ app: { enableExperimental } }: State) => enableExperimental);
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions x-pack/plugins/security_solution/public/common/links/links.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
import { AppDeepLink, AppNavLinkStatus, Capabilities } from '@kbn/core/public';
import { get } from 'lodash';
import { SecurityPageName } from '../../../common/constants';
import { useEnableExperimental } from '../hooks/use_experimental_features';
import { useLicense } from '../hooks/use_license';
import { useKibana } from '../lib/kibana';
import { appLinks, getAppLinks } from './app_links';
import {
Feature,
Expand Down Expand Up @@ -195,3 +198,11 @@ export const getAncestorLinksInfo = (id: SecurityPageName): LinkInfo[] => {
export const needsUrlState = (id: SecurityPageName): boolean => {
return !getNormalizedLink(id).skipUrlState;
};

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

return getNavLinkItems({ enableExperimental, license, capabilities });
};
11 changes: 10 additions & 1 deletion x-pack/plugins/security_solution/public/common/links/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import { Capabilities } from '@kbn/core/types';
import { LicenseType } from '@kbn/licensing-plugin/common/types';
import { IconType } from '@elastic/eui';
import { LicenseService } from '../../../common/license';
import { ExperimentalFeatures } from '../../../common/experimental_features';
import { CASES_FEATURE_ID, SecurityPageName, SERVER_APP_ID } from '../../../common/constants';
Expand Down Expand Up @@ -41,8 +42,16 @@ export interface LinkItem {
globalSearchEnabled?: boolean;
globalSearchKeywords?: string[];
hideWhenExperimentalKey?: keyof ExperimentalFeatures;
icon?: string;
/**
* Icon that is displayed on menu navigation landing page.
* Only required for pages that are displayed inside a landing page.
*/
icon?: IconType;
id: SecurityPageName;
/**
* Image that is displayed on menu navigation landing page.
* Only required for pages that are displayed inside a landing page.
*/
image?: string;
isBeta?: boolean;
licenseType?: LicenseType;
Expand Down
6 changes: 6 additions & 0 deletions x-pack/plugins/security_solution/public/hosts/links.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,16 @@ import { i18n } from '@kbn/i18n';
import { HOSTS_PATH, SecurityPageName } from '../../common/constants';
import { HOSTS } from '../app/translations';
import { LinkItem } from '../common/links/types';
import hostsPageImg from '../common/images/hosts_page.png';

export const links: LinkItem = {
id: SecurityPageName.hosts,
title: HOSTS,
image: hostsPageImg,
description: i18n.translate('xpack.securitySolution.landing.threatHunting.hostsDescription', {
defaultMessage:
'Computer or other device that communicates with other hosts on a network. Hosts on a network include clients and servers -- that send or receive data, services or applications.',
}),
path: HOSTS_PATH,
globalNavEnabled: true,
globalSearchKeywords: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,18 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import {
EuiFlexGrid,
EuiFlexGroup,
EuiFlexItem,
EuiIcon,
EuiText,
EuiTitle,
IconType,
} from '@elastic/eui';
import { EuiFlexGrid, EuiFlexGroup, EuiFlexItem, EuiIcon, EuiText, EuiTitle } from '@elastic/eui';
import React from 'react';
import styled from 'styled-components';
import { SecurityPageName } from '../../app/types';

import {
SecuritySolutionLinkAnchor,
withSecuritySolutionLink,
} from '../../common/components/links';
import { NavLinkItem } from '../../common/links/types';

interface LandingLinksImagesProps {
items: NavItem[];
}

export interface NavItem {
id: SecurityPageName;
label: string;
icon: IconType;
description: string;
path?: string;
items: NavLinkItem[];
}

const Link = styled.a`
Expand All @@ -50,7 +35,7 @@ const StyledEuiTitle = styled(EuiTitle)`

export const LandingLinksIcons: React.FC<LandingLinksImagesProps> = ({ items }) => (
<EuiFlexGrid columns={3} gutterSize="xl">
{items.map(({ label, description, path, id, icon }) => (
{items.map(({ title, description, id, icon }) => (
<EuiFlexItem key={id} data-test-subj="LandingItem">
<EuiFlexGroup
direction="column"
Expand All @@ -59,14 +44,14 @@ export const LandingLinksIcons: React.FC<LandingLinksImagesProps> = ({ items })
responsive={false}
>
<EuiFlexItem grow={false}>
<SecuritySolutionLink tabIndex={-1} deepLinkId={id} path={path}>
<EuiIcon aria-hidden="true" size="xl" type={icon} role="presentation" />
<SecuritySolutionLink tabIndex={-1} deepLinkId={id}>
<EuiIcon aria-hidden="true" size="xl" type={icon ?? ''} role="presentation" />
</SecuritySolutionLink>
</EuiFlexItem>
<EuiFlexItem>
<StyledEuiTitle size="xxs">
<SecuritySolutionLinkAnchor deepLinkId={id} path={path}>
<h2>{label}</h2>
<SecuritySolutionLinkAnchor deepLinkId={id}>
<h2>{title}</h2>
</SecuritySolutionLinkAnchor>
</StyledEuiTitle>
</EuiFlexItem>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,11 @@
import { EuiFlexGroup, EuiFlexItem, EuiImage, EuiPanel, EuiText, EuiTitle } from '@elastic/eui';
import React from 'react';
import styled from 'styled-components';
import { SecurityPageName } from '../../app/types';
import { withSecuritySolutionLink } from '../../common/components/links';
import { LinkInfo } from '../../common/links/types';

interface LandingLinksImagesProps {
items: NavItem[];
}

export interface NavItem {
id: SecurityPageName;
label: string;
image: string;
description: string;
path?: string;
items: LinkInfo[];
}

const PrimaryEuiTitle = styled(EuiTitle)`
Expand Down Expand Up @@ -47,24 +39,26 @@ const Content = styled(EuiFlexItem)`

export const LandingLinksImages: React.FC<LandingLinksImagesProps> = ({ items }) => (
<EuiFlexGroup direction="column">
{items.map(({ label, description, path, image, id }) => (
{items.map(({ title, description, image, id }) => (
<EuiFlexItem key={id} data-test-subj="LandingItem">
<SecuritySolutionLink deepLinkId={id} path={path} tabIndex={-1}>
<SecuritySolutionLink deepLinkId={id} tabIndex={-1}>
{/* Empty onClick is to force hover style on `EuiPanel` */}
<EuiPanel hasBorder hasShadow={false} paddingSize="m" onClick={() => {}}>
<EuiFlexGroup>
<StyledFlexItem grow={false}>
<EuiImage
data-test-subj="LandingLinksImage"
size="l"
role="presentation"
alt=""
src={image}
/>
{image && (
<EuiImage
data-test-subj="LandingLinksImage"
size="l"
role="presentation"
alt=""
src={image}
/>
)}
</StyledFlexItem>
<Content>
<PrimaryEuiTitle size="s">
<h2>{label}</h2>
<h2>{title}</h2>
</PrimaryEuiTitle>
<LandingLinksDescripton size="s" color="text">
{description}
Expand Down
31 changes: 31 additions & 0 deletions x-pack/plugins/security_solution/public/landing_pages/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* 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';
import { SecurityPageName } from '../app/types';

export const MANAGE_NAVIGATION_CATEGORIES = [
{
label: i18n.translate('xpack.securitySolution.landing.siemTitle', {
defaultMessage: 'SIEM',
}),
itemIds: [SecurityPageName.rules, SecurityPageName.exceptions],
},
{
label: i18n.translate('xpack.securitySolution.landing.endpointsTitle', {
defaultMessage: 'ENDPOINTS',
}),
itemIds: [
SecurityPageName.endpoints,
SecurityPageName.policies,
SecurityPageName.trustedApps,
SecurityPageName.eventFilters,
SecurityPageName.blocklist,
SecurityPageName.hostIsolationExceptions,
],
},
];
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,24 @@
* 2.0.
*/
import React from 'react';
import { i18n } from '@kbn/i18n';
import { SecurityPageName } from '../../app/types';
import { HeaderPage } from '../../common/components/header_page';
import { SecuritySolutionPageWrapper } from '../../common/components/page_wrapper';
import { SpyRoute } from '../../common/utils/route/spy_routes';
import { LandingLinksImages, NavItem } from '../components/landing_links_images';
import { LandingLinksImages } from '../components/landing_links_images';
import { DASHBOARDS_PAGE_TITLE } from './translations';
import overviewPageImg from '../../common/images/overview_page.png';
import { OVERVIEW } from '../../app/translations';
import { useAppNavLinks } from '../../common/links';

const items: NavItem[] = [
{
id: SecurityPageName.overview,
label: OVERVIEW,
description: i18n.translate('xpack.securitySolution.landing.dashboards.overviewDescription', {
defaultMessage: 'What is going in your secuity environment',
}),
image: overviewPageImg,
},
];
export const DashboardsLandingPage = () => {
const dashboardlinks = useAppNavLinks().find(
({ id }) => id === SecurityPageName.dashboardsLanding
);

export const DashboardsLandingPage = () => (
<SecuritySolutionPageWrapper>
<HeaderPage title={DASHBOARDS_PAGE_TITLE} />
<LandingLinksImages items={items} />
<SpyRoute pageName={SecurityPageName.dashboardsLanding} />
</SecuritySolutionPageWrapper>
);
return (
<SecuritySolutionPageWrapper>
<HeaderPage title={DASHBOARDS_PAGE_TITLE} />
<LandingLinksImages items={dashboardlinks?.links ?? []} />
<SpyRoute pageName={SecurityPageName.dashboardsLanding} />
</SecuritySolutionPageWrapper>
);
};
Loading

0 comments on commit 208e065

Please sign in to comment.