Skip to content

Commit

Permalink
[SIEM] Fix link on overview page (elastic#60348)
Browse files Browse the repository at this point in the history
* Fix link on overview page

* no needs of useMemo

* clean up

* review I

* review II

* review III
  • Loading branch information
XavierM committed Mar 17, 2020
1 parent c846272 commit 87105f3
Show file tree
Hide file tree
Showing 16 changed files with 146 additions and 87 deletions.
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;
* you may not use this file except in compliance with the Elastic License.
*/

import { appendSearch } from './helpers';

describe('appendSearch', () => {
test('should return empty string if no parameter', () => {
expect(appendSearch()).toEqual('');
});
test('should return empty string if parameter is undefined', () => {
expect(appendSearch(undefined)).toEqual('');
});
test('should return parameter if parameter is defined', () => {
expect(appendSearch('helloWorld')).toEqual('helloWorld');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

export const appendSearch = (search?: string) => (search != null ? `${search}` : '');
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import React from 'react';
import { RouteComponentProps } from 'react-router-dom';

import { DetectionEngineTab } from '../../pages/detection_engine/types';
import { appendSearch } from './helpers';
import { RedirectWrapper } from './redirect_wrapper';

export type DetectionEngineComponentProps = RouteComponentProps<{
Expand Down Expand Up @@ -63,9 +64,10 @@ export const RedirectToEditRulePage = ({

const baseDetectionEngineUrl = `#/link-to/${DETECTION_ENGINE_PAGE_NAME}`;

export const getDetectionEngineUrl = () => `${baseDetectionEngineUrl}`;
export const getDetectionEngineAlertUrl = () =>
`${baseDetectionEngineUrl}/${DetectionEngineTab.alerts}`;
export const getDetectionEngineUrl = (search?: string) =>
`${baseDetectionEngineUrl}${appendSearch(search)}`;
export const getDetectionEngineAlertUrl = (search?: string) =>
`${baseDetectionEngineUrl}/${DetectionEngineTab.alerts}${appendSearch(search)}`;
export const getDetectionEngineTabUrl = (tabPath: string) => `${baseDetectionEngineUrl}/${tabPath}`;
export const getRulesUrl = () => `${baseDetectionEngineUrl}/rules`;
export const getCreateRuleUrl = () => `${baseDetectionEngineUrl}/rules/create`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@
import React from 'react';
import { RouteComponentProps } from 'react-router-dom';

import { RedirectWrapper } from './redirect_wrapper';
import { HostsTableType } from '../../store/hosts/model';
import { SiemPageName } from '../../pages/home/types';

import { appendSearch } from './helpers';
import { RedirectWrapper } from './redirect_wrapper';

export type HostComponentProps = RouteComponentProps<{
detailName: string;
tabName: HostsTableType;
Expand Down Expand Up @@ -44,9 +46,10 @@ export const RedirectToHostDetailsPage = ({

const baseHostsUrl = `#/link-to/${SiemPageName.hosts}`;

export const getHostsUrl = () => baseHostsUrl;
export const getHostsUrl = (search?: string) => `${baseHostsUrl}${appendSearch(search)}`;

export const getTabsOnHostsUrl = (tabName: HostsTableType) => `${baseHostsUrl}/${tabName}`;
export const getTabsOnHostsUrl = (tabName: HostsTableType, search?: string) =>
`${baseHostsUrl}/${tabName}${appendSearch(search)}`;

export const getHostDetailsUrl = (detailName: string) => `${baseHostsUrl}/${detailName}`;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@
import React from 'react';
import { RouteComponentProps } from 'react-router-dom';

import { RedirectWrapper } from './redirect_wrapper';
import { SiemPageName } from '../../pages/home/types';
import { FlowTarget, FlowTargetSourceDest } from '../../graphql/types';

import { appendSearch } from './helpers';
import { RedirectWrapper } from './redirect_wrapper';

export type NetworkComponentProps = RouteComponentProps<{
detailName?: string;
flowTarget?: string;
Expand All @@ -33,7 +35,7 @@ export const RedirectToNetworkPage = ({
);

const baseNetworkUrl = `#/link-to/${SiemPageName.network}`;
export const getNetworkUrl = () => baseNetworkUrl;
export const getNetworkUrl = (search?: string) => `${baseNetworkUrl}${appendSearch(search)}`;
export const getIPDetailsUrl = (
detailName: string,
flowTarget?: FlowTarget | FlowTargetSourceDest
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@

import React from 'react';
import { RouteComponentProps } from 'react-router-dom';
import { RedirectWrapper } from './redirect_wrapper';

import { SiemPageName } from '../../pages/home/types';

import { appendSearch } from './helpers';
import { RedirectWrapper } from './redirect_wrapper';

export type TimelineComponentProps = RouteComponentProps<{
search: string;
}>;
Expand All @@ -17,4 +20,5 @@ export const RedirectToTimelinesPage = ({ location: { search } }: TimelineCompon
<RedirectWrapper to={`/${SiemPageName.timelines}${search}`} />
);

export const getTimelinesUrl = () => `#/link-to/${SiemPageName.timelines}`;
export const getTimelinesUrl = (search?: string) =>
`#/link-to/${SiemPageName.timelines}${appendSearch(search)}`;
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,17 @@ import { Location } from 'history';
import { UrlInputsModel } from '../../store/inputs/model';
import { TimelineUrl } from '../../store/timeline/model';
import { CONSTANTS } from '../url_state/constants';
import { URL_STATE_KEYS, KeyUrlState } from '../url_state/types';
import { URL_STATE_KEYS, KeyUrlState, UrlState } from '../url_state/types';
import {
replaceQueryStringInLocation,
replaceStateKeyInQueryString,
getQueryStringFromLocation,
} from '../url_state/helpers';
import { Query, Filter } from '../../../../../../../src/plugins/data/public';

import { TabNavigationProps } from './tab_navigation/types';
import { SearchNavTab } from './types';

export const getSearch = (tab: SearchNavTab, urlState: TabNavigationProps): string => {
export const getSearch = (tab: SearchNavTab, urlState: UrlState): string => {
if (tab && tab.urlKey != null && URL_STATE_KEYS[tab.urlKey] != null) {
return URL_STATE_KEYS[tab.urlKey].reduce<Location>(
(myLocation: Location, urlKey: KeyUrlState) => {
Expand Down Expand Up @@ -58,7 +57,7 @@ export const getSearch = (tab: SearchNavTab, urlState: TabNavigationProps): stri
);
},
{
pathname: urlState.pathName,
pathname: '',
hash: '',
search: '',
state: '',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@ export const TabNavigationComponent = (props: TabNavigationProps) => {
() =>
Object.values(navTabs).map(tab => {
const isSelected = selectedTabId === tab.id;
const hrefWithSearch = tab.href + getSearch(tab, props);
const { query, filters, savedQuery, timerange, timeline } = props;
const hrefWithSearch =
tab.href + getSearch(tab, { query, filters, savedQuery, timerange, timeline });

return (
<TabNavigationItem
Expand Down
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;
* you may not use this file except in compliance with the Elastic License.
*/

import { isEqual } from 'lodash/fp';
import { useMemo } from 'react';
import { useSelector } from 'react-redux';

import { makeMapStateToProps } from '../url_state/helpers';
import { getSearch } from './helpers';
import { SearchNavTab } from './types';

export const useGetUrlSearch = (tab: SearchNavTab) => {
const mapState = makeMapStateToProps();
const { urlState } = useSelector(mapState, isEqual);
const urlSearch = useMemo(() => getSearch(tab, urlState), [tab, urlState]);
return urlSearch;
};
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { isEmpty } from 'lodash/fp';
import { EuiButton, EuiFlexItem, EuiPanel } from '@elastic/eui';
import numeral from '@elastic/numeral';
import { FormattedMessage } from '@kbn/i18n/react';
import React from 'react';
import React, { useMemo } from 'react';

import { DEFAULT_NUMBER_FORMAT } from '../../../../../common/constants';
import { ESQuery } from '../../../../../common/typed_json';
Expand All @@ -23,6 +23,8 @@ import { getOverviewHostStats, OverviewHostStats } from '../overview_host_stats'
import { manageQuery } from '../../../page/manage_query';
import { inputsModel } from '../../../../store/inputs';
import { InspectButtonContainer } from '../../../inspect';
import { useGetUrlSearch } from '../../../navigation/use_get_url_search';
import { navTabs } from '../../../../pages/home/home_navigations';

export interface OwnProps {
startDate: number;
Expand Down Expand Up @@ -51,7 +53,15 @@ const OverviewHostComponent: React.FC<OverviewHostProps> = ({
setQuery,
}) => {
const [defaultNumberFormat] = useUiSetting$<string>(DEFAULT_NUMBER_FORMAT);

const urlSearch = useGetUrlSearch(navTabs.hosts);
const hostPageButton = useMemo(
() => (
<EuiButton href={getHostsUrl(urlSearch)}>
<FormattedMessage id="xpack.siem.overview.hostsAction" defaultMessage="View hosts" />
</EuiButton>
),
[urlSearch]
);
return (
<EuiFlexItem>
<InspectButtonContainer>
Expand Down Expand Up @@ -95,12 +105,7 @@ const OverviewHostComponent: React.FC<OverviewHostProps> = ({
/>
}
>
<EuiButton href={getHostsUrl()}>
<FormattedMessage
id="xpack.siem.overview.hostsAction"
defaultMessage="View hosts"
/>
</EuiButton>
{hostPageButton}
</HeaderSection>

<OverviewHostStatsManage
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { isEmpty } from 'lodash/fp';
import { EuiButton, EuiFlexItem, EuiPanel } from '@elastic/eui';
import numeral from '@elastic/numeral';
import { FormattedMessage } from '@kbn/i18n/react';
import React from 'react';
import React, { useMemo } from 'react';

import { DEFAULT_NUMBER_FORMAT } from '../../../../../common/constants';
import { ESQuery } from '../../../../../common/typed_json';
Expand All @@ -23,6 +23,8 @@ import { inputsModel } from '../../../../store/inputs';
import { getOverviewNetworkStats, OverviewNetworkStats } from '../overview_network_stats';
import { getNetworkUrl } from '../../../link_to';
import { InspectButtonContainer } from '../../../inspect';
import { useGetUrlSearch } from '../../../navigation/use_get_url_search';
import { navTabs } from '../../../../pages/home/home_navigations';

export interface OverviewNetworkProps {
startDate: number;
Expand Down Expand Up @@ -50,7 +52,15 @@ const OverviewNetworkComponent: React.FC<OverviewNetworkProps> = ({
setQuery,
}) => {
const [defaultNumberFormat] = useUiSetting$<string>(DEFAULT_NUMBER_FORMAT);

const urlSearch = useGetUrlSearch(navTabs.network);
const networkPageButton = useMemo(
() => (
<EuiButton href={getNetworkUrl(urlSearch)}>
<FormattedMessage id="xpack.siem.overview.networkAction" defaultMessage="View network" />
</EuiButton>
),
[urlSearch]
);
return (
<EuiFlexItem>
<InspectButtonContainer>
Expand Down Expand Up @@ -96,12 +106,7 @@ const OverviewNetworkComponent: React.FC<OverviewNetworkProps> = ({
/>
}
>
<EuiButton href={getNetworkUrl()}>
<FormattedMessage
id="xpack.siem.overview.networkAction"
defaultMessage="View network"
/>
</EuiButton>
{networkPageButton}
</HeaderSection>

<OverviewNetworkStatsManage
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import ApolloClient from 'apollo-client';
import { EuiHorizontalRule, EuiLink, EuiText } from '@elastic/eui';
import React, { useCallback } from 'react';
import React, { useCallback, useMemo } from 'react';
import { connect, ConnectedProps } from 'react-redux';
import { Dispatch } from 'redux';
import { ActionCreator } from 'typescript-fsa';
Expand All @@ -21,6 +21,9 @@ import { updateIsLoading as dispatchUpdateIsLoading } from '../../store/timeline
import { RecentTimelines } from './recent_timelines';
import * as i18n from './translations';
import { FilterMode } from './types';
import { useGetUrlSearch } from '../navigation/use_get_url_search';
import { navTabs } from '../../pages/home/home_navigations';
import { getTimelinesUrl } from '../link_to/redirect_to_timelines';

interface OwnProps {
apolloClient: ApolloClient<{}>;
Expand All @@ -47,6 +50,11 @@ const StatefulRecentTimelinesComponent = React.memo<Props>(

const noTimelinesMessage =
filterBy === 'favorites' ? i18n.NO_FAVORITE_TIMELINES : i18n.NO_TIMELINES;
const urlSearch = useGetUrlSearch(navTabs.timelines);
const linkAllTimelines = useMemo(
() => <EuiLink href={getTimelinesUrl(urlSearch)}>{i18n.VIEW_ALL_TIMELINES}</EuiLink>,
[urlSearch]
);

return (
<AllTimelinesQuery
Expand All @@ -73,9 +81,7 @@ const StatefulRecentTimelinesComponent = React.memo<Props>(
/>
)}
<EuiHorizontalRule margin="s" />
<EuiText size="xs">
<EuiLink href="#/link-to/timelines">{i18n.VIEW_ALL_TIMELINES}</EuiLink>
</EuiText>
<EuiText size="xs">{linkAllTimelines}</EuiText>
</>
)}
</AllTimelinesQuery>
Expand Down
38 changes: 2 additions & 36 deletions x-pack/legacy/plugins/siem/public/components/url_state/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,7 @@ import { TimelineUrl } from '../../store/timeline/model';
import { formatDate } from '../super_date_picker';
import { NavTab } from '../navigation/types';
import { CONSTANTS, UrlStateType } from './constants';
import {
LocationTypes,
UrlStateContainerPropTypes,
ReplaceStateInLocation,
UpdateUrlStateString,
} from './types';
import { ReplaceStateInLocation, UpdateUrlStateString } from './types';

export const decodeRisonUrlState = <T>(value: string | undefined): T | null => {
try {
Expand Down Expand Up @@ -113,42 +108,13 @@ export const getTitle = (
return navTabs[pageName] != null ? navTabs[pageName].name : '';
};

export const getCurrentLocation = (
pageName: string,
detailName: string | undefined
): LocationTypes => {
if (pageName === SiemPageName.overview) {
return CONSTANTS.overviewPage;
} else if (pageName === SiemPageName.hosts) {
if (detailName != null) {
return CONSTANTS.hostsDetails;
}
return CONSTANTS.hostsPage;
} else if (pageName === SiemPageName.network) {
if (detailName != null) {
return CONSTANTS.networkDetails;
}
return CONSTANTS.networkPage;
} else if (pageName === SiemPageName.detections) {
return CONSTANTS.detectionsPage;
} else if (pageName === SiemPageName.timelines) {
return CONSTANTS.timelinePage;
} else if (pageName === SiemPageName.case) {
if (detailName != null) {
return CONSTANTS.caseDetails;
}
return CONSTANTS.casePage;
}
return CONSTANTS.unknown;
};

export const makeMapStateToProps = () => {
const getInputsSelector = inputsSelectors.inputsSelector();
const getGlobalQuerySelector = inputsSelectors.globalQuerySelector();
const getGlobalFiltersQuerySelector = inputsSelectors.globalFiltersQuerySelector();
const getGlobalSavedQuerySelector = inputsSelectors.globalSavedQuerySelector();
const getTimelines = timelineSelectors.getTimelines();
const mapStateToProps = (state: State, { pageName, detailName }: UrlStateContainerPropTypes) => {
const mapStateToProps = (state: State) => {
const inputState = getInputsSelector(state);
const { linkTo: globalLinkTo, timerange: globalTimerange } = inputState.global;
const { linkTo: timelineLinkTo, timerange: timelineTimerange } = inputState.timeline;
Expand Down
Loading

0 comments on commit 87105f3

Please sign in to comment.