From 0dc73122a54ec06676b8e35375649492bbe92b3c Mon Sep 17 00:00:00 2001 From: Zacqary Adam Xeper Date: Thu, 6 Jul 2023 14:34:55 -0500 Subject: [PATCH] [RAM] Move maintenance window callout to @kbn/alerts-ui-shared package (#160678) ## Summary Moves the Security Solution's `MaintenanceWindowCallout` into a shared KBN package to make it more accessible by other plugins. ### Checklist - [x] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [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: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- packages/kbn-alerts-ui-shared/index.ts | 1 + .../src/maintenance_window_callout/api.ts | 20 +++ .../maintenance_window_callout/index.test.tsx | 151 +++++++++++------- .../src/maintenance_window_callout/index.tsx | 60 +++++++ .../src/maintenance_window_callout/types.ts | 65 ++++++++ .../use_fetch_active_maintenance_windows.ts | 42 +++++ packages/kbn-alerts-ui-shared/tsconfig.json | 6 +- .../maintenance_window_callout/api.ts | 18 --- .../maintenance_window_callout.tsx | 43 ----- .../translations.ts | 36 ----- .../use_fetch_active_maintenance_windows.ts | 29 ---- .../pages/rule_management/index.tsx | 7 +- .../plugins/security_solution/tsconfig.json | 3 +- .../translations/translations/fr-FR.json | 4 - .../translations/translations/ja-JP.json | 4 - .../translations/translations/zh-CN.json | 4 - 16 files changed, 289 insertions(+), 204 deletions(-) create mode 100644 packages/kbn-alerts-ui-shared/src/maintenance_window_callout/api.ts rename x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/maintenance_window_callout/maintenance_window_callout.test.tsx => packages/kbn-alerts-ui-shared/src/maintenance_window_callout/index.test.tsx (67%) create mode 100644 packages/kbn-alerts-ui-shared/src/maintenance_window_callout/index.tsx create mode 100644 packages/kbn-alerts-ui-shared/src/maintenance_window_callout/types.ts create mode 100644 packages/kbn-alerts-ui-shared/src/maintenance_window_callout/use_fetch_active_maintenance_windows.ts delete mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/maintenance_window_callout/api.ts delete mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/maintenance_window_callout/maintenance_window_callout.tsx delete mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/maintenance_window_callout/translations.ts delete mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/maintenance_window_callout/use_fetch_active_maintenance_windows.ts diff --git a/packages/kbn-alerts-ui-shared/index.ts b/packages/kbn-alerts-ui-shared/index.ts index 431c6803c36d4..6815a66bce902 100644 --- a/packages/kbn-alerts-ui-shared/index.ts +++ b/packages/kbn-alerts-ui-shared/index.ts @@ -8,3 +8,4 @@ export { AlertLifecycleStatusBadge } from './src/alert_lifecycle_status_badge'; export type { AlertLifecycleStatusBadgeProps } from './src/alert_lifecycle_status_badge'; +export { MaintenanceWindowCallout } from './src/maintenance_window_callout'; diff --git a/packages/kbn-alerts-ui-shared/src/maintenance_window_callout/api.ts b/packages/kbn-alerts-ui-shared/src/maintenance_window_callout/api.ts new file mode 100644 index 0000000000000..fede1a30c9035 --- /dev/null +++ b/packages/kbn-alerts-ui-shared/src/maintenance_window_callout/api.ts @@ -0,0 +1,20 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { KibanaServices } from './types'; + +export const fetchActiveMaintenanceWindows = async ( + http: KibanaServices['http'], + signal?: AbortSignal +) => + http.fetch(INTERNAL_ALERTING_API_GET_ACTIVE_MAINTENANCE_WINDOWS_PATH, { + method: 'GET', + signal, + }); + +const INTERNAL_ALERTING_API_GET_ACTIVE_MAINTENANCE_WINDOWS_PATH = `/internal/alerting/rules/maintenance_window/_active`; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/maintenance_window_callout/maintenance_window_callout.test.tsx b/packages/kbn-alerts-ui-shared/src/maintenance_window_callout/index.test.tsx similarity index 67% rename from x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/maintenance_window_callout/maintenance_window_callout.test.tsx rename to packages/kbn-alerts-ui-shared/src/maintenance_window_callout/index.test.tsx index c7ce00f50e881..9644958ea0245 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/maintenance_window_callout/maintenance_window_callout.test.tsx +++ b/packages/kbn-alerts-ui-shared/src/maintenance_window_callout/index.test.tsx @@ -1,33 +1,36 @@ /* * 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. + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. */ import React from 'react'; -import { render, waitFor, cleanup } from '@testing-library/react'; +import { I18nProvider } from '@kbn/i18n-react'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { render, waitFor, cleanup } from '@testing-library/react'; import { MaintenanceWindowStatus, MAINTENANCE_WINDOW_FEATURE_ID, } from '@kbn/alerting-plugin/common'; import type { MaintenanceWindow } from '@kbn/alerting-plugin/common'; import type { AsApiContract } from '@kbn/alerting-plugin/server/routes/lib'; -import { useKibana } from '../../../../common/lib/kibana'; -import { useAppToasts } from '../../../../common/hooks/use_app_toasts'; -import { useAppToastsMock } from '../../../../common/hooks/use_app_toasts.mock'; -import { MaintenanceWindowCallout } from './maintenance_window_callout'; -import { TestProviders } from '../../../../common/mock'; +import { MaintenanceWindowCallout } from '.'; import { fetchActiveMaintenanceWindows } from './api'; -jest.mock('../../../../common/hooks/use_app_toasts'); - jest.mock('./api', () => ({ fetchActiveMaintenanceWindows: jest.fn(() => Promise.resolve([])), })); -jest.mock('../../../../common/lib/kibana'); +const TestProviders: React.FC<{}> = ({ children }) => { + const queryClient = new QueryClient(); + return ( + + {children} + + ); +}; const RUNNING_MAINTENANCE_WINDOW_1: Partial = { title: 'Running maintenance window 1', @@ -72,29 +75,37 @@ const UPCOMING_MAINTENANCE_WINDOW: Partial = { ], }; -const useKibanaMock = useKibana as jest.Mock; const fetchActiveMaintenanceWindowsMock = fetchActiveMaintenanceWindows as jest.Mock; -describe('MaintenanceWindowCallout', () => { - let appToastsMock: jest.Mocked>; +const kibanaServicesMock = { + application: { + capabilities: { + [MAINTENANCE_WINDOW_FEATURE_ID]: { + save: true, + show: true, + }, + }, + }, + notifications: { + toasts: { + addError: jest.fn(), + add: jest.fn(), + remove: jest.fn(), + get$: jest.fn(), + addInfo: jest.fn(), + addWarning: jest.fn(), + addDanger: jest.fn(), + addSuccess: jest.fn(), + }, + }, + http: { + fetch: jest.fn(), + }, +}; +describe('MaintenanceWindowCallout', () => { beforeEach(() => { jest.resetAllMocks(); - - appToastsMock = useAppToastsMock.create(); - (useAppToasts as jest.Mock).mockReturnValue(appToastsMock); - useKibanaMock.mockReturnValue({ - services: { - application: { - capabilities: { - [MAINTENANCE_WINDOW_FEATURE_ID]: { - save: true, - show: true, - }, - }, - }, - }, - }); }); afterEach(() => { @@ -105,7 +116,10 @@ describe('MaintenanceWindowCallout', () => { it('should be visible if currently there is at least one "running" maintenance window', async () => { fetchActiveMaintenanceWindowsMock.mockResolvedValue([RUNNING_MAINTENANCE_WINDOW_1]); - const { findAllByText } = render(, { wrapper: TestProviders }); + const { findAllByText } = render( + , + { wrapper: TestProviders } + ); expect(await findAllByText('Maintenance window is running')).toHaveLength(1); expect(fetchActiveMaintenanceWindowsMock).toHaveBeenCalledTimes(1); @@ -117,7 +131,10 @@ describe('MaintenanceWindowCallout', () => { RUNNING_MAINTENANCE_WINDOW_2, ]); - const { findAllByText } = render(, { wrapper: TestProviders }); + const { findAllByText } = render( + , + { wrapper: TestProviders } + ); expect(await findAllByText('Maintenance window is running')).toHaveLength(1); expect(fetchActiveMaintenanceWindowsMock).toHaveBeenCalledTimes(1); @@ -126,8 +143,12 @@ describe('MaintenanceWindowCallout', () => { it('should be visible if currently there is a recurring "running" maintenance window', async () => { fetchActiveMaintenanceWindowsMock.mockResolvedValue([RECURRING_RUNNING_MAINTENANCE_WINDOW]); - const { findByText } = render(, { wrapper: TestProviders }); + const { findByText } = render( + , + { wrapper: TestProviders } + ); + // @ts-expect-error Jest types are incomplete in packages expect(await findByText('Maintenance window is running')).toBeInTheDocument(); expect(fetchActiveMaintenanceWindowsMock).toHaveBeenCalledTimes(1); }); @@ -137,8 +158,10 @@ describe('MaintenanceWindowCallout', () => { [] // API returns an empty array if there are no active maintenance windows ); - const { container } = render(, { wrapper: TestProviders }); - + const { container } = render(, { + wrapper: TestProviders, + }); + // @ts-expect-error Jest types are incomplete in packages expect(container).toBeEmptyDOMElement(); expect(fetchActiveMaintenanceWindowsMock).toHaveBeenCalledTimes(1); }); @@ -146,8 +169,10 @@ describe('MaintenanceWindowCallout', () => { it('should NOT be visible if currently there are only "upcoming" maintenance windows', async () => { fetchActiveMaintenanceWindowsMock.mockResolvedValue([UPCOMING_MAINTENANCE_WINDOW]); - const { container } = render(, { wrapper: TestProviders }); - + const { container } = render(, { + wrapper: TestProviders, + }); + // @ts-expect-error Jest types are incomplete in packages expect(container).toBeEmptyDOMElement(); expect(fetchActiveMaintenanceWindowsMock).toHaveBeenCalledTimes(1); }); @@ -179,11 +204,13 @@ describe('MaintenanceWindowCallout', () => { const mockError = new Error('Network error'); fetchActiveMaintenanceWindowsMock.mockRejectedValue(mockError); - render(, { wrapper: createReactQueryWrapper() }); + render(, { + wrapper: createReactQueryWrapper(), + }); await waitFor(() => { - expect(appToastsMock.addError).toHaveBeenCalledTimes(1); - expect(appToastsMock.addError).toHaveBeenCalledWith(mockError, { + expect(kibanaServicesMock.notifications.toasts.addError).toHaveBeenCalledTimes(1); + expect(kibanaServicesMock.notifications.toasts.addError).toHaveBeenCalledWith(mockError, { title: 'Failed to check if maintenance windows are active', toastMessage: 'Rule notifications are stopped while the maintenance window is running.', }); @@ -191,42 +218,44 @@ describe('MaintenanceWindowCallout', () => { }); it('should return null if window maintenance privilege is NONE', async () => { - useKibanaMock.mockReturnValue({ - services: { - application: { - capabilities: { - [MAINTENANCE_WINDOW_FEATURE_ID]: { - save: false, - show: false, - }, + const servicesMock = { + ...kibanaServicesMock, + application: { + capabilities: { + [MAINTENANCE_WINDOW_FEATURE_ID]: { + save: false, + show: false, }, }, }, - }); + }; fetchActiveMaintenanceWindowsMock.mockResolvedValue([RUNNING_MAINTENANCE_WINDOW_1]); - const { container } = render(, { wrapper: TestProviders }); - + const { container } = render(, { + wrapper: TestProviders, + }); + // @ts-expect-error Jest types are incomplete in packages expect(container).toBeEmptyDOMElement(); }); it('should work as expected if window maintenance privilege is READ ', async () => { - useKibanaMock.mockReturnValue({ - services: { - application: { - capabilities: { - [MAINTENANCE_WINDOW_FEATURE_ID]: { - save: false, - show: true, - }, + const servicesMock = { + ...kibanaServicesMock, + application: { + capabilities: { + [MAINTENANCE_WINDOW_FEATURE_ID]: { + save: false, + show: true, }, }, }, - }); + }; fetchActiveMaintenanceWindowsMock.mockResolvedValue([RUNNING_MAINTENANCE_WINDOW_1]); - const { findByText } = render(, { wrapper: TestProviders }); - + const { findByText } = render(, { + wrapper: TestProviders, + }); + // @ts-expect-error Jest types are incomplete in packages expect(await findByText('Maintenance window is running')).toBeInTheDocument(); }); }); diff --git a/packages/kbn-alerts-ui-shared/src/maintenance_window_callout/index.tsx b/packages/kbn-alerts-ui-shared/src/maintenance_window_callout/index.tsx new file mode 100644 index 0000000000000..fcd3b81890d46 --- /dev/null +++ b/packages/kbn-alerts-ui-shared/src/maintenance_window_callout/index.tsx @@ -0,0 +1,60 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { EuiCallOut } from '@elastic/eui'; +import { MaintenanceWindow, MaintenanceWindowStatus, KibanaServices } from './types'; +import { useFetchActiveMaintenanceWindows } from './use_fetch_active_maintenance_windows'; + +const MAINTENANCE_WINDOW_FEATURE_ID = 'maintenanceWindow'; +const MAINTENANCE_WINDOW_RUNNING = i18n.translate( + 'alertsUIShared.maintenanceWindowCallout.maintenanceWindowActive', + { + defaultMessage: 'Maintenance window is running', + } +); +const MAINTENANCE_WINDOW_RUNNING_DESCRIPTION = i18n.translate( + 'alertsUIShared.maintenanceWindowCallout.maintenanceWindowActiveDescription', + { + defaultMessage: 'Rule notifications are stopped while the maintenance window is running.', + } +); + +export function MaintenanceWindowCallout({ + kibanaServices, +}: { + kibanaServices: KibanaServices; +}): JSX.Element | null { + const { + application: { capabilities }, + } = kibanaServices; + + const isMaintenanceWindowDisabled = + !capabilities[MAINTENANCE_WINDOW_FEATURE_ID].show && + !capabilities[MAINTENANCE_WINDOW_FEATURE_ID].save; + const { data } = useFetchActiveMaintenanceWindows(kibanaServices, { + enabled: !isMaintenanceWindowDisabled, + }); + + if (isMaintenanceWindowDisabled) { + return null; + } + + const activeMaintenanceWindows = (data as MaintenanceWindow[]) || []; + + if (activeMaintenanceWindows.some(({ status }) => status === MaintenanceWindowStatus.Running)) { + return ( + + {MAINTENANCE_WINDOW_RUNNING_DESCRIPTION} + + ); + } + + return null; +} diff --git a/packages/kbn-alerts-ui-shared/src/maintenance_window_callout/types.ts b/packages/kbn-alerts-ui-shared/src/maintenance_window_callout/types.ts new file mode 100644 index 0000000000000..52c5dc4d48c8a --- /dev/null +++ b/packages/kbn-alerts-ui-shared/src/maintenance_window_callout/types.ts @@ -0,0 +1,65 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ +import type { WeekdayStr, Options } from '@kbn/rrule'; +import { CoreStart } from '@kbn/core/public'; + +export enum MaintenanceWindowStatus { + Running = 'running', + Upcoming = 'upcoming', + Finished = 'finished', + Archived = 'archived', +} + +export interface MaintenanceWindowModificationMetadata { + createdBy: string | null; + updatedBy: string | null; + createdAt: string; + updatedAt: string; +} + +export interface DateRange { + gte: string; + lte: string; +} + +export interface MaintenanceWindowSOProperties { + title: string; + enabled: boolean; + duration: number; + expirationDate: string; + events: DateRange[]; + rRule: RRuleParams; +} + +export type MaintenanceWindowSOAttributes = MaintenanceWindowSOProperties & + MaintenanceWindowModificationMetadata; + +export type MaintenanceWindow = MaintenanceWindowSOAttributes & { + status: MaintenanceWindowStatus; + eventStartTime: string | null; + eventEndTime: string | null; + id: string; +}; + +export type RRuleParams = Partial & Pick; + +// An iCal RRULE to define a recurrence schedule, see https://github.com/jakubroztocil/rrule for the spec +export type RRuleRecord = Omit & { + dtstart: string; + byweekday?: Array; + wkst?: WeekdayStr; + until?: string; +}; + +export interface KibanaServices { + application: { + capabilities: Record; + }; + http: Pick; + notifications: Pick; +} diff --git a/packages/kbn-alerts-ui-shared/src/maintenance_window_callout/use_fetch_active_maintenance_windows.ts b/packages/kbn-alerts-ui-shared/src/maintenance_window_callout/use_fetch_active_maintenance_windows.ts new file mode 100644 index 0000000000000..fba5da239b09c --- /dev/null +++ b/packages/kbn-alerts-ui-shared/src/maintenance_window_callout/use_fetch_active_maintenance_windows.ts @@ -0,0 +1,42 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { UseQueryOptions } from '@tanstack/react-query'; +import { useQuery } from '@tanstack/react-query'; +import { i18n } from '@kbn/i18n'; +import { KibanaServices } from './types'; +import { fetchActiveMaintenanceWindows } from './api'; + +export const useFetchActiveMaintenanceWindows = ( + { http, notifications: { toasts } }: KibanaServices, + { enabled }: Pick +) => { + return useQuery( + ['GET', INTERNAL_ALERTING_API_GET_ACTIVE_MAINTENANCE_WINDOWS_PATH], + ({ signal }) => fetchActiveMaintenanceWindows(http, signal), + { + enabled, + refetchInterval: 60000, + onError: (error: Error) => { + toasts.addError(error, { title: FETCH_ERROR, toastMessage: FETCH_ERROR_DESCRIPTION }); + }, + } + ); +}; + +const INTERNAL_ALERTING_API_GET_ACTIVE_MAINTENANCE_WINDOWS_PATH = `/internal/alerting/rules/maintenance_window/_active`; +const FETCH_ERROR = i18n.translate('alertsUIShared.maintenanceWindowCallout.fetchError', { + defaultMessage: 'Failed to check if maintenance windows are active', +}); + +const FETCH_ERROR_DESCRIPTION = i18n.translate( + 'alertsUIShared.maintenanceWindowCallout.fetchErrorDescription', + { + defaultMessage: 'Rule notifications are stopped while the maintenance window is running.', + } +); diff --git a/packages/kbn-alerts-ui-shared/tsconfig.json b/packages/kbn-alerts-ui-shared/tsconfig.json index 045e79467b3b7..7573505ebcd3f 100644 --- a/packages/kbn-alerts-ui-shared/tsconfig.json +++ b/packages/kbn-alerts-ui-shared/tsconfig.json @@ -17,6 +17,10 @@ ], "kbn_references": [ "@kbn/i18n", - "@kbn/rule-data-utils" + "@kbn/rule-data-utils", + "@kbn/core", + "@kbn/i18n-react", + "@kbn/alerting-plugin", + "@kbn/rrule" ] } diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/maintenance_window_callout/api.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/maintenance_window_callout/api.ts deleted file mode 100644 index 9d3c28429df5b..0000000000000 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/maintenance_window_callout/api.ts +++ /dev/null @@ -1,18 +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 type { MaintenanceWindow } from '@kbn/alerting-plugin/common/maintenance_window'; -import { INTERNAL_ALERTING_API_GET_ACTIVE_MAINTENANCE_WINDOWS_PATH } from '@kbn/alerting-plugin/common'; -import { KibanaServices } from '../../../../common/lib/kibana'; - -export const fetchActiveMaintenanceWindows = async ( - signal?: AbortSignal -): Promise => - KibanaServices.get().http.fetch(INTERNAL_ALERTING_API_GET_ACTIVE_MAINTENANCE_WINDOWS_PATH, { - method: 'GET', - signal, - }); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/maintenance_window_callout/maintenance_window_callout.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/maintenance_window_callout/maintenance_window_callout.tsx deleted file mode 100644 index 5a1d21b39a65b..0000000000000 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/maintenance_window_callout/maintenance_window_callout.tsx +++ /dev/null @@ -1,43 +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 { EuiCallOut } from '@elastic/eui'; -import { - MaintenanceWindowStatus, - MAINTENANCE_WINDOW_FEATURE_ID, -} from '@kbn/alerting-plugin/common'; -import { useFetchActiveMaintenanceWindows } from './use_fetch_active_maintenance_windows'; -import * as i18n from './translations'; -import { useKibana } from '../../../../common/lib/kibana'; - -export function MaintenanceWindowCallout(): JSX.Element | null { - const { - application: { capabilities }, - } = useKibana().services; - - const isMaintenanceWindowDisabled = - !capabilities[MAINTENANCE_WINDOW_FEATURE_ID].show && - !capabilities[MAINTENANCE_WINDOW_FEATURE_ID].save; - const { data } = useFetchActiveMaintenanceWindows({ enabled: !isMaintenanceWindowDisabled }); - - if (isMaintenanceWindowDisabled) { - return null; - } - - const activeMaintenanceWindows = data || []; - - if (activeMaintenanceWindows.some(({ status }) => status === MaintenanceWindowStatus.Running)) { - return ( - - {i18n.MAINTENANCE_WINDOW_RUNNING_DESCRIPTION} - - ); - } - - return null; -} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/maintenance_window_callout/translations.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/maintenance_window_callout/translations.ts deleted file mode 100644 index a3a7e9c1fdbc7..0000000000000 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/maintenance_window_callout/translations.ts +++ /dev/null @@ -1,36 +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 { i18n } from '@kbn/i18n'; - -export const MAINTENANCE_WINDOW_RUNNING = i18n.translate( - 'xpack.securitySolution.detectionEngine.ruleManagementUi.maintenanceWindowCallout.maintenanceWindowActive', - { - defaultMessage: 'Maintenance window is running', - } -); - -export const MAINTENANCE_WINDOW_RUNNING_DESCRIPTION = i18n.translate( - 'xpack.securitySolution.detectionEngine.ruleManagementUi.maintenanceWindowCallout.maintenanceWindowActiveDescription', - { - defaultMessage: 'Rule notifications are stopped while the maintenance window is running.', - } -); - -export const FETCH_ERROR = i18n.translate( - 'xpack.securitySolution.detectionEngine.ruleManagementUi.maintenanceWindowCallout.fetchError', - { - defaultMessage: 'Failed to check if maintenance windows are active', - } -); - -export const FETCH_ERROR_DESCRIPTION = i18n.translate( - 'xpack.securitySolution.detectionEngine.ruleManagementUi.maintenanceWindowCallout.fetchErrorDescription', - { - defaultMessage: 'Rule notifications are stopped while the maintenance window is running.', - } -); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/maintenance_window_callout/use_fetch_active_maintenance_windows.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/maintenance_window_callout/use_fetch_active_maintenance_windows.ts deleted file mode 100644 index 69aecfa794357..0000000000000 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/maintenance_window_callout/use_fetch_active_maintenance_windows.ts +++ /dev/null @@ -1,29 +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 type { UseQueryOptions } from '@tanstack/react-query'; -import { useQuery } from '@tanstack/react-query'; -import { INTERNAL_ALERTING_API_GET_ACTIVE_MAINTENANCE_WINDOWS_PATH } from '@kbn/alerting-plugin/common'; -import { useAppToasts } from '../../../../common/hooks/use_app_toasts'; -import * as i18n from './translations'; -import { fetchActiveMaintenanceWindows } from './api'; - -export const useFetchActiveMaintenanceWindows = ({ enabled }: Pick) => { - const { addError } = useAppToasts(); - - return useQuery( - ['GET', INTERNAL_ALERTING_API_GET_ACTIVE_MAINTENANCE_WINDOWS_PATH], - ({ signal }) => fetchActiveMaintenanceWindows(signal), - { - enabled, - refetchInterval: 60000, - onError: (error) => { - addError(error, { title: i18n.FETCH_ERROR, toastMessage: i18n.FETCH_ERROR_DESCRIPTION }); - }, - } - ); -}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/rule_management/index.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/rule_management/index.tsx index 43c09c7bf451c..d7a4362585e98 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/rule_management/index.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/rule_management/index.tsx @@ -6,6 +6,7 @@ */ import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiToolTip } from '@elastic/eui'; +import { MaintenanceWindowCallout } from '@kbn/alerts-ui-shared'; import React, { useCallback } from 'react'; import { APP_UI_ID } from '../../../../../common/constants'; import { SecurityPageName } from '../../../../app/types'; @@ -29,7 +30,6 @@ import * as i18n from '../../../../detections/pages/detection_engine/rules/trans import { useInvalidateFetchRuleManagementFiltersQuery } from '../../../rule_management/api/hooks/use_fetch_rule_management_filters_query'; import { useInvalidateFindRulesQuery } from '../../../rule_management/api/hooks/use_find_rules_query'; import { importRules } from '../../../rule_management/logic'; -import { MaintenanceWindowCallout } from '../../components/maintenance_window_callout/maintenance_window_callout'; import { AllRules } from '../../components/rules_table'; import { RulesPageTourComponent } from '../../components/rules_table/alternative_tour/tour'; import { RulesTableContextProvider } from '../../components/rules_table/rules_table/rules_table_context'; @@ -38,7 +38,8 @@ import { SuperHeader } from './super_header'; const RulesPageComponent: React.FC = () => { const [isImportModalVisible, showImportModal, hideImportModal] = useBoolState(); const [isValueListFlyoutVisible, showValueListFlyout, hideValueListFlyout] = useBoolState(); - const { navigateToApp } = useKibana().services.application; + const kibanaServices = useKibana().services; + const { navigateToApp } = kibanaServices.application; const invalidateFindRulesQuery = useInvalidateFindRulesQuery(); const invalidateFetchRuleManagementFilters = useInvalidateFetchRuleManagementFiltersQuery(); const invalidateRules = useCallback(() => { @@ -145,7 +146,7 @@ const RulesPageComponent: React.FC = () => { - + diff --git a/x-pack/plugins/security_solution/tsconfig.json b/x-pack/plugins/security_solution/tsconfig.json index d272cb53f4d80..8fd41f43eab37 100644 --- a/x-pack/plugins/security_solution/tsconfig.json +++ b/x-pack/plugins/security_solution/tsconfig.json @@ -161,6 +161,7 @@ "@kbn/discover-plugin", "@kbn/field-formats-plugin", "@kbn/dev-proc-runner", - "@kbn/cloud-chat-plugin" + "@kbn/cloud-chat-plugin", + "@kbn/alerts-ui-shared" ] } diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 28590adc654b8..f24cbbec1c71d 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -31031,10 +31031,6 @@ "xpack.securitySolution.detectionEngine.ruleDetails.ruleExecutionLog.timestampColumnTooltip": "Date et heures auxquelles l'exécution de la règle a été lancée.", "xpack.securitySolution.detectionEngine.ruleDetails.ruleExecutionResultsTab": "Résultats d'exécution", "xpack.securitySolution.detectionEngine.ruleDetails.unknownDescription": "Inconnu", - "xpack.securitySolution.detectionEngine.ruleManagementUi.maintenanceWindowCallout.fetchError": "Impossible de vérifier si une fenêtre de maintenance est en cours d'exécution", - "xpack.securitySolution.detectionEngine.ruleManagementUi.maintenanceWindowCallout.fetchErrorDescription": "Les actions de notification ne s'exécutent pas lorsqu'une fenêtre de maintenance est en cours.", - "xpack.securitySolution.detectionEngine.ruleManagementUi.maintenanceWindowCallout.maintenanceWindowActive": "Une fenêtre de maintenance est en cours d'exécution", - "xpack.securitySolution.detectionEngine.ruleManagementUi.maintenanceWindowCallout.maintenanceWindowActiveDescription": "Les actions de notification ne s'exécutent pas lorsqu'une fenêtre de maintenance est en cours.", "xpack.securitySolution.detectionEngine.ruleManagementUi.rulesTable.mlJobsWarning.popover.buttonLabel": "Visitez la page des détails de règle pour effectuer votre investigation", "xpack.securitySolution.detectionEngine.ruleManagementUi.rulesTable.mlJobsWarning.popover.description": "Les tâches suivantes ne sont pas en cours d'exécution et la règle pourra donc générer des résultats incorrects :", "xpack.securitySolution.detectionEngine.ruleMonitoring.eventTypeFilter.filterTitle": "Type d'événement", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index d87d2be8ee3d3..38044787397c5 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -31016,10 +31016,6 @@ "xpack.securitySolution.detectionEngine.ruleDetails.ruleExecutionLog.timestampColumnTooltip": "日時ルール実行が開始されました。", "xpack.securitySolution.detectionEngine.ruleDetails.ruleExecutionResultsTab": "実行結果", "xpack.securitySolution.detectionEngine.ruleDetails.unknownDescription": "不明", - "xpack.securitySolution.detectionEngine.ruleManagementUi.maintenanceWindowCallout.fetchError": "現在保守時間枠が実行中かどうかを確認できませんでした", - "xpack.securitySolution.detectionEngine.ruleManagementUi.maintenanceWindowCallout.fetchErrorDescription": "保守時間枠が実行中の場合は通知アクションが実行されません。", - "xpack.securitySolution.detectionEngine.ruleManagementUi.maintenanceWindowCallout.maintenanceWindowActive": "現在保守時間枠が実行中です", - "xpack.securitySolution.detectionEngine.ruleManagementUi.maintenanceWindowCallout.maintenanceWindowActiveDescription": "保守時間枠が実行中の場合は通知アクションが実行されません。", "xpack.securitySolution.detectionEngine.ruleManagementUi.rulesTable.mlJobsWarning.popover.buttonLabel": "ルール詳細ページを表示して調査してください", "xpack.securitySolution.detectionEngine.ruleManagementUi.rulesTable.mlJobsWarning.popover.description": "次のジョブが実行されていないため、ルールで正しくない結果が生成されている可能性があります。", "xpack.securitySolution.detectionEngine.ruleMonitoring.eventTypeFilter.filterTitle": "イベントタイプ", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 5d3c8e37ad605..fba9691609c0a 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -31012,10 +31012,6 @@ "xpack.securitySolution.detectionEngine.ruleDetails.ruleExecutionLog.timestampColumnTooltip": "已发起日期时间规则执行。", "xpack.securitySolution.detectionEngine.ruleDetails.ruleExecutionResultsTab": "执行结果", "xpack.securitySolution.detectionEngine.ruleDetails.unknownDescription": "未知", - "xpack.securitySolution.detectionEngine.ruleManagementUi.maintenanceWindowCallout.fetchError": "无法检查当前是否运行有任何维护窗口", - "xpack.securitySolution.detectionEngine.ruleManagementUi.maintenanceWindowCallout.fetchErrorDescription": "维护窗口正在运行时,通知操作无法运行。", - "xpack.securitySolution.detectionEngine.ruleManagementUi.maintenanceWindowCallout.maintenanceWindowActive": "维护窗口当前正在运行", - "xpack.securitySolution.detectionEngine.ruleManagementUi.maintenanceWindowCallout.maintenanceWindowActiveDescription": "维护窗口正在运行时,通知操作无法运行。", "xpack.securitySolution.detectionEngine.ruleManagementUi.rulesTable.mlJobsWarning.popover.buttonLabel": "访问规则详情页面以进行调查", "xpack.securitySolution.detectionEngine.ruleManagementUi.rulesTable.mlJobsWarning.popover.description": "以下作业未运行,可能导致规则生成错误的结果:", "xpack.securitySolution.detectionEngine.ruleMonitoring.eventTypeFilter.filterTitle": "事件类型",