From daf58759a89071996eb998dc7c794615f03b60c1 Mon Sep 17 00:00:00 2001 From: Frank Hassanabad Date: Sun, 17 Jan 2021 14:53:27 -0700 Subject: [PATCH] [Security Solutions][Detection Engine] Removes duplicate API calls (#88420) (#88566) ## Summary This removes some duplicate API calls to reduce pressure on the backend and speed up querying times within the application for the front end. This fixes some of the issues of https://github.com/elastic/kibana/issues/82327, but there are several performance improvements that are going to be needed to help reduce the slowness when you have a system under a lot of pressure. So far this removes duplication for these API calls when you are on the manage detection rules page: ```ts api/detection_engine/rules/_find api/detection_engine/rules/_find_statuses api/detection_engine/tags ``` Screen Shot 2021-01-14 at 3 53 21 PM * This hides the tags and searches while the page is loading to avoid duplicate calls when the pre-packaged rules counts come back * This untangles the refetchRules from the refetchPrePackagedRulesStatus as two separate calls to avoid issues we have with re-rendering and re-calling the backend. ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../detection_engine/alerts/use_query.tsx | 2 +- .../alerts/use_signal_index.tsx | 2 +- .../containers/detection_engine/rules/api.ts | 6 +- .../detection_engine/rules/types.ts | 6 +- .../rules/use_pre_packaged_rules.tsx | 2 +- .../rules/use_rule_status.tsx | 4 +- .../detection_engine/rules/use_rules.test.tsx | 15 +++++ .../detection_engine/rules/use_rules.tsx | 25 ++------ .../rules/all/batch_actions.tsx | 14 +++-- .../rules/all/columns.test.tsx | 3 + .../detection_engine/rules/all/columns.tsx | 14 +++-- .../rules/all/exceptions/exceptions_table.tsx | 2 +- .../detection_engine/rules/all/index.tsx | 4 +- .../rules/all/reducer.test.ts | 6 ++ .../rules/all/rules_tables.tsx | 61 +++++++++++-------- .../pages/detection_engine/rules/index.tsx | 10 +-- 16 files changed, 105 insertions(+), 71 deletions(-) diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_query.tsx b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_query.tsx index 9c992fa872705f..3bef1d8edd048e 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_query.tsx +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_query.tsx @@ -9,7 +9,7 @@ import React, { SetStateAction, useEffect, useState } from 'react'; import { fetchQueryAlerts } from './api'; import { AlertSearchResponse } from './types'; -type Func = () => void; +type Func = () => Promise; export interface ReturnQueryAlerts { loading: boolean; diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_signal_index.tsx b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_signal_index.tsx index 1233456359b7fb..5ebdb38b8dd5c5 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_signal_index.tsx +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_signal_index.tsx @@ -11,7 +11,7 @@ import { createSignalIndex, getSignalIndex } from './api'; import * as i18n from './translations'; import { isSecurityAppError } from '../../../../common/utils/api'; -type Func = () => void; +type Func = () => Promise; export interface ReturnSignalIndex { loading: boolean; diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.ts b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.ts index da33b7841c7a90..f602a0a9523c7a 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.ts +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.ts @@ -120,9 +120,9 @@ export const fetchRules = async ({ ...showElasticRuleFilter, ].join(' AND '); - const tags = [ - ...(filterOptions.tags?.map((t) => `alert.attributes.tags: "${t.replace(/"/g, '\\"')}"`) ?? []), - ].join(' AND '); + const tags = filterOptions.tags + .map((t) => `alert.attributes.tags: "${t.replace(/"/g, '\\"')}"`) + .join(' AND '); const filterString = filtersWithoutTags !== '' && tags !== '' diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/types.ts b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/types.ts index b930212610ae9f..6eefa7f732bec4 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/types.ts +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/types.ts @@ -177,9 +177,9 @@ export interface FilterOptions { filter: string; sortField: RulesSortingFields; sortOrder: SortOrder; - showCustomRules?: boolean; - showElasticRules?: boolean; - tags?: string[]; + showCustomRules: boolean; + showElasticRules: boolean; + tags: string[]; } export interface FetchRulesResponse { diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_pre_packaged_rules.tsx b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_pre_packaged_rules.tsx index 48530ddeb181eb..d83d4e0caa9771 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_pre_packaged_rules.tsx +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_pre_packaged_rules.tsx @@ -20,7 +20,7 @@ import { getPrePackagedTimelineStatus, } from '../../../pages/detection_engine/rules/helpers'; -type Func = () => void; +type Func = () => Promise; export type CreatePreBuiltRules = () => Promise; interface ReturnPrePackagedTimelines { diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_status.tsx b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_status.tsx index 0e96f58ee68741..ddf50e9edae518 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_status.tsx +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_status.tsx @@ -113,9 +113,11 @@ export const useRulesStatuses = (rules: Rules): ReturnRulesStatuses => { setLoading(false); } }; - if (rules != null && rules.length > 0) { + + if (rules.length > 0) { fetchData(rules.map((r) => r.id)); } + return () => { isSubscribed = false; abortCtrl.abort(); diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rules.test.tsx b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rules.test.tsx index 76f2a5b58754ee..a874acf36c525f 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rules.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rules.test.tsx @@ -27,6 +27,9 @@ describe('useRules', () => { filter: '', sortField: 'created_at', sortOrder: 'desc', + tags: [], + showCustomRules: false, + showElasticRules: false, }, }) ); @@ -48,6 +51,9 @@ describe('useRules', () => { filter: '', sortField: 'created_at', sortOrder: 'desc', + tags: [], + showCustomRules: false, + showElasticRules: false, }, }) ); @@ -153,6 +159,9 @@ describe('useRules', () => { filter: '', sortField: 'created_at', sortOrder: 'desc', + tags: [], + showCustomRules: false, + showElasticRules: false, }, }) ); @@ -182,6 +191,9 @@ describe('useRules', () => { filter: '', sortField: 'created_at', sortOrder: 'desc', + tags: [], + showCustomRules: false, + showElasticRules: false, }, }, } @@ -198,6 +210,9 @@ describe('useRules', () => { filter: 'hello world', sortField: 'created_at', sortOrder: 'desc', + tags: [], + showCustomRules: false, + showElasticRules: false, }, }); await waitForNextUpdate(); diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rules.tsx b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rules.tsx index 2ada6d8426ce1d..9b4a5ce8c23c32 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rules.tsx +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rules.tsx @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import { noop } from 'lodash/fp'; import { useEffect, useState, useRef } from 'react'; import { FetchRulesResponse, FilterOptions, PaginationOptions, Rule } from './types'; @@ -12,16 +11,11 @@ import { errorToToaster, useStateToaster } from '../../../../common/components/t import { fetchRules } from './api'; import * as i18n from './translations'; -export type ReturnRules = [ - boolean, - FetchRulesResponse | null, - (refreshPrePackagedRule?: boolean) => void -]; +export type ReturnRules = [boolean, FetchRulesResponse | null, () => Promise]; export interface UseRules { pagination: PaginationOptions; filterOptions: FilterOptions; - refetchPrePackagedRulesStatus?: () => void; dispatchRulesInReducer?: (rules: Rule[], pagination: Partial) => void; } @@ -34,20 +28,19 @@ export interface UseRules { export const useRules = ({ pagination, filterOptions, - refetchPrePackagedRulesStatus, dispatchRulesInReducer, }: UseRules): ReturnRules => { const [rules, setRules] = useState(null); - const reFetchRules = useRef<(refreshPrePackagedRule?: boolean) => void>(noop); + const reFetchRules = useRef<() => Promise>(() => Promise.resolve()); const [loading, setLoading] = useState(true); const [, dispatchToaster] = useStateToaster(); - const filterTags = filterOptions.tags?.sort().join(); + const filterTags = filterOptions.tags.sort().join(); useEffect(() => { let isSubscribed = true; const abortCtrl = new AbortController(); - async function fetchData() { + const fetchData = async () => { try { setLoading(true); const fetchRulesResult = await fetchRules({ @@ -77,15 +70,10 @@ export const useRules = ({ if (isSubscribed) { setLoading(false); } - } + }; fetchData(); - reFetchRules.current = (refreshPrePackagedRule: boolean = false) => { - fetchData(); - if (refreshPrePackagedRule && refetchPrePackagedRulesStatus != null) { - refetchPrePackagedRulesStatus(); - } - }; + reFetchRules.current = (): Promise => fetchData(); return () => { isSubscribed = false; abortCtrl.abort(); @@ -100,7 +88,6 @@ export const useRules = ({ filterTags, filterOptions.showCustomRules, filterOptions.showElasticRules, - refetchPrePackagedRulesStatus, ]); return [loading, rules, reFetchRules.current]; diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/batch_actions.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/batch_actions.tsx index f911fbddd81c78..1ed534069470bd 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/batch_actions.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/batch_actions.tsx @@ -27,7 +27,8 @@ interface GetBatchItems { hasMlPermissions: boolean; hasActionsPrivileges: boolean; loadingRuleIds: string[]; - reFetchRules: (refreshPrePackagedRule?: boolean) => void; + reFetchRules: () => Promise; + refetchPrePackagedRulesStatus: () => Promise; rules: Rule[]; selectedRuleIds: string[]; } @@ -39,17 +40,18 @@ export const getBatchItems = ({ hasMlPermissions, loadingRuleIds, reFetchRules, + refetchPrePackagedRulesStatus, rules, selectedRuleIds, hasActionsPrivileges, }: GetBatchItems) => { - const selectedRules = selectedRuleIds.reduce((acc, id) => { + const selectedRules = selectedRuleIds.reduce>((acc, id) => { const found = rules.find((r) => r.id === id); if (found != null) { return { [id]: found, ...acc }; } return acc; - }, {} as Record); + }, {}); const containsEnabled = selectedRuleIds.some((id) => selectedRules[id]?.enabled ?? false); const containsDisabled = selectedRuleIds.some((id) => !selectedRules[id]?.enabled ?? false); @@ -139,7 +141,8 @@ export const getBatchItems = ({ dispatch, dispatchToaster ); - reFetchRules(true); + await reFetchRules(); + await refetchPrePackagedRulesStatus(); }} > { closePopover(); await deleteRulesAction(selectedRuleIds, dispatch, dispatchToaster); - reFetchRules(true); + await reFetchRules(); + await refetchPrePackagedRulesStatus(); }} > {i18n.BATCH_ACTION_DELETE_SELECTED} diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/columns.test.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/columns.test.tsx index 564b382b7b29f9..c48ba49e8db2b6 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/columns.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/columns.test.tsx @@ -27,6 +27,7 @@ describe('AllRulesTable Columns', () => { const dispatch = jest.fn(); const dispatchToaster = jest.fn(); const reFetchRules = jest.fn(); + const refetchPrePackagedRulesStatus = jest.fn(); beforeEach(() => { results = []; @@ -53,6 +54,7 @@ describe('AllRulesTable Columns', () => { dispatchToaster, history, reFetchRules, + refetchPrePackagedRulesStatus, true )[1]; await duplicateRulesActionObject.onClick(rule); @@ -75,6 +77,7 @@ describe('AllRulesTable Columns', () => { dispatchToaster, history, reFetchRules, + refetchPrePackagedRulesStatus, true )[3]; await deleteRulesActionObject.onClick(rule); diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/columns.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/columns.tsx index 2b03d6dd4de364..0d585b44638153 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/columns.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/columns.tsx @@ -43,7 +43,8 @@ export const getActions = ( dispatch: React.Dispatch, dispatchToaster: Dispatch, history: H.History, - reFetchRules: (refreshPrePackagedRule?: boolean) => void, + reFetchRules: () => Promise, + refetchPrePackagedRulesStatus: () => Promise, actionsPrivileges: | boolean | Readonly<{ @@ -77,7 +78,8 @@ export const getActions = ( enabled: (rowItem: Rule) => canEditRuleWithActions(rowItem, actionsPrivileges), onClick: async (rowItem: Rule) => { await duplicateRulesAction([rowItem], [rowItem.id], dispatch, dispatchToaster); - await reFetchRules(true); + await reFetchRules(); + await refetchPrePackagedRulesStatus(); }, }, { @@ -95,7 +97,8 @@ export const getActions = ( name: i18n.DELETE_RULE, onClick: async (rowItem: Rule) => { await deleteRulesAction([rowItem.id], dispatch, dispatchToaster); - await reFetchRules(true); + await reFetchRules(); + await refetchPrePackagedRulesStatus(); }, }, ]; @@ -115,7 +118,8 @@ interface GetColumns { hasMlPermissions: boolean; hasNoPermissions: boolean; loadingRuleIds: string[]; - reFetchRules: (refreshPrePackagedRule?: boolean) => void; + reFetchRules: () => Promise; + refetchPrePackagedRulesStatus: () => Promise; hasReadActionsPrivileges: | boolean | Readonly<{ @@ -132,6 +136,7 @@ export const getColumns = ({ hasNoPermissions, loadingRuleIds, reFetchRules, + refetchPrePackagedRulesStatus, hasReadActionsPrivileges, }: GetColumns): RulesColumns[] => { const cols: RulesColumns[] = [ @@ -279,6 +284,7 @@ export const getColumns = ({ dispatchToaster, history, reFetchRules, + refetchPrePackagedRulesStatus, hasReadActionsPrivileges ), width: '40px', diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/exceptions/exceptions_table.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/exceptions/exceptions_table.tsx index ccd00daf5e5aa1..cc04c205abce88 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/exceptions/exceptions_table.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/exceptions/exceptions_table.tsx @@ -36,7 +36,7 @@ import { patchRule } from '../../../../../containers/detection_engine/rules/api' // eslint-disable-next-line @typescript-eslint/no-explicit-any const MyEuiBasicTable = styled(EuiBasicTable as any)`` as any; -export type Func = () => void; +export type Func = () => Promise; export interface ExceptionListFilter { name?: string | null; list_id?: string | null; diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/index.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/index.tsx index 4c4095ee6f7405..381f104855bf3a 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/index.tsx @@ -20,12 +20,12 @@ interface AllRulesProps { hasNoPermissions: boolean; loading: boolean; loadingCreatePrePackagedRules: boolean; - refetchPrePackagedRulesStatus: () => void; + refetchPrePackagedRulesStatus: () => Promise; rulesCustomInstalled: number | null; rulesInstalled: number | null; rulesNotInstalled: number | null; rulesNotUpdated: number | null; - setRefreshRulesData: (refreshRule: (refreshPrePackagedRule?: boolean) => void) => void; + setRefreshRulesData: (refreshRule: () => Promise) => void; } export enum AllRulesTabs { diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/reducer.test.ts b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/reducer.test.ts index 0456111074b606..7501f4377740eb 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/reducer.test.ts +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/reducer.test.ts @@ -14,6 +14,9 @@ const initialState: State = { filter: '', sortField: 'enabled', sortOrder: 'desc', + tags: [], + showCustomRules: false, + showElasticRules: false, }, loadingRuleIds: [], loadingRulesAction: null, @@ -193,6 +196,9 @@ describe('allRulesReducer', () => { filter: 'host.name:*', sortField: 'enabled', sortOrder: 'desc', + tags: [], + showCustomRules: false, + showElasticRules: false, }; const { filterOptions, pagination } = reducer(initialState, { type: 'updateFilterOptions', diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/rules_tables.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/rules_tables.tsx index 232fb118fb2f76..2ae124dc861043 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/rules_tables.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/rules_tables.tsx @@ -60,6 +60,9 @@ const initialState: State = { filter: '', sortField: INITIAL_SORT_FIELD, sortOrder: 'desc', + tags: [], + showCustomRules: false, + showElasticRules: false, }, loadingRuleIds: [], loadingRulesAction: null, @@ -82,12 +85,12 @@ interface RulesTableProps { hasNoPermissions: boolean; loading: boolean; loadingCreatePrePackagedRules: boolean; - refetchPrePackagedRulesStatus: () => void; + refetchPrePackagedRulesStatus: () => Promise; rulesCustomInstalled: number | null; rulesInstalled: number | null; rulesNotInstalled: number | null; rulesNotUpdated: number | null; - setRefreshRulesData: (refreshRule: (refreshPrePackagedRule?: boolean) => void) => void; + setRefreshRulesData: (refreshRule: () => Promise) => void; selectedTab: AllRulesTabs; } @@ -183,10 +186,9 @@ export const RulesTables = React.memo( }); }, []); - const [isLoadingRules, , reFetchRulesData] = useRules({ + const [isLoadingRules, , reFetchRules] = useRules({ pagination, filterOptions, - refetchPrePackagedRulesStatus, dispatchRulesInReducer: setRules, }); @@ -220,7 +222,8 @@ export const RulesTables = React.memo( hasActionsPrivileges, loadingRuleIds, selectedRuleIds, - reFetchRules: reFetchRulesData, + reFetchRules, + refetchPrePackagedRulesStatus, rules, }); }, @@ -229,7 +232,8 @@ export const RulesTables = React.memo( dispatchToaster, hasMlPermissions, loadingRuleIds, - reFetchRulesData, + reFetchRules, + refetchPrePackagedRulesStatus, rules, selectedRuleIds, hasActionsPrivileges, @@ -273,19 +277,22 @@ export const RulesTables = React.memo( (loadingRulesAction === 'enable' || loadingRulesAction === 'disable') ? loadingRuleIds : [], - reFetchRules: reFetchRulesData, + reFetchRules, + refetchPrePackagedRulesStatus, hasReadActionsPrivileges: hasActionsPrivileges, }); - // eslint-disable-next-line react-hooks/exhaustive-deps }, [ dispatch, dispatchToaster, formatUrl, + refetchPrePackagedRulesStatus, + hasActionsPrivileges, + hasNoPermissions, hasMlPermissions, history, loadingRuleIds, loadingRulesAction, - reFetchRulesData, + reFetchRules, ]); const monitoringColumns = useMemo(() => getMonitoringColumns(history, formatUrl), [ @@ -294,10 +301,8 @@ export const RulesTables = React.memo( ]); useEffect(() => { - if (reFetchRulesData != null) { - setRefreshRulesData(reFetchRulesData); - } - }, [reFetchRulesData, setRefreshRulesData]); + setRefreshRulesData(reFetchRules); + }, [reFetchRules, setRefreshRulesData]); useEffect(() => { if (initLoading && !loading && !isLoadingRules && !isLoadingRulesStatuses) { @@ -306,11 +311,12 @@ export const RulesTables = React.memo( }, [initLoading, loading, isLoadingRules, isLoadingRulesStatuses]); const handleCreatePrePackagedRules = useCallback(async () => { - if (createPrePackagedRules != null && reFetchRulesData != null) { + if (createPrePackagedRules != null) { await createPrePackagedRules(); - reFetchRulesData(true); + await reFetchRules(); + await refetchPrePackagedRulesStatus(); } - }, [createPrePackagedRules, reFetchRulesData]); + }, [createPrePackagedRules, reFetchRules, refetchPrePackagedRulesStatus]); const euiBasicTableSelectionProps = useMemo( () => ({ @@ -343,12 +349,13 @@ export const RulesTables = React.memo( return false; }, [loadingRuleIds, loadingRulesAction]); - const handleRefreshData = useCallback((): void => { - if (reFetchRulesData != null && !isLoadingAnActionOnRule) { - reFetchRulesData(true); + const handleRefreshData = useCallback(async (): Promise => { + if (!isLoadingAnActionOnRule) { + await reFetchRules(); + await refetchPrePackagedRulesStatus(); setLastRefreshDate(); } - }, [reFetchRulesData, isLoadingAnActionOnRule, setLastRefreshDate]); + }, [reFetchRules, isLoadingAnActionOnRule, setLastRefreshDate, refetchPrePackagedRulesStatus]); const handleResetIdleTimer = useCallback((): void => { if (isRefreshOn) { @@ -458,12 +465,14 @@ export const RulesTables = React.memo( /> } > - + {shouldShowRulesTable && ( + + )} {isLoadingAnActionOnRule && !initLoading && ( diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/index.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/index.tsx index dc2e99b90da404..9423604e546e9c 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/index.tsx @@ -35,7 +35,7 @@ import { SecurityPageName } from '../../../../app/types'; import { LinkButton } from '../../../../common/components/links'; import { useFormatUrl } from '../../../../common/components/link_to'; -type Func = (refreshPrePackagedRule?: boolean) => void; +type Func = () => Promise; const RulesPageComponent: React.FC = () => { const history = useHistory(); @@ -94,20 +94,22 @@ const RulesPageComponent: React.FC = () => { const handleRefreshRules = useCallback(async () => { if (refreshRulesData.current != null) { - refreshRulesData.current(true); + await refreshRulesData.current(); } }, [refreshRulesData]); const handleCreatePrePackagedRules = useCallback(async () => { if (createPrePackagedRules != null) { await createPrePackagedRules(); - handleRefreshRules(); + return handleRefreshRules(); } }, [createPrePackagedRules, handleRefreshRules]); const handleRefetchPrePackagedRulesStatus = useCallback(() => { if (refetchPrePackagedRulesStatus != null) { - refetchPrePackagedRulesStatus(); + return refetchPrePackagedRulesStatus(); + } else { + return Promise.resolve(); } }, [refetchPrePackagedRulesStatus]);