From 4f3b3ef0705406ff24b451c09fe49ca8aa06eda0 Mon Sep 17 00:00:00 2001 From: Faisal Kanout Date: Tue, 7 Jun 2022 13:08:55 +0200 Subject: [PATCH 1/7] Move rule actions to the hook which is right call --- .../public/hooks/use_fetch_rule_actions.ts | 51 ---------------- .../use_fetch_rule_actions_connectors.ts | 59 +++++++++++++++++++ .../pages/rule_details/components/actions.tsx | 20 ++++--- .../public/pages/rule_details/types.ts | 3 +- 4 files changed, 72 insertions(+), 61 deletions(-) delete mode 100644 x-pack/plugins/observability/public/hooks/use_fetch_rule_actions.ts create mode 100644 x-pack/plugins/observability/public/hooks/use_fetch_rule_actions_connectors.ts diff --git a/x-pack/plugins/observability/public/hooks/use_fetch_rule_actions.ts b/x-pack/plugins/observability/public/hooks/use_fetch_rule_actions.ts deleted file mode 100644 index eaf01ed5ba59d4..00000000000000 --- a/x-pack/plugins/observability/public/hooks/use_fetch_rule_actions.ts +++ /dev/null @@ -1,51 +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 { useEffect, useState, useCallback } from 'react'; -import { ActionConnector, loadAllActions } from '@kbn/triggers-actions-ui-plugin/public'; -import { FetchRuleActionsProps } from '../pages/rule_details/types'; -import { ACTIONS_LOAD_ERROR } from '../pages/rule_details/translations'; - -interface FetchActions { - isLoadingActions: boolean; - allActions: Array>>; - errorActions: string | undefined; -} - -export function useFetchRuleActions({ http }: FetchRuleActionsProps) { - const [ruleActions, setRuleActions] = useState({ - isLoadingActions: true, - allActions: [] as Array>>, - errorActions: undefined, - }); - - const fetchRuleActions = useCallback(async () => { - try { - const response = await loadAllActions({ - http, - }); - setRuleActions((oldState: FetchActions) => ({ - ...oldState, - isLoadingActions: false, - allActions: response, - })); - } catch (error) { - setRuleActions((oldState: FetchActions) => ({ - ...oldState, - isLoadingActions: false, - errorActions: ACTIONS_LOAD_ERROR( - error instanceof Error ? error.message : typeof error === 'string' ? error : '' - ), - })); - } - }, [http]); - useEffect(() => { - fetchRuleActions(); - }, [fetchRuleActions]); - - return { ...ruleActions, reloadRuleActions: fetchRuleActions }; -} diff --git a/x-pack/plugins/observability/public/hooks/use_fetch_rule_actions_connectors.ts b/x-pack/plugins/observability/public/hooks/use_fetch_rule_actions_connectors.ts new file mode 100644 index 00000000000000..13cb0114fa041e --- /dev/null +++ b/x-pack/plugins/observability/public/hooks/use_fetch_rule_actions_connectors.ts @@ -0,0 +1,59 @@ +/* + * 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 { useEffect, useState, useCallback } from 'react'; +import { ActionConnector, loadAllActions } from '@kbn/triggers-actions-ui-plugin/public'; +import { intersectionBy } from 'lodash'; +import { FetchRuleActionsConnectorsProps } from '../pages/rule_details/types'; +import { ACTIONS_LOAD_ERROR } from '../pages/rule_details/translations'; + +interface FetchActionsConnectors { + isLoadingActionsConnectors: boolean; + actionsConnectors: Array>>; + errorActionsConnectors?: string; +} + +export function useFetchRuleActionsConnectors({ + http, + ruleActions, +}: FetchRuleActionsConnectorsProps) { + const [actionsConnectors, setActionConnector] = useState({ + isLoadingActionsConnectors: true, + actionsConnectors: [] as Array>>, + errorActionsConnectors: undefined, + }); + + const fetchRuleActionsConnectors = useCallback(async () => { + try { + const allActions = await loadAllActions({ + http, + }); + const actions = intersectionBy(allActions, ruleActions, 'actionTypeId'); + setActionConnector((oldState: FetchActionsConnectors) => ({ + ...oldState, + isLoadingActionsConnectors: false, + actionsConnectors: actions, + })); + } catch (error) { + setActionConnector((oldState: FetchActionsConnectors) => ({ + ...oldState, + isLoadingActionsConnectors: false, + errorActionsConnectors: ACTIONS_LOAD_ERROR( + error instanceof Error ? error.message : typeof error === 'string' ? error : '' + ), + })); + } + }, [http, ruleActions]); + useEffect(() => { + fetchRuleActionsConnectors(); + }, [fetchRuleActionsConnectors]); + + return { + ...actionsConnectors, + reloadRuleActions: fetchRuleActionsConnectors, + }; +} diff --git a/x-pack/plugins/observability/public/pages/rule_details/components/actions.tsx b/x-pack/plugins/observability/public/pages/rule_details/components/actions.tsx index d3dbe3cf4bdef6..697c3fef945ad2 100644 --- a/x-pack/plugins/observability/public/pages/rule_details/components/actions.tsx +++ b/x-pack/plugins/observability/public/pages/rule_details/components/actions.tsx @@ -14,11 +14,10 @@ import { IconType, EuiLoadingSpinner, } from '@elastic/eui'; -import { intersectionBy } from 'lodash'; import { suspendedComponentWithProps } from '@kbn/triggers-actions-ui-plugin/public'; import { i18n } from '@kbn/i18n'; import { ActionsProps } from '../types'; -import { useFetchRuleActions } from '../../../hooks/use_fetch_rule_actions'; +import { useFetchRuleActionsConnectors } from '../../../hooks/use_fetch_rule_actions_connectors'; import { useKibana } from '../../../utils/kibana_react'; export function Actions({ ruleActions, actionTypeRegistry }: ActionsProps) { @@ -26,12 +25,16 @@ export function Actions({ ruleActions, actionTypeRegistry }: ActionsProps) { http, notifications: { toasts }, } = useKibana().services; - const { isLoadingActions, allActions, errorActions } = useFetchRuleActions({ http }); + const { isLoadingActionsConnectors, actionsConnectors, errorActionsConnectors } = + useFetchRuleActionsConnectors({ + http, + ruleActions, + }); useEffect(() => { - if (errorActions) { - toasts.addDanger({ title: errorActions }); + if (errorActionsConnectors) { + toasts.addDanger({ title: errorActionsConnectors }); } - }, [errorActions, toasts]); + }, [errorActionsConnectors, toasts]); if (ruleActions && ruleActions.length <= 0) return ( @@ -49,11 +52,10 @@ export function Actions({ ruleActions, actionTypeRegistry }: ActionsProps) { ? actionGroup?.iconClass : suspendedComponentWithProps(actionGroup?.iconClass as React.ComponentType); } - const actions = intersectionBy(allActions, ruleActions, 'actionTypeId'); - if (isLoadingActions) return ; + if (isLoadingActionsConnectors) return ; return ( - {actions.map(({ actionTypeId, name }) => ( + {actionsConnectors.map(({ actionTypeId, name }) => ( diff --git a/x-pack/plugins/observability/public/pages/rule_details/types.ts b/x-pack/plugins/observability/public/pages/rule_details/types.ts index 4b1c62f7dbb9a3..5b60d8bf2efe2d 100644 --- a/x-pack/plugins/observability/public/pages/rule_details/types.ts +++ b/x-pack/plugins/observability/public/pages/rule_details/types.ts @@ -36,8 +36,9 @@ export interface FetchRuleSummaryProps { ruleId: string; http: HttpSetup; } -export interface FetchRuleActionsProps { +export interface FetchRuleActionsConnectorsProps { http: HttpSetup; + ruleActions: any[]; } export interface FetchRuleExecutionLogProps { From e9801cb19ba26f06464db435d9e97c54a59668ef Mon Sep 17 00:00:00 2001 From: Faisal Kanout Date: Tue, 7 Jun 2022 13:18:35 +0200 Subject: [PATCH 2/7] Update naming --- .../hooks/use_fetch_rule_action_connectors.ts | 59 +++++++++++++++++++ .../use_fetch_rule_actions_connectors.ts | 59 ------------------- .../pages/rule_details/components/actions.tsx | 16 ++--- .../public/pages/rule_details/types.ts | 2 +- 4 files changed, 68 insertions(+), 68 deletions(-) create mode 100644 x-pack/plugins/observability/public/hooks/use_fetch_rule_action_connectors.ts delete mode 100644 x-pack/plugins/observability/public/hooks/use_fetch_rule_actions_connectors.ts diff --git a/x-pack/plugins/observability/public/hooks/use_fetch_rule_action_connectors.ts b/x-pack/plugins/observability/public/hooks/use_fetch_rule_action_connectors.ts new file mode 100644 index 00000000000000..6ce88e0c3ed23e --- /dev/null +++ b/x-pack/plugins/observability/public/hooks/use_fetch_rule_action_connectors.ts @@ -0,0 +1,59 @@ +/* + * 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 { useEffect, useState, useCallback } from 'react'; +import { ActionConnector, loadAllActions } from '@kbn/triggers-actions-ui-plugin/public'; +import { intersectionBy } from 'lodash'; +import { FetchRuleActionConnectorsProps } from '../pages/rule_details/types'; +import { ACTIONS_LOAD_ERROR } from '../pages/rule_details/translations'; + +interface FetchActionConnectors { + isLoadingActionConnectors: boolean; + actionConnectors: Array>>; + errorActionConnectors?: string; +} + +export function useFetchRuleActionConnectors({ + http, + ruleActions, +}: FetchRuleActionConnectorsProps) { + const [actionConnectors, setActionConnector] = useState({ + isLoadingActionConnectors: true, + actionConnectors: [] as Array>>, + errorActionConnectors: undefined, + }); + + const fetchRuleActionConnectors = useCallback(async () => { + try { + const allActions = await loadAllActions({ + http, + }); + const actions = intersectionBy(allActions, ruleActions, 'actionTypeId'); + setActionConnector((oldState: FetchActionConnectors) => ({ + ...oldState, + isLoadingActionConnectors: false, + actionConnectors: actions, + })); + } catch (error) { + setActionConnector((oldState: FetchActionConnectors) => ({ + ...oldState, + isLoadingActionConnectors: false, + errorActionConnectors: ACTIONS_LOAD_ERROR( + error instanceof Error ? error.message : typeof error === 'string' ? error : '' + ), + })); + } + }, [http, ruleActions]); + useEffect(() => { + fetchRuleActionConnectors(); + }, [fetchRuleActionConnectors]); + + return { + ...actionConnectors, + reloadRuleActionConnectors: fetchRuleActionConnectors, + }; +} diff --git a/x-pack/plugins/observability/public/hooks/use_fetch_rule_actions_connectors.ts b/x-pack/plugins/observability/public/hooks/use_fetch_rule_actions_connectors.ts deleted file mode 100644 index 13cb0114fa041e..00000000000000 --- a/x-pack/plugins/observability/public/hooks/use_fetch_rule_actions_connectors.ts +++ /dev/null @@ -1,59 +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 { useEffect, useState, useCallback } from 'react'; -import { ActionConnector, loadAllActions } from '@kbn/triggers-actions-ui-plugin/public'; -import { intersectionBy } from 'lodash'; -import { FetchRuleActionsConnectorsProps } from '../pages/rule_details/types'; -import { ACTIONS_LOAD_ERROR } from '../pages/rule_details/translations'; - -interface FetchActionsConnectors { - isLoadingActionsConnectors: boolean; - actionsConnectors: Array>>; - errorActionsConnectors?: string; -} - -export function useFetchRuleActionsConnectors({ - http, - ruleActions, -}: FetchRuleActionsConnectorsProps) { - const [actionsConnectors, setActionConnector] = useState({ - isLoadingActionsConnectors: true, - actionsConnectors: [] as Array>>, - errorActionsConnectors: undefined, - }); - - const fetchRuleActionsConnectors = useCallback(async () => { - try { - const allActions = await loadAllActions({ - http, - }); - const actions = intersectionBy(allActions, ruleActions, 'actionTypeId'); - setActionConnector((oldState: FetchActionsConnectors) => ({ - ...oldState, - isLoadingActionsConnectors: false, - actionsConnectors: actions, - })); - } catch (error) { - setActionConnector((oldState: FetchActionsConnectors) => ({ - ...oldState, - isLoadingActionsConnectors: false, - errorActionsConnectors: ACTIONS_LOAD_ERROR( - error instanceof Error ? error.message : typeof error === 'string' ? error : '' - ), - })); - } - }, [http, ruleActions]); - useEffect(() => { - fetchRuleActionsConnectors(); - }, [fetchRuleActionsConnectors]); - - return { - ...actionsConnectors, - reloadRuleActions: fetchRuleActionsConnectors, - }; -} diff --git a/x-pack/plugins/observability/public/pages/rule_details/components/actions.tsx b/x-pack/plugins/observability/public/pages/rule_details/components/actions.tsx index 697c3fef945ad2..aedee4b4d63e2b 100644 --- a/x-pack/plugins/observability/public/pages/rule_details/components/actions.tsx +++ b/x-pack/plugins/observability/public/pages/rule_details/components/actions.tsx @@ -17,7 +17,7 @@ import { import { suspendedComponentWithProps } from '@kbn/triggers-actions-ui-plugin/public'; import { i18n } from '@kbn/i18n'; import { ActionsProps } from '../types'; -import { useFetchRuleActionsConnectors } from '../../../hooks/use_fetch_rule_actions_connectors'; +import { useFetchRuleActionConnectors } from '../../../hooks/use_fetch_rule_action_connectors'; import { useKibana } from '../../../utils/kibana_react'; export function Actions({ ruleActions, actionTypeRegistry }: ActionsProps) { @@ -25,16 +25,16 @@ export function Actions({ ruleActions, actionTypeRegistry }: ActionsProps) { http, notifications: { toasts }, } = useKibana().services; - const { isLoadingActionsConnectors, actionsConnectors, errorActionsConnectors } = - useFetchRuleActionsConnectors({ + const { isLoadingActionConnectors, actionConnectors, errorActionConnectors } = + useFetchRuleActionConnectors({ http, ruleActions, }); useEffect(() => { - if (errorActionsConnectors) { - toasts.addDanger({ title: errorActionsConnectors }); + if (errorActionConnectors) { + toasts.addDanger({ title: errorActionConnectors }); } - }, [errorActionsConnectors, toasts]); + }, [errorActionConnectors, toasts]); if (ruleActions && ruleActions.length <= 0) return ( @@ -52,10 +52,10 @@ export function Actions({ ruleActions, actionTypeRegistry }: ActionsProps) { ? actionGroup?.iconClass : suspendedComponentWithProps(actionGroup?.iconClass as React.ComponentType); } - if (isLoadingActionsConnectors) return ; + if (isLoadingActionConnectors) return ; return ( - {actionsConnectors.map(({ actionTypeId, name }) => ( + {actionConnectors.map(({ actionTypeId, name }) => ( diff --git a/x-pack/plugins/observability/public/pages/rule_details/types.ts b/x-pack/plugins/observability/public/pages/rule_details/types.ts index 5b60d8bf2efe2d..7906e6c8af29ae 100644 --- a/x-pack/plugins/observability/public/pages/rule_details/types.ts +++ b/x-pack/plugins/observability/public/pages/rule_details/types.ts @@ -36,7 +36,7 @@ export interface FetchRuleSummaryProps { ruleId: string; http: HttpSetup; } -export interface FetchRuleActionsConnectorsProps { +export interface FetchRuleActionConnectorsProps { http: HttpSetup; ruleActions: any[]; } From 9230454c99ee15757c00b2c8e590c6d859c002ef Mon Sep 17 00:00:00 2001 From: Faisal Kanout Date: Tue, 7 Jun 2022 14:55:57 +0200 Subject: [PATCH 3/7] Fix when a connector is deleted from connector page in Stack Management --- .../public/pages/rule_details/components/actions.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/observability/public/pages/rule_details/components/actions.tsx b/x-pack/plugins/observability/public/pages/rule_details/components/actions.tsx index aedee4b4d63e2b..7feb8c8d271863 100644 --- a/x-pack/plugins/observability/public/pages/rule_details/components/actions.tsx +++ b/x-pack/plugins/observability/public/pages/rule_details/components/actions.tsx @@ -35,7 +35,8 @@ export function Actions({ ruleActions, actionTypeRegistry }: ActionsProps) { toasts.addDanger({ title: errorActionConnectors }); } }, [errorActionConnectors, toasts]); - if (ruleActions && ruleActions.length <= 0) + + if (!actionConnectors || actionConnectors.length <= 0) return ( From afc9342e3a2b63fc7c57ec08fa958e77828802b3 Mon Sep 17 00:00:00 2001 From: Faisal Kanout Date: Tue, 7 Jun 2022 17:26:27 +0200 Subject: [PATCH 4/7] Fix tests --- .../public/pages/rule_details/components/actions.test.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/observability/public/pages/rule_details/components/actions.test.tsx b/x-pack/plugins/observability/public/pages/rule_details/components/actions.test.tsx index 9000d9dbf5f99e..6212c550d42650 100644 --- a/x-pack/plugins/observability/public/pages/rule_details/components/actions.test.tsx +++ b/x-pack/plugins/observability/public/pages/rule_details/components/actions.test.tsx @@ -17,11 +17,11 @@ jest.mock('../../../utils/kibana_react', () => ({ useKibana: jest.fn(() => mockUseKibanaReturnValue), })); -jest.mock('../../../hooks/use_fetch_rule_actions', () => ({ +jest.mock('../../../hooks/use_fetch_rule_action_connectors', () => ({ useFetchRuleActions: jest.fn(), })); -const { useFetchRuleActions } = jest.requireMock('../../../hooks/use_fetch_rule_actions'); +const { useFetchRuleActions } = jest.requireMock('../../../hooks/use_fetch_rule_action_connectors'); describe('Actions', () => { let wrapper: ReactWrapper; From 2ddb66b4ac9683cf2fb2c6a4fa9c3fc67377def2 Mon Sep 17 00:00:00 2001 From: Faisal Kanout Date: Wed, 8 Jun 2022 11:47:24 +0200 Subject: [PATCH 5/7] Update tests and mock loadAllActions API --- .../rule_details/components/actions.test.tsx | 51 +++++++++++-------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/x-pack/plugins/observability/public/pages/rule_details/components/actions.test.tsx b/x-pack/plugins/observability/public/pages/rule_details/components/actions.test.tsx index 6212c550d42650..3b4dbda5423803 100644 --- a/x-pack/plugins/observability/public/pages/rule_details/components/actions.test.tsx +++ b/x-pack/plugins/observability/public/pages/rule_details/components/actions.test.tsx @@ -5,7 +5,12 @@ * 2.0. */ import React from 'react'; -import { ReactWrapper, mount } from 'enzyme'; +import { mount } from 'enzyme'; +import { nextTick } from '@kbn/test-jest-helpers'; + +// import { nextTick } from '@kbn/test-jest-helpers'; + +import { act } from 'react-dom/test-utils'; import { Actions } from './actions'; import { observabilityPublicPluginsStartMock } from '../../../observability_public_plugins_start.mock'; import { kibanaStartMock } from '../../../utils/kibana_react.mock'; @@ -17,14 +22,11 @@ jest.mock('../../../utils/kibana_react', () => ({ useKibana: jest.fn(() => mockUseKibanaReturnValue), })); -jest.mock('../../../hooks/use_fetch_rule_action_connectors', () => ({ - useFetchRuleActions: jest.fn(), +jest.mock('@kbn/triggers-actions-ui-plugin/public/application/lib/action_connector_api', () => ({ + loadAllActions: jest.fn(), })); -const { useFetchRuleActions } = jest.requireMock('../../../hooks/use_fetch_rule_action_connectors'); - describe('Actions', () => { - let wrapper: ReactWrapper; async function setup() { const ruleActions = [ { @@ -38,26 +40,28 @@ describe('Actions', () => { actionTypeId: '.slack', }, ]; - const allActions = [ + const { loadAllActions } = jest.requireMock( + '@kbn/triggers-actions-ui-plugin/public/application/lib/action_connector_api' + ); + loadAllActions.mockResolvedValueOnce([ { - id: 1, - name: 'Server log', + id: 'a0d2f6c0-e682-11ec-843b-213c67313f8c', + name: 'Email', + config: {}, + actionTypeId: '.email', + }, + { + id: 'f57cabc0-e660-11ec-8241-7deb55b17f15', + name: 'logs', + config: {}, actionTypeId: '.server-log', }, { - id: 2, + id: '05b7ab30-e683-11ec-843b-213c67313f8c', name: 'Slack', actionTypeId: '.slack', }, - { - id: 3, - name: 'Email', - actionTypeId: '.email', - }, - ]; - useFetchRuleActions.mockReturnValue({ - allActions, - }); + ]); const actionTypeRegistryMock = observabilityPublicPluginsStartMock.createStart().triggersActionsUi.actionTypeRegistry; @@ -67,13 +71,18 @@ describe('Actions', () => { { id: '.email', iconClass: 'email' }, { id: '.index', iconClass: 'indexOpen' }, ]); - wrapper = mount( + const wrapper = mount( ); + await act(async () => { + await nextTick(); + wrapper.update(); + }); + return wrapper; } it("renders action connector icons for user's selected rule actions", async () => { - await setup(); + const wrapper = await setup(); wrapper.debug(); expect(wrapper.find('[data-euiicon-type]').length).toBe(2); expect(wrapper.find('[data-euiicon-type="logsApp"]').length).toBe(1); From 3f948ccf5896f1f3be0523aac01fd98fc7090680 Mon Sep 17 00:00:00 2001 From: Faisal Kanout Date: Wed, 8 Jun 2022 11:53:32 +0200 Subject: [PATCH 6/7] Remove unused import --- .../public/pages/rule_details/components/actions.test.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/x-pack/plugins/observability/public/pages/rule_details/components/actions.test.tsx b/x-pack/plugins/observability/public/pages/rule_details/components/actions.test.tsx index 3b4dbda5423803..707c1204d1564f 100644 --- a/x-pack/plugins/observability/public/pages/rule_details/components/actions.test.tsx +++ b/x-pack/plugins/observability/public/pages/rule_details/components/actions.test.tsx @@ -7,9 +7,6 @@ import React from 'react'; import { mount } from 'enzyme'; import { nextTick } from '@kbn/test-jest-helpers'; - -// import { nextTick } from '@kbn/test-jest-helpers'; - import { act } from 'react-dom/test-utils'; import { Actions } from './actions'; import { observabilityPublicPluginsStartMock } from '../../../observability_public_plugins_start.mock'; From f112bca39320da4721ca263311963f5db07dc7fa Mon Sep 17 00:00:00 2001 From: Faisal Kanout Date: Wed, 8 Jun 2022 12:29:24 +0200 Subject: [PATCH 7/7] Call the connectors API only when the rule has actions --- .../public/hooks/use_fetch_rule_action_connectors.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/x-pack/plugins/observability/public/hooks/use_fetch_rule_action_connectors.ts b/x-pack/plugins/observability/public/hooks/use_fetch_rule_action_connectors.ts index 6ce88e0c3ed23e..cae7607f1d084c 100644 --- a/x-pack/plugins/observability/public/hooks/use_fetch_rule_action_connectors.ts +++ b/x-pack/plugins/observability/public/hooks/use_fetch_rule_action_connectors.ts @@ -29,6 +29,14 @@ export function useFetchRuleActionConnectors({ const fetchRuleActionConnectors = useCallback(async () => { try { + if (!ruleActions || ruleActions.length <= 0) { + setActionConnector((oldState: FetchActionConnectors) => ({ + ...oldState, + isLoadingActionConnectors: false, + actionConnectors: [], + })); + return; + } const allActions = await loadAllActions({ http, });