diff --git a/x-pack/plugins/security_solution/common/types/timeline/index.ts b/x-pack/plugins/security_solution/common/types/timeline/index.ts index 1ea9b5752e0cc..26a30e7c8f239 100644 --- a/x-pack/plugins/security_solution/common/types/timeline/index.ts +++ b/x-pack/plugins/security_solution/common/types/timeline/index.ts @@ -280,6 +280,7 @@ export enum TimelineId { active = 'timeline-1', casePage = 'timeline-case', test = 'test', // Reserved for testing purposes + test2 = 'test2', } export const TimelineIdLiteralRt = runtimeTypes.union([ diff --git a/x-pack/plugins/security_solution/public/common/components/events_viewer/events_viewer.test.tsx b/x-pack/plugins/security_solution/public/common/components/events_viewer/events_viewer.test.tsx index 4364ca2d3465d..6dad6c439ce46 100644 --- a/x-pack/plugins/security_solution/public/common/components/events_viewer/events_viewer.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/events_viewer/events_viewer.test.tsx @@ -119,7 +119,7 @@ describe('EventsViewer', () => { let testProps = { defaultModel: eventsDefaultModel, end: to, - id: 'test-stateful-events-viewer', + id: TimelineId.test, start: from, scopeId: SourcererScopeName.timeline, }; @@ -155,7 +155,7 @@ describe('EventsViewer', () => { indexName: 'auditbeat-7.10.1-2020.12.18-000001', }, tabType: 'query', - timelineId: 'test-stateful-events-viewer', + timelineId: TimelineId.test, }, type: 'x-pack/security_solution/local/timeline/TOGGLE_EXPANDED_EVENT', }); @@ -199,17 +199,22 @@ describe('EventsViewer', () => { defaultHeaders.forEach((header) => { test(`it renders the ${header.id} default EventsViewer column header`, () => { + testProps = { + ...testProps, + // Update with a new id, to force columns back to default. + id: TimelineId.test2, + }; const wrapper = mount( ); - defaultHeaders.forEach((h) => + defaultHeaders.forEach((h) => { expect(wrapper.find(`[data-test-subj="header-text-${header.id}"]`).first().exists()).toBe( true - ) - ); + ); + }); }); }); }); diff --git a/x-pack/plugins/security_solution/public/common/components/events_viewer/events_viewer.tsx b/x-pack/plugins/security_solution/public/common/components/events_viewer/events_viewer.tsx index 77573dbab0a53..254309aee906b 100644 --- a/x-pack/plugins/security_solution/public/common/components/events_viewer/events_viewer.tsx +++ b/x-pack/plugins/security_solution/public/common/components/events_viewer/events_viewer.tsx @@ -117,7 +117,7 @@ interface Props { filters: Filter[]; headerFilterGroup?: React.ReactNode; height?: number; - id: string; + id: TimelineId; indexNames: string[]; indexPattern: IIndexPattern; isLive: boolean; diff --git a/x-pack/plugins/security_solution/public/common/components/events_viewer/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/events_viewer/index.test.tsx index c2fbfdb666e04..5004c23f9111c 100644 --- a/x-pack/plugins/security_solution/public/common/components/events_viewer/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/events_viewer/index.test.tsx @@ -16,6 +16,7 @@ import { useMountAppended } from '../../utils/use_mount_appended'; import { mockEventViewerResponse } from './mock'; import { StatefulEventsViewer } from '.'; import { eventsDefaultModel } from './default_model'; +import { TimelineId } from '../../../../common/types/timeline'; import { SourcererScopeName } from '../../store/sourcerer/model'; import { useTimelineEvents } from '../../../timelines/containers'; @@ -36,7 +37,7 @@ const testProps = { defaultModel: eventsDefaultModel, end: to, indexNames: [], - id: 'test-stateful-events-viewer', + id: TimelineId.test, scopeId: SourcererScopeName.default, start: from, }; diff --git a/x-pack/plugins/security_solution/public/common/components/events_viewer/index.tsx b/x-pack/plugins/security_solution/public/common/components/events_viewer/index.tsx index 526bc312172b0..2b5420674b89c 100644 --- a/x-pack/plugins/security_solution/public/common/components/events_viewer/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/events_viewer/index.tsx @@ -12,6 +12,7 @@ import styled from 'styled-components'; import { inputsModel, inputsSelectors, State } from '../../store'; import { inputsActions } from '../../store/actions'; +import { TimelineId } from '../../../../common/types/timeline'; import { timelineSelectors, timelineActions } from '../../../timelines/store/timeline'; import { SubsetTimelineModel, TimelineModel } from '../../../timelines/store/timeline/model'; import { Filter } from '../../../../../../../src/plugins/data/public'; @@ -34,7 +35,7 @@ const FullScreenContainer = styled.div<{ $isFullScreen: boolean }>` export interface OwnProps { defaultModel: SubsetTimelineModel; end: string; - id: string; + id: TimelineId; scopeId: SourcererScopeName; start: string; headerFilterGroup?: React.ReactNode; diff --git a/x-pack/plugins/security_solution/public/resolver/store/data/reducer.ts b/x-pack/plugins/security_solution/public/resolver/store/data/reducer.ts index 8df0c92ca83e5..b5864a0a83cf2 100644 --- a/x-pack/plugins/security_solution/public/resolver/store/data/reducer.ts +++ b/x-pack/plugins/security_solution/public/resolver/store/data/reducer.ts @@ -19,6 +19,7 @@ const initialState: DataState = { data: null, }, resolverComponentInstanceID: undefined, + indices: [], }; /* eslint-disable complexity */ export const dataReducer: Reducer = (state = initialState, action) => { @@ -35,6 +36,7 @@ export const dataReducer: Reducer = (state = initialS }, resolverComponentInstanceID: action.payload.resolverComponentInstanceID, locationSearch: action.payload.locationSearch, + indices: action.payload.indices, }; const panelViewAndParameters = selectors.panelViewAndParameters(nextState); return { diff --git a/x-pack/plugins/security_solution/public/resolver/store/data/selectors.test.ts b/x-pack/plugins/security_solution/public/resolver/store/data/selectors.test.ts index c372c98c6e060..b864bb254a5fc 100644 --- a/x-pack/plugins/security_solution/public/resolver/store/data/selectors.test.ts +++ b/x-pack/plugins/security_solution/public/resolver/store/data/selectors.test.ts @@ -664,4 +664,85 @@ describe('data state', () => { `); }); }); + describe('when the resolver tree response is complete, still use non-default indices', () => { + beforeEach(() => { + const { resolverTree } = mockTreeWithNoAncestorsAnd2Children({ + originID: 'a', + firstChildID: 'b', + secondChildID: 'c', + }); + const { schema, dataSource } = endpointSourceSchema(); + actions = [ + { + type: 'serverReturnedResolverData', + payload: { + result: resolverTree, + dataSource, + schema, + parameters: { + databaseDocumentID: '', + indices: ['someNonDefaultIndex'], + filters: {}, + }, + }, + }, + ]; + }); + it('should have an empty array for tree parameter indices, and a non empty array for event indices', () => { + const treeParameterIndices = selectors.treeParameterIndices(state()); + expect(treeParameterIndices.length).toBe(0); + const eventIndices = selectors.eventIndices(state()); + expect(eventIndices.length).toBe(1); + }); + }); + describe('when the resolver tree response is pending use the same indices the user is currently looking at data from', () => { + beforeEach(() => { + const { resolverTree } = mockTreeWithNoAncestorsAnd2Children({ + originID: 'a', + firstChildID: 'b', + secondChildID: 'c', + }); + const { schema, dataSource } = endpointSourceSchema(); + actions = [ + { + type: 'serverReturnedResolverData', + payload: { + result: resolverTree, + dataSource, + schema, + parameters: { + databaseDocumentID: '', + indices: ['defaultIndex'], + filters: {}, + }, + }, + }, + { + type: 'appReceivedNewExternalProperties', + payload: { + databaseDocumentID: '', + resolverComponentInstanceID: '', + locationSearch: '', + indices: ['someNonDefaultIndex', 'someOtherIndex'], + shouldUpdate: false, + filters: {}, + }, + }, + { + type: 'appRequestedResolverData', + payload: { + databaseDocumentID: '', + indices: ['someNonDefaultIndex', 'someOtherIndex'], + filters: {}, + }, + }, + ]; + }); + it('should have an empty array for tree parameter indices, and the same set of indices as the last tree response', () => { + const treeParameterIndices = selectors.treeParameterIndices(state()); + expect(treeParameterIndices.length).toBe(0); + const eventIndices = selectors.eventIndices(state()); + expect(eventIndices.length).toBe(1); + }); + }); }); diff --git a/x-pack/plugins/security_solution/public/resolver/store/data/selectors.ts b/x-pack/plugins/security_solution/public/resolver/store/data/selectors.ts index a39aa4f0cd983..fb6fb6073d7cf 100644 --- a/x-pack/plugins/security_solution/public/resolver/store/data/selectors.ts +++ b/x-pack/plugins/security_solution/public/resolver/store/data/selectors.ts @@ -63,6 +63,13 @@ export function resolverComponentInstanceID(state: DataState): string { return state.resolverComponentInstanceID ? state.resolverComponentInstanceID : ''; } +/** + * The indices resolver should use, passed in as external props. + */ +const currentIndices = (state: DataState): string[] => { + return state.indices; +}; + /** * The last NewResolverTree we received, if any. It may be stale (it might not be for the same databaseDocumentID that * we're currently interested in. @@ -71,6 +78,12 @@ const resolverTreeResponse = (state: DataState): NewResolverTree | undefined => return state.tree?.lastResponse?.successful ? state.tree?.lastResponse.result : undefined; }; +const lastResponseIndices = (state: DataState): string[] | undefined => { + return state.tree?.lastResponse?.successful + ? state.tree?.lastResponse?.parameters?.indices + : undefined; +}; + /** * If we received a NewResolverTree, return the schema associated with that tree, otherwise return undefined. * As of writing, this is only used for the info popover in the graph_controls panel @@ -336,10 +349,22 @@ export const timeRangeFilters = createSelector( /** * The indices to use for the requests with the backend. */ -export const treeParamterIndices = createSelector(treeParametersToFetch, (parameters) => { +export const treeParameterIndices = createSelector(treeParametersToFetch, (parameters) => { return parameters?.indices ?? []; }); +/** + * Panel requests should not use indices derived from the tree parameter selector, as this is only defined briefly while the resolver_tree_fetcher middleware is running. + * Instead, panel requests should use the indices used by the last good request, falling back to the indices passed as external props. + */ +export const eventIndices = createSelector( + lastResponseIndices, + currentIndices, + function eventIndices(lastIndices, current): string[] { + return lastIndices ?? current ?? []; + } +); + export const layout: (state: DataState) => IsometricTaxiLayout = createSelector( tree, originID, diff --git a/x-pack/plugins/security_solution/public/resolver/store/middleware/current_related_event_fetcher.ts b/x-pack/plugins/security_solution/public/resolver/store/middleware/current_related_event_fetcher.ts index 3b8389182e990..33772dddd676e 100644 --- a/x-pack/plugins/security_solution/public/resolver/store/middleware/current_related_event_fetcher.ts +++ b/x-pack/plugins/security_solution/public/resolver/store/middleware/current_related_event_fetcher.ts @@ -32,7 +32,7 @@ export function CurrentRelatedEventFetcher( const state = api.getState(); const newParams = selectors.panelViewAndParameters(state); - const indices = selectors.treeParameterIndices(state); + const indices = selectors.eventIndices(state); const oldParams = last; last = newParams; diff --git a/x-pack/plugins/security_solution/public/resolver/store/middleware/node_data_fetcher.ts b/x-pack/plugins/security_solution/public/resolver/store/middleware/node_data_fetcher.ts index 696e7f921673b..074fdf7535790 100644 --- a/x-pack/plugins/security_solution/public/resolver/store/middleware/node_data_fetcher.ts +++ b/x-pack/plugins/security_solution/public/resolver/store/middleware/node_data_fetcher.ts @@ -38,7 +38,7 @@ export function NodeDataFetcher( * This gets the visible nodes that we haven't already requested or received data for */ const newIDsToRequest: Set = selectors.newIDsToRequest(state)(Number.POSITIVE_INFINITY); - const indices = selectors.treeParameterIndices(state); + const indices = selectors.eventIndices(state); if (newIDsToRequest.size <= 0) { return; diff --git a/x-pack/plugins/security_solution/public/resolver/store/middleware/related_events_fetcher.ts b/x-pack/plugins/security_solution/public/resolver/store/middleware/related_events_fetcher.ts index fbce03caf64d8..19a11e07a9d87 100644 --- a/x-pack/plugins/security_solution/public/resolver/store/middleware/related_events_fetcher.ts +++ b/x-pack/plugins/security_solution/public/resolver/store/middleware/related_events_fetcher.ts @@ -27,7 +27,7 @@ export function RelatedEventsFetcher( const newParams = selectors.panelViewAndParameters(state); const isLoadingMoreEvents = selectors.isLoadingMoreNodeEventsInCategory(state); - const indices = selectors.treeParameterIndices(state); + const indices = selectors.eventIndices(state); const oldParams = last; const timeRangeFilters = selectors.timeRangeFilters(state); diff --git a/x-pack/plugins/security_solution/public/resolver/store/selectors.ts b/x-pack/plugins/security_solution/public/resolver/store/selectors.ts index a845de57bbdc6..4c088a8be4ed9 100644 --- a/x-pack/plugins/security_solution/public/resolver/store/selectors.ts +++ b/x-pack/plugins/security_solution/public/resolver/store/selectors.ts @@ -80,9 +80,14 @@ export const treeRequestParametersToAbort = composeSelectors( */ export const treeParameterIndices = composeSelectors( dataStateSelector, - dataSelectors.treeParamterIndices + dataSelectors.treeParameterIndices ); +/** + * An array of indices to use for resolver panel requests. + */ +export const eventIndices = composeSelectors(dataStateSelector, dataSelectors.eventIndices); + export const resolverComponentInstanceID = composeSelectors( dataStateSelector, dataSelectors.resolverComponentInstanceID diff --git a/x-pack/plugins/security_solution/public/resolver/types.ts b/x-pack/plugins/security_solution/public/resolver/types.ts index d3ddc51429ccd..e6a004938a267 100644 --- a/x-pack/plugins/security_solution/public/resolver/types.ts +++ b/x-pack/plugins/security_solution/public/resolver/types.ts @@ -376,6 +376,8 @@ export interface DataState { */ readonly resolverComponentInstanceID?: string; + readonly indices: string[]; + /** * The `search` part of the URL. */ diff --git a/x-pack/plugins/security_solution/public/timelines/components/flyout/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/flyout/index.test.tsx index 3783f5591c43e..f57ce42e7e079 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/flyout/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/flyout/index.test.tsx @@ -18,6 +18,7 @@ import { kibanaObservable, createSecuritySolutionStorageMock, } from '../../../common/mock'; +import { TimelineId } from '../../../../common/types/timeline'; import { createStore, State } from '../../../common/store'; import * as timelineActions from '../../store/timeline/actions'; @@ -43,7 +44,7 @@ describe('Flyout', () => { const { storage } = createSecuritySolutionStorageMock(); const props = { onAppLeave: jest.fn(), - timelineId: 'test', + timelineId: TimelineId.test, }; beforeEach(() => { diff --git a/x-pack/plugins/security_solution/public/timelines/components/flyout/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/flyout/index.tsx index f7518c2c34f66..bd7c7fbd1941f 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/flyout/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/flyout/index.tsx @@ -26,7 +26,7 @@ const Visible = styled.div<{ show?: boolean }>` Visible.displayName = 'Visible'; interface OwnProps { - timelineId: string; + timelineId: TimelineId; onAppLeave: (handler: AppLeaveHandler) => void; } diff --git a/x-pack/plugins/security_solution/public/timelines/components/flyout/pane/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/flyout/pane/index.test.tsx index e16cec78cf13b..4ccc7ef5b5bc5 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/flyout/pane/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/flyout/pane/index.test.tsx @@ -9,13 +9,14 @@ import { shallow } from 'enzyme'; import React from 'react'; import { TestProviders } from '../../../../common/mock'; +import { TimelineId } from '../../../../../common/types/timeline'; import { Pane } from '.'; describe('Pane', () => { test('renders correctly against snapshot', () => { const EmptyComponent = shallow( - + ); expect(EmptyComponent.find('Pane')).toMatchSnapshot(); diff --git a/x-pack/plugins/security_solution/public/timelines/components/flyout/pane/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/flyout/pane/index.tsx index a4d85bd76b105..e63ffedf3da7c 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/flyout/pane/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/flyout/pane/index.tsx @@ -11,12 +11,13 @@ import styled from 'styled-components'; import { useDispatch } from 'react-redux'; import { StatefulTimeline } from '../../timeline'; +import { TimelineId } from '../../../../../common/types/timeline'; import * as i18n from './translations'; import { timelineActions } from '../../../store/timeline'; import { focusActiveTimelineButton } from '../../timeline/helpers'; interface FlyoutPaneComponentProps { - timelineId: string; + timelineId: TimelineId; } const EuiFlyoutContainer = styled.div` diff --git a/x-pack/plugins/security_solution/public/timelines/components/graph_overlay/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/graph_overlay/index.test.tsx index c0e1a54faa8dd..1286208bff9e6 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/graph_overlay/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/graph_overlay/index.test.tsx @@ -15,7 +15,6 @@ import { } from '../../../common/containers/use_full_screen'; import { mockTimelineModel, TestProviders } from '../../../common/mock'; import { TimelineId } from '../../../../common/types/timeline'; - import { GraphOverlay } from '.'; jest.mock('../../../common/hooks/use_selector', () => ({ @@ -28,6 +27,10 @@ jest.mock('../../../common/containers/use_full_screen', () => ({ useTimelineFullScreen: jest.fn(), })); +jest.mock('../../../resolver/view/use_resolver_query_params_cleaner'); +jest.mock('../../../resolver/view/use_state_syncing_actions'); +jest.mock('../../../resolver/view/use_sync_selected_node'); + describe('GraphOverlay', () => { beforeEach(() => { (useGlobalFullScreen as jest.Mock).mockReturnValue({ @@ -42,12 +45,11 @@ describe('GraphOverlay', () => { describe('when used in an events viewer (i.e. in the Detections view, or the Host > Events view)', () => { const isEventViewer = true; - const timelineId = 'used-as-an-events-viewer'; test('it has 100% width when isEventViewer is true and NOT in full screen mode', async () => { const wrapper = mount( - + ); @@ -69,7 +71,7 @@ describe('GraphOverlay', () => { const wrapper = mount( - + ); diff --git a/x-pack/plugins/security_solution/public/timelines/components/graph_overlay/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/graph_overlay/index.tsx index 1b3a0c21ef683..9c9c56461609d 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/graph_overlay/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/graph_overlay/index.tsx @@ -20,7 +20,7 @@ import styled from 'styled-components'; import { FULL_SCREEN } from '../timeline/body/column_headers/translations'; import { EXIT_FULL_SCREEN } from '../../../common/components/exit_full_screen/translations'; -import { DEFAULT_INDEX_KEY, FULL_SCREEN_TOGGLED_CLASS_NAME } from '../../../../common/constants'; +import { FULL_SCREEN_TOGGLED_CLASS_NAME } from '../../../../common/constants'; import { useGlobalFullScreen, useTimelineFullScreen, @@ -30,6 +30,8 @@ import { TimelineId } from '../../../../common/types/timeline'; import { timelineSelectors } from '../../store/timeline'; import { timelineDefaults } from '../../store/timeline/defaults'; import { isFullScreen } from '../timeline/body/column_headers'; +import { useSourcererScope } from '../../../common/containers/sourcerer'; +import { SourcererScopeName } from '../../../common/store/sourcerer/model'; import { updateTimelineGraphEventId } from '../../../timelines/store/timeline/actions'; import { Resolver } from '../../../resolver/view'; import { @@ -38,8 +40,6 @@ import { endSelector, } from '../../../common/components/super_date_picker/selectors'; import * as i18n from './translations'; -import { useUiSetting$ } from '../../../common/lib/kibana'; -import { useSignalIndex } from '../../../detections/containers/detection_engine/alerts/use_signal_index'; const OverlayContainer = styled.div` ${({ $restrictWidth }: { $restrictWidth: boolean }) => @@ -61,14 +61,14 @@ const FullScreenButtonIcon = styled(EuiButtonIcon)` interface OwnProps { isEventViewer: boolean; - timelineId: string; + timelineId: TimelineId; } interface NavigationProps { fullScreen: boolean; globalFullScreen: boolean; onCloseOverlay: () => void; - timelineId: string; + timelineId: TimelineId; timelineFullScreen: boolean; toggleFullScreen: () => void; } @@ -169,16 +169,14 @@ const GraphOverlayComponent: React.FC = ({ isEventViewer, timelineId } globalFullScreen, ]); - const { signalIndexName } = useSignalIndex(); - const [siemDefaultIndices] = useUiSetting$(DEFAULT_INDEX_KEY); - const indices: string[] | null = useMemo(() => { - if (signalIndexName === null) { - return null; - } else { - return [...siemDefaultIndices, signalIndexName]; - } - }, [signalIndexName, siemDefaultIndices]); + let sourcereScope = SourcererScopeName.default; + if ([TimelineId.detectionsRulesDetailsPage, TimelineId.detectionsPage].includes(timelineId)) { + sourcereScope = SourcererScopeName.detections; + } else if (timelineId === TimelineId.active) { + sourcereScope = SourcererScopeName.timeline; + } + const { selectedPatterns } = useSourcererScope(sourcereScope); return ( = ({ isEventViewer, timelineId } - {graphEventId !== undefined && indices !== null ? ( + {graphEventId !== undefined ? ( diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/graph_tab_content/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/graph_tab_content/index.tsx index db4867e1abfe7..1678a92c4cdaa 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/graph_tab_content/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/graph_tab_content/index.tsx @@ -9,10 +9,11 @@ import React, { useMemo } from 'react'; import { timelineSelectors } from '../../../store/timeline'; import { useShallowEqualSelector } from '../../../../common/hooks/use_selector'; +import { TimelineId } from '../../../../../common/types/timeline'; import { GraphOverlay } from '../../graph_overlay'; interface GraphTabContentProps { - timelineId: string; + timelineId: TimelineId; } const GraphTabContentComponent: React.FC = ({ timelineId }) => { diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/index.test.tsx index 219d32f147b60..e7422e32805a9 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/index.test.tsx @@ -12,7 +12,7 @@ import useResizeObserver from 'use-resize-observer/polyfilled'; import { DragDropContextWrapper } from '../../../common/components/drag_and_drop/drag_drop_context_wrapper'; import '../../../common/mock/match_media'; import { mockBrowserFields, mockDocValueFields } from '../../../common/containers/source/mock'; - +import { TimelineId } from '../../../../common/types/timeline'; import { mockIndexNames, mockIndexPattern, TestProviders } from '../../../common/mock'; import { StatefulTimeline, Props as StatefulTimelineOwnProps } from './index'; @@ -55,7 +55,7 @@ jest.mock('../../../common/containers/sourcerer', () => { }); describe('StatefulTimeline', () => { const props: StatefulTimelineOwnProps = { - timelineId: 'timeline-test', + timelineId: TimelineId.test, }; beforeEach(() => { @@ -91,7 +91,7 @@ describe('StatefulTimeline', () => { ); expect( wrapper - .find(`[data-timeline-id="timeline-test"].${SELECTOR_TIMELINE_GLOBAL_CONTAINER}`) + .find(`[data-timeline-id="test"].${SELECTOR_TIMELINE_GLOBAL_CONTAINER}`) .first() .exists() ).toEqual(true); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/index.tsx index 9cb95daba685b..c37fc93e33b08 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/index.tsx @@ -18,7 +18,7 @@ import { isTab } from '../../../common/components/accessibility/helpers'; import { useSourcererScope } from '../../../common/containers/sourcerer'; import { SourcererScopeName } from '../../../common/store/sourcerer/model'; import { FlyoutHeader, FlyoutHeaderPanel } from '../flyout/header'; -import { TimelineType, TimelineTabs } from '../../../../common/types/timeline'; +import { TimelineType, TimelineTabs, TimelineId } from '../../../../common/types/timeline'; import { useDeepEqualSelector, useShallowEqualSelector } from '../../../common/hooks/use_selector'; import { activeTimeline } from '../../containers/active_timeline_context'; import { EVENTS_COUNT_BUTTON_CLASS_NAME, onTimelineTabKeyPressed } from './helpers'; @@ -35,7 +35,7 @@ const TimelineTemplateBadge = styled.div` `; export interface Props { - timelineId: string; + timelineId: TimelineId; } const TimelineSavingProgressComponent: React.FC = ({ timelineId }) => { diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs_content/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs_content/index.tsx index 9f6bfcf7e320c..ca70e4ae64686 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs_content/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs_content/index.tsx @@ -9,7 +9,7 @@ import { EuiBadge, EuiLoadingContent, EuiTabs, EuiTab } from '@elastic/eui'; import React, { lazy, memo, Suspense, useCallback, useEffect, useMemo } from 'react'; import { useDispatch } from 'react-redux'; import styled from 'styled-components'; -import { TimelineTabs } from '../../../../../common/types/timeline'; +import { TimelineTabs, TimelineId } from '../../../../../common/types/timeline'; import { useShallowEqualSelector, @@ -42,7 +42,7 @@ const NotesTabContent = lazy(() => import('../notes_tab_content')); const PinnedTabContent = lazy(() => import('../pinned_tab_content')); interface BasicTimelineTab { - timelineId: string; + timelineId: TimelineId; graphEventId?: string; }