diff --git a/x-pack/plugins/observability_solution/observability/public/pages/alert_details/alert_details.test.tsx b/x-pack/plugins/observability_solution/observability/public/pages/alert_details/alert_details.test.tsx
index 1089bb52b7ed4..877b0b965d1ce 100644
--- a/x-pack/plugins/observability_solution/observability/public/pages/alert_details/alert_details.test.tsx
+++ b/x-pack/plugins/observability_solution/observability/public/pages/alert_details/alert_details.test.tsx
@@ -23,7 +23,7 @@ import { Subset } from '../../typings';
import { useKibana } from '../../utils/kibana_react';
import { kibanaStartMock } from '../../utils/kibana_react.mock';
import { render } from '../../utils/test_helper';
-import { AlertDetails } from './alert_details';
+import { AlertDetails, getPageTitle } from './alert_details';
import { alertDetail, alertWithNoData } from './mock/alert';
jest.mock('react-router-dom', () => ({
@@ -128,6 +128,34 @@ describe('Alert details', () => {
config
);
+ describe('getPageTitle', () => {
+ const renderPageTitle = (ruleCategory: string) =>
+ render(
+
+ {getPageTitle(ruleCategory)}
+ ,
+ config
+ );
+
+ it('should display Log threshold title', () => {
+ const { getByTestId } = renderPageTitle('Log threshold');
+
+ expect(getByTestId('title').textContent).toContain('Log threshold breached');
+ });
+
+ it('should display Anomaly title', () => {
+ const { getByTestId } = renderPageTitle('Anomaly');
+
+ expect(getByTestId('title').textContent).toContain('Anomaly detected');
+ });
+
+ it('should display Inventory title', () => {
+ const { getByTestId } = renderPageTitle('Inventory');
+
+ expect(getByTestId('title').textContent).toContain('Inventory threshold breached');
+ });
+ });
+
it('should show the alert detail page with all necessary components', async () => {
useFetchAlertDetailMock.mockReturnValue([false, alertDetail]);
diff --git a/x-pack/plugins/observability_solution/observability/public/pages/alert_details/alert_details.tsx b/x-pack/plugins/observability_solution/observability/public/pages/alert_details/alert_details.tsx
index 9561dc37b3e7f..e7533c226df58 100644
--- a/x-pack/plugins/observability_solution/observability/public/pages/alert_details/alert_details.tsx
+++ b/x-pack/plugins/observability_solution/observability/public/pages/alert_details/alert_details.tsx
@@ -13,6 +13,7 @@ import {
EuiPanel,
EuiSpacer,
EuiTabbedContent,
+ EuiLoadingSpinner,
EuiTabbedContentTab,
useEuiTheme,
} from '@elastic/eui';
@@ -36,7 +37,7 @@ import { useKibana } from '../../utils/kibana_react';
import { useFetchRule } from '../../hooks/use_fetch_rule';
import { usePluginContext } from '../../hooks/use_plugin_context';
import { AlertData, useFetchAlertDetail } from '../../hooks/use_fetch_alert_detail';
-import { PageTitle, pageTitleContent } from './components/page_title';
+import { PageTitleContent } from './components/page_title_content';
import { HeaderActions } from './components/header_actions';
import { AlertSummary, AlertSummaryField } from './components/alert_summary';
import { CenterJustifiedSpinner } from '../../components/center_justified_spinner';
@@ -68,6 +69,16 @@ const RELATED_ALERTS_TAB_ID = 'related_alerts';
const ALERT_DETAILS_TAB_URL_STORAGE_KEY = 'tabId';
type TabId = typeof OVERVIEW_TAB_ID | typeof METADATA_TAB_ID | typeof RELATED_ALERTS_TAB_ID;
+export const getPageTitle = (ruleCategory: string) => {
+ return i18n.translate('xpack.observability.pages.alertDetails.pageTitle.title', {
+ defaultMessage:
+ '{ruleCategory} {ruleCategory, select, Anomaly {detected} Inventory {threshold breached} other {breached}}',
+ values: {
+ ruleCategory,
+ },
+ });
+};
+
export function AlertDetails() {
const {
cases: {
@@ -154,7 +165,7 @@ export function AlertDetails() {
},
{
text: alertDetail
- ? pageTitleContent(alertDetail.formatted.fields[ALERT_RULE_CATEGORY])
+ ? getPageTitle(alertDetail.formatted.fields[ALERT_RULE_CATEGORY])
: defaultBreadcrumb,
},
]);
@@ -274,8 +285,13 @@ export function AlertDetails() {
return (
+ ),
+ children: (
+ = (props: PageTitleProps) => (
+const Template: ComponentStory = (props: PageTitleContentProps) => (
);
-const TemplateWithPageTemplate: ComponentStory = (props: PageTitleProps) => (
+const TemplateWithPageTemplate: ComponentStory = (
+ props: PageTitleContentProps
+) => (
- } bottomBorder={false} />
+ } bottomBorder={false} />
);
@@ -33,21 +34,8 @@ const defaultProps = {
alert,
};
-export const PageTitle = Template.bind({});
-PageTitle.args = defaultProps;
-
-export const PageTitleForAnomaly = Template.bind({});
-PageTitleForAnomaly.args = {
- ...{
- alert: {
- ...defaultProps.alert,
- fields: {
- ...defaultProps.alert.fields,
- [ALERT_RULE_CATEGORY]: 'Anomaly',
- },
- },
- },
-};
+export const PageTitleContent = Template.bind({});
+PageTitleContent.args = defaultProps;
export const PageTitleUsedWithinPageTemplate = TemplateWithPageTemplate.bind({});
PageTitleUsedWithinPageTemplate.args = {
diff --git a/x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/page_title.tsx b/x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/page_title.tsx
deleted file mode 100644
index 91ba564df7216..0000000000000
--- a/x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/page_title.tsx
+++ /dev/null
@@ -1,128 +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 moment from 'moment';
-import React from 'react';
-import {
- EuiFlexGroup,
- EuiFlexItem,
- EuiLoadingSpinner,
- EuiSpacer,
- EuiText,
- useEuiTheme,
-} from '@elastic/eui';
-import { AlertLifecycleStatusBadge } from '@kbn/alerts-ui-shared';
-import { i18n } from '@kbn/i18n';
-import { FormattedMessage } from '@kbn/i18n-react';
-import {
- AlertStatus,
- ALERT_DURATION,
- ALERT_FLAPPING,
- ALERT_RULE_CATEGORY,
- TIMESTAMP,
-} from '@kbn/rule-data-utils';
-import { css } from '@emotion/react';
-import { asDuration } from '../../../../common/utils/formatters';
-import { TopAlert } from '../../../typings/alerts';
-
-export interface PageTitleProps {
- alert: TopAlert | null;
- alertStatus?: AlertStatus;
- dataTestSubj: string;
-}
-
-export function pageTitleContent(ruleCategory: string) {
- return i18n.translate('xpack.observability.pages.alertDetails.pageTitle.title', {
- defaultMessage:
- '{ruleCategory} {ruleCategory, select, Anomaly {detected} Inventory {threshold breached} other {breached}}',
- values: {
- ruleCategory,
- },
- });
-}
-
-export function PageTitle({ alert, alertStatus, dataTestSubj }: PageTitleProps) {
- const { euiTheme } = useEuiTheme();
-
- if (!alert) return ;
-
- return (
-
-
- {pageTitleContent(alert.fields[ALERT_RULE_CATEGORY])}
-
-
-
-
- {alertStatus && (
-
- )}
-
-
-
-
-
- :
-
-
- {moment(Number(alert.start)).locale(i18n.getLocale()).fromNow()}
-
-
-
-
-
-
-
- :
-
-
- {asDuration(Number(alert.fields[ALERT_DURATION]))}
-
-
-
-
-
-
-
- :
-
-
- {moment(alert.fields[TIMESTAMP]?.toString()).locale(i18n.getLocale()).fromNow()}
-
-
-
-
-
- );
-}
diff --git a/x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/page_title.test.tsx b/x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/page_title_content.test.tsx
similarity index 58%
rename from x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/page_title.test.tsx
rename to x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/page_title_content.test.tsx
index d22e60eeef4d0..d65c4f84c99dd 100644
--- a/x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/page_title.test.tsx
+++ b/x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/page_title_content.test.tsx
@@ -10,72 +10,29 @@ import { render } from '@testing-library/react';
import { __IntlProvider as IntlProvider } from '@kbn/i18n-react';
import {
AlertStatus,
- ALERT_RULE_CATEGORY,
ALERT_STATUS,
ALERT_STATUS_ACTIVE,
ALERT_STATUS_RECOVERED,
ALERT_STATUS_UNTRACKED,
} from '@kbn/rule-data-utils';
-import { PageTitle, PageTitleProps } from './page_title';
+import { PageTitleContent, PageTitleContentProps } from './page_title_content';
import { alert } from '../mock/alert';
-describe('Page Title', () => {
+describe('Page Title Content', () => {
const defaultProps = {
alert,
alertStatus: ALERT_STATUS_ACTIVE as AlertStatus,
dataTestSubj: 'ruleTypeId',
};
- const renderComp = (props: PageTitleProps) => {
+ const renderComp = (props: PageTitleContentProps) => {
return render(
-
+
);
};
- it('should display Log threshold title', () => {
- const { getByTestId } = renderComp(defaultProps);
-
- expect(getByTestId('ruleTypeId').textContent).toContain('Log threshold breached');
- });
-
- it('should display Anomaly title', () => {
- const props: PageTitleProps = {
- alert: {
- ...defaultProps.alert,
- fields: {
- ...defaultProps.alert.fields,
- [ALERT_RULE_CATEGORY]: 'Anomaly',
- },
- },
- alertStatus: defaultProps.alertStatus as AlertStatus,
- dataTestSubj: defaultProps.dataTestSubj,
- };
-
- const { getByTestId } = renderComp(props);
-
- expect(getByTestId('ruleTypeId').textContent).toContain('Anomaly detected');
- });
-
- it('should display Inventory title', () => {
- const props: PageTitleProps = {
- alert: {
- ...defaultProps.alert,
- fields: {
- ...defaultProps.alert.fields,
- [ALERT_RULE_CATEGORY]: 'Inventory',
- },
- },
- alertStatus: defaultProps.alertStatus as AlertStatus,
- dataTestSubj: defaultProps.dataTestSubj,
- };
-
- const { getByTestId } = renderComp(props);
-
- expect(getByTestId('ruleTypeId').textContent).toContain('Inventory threshold breached');
- });
-
it('should display an active badge when alert is active', async () => {
const { getByText } = renderComp(defaultProps);
expect(getByText('Active')).toBeTruthy();
diff --git a/x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/page_title_content.tsx b/x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/page_title_content.tsx
new file mode 100644
index 0000000000000..11fc6d0a476bb
--- /dev/null
+++ b/x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/page_title_content.tsx
@@ -0,0 +1,101 @@
+/*
+ * 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 moment from 'moment';
+import { EuiFlexGroup, EuiFlexItem, EuiText, useEuiTheme } from '@elastic/eui';
+import { AlertLifecycleStatusBadge } from '@kbn/alerts-ui-shared';
+import { i18n } from '@kbn/i18n';
+import { FormattedMessage } from '@kbn/i18n-react';
+import { AlertStatus, ALERT_DURATION, ALERT_FLAPPING, TIMESTAMP } from '@kbn/rule-data-utils';
+import { css } from '@emotion/react';
+import { asDuration } from '../../../../common/utils/formatters';
+import { TopAlert } from '../../../typings/alerts';
+
+export interface PageTitleContentProps {
+ alert: TopAlert | null;
+ alertStatus?: AlertStatus;
+ dataTestSubj: string;
+}
+
+export function PageTitleContent({ alert, alertStatus, dataTestSubj }: PageTitleContentProps) {
+ const { euiTheme } = useEuiTheme();
+
+ if (!alert) {
+ return null;
+ }
+
+ return (
+
+
+ {alertStatus && (
+
+ )}
+
+
+
+
+
+ :
+
+
+ {moment(Number(alert.start)).locale(i18n.getLocale()).fromNow()}
+
+
+
+
+
+
+
+ :
+
+
+ {asDuration(Number(alert.fields[ALERT_DURATION]))}
+
+
+
+
+
+
+
+ :
+
+
+ {moment(alert.fields[TIMESTAMP]?.toString()).locale(i18n.getLocale()).fromNow()}
+
+
+
+
+ );
+}