diff --git a/x-pack/plugins/observability/public/config/translations.ts b/x-pack/plugins/observability/public/config/translations.ts index e39dcb338d3a5..042650b94c084 100644 --- a/x-pack/plugins/observability/public/config/translations.ts +++ b/x-pack/plugins/observability/public/config/translations.ts @@ -122,9 +122,4 @@ export const translations = { } ), }, - alertsSearchBar: { - placeholder: i18n.translate('xpack.observability.alerts.searchBarPlaceholder', { - defaultMessage: 'Search alerts (e.g. kibana.alert.evaluation.threshold > 75)', - }), - }, }; diff --git a/x-pack/plugins/observability/public/pages/alerts/components/alerts_search_bar.tsx b/x-pack/plugins/observability/public/pages/alerts/components/alerts_search_bar.tsx deleted file mode 100644 index e1dd3743e3871..0000000000000 --- a/x-pack/plugins/observability/public/pages/alerts/components/alerts_search_bar.tsx +++ /dev/null @@ -1,66 +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, { useState } from 'react'; -import { DataView } from '@kbn/data-views-plugin/common'; -import { useKibana } from '@kbn/kibana-react-plugin/public'; -import type { ValidFeatureId } from '@kbn/rule-data-utils'; -import { translations } from '../../../config'; -import { ObservabilityAppServices } from '../../../application/types'; -import { useAlertDataView } from '../../../hooks/use_alert_data_view'; - -type QueryLanguageType = 'lucene' | 'kuery'; - -const NO_INDEX_PATTERNS: DataView[] = []; - -export function AlertsSearchBar({ - appName, - featureIds, - query, - onQueryChange, - rangeFrom, - rangeTo, -}: { - appName: string; - featureIds: ValidFeatureId[]; - rangeFrom?: string; - rangeTo?: string; - query?: string; - onQueryChange: ({}: { - dateRange: { from: string; to: string; mode?: 'absolute' | 'relative' }; - query?: string; - }) => void; -}) { - const { - unifiedSearch: { - ui: { SearchBar }, - }, - } = useKibana().services; - - const [queryLanguage, setQueryLanguage] = useState('kuery'); - const { value: dataView, loading, error } = useAlertDataView(featureIds); - - return ( - { - onQueryChange({ - dateRange, - query: typeof nextQuery?.query === 'string' ? nextQuery.query : '', - }); - setQueryLanguage((nextQuery?.language ?? 'kuery') as QueryLanguageType); - }} - /> - ); -} diff --git a/x-pack/plugins/observability/public/pages/alerts/components/index.ts b/x-pack/plugins/observability/public/pages/alerts/components/index.ts index 592ab16ddcadf..0f3422049d2c6 100644 --- a/x-pack/plugins/observability/public/pages/alerts/components/index.ts +++ b/x-pack/plugins/observability/public/pages/alerts/components/index.ts @@ -9,7 +9,6 @@ export * from './alerts_flyout'; export * from './render_cell_value'; export * from './severity_badge'; export * from './workflow_status_filter'; -export * from './alerts_search_bar'; export * from './filter_for_value'; export * from './parse_alert'; export * from './alerts_status_filter'; diff --git a/x-pack/plugins/observability/public/pages/alerts/containers/alerts_page/alerts_page.tsx b/x-pack/plugins/observability/public/pages/alerts/containers/alerts_page/alerts_page.tsx index f18b3741b33ff..ead8a2e89e117 100644 --- a/x-pack/plugins/observability/public/pages/alerts/containers/alerts_page/alerts_page.tsx +++ b/x-pack/plugins/observability/public/pages/alerts/containers/alerts_page/alerts_page.tsx @@ -29,7 +29,7 @@ import { useAlertsPageStateContainer, } from '../state_container'; import './styles.scss'; -import { AlertsStatusFilter, AlertsSearchBar, ALERT_STATUS_QUERY } from '../../components'; +import { AlertsStatusFilter, ALERT_STATUS_QUERY } from '../../components'; import { renderRuleStats } from '../../components/rule_stats'; import { ObservabilityAppServices } from '../../../../application/types'; import { ALERTS_PER_PAGE, ALERTS_TABLE_ID } from './constants'; @@ -46,7 +46,11 @@ function AlertsPage() { docLinks, http, notifications: { toasts }, - triggersActionsUi: { alertsTableConfigurationRegistry, getAlertsStateTable: AlertsStateTable }, + triggersActionsUi: { + alertsTableConfigurationRegistry, + getAlertsStateTable: AlertsStateTable, + getAlertsSearchBar: AlertsSearchBar, + }, data: { query: { timefilter: { timefilter: timeFilterService }, diff --git a/x-pack/plugins/observability/public/plugin.ts b/x-pack/plugins/observability/public/plugin.ts index ec08bbb7bd0d0..c5152104e3bc3 100644 --- a/x-pack/plugins/observability/public/plugin.ts +++ b/x-pack/plugins/observability/public/plugin.ts @@ -38,7 +38,6 @@ import { } from '@kbn/triggers-actions-ui-plugin/public'; import { SecurityPluginStart } from '@kbn/security-plugin/public'; import { GuidedOnboardingPluginStart } from '@kbn/guided-onboarding-plugin/public'; -import { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public'; import { observabilityAppId, observabilityFeatureId, casesPath } from '../common'; import { createLazyObservabilityPageTemplate } from './components/shared'; import { registerDataHandler } from './data_handler'; @@ -95,7 +94,6 @@ export interface ObservabilityPublicPluginsStart { actionTypeRegistry: ActionTypeRegistryContract; security: SecurityPluginStart; guidedOnboarding: GuidedOnboardingPluginStart; - unifiedSearch: UnifiedSearchPublicPluginStart; } export type ObservabilityPublicStart = ReturnType; diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index cf5350b4af2f6..13e8d52f36c6f 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -23290,7 +23290,6 @@ "xpack.observability.alerts.ruleStats.loadError": "Impossible de charger les statistiques de règles", "xpack.observability.alerts.ruleStats.muted": "Répété", "xpack.observability.alerts.ruleStats.ruleCount": "Nombre de règles", - "xpack.observability.alerts.searchBarPlaceholder": "Alertes de recherche (par exemple, kibana.alert.evaluation.threshold > 75)", "xpack.observability.alerts.workflowStatusFilter.acknowledgedButtonLabel": "Reconnue(s)", "xpack.observability.alerts.workflowStatusFilter.closedButtonLabel": "Fermé", "xpack.observability.alerts.workflowStatusFilter.openButtonLabel": "Ouvrir", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 9bf83166e2cab..b4dafbf2af6ca 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -23269,7 +23269,6 @@ "xpack.observability.alerts.ruleStats.loadError": "ルール統計情報を読み込めません", "xpack.observability.alerts.ruleStats.muted": "スヌーズ済み", "xpack.observability.alerts.ruleStats.ruleCount": "ルール数", - "xpack.observability.alerts.searchBarPlaceholder": "検索アラート(例:kibana.alert.evaluation.threshold > 75)", "xpack.observability.alerts.workflowStatusFilter.acknowledgedButtonLabel": "認識", "xpack.observability.alerts.workflowStatusFilter.closedButtonLabel": "終了", "xpack.observability.alerts.workflowStatusFilter.openButtonLabel": "開く", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 4f153aeee34ce..6fd802162e941 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -23300,7 +23300,6 @@ "xpack.observability.alerts.ruleStats.loadError": "无法加载规则统计信息", "xpack.observability.alerts.ruleStats.muted": "已暂停", "xpack.observability.alerts.ruleStats.ruleCount": "规则计数", - "xpack.observability.alerts.searchBarPlaceholder": "搜索告警(例如 kibana.alert.evaluation.threshold > 75)", "xpack.observability.alerts.workflowStatusFilter.acknowledgedButtonLabel": "已确认", "xpack.observability.alerts.workflowStatusFilter.closedButtonLabel": "已关闭", "xpack.observability.alerts.workflowStatusFilter.openButtonLabel": "打开", diff --git a/x-pack/plugins/observability/public/hooks/use_alert_data_view.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_alert_data_view.test.ts similarity index 78% rename from x-pack/plugins/observability/public/hooks/use_alert_data_view.test.ts rename to x-pack/plugins/triggers_actions_ui/public/application/hooks/use_alert_data_view.test.ts index 77db2492d4227..05696e19c618a 100644 --- a/x-pack/plugins/observability/public/hooks/use_alert_data_view.test.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_alert_data_view.test.ts @@ -6,35 +6,41 @@ */ import { DataView } from '@kbn/data-views-plugin/common'; +import { AlertConsumers } from '@kbn/rule-data-utils'; +import { createStartServicesMock } from '../../common/lib/kibana/kibana_react.mock'; import type { ValidFeatureId } from '@kbn/rule-data-utils'; import { act, renderHook } from '@testing-library/react-hooks'; import { AsyncState } from 'react-use/lib/useAsync'; -import { kibanaStartMock } from '../utils/kibana_react.mock'; -import { observabilityAlertFeatureIds } from '../config'; import { useAlertDataView } from './use_alert_data_view'; -const mockUseKibanaReturnValue = kibanaStartMock.startContract(); +const mockUseKibanaReturnValue = createStartServicesMock(); jest.mock('@kbn/kibana-react-plugin/public', () => ({ __esModule: true, - useKibana: jest.fn(() => mockUseKibanaReturnValue), + useKibana: jest.fn(() => ({ + services: mockUseKibanaReturnValue, + })), })); describe('useAlertDataView', () => { const mockedDataView = 'dataView'; + const observabilityAlertFeatureIds: ValidFeatureId[] = [ + AlertConsumers.APM, + AlertConsumers.INFRASTRUCTURE, + AlertConsumers.LOGS, + AlertConsumers.UPTIME, + ]; beforeEach(() => { - mockUseKibanaReturnValue.services.http.get.mockImplementation(async () => ({ + mockUseKibanaReturnValue.http.get = jest.fn().mockReturnValue({ index_name: [ '.alerts-observability.uptime.alerts-*', '.alerts-observability.metrics.alerts-*', '.alerts-observability.logs.alerts-*', '.alerts-observability.apm.alerts-*', ], - })); - mockUseKibanaReturnValue.services.data.dataViews.create.mockImplementation( - async () => mockedDataView - ); + }); + mockUseKibanaReturnValue.data.dataViews.create = jest.fn().mockReturnValue(mockedDataView); }); afterEach(() => { @@ -77,7 +83,7 @@ describe('useAlertDataView', () => { it('returns error with no data when error happens', async () => { const error = new Error('http error'); - mockUseKibanaReturnValue.services.http.get.mockImplementation(async () => { + mockUseKibanaReturnValue.http.get = jest.fn().mockImplementation(async () => { throw error; }); diff --git a/x-pack/plugins/observability/public/hooks/use_alert_data_view.ts b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_alert_data_view.ts similarity index 87% rename from x-pack/plugins/observability/public/hooks/use_alert_data_view.ts rename to x-pack/plugins/triggers_actions_ui/public/application/hooks/use_alert_data_view.ts index aad2a8e030eba..9da62ed75243d 100644 --- a/x-pack/plugins/observability/public/hooks/use_alert_data_view.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_alert_data_view.ts @@ -11,11 +11,10 @@ import { BASE_RAC_ALERTS_API_PATH } from '@kbn/rule-registry-plugin/common'; import type { ValidFeatureId } from '@kbn/rule-data-utils'; import useAsync from 'react-use/lib/useAsync'; import type { AsyncState } from 'react-use/lib/useAsync'; - -import { ObservabilityAppServices } from '../application/types'; +import { TriggersAndActionsUiServices } from '../..'; export function useAlertDataView(featureIds: ValidFeatureId[]): AsyncState { - const { http, data: dataService } = useKibana().services; + const { http, data: dataService } = useKibana().services; const features = featureIds.sort().join(','); const dataView = useAsync(async () => { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/alerts_search_bar.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/alerts_search_bar.tsx new file mode 100644 index 0000000000000..193d6abf1433b --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/alerts_search_bar.tsx @@ -0,0 +1,62 @@ +/* + * 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, { useCallback, useState } from 'react'; +import { useKibana } from '@kbn/kibana-react-plugin/public'; +import { NO_INDEX_PATTERNS } from './constants'; +import { SEARCH_BAR_PLACEHOLDER } from './translations'; +import { AlertsSearchBarProps, QueryLanguageType } from './types'; +import { useAlertDataView } from '../../hooks/use_alert_data_view'; +import { TriggersAndActionsUiServices } from '../../..'; + +// TODO Share buildEsQuery to be used between AlertsSearchBar and AlertsStateTable component https://github.com/elastic/kibana/issues/144615 +export function AlertsSearchBar({ + appName, + featureIds, + query, + onQueryChange, + rangeFrom, + rangeTo, +}: AlertsSearchBarProps) { + const { + unifiedSearch: { + ui: { SearchBar }, + }, + } = useKibana().services; + + const [queryLanguage, setQueryLanguage] = useState('kuery'); + const { value: dataView, loading, error } = useAlertDataView(featureIds); + + const onQuerySubmit = useCallback( + (payload) => { + const { dateRange, query: nextQuery } = payload; + onQueryChange({ + dateRange, + query: typeof nextQuery?.query === 'string' ? nextQuery.query : '', + }); + setQueryLanguage((nextQuery?.language ?? 'kuery') as QueryLanguageType); + }, + [onQueryChange, setQueryLanguage] + ); + + return ( + + ); +} + +// eslint-disable-next-line import/no-default-export +export { AlertsSearchBar as default }; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/constants.ts b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/constants.ts new file mode 100644 index 0000000000000..e1eca7239cc9d --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/constants.ts @@ -0,0 +1,10 @@ +/* + * 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 { DataView } from '@kbn/data-views-plugin/common'; + +export const NO_INDEX_PATTERNS: DataView[] = []; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/index.ts b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/index.ts new file mode 100644 index 0000000000000..bfc3f022c37cf --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/index.ts @@ -0,0 +1,10 @@ +/* + * 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. + */ + +export { AlertsSearchBar } from './alerts_search_bar'; + +export type { AlertsSearchBarProps } from './types'; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/translations.ts b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/translations.ts new file mode 100644 index 0000000000000..a5f4fc4b5754e --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/translations.ts @@ -0,0 +1,15 @@ +/* + * 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 SEARCH_BAR_PLACEHOLDER = i18n.translate( + 'xpack.triggersActionsUI.alertsSearchBar.placeholder', + { + defaultMessage: 'Search alerts (e.g. kibana.alert.evaluation.threshold > 75)', + } +); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/types.ts b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/types.ts new file mode 100644 index 0000000000000..86e3e60ef059e --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/types.ts @@ -0,0 +1,22 @@ +/* + * 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 { ValidFeatureId } from '@kbn/rule-data-utils'; + +export type QueryLanguageType = 'lucene' | 'kuery'; + +export interface AlertsSearchBarProps { + appName: string; + featureIds: ValidFeatureId[]; + rangeFrom?: string; + rangeTo?: string; + query?: string; + onQueryChange: ({}: { + dateRange: { from: string; to: string; mode?: 'absolute' | 'relative' }; + query?: string; + }) => void; +} diff --git a/x-pack/plugins/triggers_actions_ui/public/common/get_alerts_search_bar.tsx b/x-pack/plugins/triggers_actions_ui/public/common/get_alerts_search_bar.tsx new file mode 100644 index 0000000000000..ddeb5e5c4c067 --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/common/get_alerts_search_bar.tsx @@ -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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { EuiLoadingSpinner } from '@elastic/eui'; +import React, { lazy, Suspense } from 'react'; +import type { AlertsSearchBarProps } from '../application/sections/alerts_search_bar'; + +const AlertsSearchBarLazy: React.FC = lazy( + () => import('../application/sections/alerts_search_bar/alerts_search_bar') +); + +export const getAlertsSearchBarLazy = (props: AlertsSearchBarProps) => ( + }> + + +); diff --git a/x-pack/plugins/triggers_actions_ui/public/mocks.ts b/x-pack/plugins/triggers_actions_ui/public/mocks.ts index 7c18ea1b6fa2c..d753feb597a6c 100644 --- a/x-pack/plugins/triggers_actions_ui/public/mocks.ts +++ b/x-pack/plugins/triggers_actions_ui/public/mocks.ts @@ -33,8 +33,10 @@ import { getRuleTagBadgeLazy } from './common/get_rule_tag_badge'; import { getRuleEventLogListLazy } from './common/get_rule_event_log_list'; import { getRulesListLazy } from './common/get_rules_list'; import { getAlertsTableStateLazy } from './common/get_alerts_table_state'; +import { getAlertsSearchBarLazy } from './common/get_alerts_search_bar'; import { getRulesListNotifyBadgeLazy } from './common/get_rules_list_notify_badge'; import { AlertsTableStateProps } from './application/sections/alerts_table/alerts_table_state'; +import { AlertsSearchBarProps } from './application/sections/alerts_search_bar'; import { CreateConnectorFlyoutProps } from './application/sections/action_connector_form/create_connector_flyout'; import { EditConnectorFlyoutProps } from './application/sections/action_connector_form/edit_connector_flyout'; import { getActionFormLazy } from './common/get_action_form'; @@ -86,6 +88,9 @@ function createStartMock(): TriggersAndActionsUIPublicPluginStart { getAlertsStateTable: (props: AlertsTableStateProps) => { return getAlertsTableStateLazy(props); }, + getAlertsSearchBar: (props: AlertsSearchBarProps) => { + return getAlertsSearchBarLazy(props); + }, getAlertsTable: (props: AlertsTableProps) => { return getAlertsTableLazy(props); }, diff --git a/x-pack/plugins/triggers_actions_ui/public/plugin.ts b/x-pack/plugins/triggers_actions_ui/public/plugin.ts index 9e4645b164f21..d8ebc2298dca9 100644 --- a/x-pack/plugins/triggers_actions_ui/public/plugin.ts +++ b/x-pack/plugins/triggers_actions_ui/public/plugin.ts @@ -23,6 +23,7 @@ import type { DataViewEditorStart } from '@kbn/data-view-editor-plugin/public'; import { Storage } from '@kbn/kibana-utils-plugin/public'; import type { SpacesPluginStart } from '@kbn/spaces-plugin/public'; import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public'; +import type { AlertsSearchBarProps } from './application/sections/alerts_search_bar'; import { TypeRegistry } from './application/type_registry'; import { getAddConnectorFlyoutLazy } from './common/get_add_connector_flyout'; @@ -72,6 +73,7 @@ import { registerAlertsTableConfiguration } from './application/sections/alerts_ import { PLUGIN_ID, CONNECTORS_PLUGIN_ID } from './common/constants'; import type { AlertsTableStateProps } from './application/sections/alerts_table/alerts_table_state'; import { getAlertsTableStateLazy } from './common/get_alerts_table_state'; +import { getAlertsSearchBarLazy } from './common/get_alerts_search_bar'; import { ActionAccordionFormProps } from './application/sections/action_connector_form/action_form'; import type { FieldBrowserProps } from './application/sections/field_browser/types'; import { getRuleDefinitionLazy } from './common/get_rule_definition'; @@ -108,6 +110,7 @@ export interface TriggersAndActionsUIPublicPluginStart { ) => ReactElement; getAlertsTable: (props: AlertsTableProps) => ReactElement; getAlertsStateTable: (props: AlertsTableStateProps) => ReactElement; + getAlertsSearchBar: (props: AlertsSearchBarProps) => ReactElement; getFieldBrowser: (props: FieldBrowserProps) => ReactElement; getRuleStatusDropdown: (props: RuleStatusDropdownProps) => ReactElement; getRuleTagFilter: (props: RuleTagFilterProps) => ReactElement; @@ -378,6 +381,9 @@ export class Plugin getAlertsStateTable: (props: AlertsTableStateProps) => { return getAlertsTableStateLazy(props); }, + getAlertsSearchBar: (props: AlertsSearchBarProps) => { + return getAlertsSearchBarLazy(props); + }, getAlertsTable: (props: AlertsTableProps) => { return getAlertsTableLazy(props); },