diff --git a/x-pack/plugins/security_solution/public/common/store/data_table/epic_local_storage.test.tsx b/x-pack/plugins/security_solution/public/common/store/data_table/epic_local_storage.test.tsx deleted file mode 100644 index d7ea246e90109..0000000000000 --- a/x-pack/plugins/security_solution/public/common/store/data_table/epic_local_storage.test.tsx +++ /dev/null @@ -1,185 +0,0 @@ -/* - * 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 from 'react'; -import { shallow } from 'enzyme'; - -// we don't have the types for waitFor just yet, so using "as waitFor" for when we do -import { waitFor } from '@testing-library/react'; -import '../../mock/match_media'; -import { - mockGlobalState, - SUB_PLUGINS_REDUCER, - TestProviders, - defaultHeaders, - createSecuritySolutionStorageMock, - kibanaObservable, -} from '../../mock'; - -import type { State } from '..'; -import { createStore } from '..'; -import { DefaultCellRenderer } from '../../../timelines/components/timeline/cell_rendering/default_cell_renderer'; -import type { EventsViewerProps } from '../../components/events_viewer'; -import { defaultRowRenderers } from '../../../timelines/components/timeline/body/renderers'; - -import { addTableInStorage } from '../../../timelines/containers/local_storage'; -import { Direction } from '../../../../common/search_strategy'; -import { StatefulEventsViewer } from '../../components/events_viewer'; -import { eventsDefaultModel } from '../../components/events_viewer/default_model'; -import { EntityType } from '@kbn/timelines-plugin/common'; -import { getDefaultControlColumn } from '../../../timelines/components/timeline/body/control_columns'; -import { SourcererScopeName } from '../sourcerer/model'; -import { TableId, dataTableActions } from '@kbn/securitysolution-data-table'; - -const { - applyDeltaToColumnWidth, - removeColumn, - updateColumnOrder, - updateColumns, - updateColumnWidth, - updateItemsPerPage, - updateSort, - upsertColumn, -} = dataTableActions; - -jest.mock('../../../timelines/containers/local_storage'); - -const addTableInStorageMock = addTableInStorage as jest.Mock; - -describe('epicLocalStorage', () => { - const state: State = mockGlobalState; - const { storage } = createSecuritySolutionStorageMock(); - let store = createStore(state, SUB_PLUGINS_REDUCER, kibanaObservable, storage); - - let testProps = {} as EventsViewerProps; - - beforeEach(() => { - store = createStore(state, SUB_PLUGINS_REDUCER, kibanaObservable, storage); - const from = '2019-08-27T22:10:56.794Z'; - const to = '2019-08-26T22:10:56.791Z'; - const ACTION_BUTTON_COUNT = 4; - - testProps = { - defaultModel: eventsDefaultModel, - end: to, - entityType: EntityType.EVENTS, - tableId: TableId.test, - leadingControlColumns: getDefaultControlColumn(ACTION_BUTTON_COUNT), - renderCellValue: DefaultCellRenderer, - rowRenderers: defaultRowRenderers, - sourcererScope: SourcererScopeName.default, - start: from, - bulkActions: false, - hasCrudPermissions: true, - }; - }); - - it('persist adding / reordering of a column correctly', async () => { - shallow( - - - - ); - store.dispatch(upsertColumn({ id: TableId.test, index: 1, column: defaultHeaders[0] })); - await waitFor(() => expect(addTableInStorageMock).toHaveBeenCalled()); - }); - - it('persist timeline when removing a column ', async () => { - shallow( - - - - ); - store.dispatch(removeColumn({ id: TableId.test, columnId: '@timestamp' })); - await waitFor(() => expect(addTableInStorageMock).toHaveBeenCalled()); - }); - - it('persists resizing of a column', async () => { - shallow( - - - - ); - store.dispatch( - applyDeltaToColumnWidth({ id: TableId.test, columnId: '@timestamp', delta: 80 }) - ); - await waitFor(() => expect(addTableInStorageMock).toHaveBeenCalled()); - }); - - it('persist the resetting of the fields', async () => { - shallow( - - - - ); - store.dispatch(updateColumns({ id: TableId.test, columns: defaultHeaders })); - await waitFor(() => expect(addTableInStorageMock).toHaveBeenCalled()); - }); - - it('persist items per page', async () => { - shallow( - - - - ); - store.dispatch(updateItemsPerPage({ id: TableId.test, itemsPerPage: 50 })); - await waitFor(() => expect(addTableInStorageMock).toHaveBeenCalled()); - }); - - it('persist the sorting of a column', async () => { - shallow( - - - - ); - store.dispatch( - updateSort({ - id: TableId.test, - sort: [ - { - columnId: 'event.severity', - columnType: 'number', - esTypes: ['long'], - sortDirection: Direction.desc, - }, - ], - }) - ); - await waitFor(() => expect(addTableInStorageMock).toHaveBeenCalled()); - }); - - it('persists updates to the column order to local storage', async () => { - shallow( - - - - ); - store.dispatch( - updateColumnOrder({ - columnIds: ['event.severity', '@timestamp', 'event.category'], - id: TableId.test, - }) - ); - await waitFor(() => expect(addTableInStorageMock).toHaveBeenCalled()); - }); - - it('persists updates to the column width to local storage', async () => { - shallow( - - - - ); - store.dispatch( - updateColumnWidth({ - columnId: 'event.severity', - id: TableId.test, - width: 123, - }) - ); - await waitFor(() => expect(addTableInStorageMock).toHaveBeenCalled()); - }); -}); diff --git a/x-pack/plugins/security_solution/public/common/store/data_table/epic_local_storage.ts b/x-pack/plugins/security_solution/public/common/store/data_table/middleware_local_storage.ts similarity index 53% rename from x-pack/plugins/security_solution/public/common/store/data_table/epic_local_storage.ts rename to x-pack/plugins/security_solution/public/common/store/data_table/middleware_local_storage.ts index f84b29341b712..0d8b63f8c283a 100644 --- a/x-pack/plugins/security_solution/public/common/store/data_table/epic_local_storage.ts +++ b/x-pack/plugins/security_solution/public/common/store/data_table/middleware_local_storage.ts @@ -5,17 +5,16 @@ * 2.0. */ -import type { Action } from 'redux'; -import { map, filter, ignoreElements, tap, withLatestFrom, delay } from 'rxjs/operators'; -import type { Epic } from 'redux-observable'; +import type { Action, Middleware } from 'redux'; import { get } from 'lodash/fp'; -import { dataTableActions } from '@kbn/securitysolution-data-table'; +import type { Storage } from '@kbn/kibana-utils-plugin/public'; +import { dataTableActions, dataTableSelectors } from '@kbn/securitysolution-data-table'; import type { TableIdLiteral } from '@kbn/securitysolution-data-table'; import { updateTotalCount } from '../../../timelines/store/actions'; import { addTableInStorage } from '../../../timelines/containers/local_storage'; -import type { TimelineEpicDependencies } from '../../../timelines/store/types'; +import type { State } from '../types'; const { applyDeltaToColumnWidth, @@ -32,8 +31,6 @@ const { upsertColumn, } = dataTableActions; -export const isNotNull = (value: T | null): value is T => value !== null; - const tableActionTypes = new Set([ removeColumn.type, upsertColumn.type, @@ -50,21 +47,19 @@ const tableActionTypes = new Set([ toggleDetailPanel.type, ]); -export const createDataTableLocalStorageEpic = - (): Epic> => - (action$, state$, { tableByIdSelector, storage }) => { - const table$ = state$.pipe(map(tableByIdSelector), filter(isNotNull)); - return action$.pipe( - delay(500), - withLatestFrom(table$), - tap(([action, tableById]) => { - if (tableActionTypes.has(action.type)) { - if (storage) { - const tableId: TableIdLiteral = get('payload.id', action); - addTableInStorage(storage, tableId, tableById[tableId]); - } - } - }), - ignoreElements() - ); +export const dataTableLocalStorageMiddleware: (storage: Storage) => Middleware<{}, State> = + (storage: Storage) => (store) => (next) => (action: Action) => { + // perform the action + const ret = next(action); + + // persist the data table state when a table action has been performed + if (tableActionTypes.has(action.type)) { + const tableById = dataTableSelectors.tableByIdSelector(store.getState()); + const tableId: TableIdLiteral = get('payload.id', action); + if (tableById && tableById[tableId] && storage) { + addTableInStorage(storage, tableId, tableById[tableId]); + } + } + + return ret; }; diff --git a/x-pack/plugins/security_solution/public/common/store/data_table/middlware_local_storage.test.ts b/x-pack/plugins/security_solution/public/common/store/data_table/middlware_local_storage.test.ts new file mode 100644 index 0000000000000..251d40527e79f --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/store/data_table/middlware_local_storage.test.ts @@ -0,0 +1,123 @@ +/* + * 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 '../../mock/match_media'; +import { + mockGlobalState, + SUB_PLUGINS_REDUCER, + defaultHeaders, + createSecuritySolutionStorageMock, + kibanaObservable, +} from '../../mock'; + +import type { State } from '..'; +import { createStore } from '..'; + +import { addTableInStorage } from '../../../timelines/containers/local_storage'; +import { Direction } from '../../../../common/search_strategy'; +import { TableId, dataTableActions } from '@kbn/securitysolution-data-table'; + +const { + applyDeltaToColumnWidth, + removeColumn, + updateColumnOrder, + updateColumns, + updateColumnWidth, + updateItemsPerPage, + updateSort, + upsertColumn, +} = dataTableActions; + +jest.mock('../../../timelines/containers/local_storage'); + +const addTableInStorageMock = addTableInStorage as jest.Mock; + +describe('DataTable localStorage middleware', () => { + const state: State = mockGlobalState; + const { storage } = createSecuritySolutionStorageMock(); + let store = createStore(state, SUB_PLUGINS_REDUCER, kibanaObservable, storage); + + beforeEach(() => { + store = createStore(state, SUB_PLUGINS_REDUCER, kibanaObservable, storage); + }); + + it('should call the storage method with the most recent table state', () => { + store.dispatch(updateItemsPerPage({ id: TableId.test, itemsPerPage: 42 })); + expect(addTableInStorageMock).toHaveBeenCalledWith( + storage, + TableId.test, + expect.objectContaining({ + itemsPerPage: 42, + }) + ); + }); + + it('persist adding / reordering of a column correctly', () => { + store.dispatch(upsertColumn({ id: TableId.test, index: 1, column: defaultHeaders[0] })); + expect(addTableInStorageMock).toHaveBeenCalled(); + }); + + it('persist timeline when removing a column ', async () => { + store.dispatch(removeColumn({ id: TableId.test, columnId: '@timestamp' })); + expect(addTableInStorageMock).toHaveBeenCalled(); + }); + + it('persists resizing of a column', async () => { + store.dispatch( + applyDeltaToColumnWidth({ id: TableId.test, columnId: '@timestamp', delta: 80 }) + ); + expect(addTableInStorageMock).toHaveBeenCalled(); + }); + + it('persist the resetting of the fields', async () => { + store.dispatch(updateColumns({ id: TableId.test, columns: defaultHeaders })); + expect(addTableInStorageMock).toHaveBeenCalled(); + }); + + it('persist items per page', async () => { + store.dispatch(updateItemsPerPage({ id: TableId.test, itemsPerPage: 50 })); + expect(addTableInStorageMock).toHaveBeenCalled(); + }); + + it('persist the sorting of a column', async () => { + store.dispatch( + updateSort({ + id: TableId.test, + sort: [ + { + columnId: 'event.severity', + columnType: 'number', + esTypes: ['long'], + sortDirection: Direction.desc, + }, + ], + }) + ); + expect(addTableInStorageMock).toHaveBeenCalled(); + }); + + it('persists updates to the column order to local storage', async () => { + store.dispatch( + updateColumnOrder({ + columnIds: ['event.severity', '@timestamp', 'event.category'], + id: TableId.test, + }) + ); + expect(addTableInStorageMock).toHaveBeenCalled(); + }); + + it('persists updates to the column width to local storage', async () => { + store.dispatch( + updateColumnWidth({ + columnId: 'event.severity', + id: TableId.test, + width: 123, + }) + ); + expect(addTableInStorageMock).toHaveBeenCalled(); + }); +}); diff --git a/x-pack/plugins/security_solution/public/common/store/epic.ts b/x-pack/plugins/security_solution/public/common/store/epic.ts index 20311d6c4a163..a5cebee7c96b6 100644 --- a/x-pack/plugins/security_solution/public/common/store/epic.ts +++ b/x-pack/plugins/security_solution/public/common/store/epic.ts @@ -9,21 +9,16 @@ import type { Epic } from 'redux-observable'; import { combineEpics } from 'redux-observable'; import type { Action } from 'redux'; import type { Observable } from 'rxjs'; -import type { Storage } from '@kbn/kibana-utils-plugin/public'; import type { CoreStart } from '@kbn/core/public'; import { createTimelineEpic } from '../../timelines/store/epic'; -import { createTimelineChangedEpic } from '../../timelines/store/epic_changed'; import { createTimelineFavoriteEpic } from '../../timelines/store/epic_favorite'; import { createTimelineNoteEpic } from '../../timelines/store/epic_note'; import { createTimelinePinnedEventEpic } from '../../timelines/store/epic_pinned_event'; import type { TimelineEpicDependencies } from '../../timelines/store/types'; -import { createDataTableLocalStorageEpic } from './data_table/epic_local_storage'; -import { createUserAssetTableLocalStorageEpic } from '../../explore/users/store/epic_storage'; import type { State } from './types'; export interface RootEpicDependencies { kibana$: Observable; - storage: Storage; } export const createRootEpic = (): Epic< @@ -34,10 +29,7 @@ export const createRootEpic = (): Epic< > => combineEpics( createTimelineEpic(), - createTimelineChangedEpic(), createTimelineFavoriteEpic(), createTimelineNoteEpic(), - createTimelinePinnedEventEpic(), - createDataTableLocalStorageEpic(), - createUserAssetTableLocalStorageEpic() + createTimelinePinnedEventEpic() ); diff --git a/x-pack/plugins/security_solution/public/common/store/middlewares.ts b/x-pack/plugins/security_solution/public/common/store/middlewares.ts new file mode 100644 index 0000000000000..f65cc2abe0a53 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/store/middlewares.ts @@ -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 type { Storage } from '@kbn/kibana-utils-plugin/public'; + +import { createTimelineMiddlewares } from '../../timelines/store/middlewares/create_timeline_middlewares'; +import { dataTableLocalStorageMiddleware } from './data_table/middleware_local_storage'; +import { userAssetTableLocalStorageMiddleware } from '../../explore/users/store/middleware_storage'; + +export function createMiddlewares(storage: Storage) { + return [ + dataTableLocalStorageMiddleware(storage), + userAssetTableLocalStorageMiddleware(storage), + ...createTimelineMiddlewares(), + ]; +} diff --git a/x-pack/plugins/security_solution/public/common/store/store.ts b/x-pack/plugins/security_solution/public/common/store/store.ts index b9f29867a32b5..bcdd7b67b3b44 100644 --- a/x-pack/plugins/security_solution/public/common/store/store.ts +++ b/x-pack/plugins/security_solution/public/common/store/store.ts @@ -24,7 +24,6 @@ import { BehaviorSubject, pluck } from 'rxjs'; import type { Storage } from '@kbn/kibana-utils-plugin/public'; import type { CoreStart } from '@kbn/core/public'; import reduceReducers from 'reduce-reducers'; -import { dataTableSelectors } from '@kbn/securitysolution-data-table'; import { initialGroupingState } from './grouping/reducer'; import type { GroupState } from './grouping/types'; import { @@ -55,6 +54,7 @@ import type { AnalyzerState } from '../../resolver/types'; import { resolverMiddlewareFactory } from '../../resolver/store/middleware'; import { dataAccessLayerFactory } from '../../resolver/data_access_layer/factory'; import { sourcererActions } from './sourcerer'; +import { createMiddlewares } from './middlewares'; let store: Store | null = null; @@ -278,8 +278,6 @@ export const createStore = ( selectNotesByIdSelector: appSelectors.selectNotesByIdSelector, timelineByIdSelector: timelineSelectors.timelineByIdSelector, timelineTimeRangeSelector: inputsSelectors.timelineTimeRangeSelector, - tableByIdSelector: dataTableSelectors.tableByIdSelector, - storage, }; const epicMiddleware = createEpicMiddleware( @@ -289,6 +287,7 @@ export const createStore = ( ); const middlewareEnhancer = applyMiddleware( + ...createMiddlewares(storage), epicMiddleware, telemetryMiddleware, ...(additionalMiddleware ?? []) diff --git a/x-pack/plugins/security_solution/public/explore/users/store/epic_storage.test.tsx b/x-pack/plugins/security_solution/public/explore/users/store/middleware_storage.test.ts similarity index 70% rename from x-pack/plugins/security_solution/public/explore/users/store/epic_storage.test.tsx rename to x-pack/plugins/security_solution/public/explore/users/store/middleware_storage.test.ts index 71274cf172197..a38c6b7e0ea1c 100644 --- a/x-pack/plugins/security_solution/public/explore/users/store/epic_storage.test.tsx +++ b/x-pack/plugins/security_solution/public/explore/users/store/middleware_storage.test.ts @@ -5,7 +5,6 @@ * 2.0. */ -import { waitFor } from '@testing-library/react'; import { createSecuritySolutionStorageMock, kibanaObservable, @@ -21,9 +20,8 @@ import type { Store } from 'redux'; let store: Store; const storage = createSecuritySolutionStorageMock().storage; -describe('UsersAssetTable EpicStorage', () => { +describe('UsersAssetTable localStorage middleware', () => { beforeEach(() => { - jest.useFakeTimers(); storage.clear(); store = createStore(mockGlobalState, SUB_PLUGINS_REDUCER, kibanaObservable, storage); }); @@ -33,22 +31,16 @@ describe('UsersAssetTable EpicStorage', () => { // Add field to the table store.dispatch(addUserAssetTableField({ tableId: UserAssetTableType.assetEntra, fieldName })); - await waitFor(() => { - return expect(getUserAssetTableFromStorage(storage)).toEqual({ - [UserAssetTableType.assetEntra]: { fields: [fieldName] }, - }); + expect(getUserAssetTableFromStorage(storage)).toEqual({ + [UserAssetTableType.assetEntra]: { fields: [fieldName] }, }); - jest.runAllTimers(); // pass the time to ensure that the state is persisted to local storage - // Remove field from the table store.dispatch( removeUserAssetTableField({ tableId: UserAssetTableType.assetEntra, fieldName }) ); - await waitFor(() => { - return expect(getUserAssetTableFromStorage(storage)).toEqual({ - [UserAssetTableType.assetEntra]: { fields: [] }, - }); + expect(getUserAssetTableFromStorage(storage)).toEqual({ + [UserAssetTableType.assetEntra]: { fields: [] }, }); }); }); diff --git a/x-pack/plugins/security_solution/public/explore/users/store/epic_storage.ts b/x-pack/plugins/security_solution/public/explore/users/store/middleware_storage.ts similarity index 51% rename from x-pack/plugins/security_solution/public/explore/users/store/epic_storage.ts rename to x-pack/plugins/security_solution/public/explore/users/store/middleware_storage.ts index 97935588cd844..80cbd1e43f79a 100644 --- a/x-pack/plugins/security_solution/public/explore/users/store/epic_storage.ts +++ b/x-pack/plugins/security_solution/public/explore/users/store/middleware_storage.ts @@ -5,34 +5,34 @@ * 2.0. */ -import type { Action } from 'redux'; -import { map, filter, ignoreElements, tap, withLatestFrom, delay } from 'rxjs/operators'; -import type { Epic } from 'redux-observable'; +import type { Action, Middleware } from 'redux'; import { get } from 'lodash/fp'; -import type { RootEpicDependencies } from '../../../common/store/epic'; +import type { Storage } from '@kbn/kibana-utils-plugin/public'; + import { usersActions } from '.'; import { selectUserAssetTables } from './selectors'; import type { UserAssetTableType } from './model'; import type { State } from '../../../common/store/types'; -export const isNotNull = (value: T | null): value is T => value !== null; import { persistUserAssetTableInStorage } from './storage'; const { removeUserAssetTableField, addUserAssetTableField } = usersActions; const tableActionTypes = new Set([removeUserAssetTableField.type, addUserAssetTableField.type]); -export const createUserAssetTableLocalStorageEpic = - (): Epic => - (action$, state$, { storage }) => { - const table$ = state$.pipe(map(selectUserAssetTables), filter(isNotNull)); - return action$.pipe( - delay(500), - withLatestFrom(table$), - tap(([action, tableById]) => { +export const userAssetTableLocalStorageMiddleware: (storage: Storage) => Middleware<{}, State> = + (storage: Storage) => (store) => (next) => (action: Action) => { + // perform the action + const ret = next(action); + + // persist the table state when a table action has been performed + if (tableActionTypes.has(action.type)) { + const tableById = selectUserAssetTables(store.getState()); + const tableId: UserAssetTableType = get('payload.tableId', action); + if (tableById && tableById[tableId] && storage) { if (tableActionTypes.has(action.type)) { - const tableId: UserAssetTableType = get('payload.tableId', action); persistUserAssetTableInStorage(storage, tableId, tableById[tableId]); } - }), - ignoreElements() - ); + } + } + + return ret; }; diff --git a/x-pack/plugins/security_solution/public/timelines/store/epic_changed.ts b/x-pack/plugins/security_solution/public/timelines/store/middlewares/changed.ts similarity index 70% rename from x-pack/plugins/security_solution/public/timelines/store/epic_changed.ts rename to x-pack/plugins/security_solution/public/timelines/store/middlewares/changed.ts index ed4294207b308..aac6fa71b4467 100644 --- a/x-pack/plugins/security_solution/public/timelines/store/epic_changed.ts +++ b/x-pack/plugins/security_solution/public/timelines/store/middlewares/changed.ts @@ -5,10 +5,8 @@ * 2.0. */ -import type { Action } from 'redux'; -import type { Epic } from 'redux-observable'; +import type { Action, Middleware } from 'redux'; import { get } from 'lodash/fp'; -import { filter, map } from 'rxjs/operators'; import { applyKqlFilterQuery, @@ -33,7 +31,7 @@ import { setSavedQueryId, setChanged, updateSavedSearch, -} from './actions'; +} from '../actions'; /** * All action types that will mark a timeline as changed @@ -65,19 +63,26 @@ const timelineChangedTypes = new Set([ ]); /** - * Maps actions that mark a timeline change to `setChanged` actions. + * Emit actions that will mark a timeline change to `setChanged` actions. * This allows to detect unsaved timeline changes when navigating away from the timeline. */ -export const createTimelineChangedEpic = (): Epic => (action$) => { - return action$.pipe( - // Only apply mapping to some actions - filter((action) => timelineChangedTypes.has(action.type)), - // Map the action to a `changed` action - map((action) => - setChanged({ - id: get('payload.id', action) as string, - changed: true, - }) - ) - ); -}; +export const timelineChangedMiddleware: Middleware = + ({ dispatch }) => + (next) => + (action: Action) => { + // perform the action + const ret = next(action); + + // if the action matches one of the "change" actions, + // dispatch a `setChanged` action on top + if (timelineChangedTypes.has(action.type)) { + dispatch( + setChanged({ + id: get('payload.id', action) as string, + changed: true, + }) + ); + } + + return ret; + }; diff --git a/x-pack/plugins/security_solution/public/timelines/store/middlewares/create_timeline_middlewares.ts b/x-pack/plugins/security_solution/public/timelines/store/middlewares/create_timeline_middlewares.ts new file mode 100644 index 0000000000000..80f320b755c7e --- /dev/null +++ b/x-pack/plugins/security_solution/public/timelines/store/middlewares/create_timeline_middlewares.ts @@ -0,0 +1,12 @@ +/* + * 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 { timelineChangedMiddleware } from './changed'; + +export function createTimelineMiddlewares() { + return [timelineChangedMiddleware]; +} diff --git a/x-pack/plugins/security_solution/public/timelines/store/types.ts b/x-pack/plugins/security_solution/public/timelines/store/types.ts index 741b906dcdebe..fa8a915ddb35d 100644 --- a/x-pack/plugins/security_solution/public/timelines/store/types.ts +++ b/x-pack/plugins/security_solution/public/timelines/store/types.ts @@ -6,7 +6,6 @@ */ import type { FilterManager } from '@kbn/data-plugin/public'; -import type { TableById } from '@kbn/securitysolution-data-table'; import type { RootEpicDependencies } from '../../common/store/epic'; import type { ColumnHeaderOptions, SortColumnTimeline } from '../../../common/types'; import type { RowRendererId } from '../../../common/api/timeline'; @@ -41,7 +40,6 @@ export interface TimelineEpicDependencies extends RootEpicDependencies { timelineTimeRangeSelector: (state: State) => inputsModel.TimeRange; selectAllTimelineQuery: () => (state: State, id: string) => inputsModel.GlobalQuery; selectNotesByIdSelector: (state: State) => NotesById; - tableByIdSelector: (state: State) => TableById; } export interface TimelineModelSettings {