mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[Actionable Observability] Add rule details locator and make AlertSummaryWidget clickable (#147103)
Resolves #141467 ## 📝 Summary - Added a [locator](https://docs.elastic.dev/kibana-dev-docs/routing-and-navigation#specifying-state) for the rule details page - Made AlertSummaryWidget clickable and implemented the related navigation for rule details page ## 🧪 How to test - Create a rule and go to the rule details page - You should be able to click on all/active/recovered sections in Alert Summary Widget and upon click going to alert tables with the correct filter https://user-images.githubusercontent.com/12370520/205959565-6c383910-763f-4214-9baa-cf191f012de9.mp4
This commit is contained in:
parent
313537c178
commit
a30d225421
14 changed files with 246 additions and 44 deletions
|
@ -54,6 +54,7 @@ export const casesPath = '/cases';
|
|||
export const uptimeOverviewLocatorID = 'UPTIME_OVERVIEW_LOCATOR';
|
||||
export const syntheticsMonitorDetailLocatorID = 'SYNTHETICS_MONITOR_DETAIL_LOCATOR';
|
||||
export const syntheticsEditMonitorLocatorID = 'SYNTHETICS_EDIT_MONITOR_LOCATOR';
|
||||
export const ruleDetailsLocatorID = 'RULE_DETAILS_LOCATOR';
|
||||
|
||||
export {
|
||||
NETWORK_TIMINGS_FIELDS,
|
||||
|
|
|
@ -31,7 +31,8 @@
|
|||
"inspector",
|
||||
"unifiedSearch",
|
||||
"security",
|
||||
"guidedOnboarding"
|
||||
"guidedOnboarding",
|
||||
"share"
|
||||
],
|
||||
"ui": true,
|
||||
"server": true,
|
||||
|
|
|
@ -22,6 +22,7 @@ import { IStorageWrapper } from '@kbn/kibana-utils-plugin/public';
|
|||
import { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||
import { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public';
|
||||
import { LensPublicStart } from '@kbn/lens-plugin/public';
|
||||
import { SharePluginStart } from '@kbn/share-plugin/public';
|
||||
import { TriggersAndActionsUIPublicPluginStart } from '@kbn/triggers-actions-ui-plugin/public';
|
||||
import { CasesUiStart } from '@kbn/cases-plugin/public';
|
||||
import { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public';
|
||||
|
@ -39,6 +40,7 @@ export interface ObservabilityAppServices {
|
|||
notifications: NotificationsStart;
|
||||
overlays: OverlayStart;
|
||||
savedObjectsClient: SavedObjectsStart['client'];
|
||||
share: SharePluginStart;
|
||||
stateTransfer: EmbeddableStateTransfer;
|
||||
storage: IStorageWrapper;
|
||||
theme: ThemeServiceStart;
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* 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 { ACTIVE_ALERTS } from '../components/shared/alert_search_bar/constants';
|
||||
import { EXECUTION_TAB, ALERTS_TAB } from '../pages/rule_details/constants';
|
||||
import { getRuleDetailsPath, RuleDetailsLocatorDefinition } from './rule_details';
|
||||
|
||||
describe('RuleDetailsLocator', () => {
|
||||
const locator = new RuleDetailsLocatorDefinition();
|
||||
const mockedRuleId = '389d3318-7e10-4996-bb45-128e1607fb7e';
|
||||
|
||||
it('should return correct url when only ruleId is provided', async () => {
|
||||
const location = await locator.getLocation({ ruleId: mockedRuleId });
|
||||
expect(location.app).toEqual('observability');
|
||||
expect(location.path).toEqual(getRuleDetailsPath(mockedRuleId));
|
||||
});
|
||||
|
||||
it('should return correct url when tabId is execution', async () => {
|
||||
const location = await locator.getLocation({ ruleId: mockedRuleId, tabId: EXECUTION_TAB });
|
||||
expect(location.path).toMatchInlineSnapshot(
|
||||
`"/alerts/rules/389d3318-7e10-4996-bb45-128e1607fb7e?tabId=execution"`
|
||||
);
|
||||
});
|
||||
|
||||
it('should return correct url when tabId is alerts without extra search params', async () => {
|
||||
const location = await locator.getLocation({ ruleId: mockedRuleId, tabId: ALERTS_TAB });
|
||||
expect(location.path).toMatchInlineSnapshot(
|
||||
`"/alerts/rules/389d3318-7e10-4996-bb45-128e1607fb7e?tabId=alerts&searchBarParams=(kuery:'',rangeFrom:now-15m,rangeTo:now,status:all)"`
|
||||
);
|
||||
});
|
||||
|
||||
it('should return correct url when tabId is alerts with search params', async () => {
|
||||
const location = await locator.getLocation({
|
||||
ruleId: mockedRuleId,
|
||||
tabId: ALERTS_TAB,
|
||||
rangeFrom: 'mockedRangeTo',
|
||||
rangeTo: 'mockedRangeFrom',
|
||||
kuery: 'mockedKuery',
|
||||
status: ACTIVE_ALERTS.status,
|
||||
});
|
||||
expect(location.path).toMatchInlineSnapshot(
|
||||
`"/alerts/rules/389d3318-7e10-4996-bb45-128e1607fb7e?tabId=alerts&searchBarParams=(kuery:mockedKuery,rangeFrom:mockedRangeTo,rangeTo:mockedRangeFrom,status:active)"`
|
||||
);
|
||||
});
|
||||
});
|
72
x-pack/plugins/observability/public/locators/rule_details.ts
Normal file
72
x-pack/plugins/observability/public/locators/rule_details.ts
Normal file
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* 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 { setStateToKbnUrl } from '@kbn/kibana-utils-plugin/public';
|
||||
import type { SerializableRecord } from '@kbn/utility-types';
|
||||
import type { LocatorDefinition } from '@kbn/share-plugin/public';
|
||||
import { ruleDetailsLocatorID } from '../../common';
|
||||
import { ALL_ALERTS } from '../components/shared/alert_search_bar/constants';
|
||||
import {
|
||||
ALERTS_TAB,
|
||||
EXECUTION_TAB,
|
||||
SEARCH_BAR_URL_STORAGE_KEY,
|
||||
} from '../pages/rule_details/constants';
|
||||
import type { TabId } from '../pages/rule_details/types';
|
||||
import type { AlertStatus } from '../../common/typings';
|
||||
|
||||
export interface RuleDetailsLocatorParams extends SerializableRecord {
|
||||
ruleId: string;
|
||||
tabId?: TabId;
|
||||
rangeFrom?: string;
|
||||
rangeTo?: string;
|
||||
kuery?: string;
|
||||
status?: AlertStatus;
|
||||
}
|
||||
|
||||
export const getRuleDetailsPath = (ruleId: string) => {
|
||||
return `/alerts/rules/${encodeURI(ruleId)}`;
|
||||
};
|
||||
|
||||
export class RuleDetailsLocatorDefinition implements LocatorDefinition<RuleDetailsLocatorParams> {
|
||||
public readonly id = ruleDetailsLocatorID;
|
||||
|
||||
public readonly getLocation = async (params: RuleDetailsLocatorParams) => {
|
||||
const { ruleId, kuery, rangeTo, tabId, rangeFrom, status } = params;
|
||||
const appState: {
|
||||
tabId?: TabId;
|
||||
rangeFrom?: string;
|
||||
rangeTo?: string;
|
||||
kuery?: string;
|
||||
status?: AlertStatus;
|
||||
} = {};
|
||||
|
||||
appState.rangeFrom = rangeFrom || 'now-15m';
|
||||
appState.rangeTo = rangeTo || 'now';
|
||||
appState.kuery = kuery || '';
|
||||
appState.status = status || ALL_ALERTS.status;
|
||||
|
||||
let path = getRuleDetailsPath(ruleId);
|
||||
|
||||
if (tabId === ALERTS_TAB) {
|
||||
path = `${path}?tabId=${tabId}`;
|
||||
path = setStateToKbnUrl(
|
||||
SEARCH_BAR_URL_STORAGE_KEY,
|
||||
appState,
|
||||
{ useHash: false, storeInHashQuery: false },
|
||||
path
|
||||
);
|
||||
} else if (tabId === EXECUTION_TAB) {
|
||||
path = `${path}?tabId=${tabId}`;
|
||||
}
|
||||
|
||||
return {
|
||||
app: 'observability',
|
||||
path,
|
||||
state: {},
|
||||
};
|
||||
};
|
||||
}
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
export const EXECUTION_TAB = 'execution';
|
||||
export const ALERTS_TAB = 'alerts';
|
||||
export const URL_STORAGE_KEY = 'searchBarParams';
|
||||
export const SEARCH_BAR_URL_STORAGE_KEY = 'searchBarParams';
|
||||
export const EVENT_ERROR_LOG_TAB = 'rule_error_log_list';
|
||||
export const RULE_DETAILS_PAGE_ID = 'rule-details-alerts-o11y';
|
||||
export const RULE_DETAILS_ALERTS_SEARCH_BAR_ID = 'rule-details-alerts-search-bar-o11y';
|
||||
|
|
|
@ -46,7 +46,7 @@ import {
|
|||
ALERTS_TAB,
|
||||
RULE_DETAILS_PAGE_ID,
|
||||
RULE_DETAILS_ALERTS_SEARCH_BAR_ID,
|
||||
URL_STORAGE_KEY,
|
||||
SEARCH_BAR_URL_STORAGE_KEY,
|
||||
} from './constants';
|
||||
import { RuleDetailsPathParams, TabId } from './types';
|
||||
import { useBreadcrumbs } from '../../hooks/use_breadcrumbs';
|
||||
|
@ -57,7 +57,9 @@ import { PageTitle } from './components';
|
|||
import { getHealthColor } from './config';
|
||||
import { hasExecuteActionsCapability, hasAllPrivilege } from './config';
|
||||
import { paths } from '../../config/paths';
|
||||
import { observabilityFeatureId } from '../../../common';
|
||||
import { ALERT_STATUS_ALL } from '../../../common/constants';
|
||||
import { AlertStatus } from '../../../common/typings';
|
||||
import { observabilityFeatureId, ruleDetailsLocatorID } from '../../../common';
|
||||
import { ALERT_STATUS_LICENSE_ERROR, rulesStatusesTranslationsMapping } from './translations';
|
||||
import { ObservabilityAppServices } from '../../application/types';
|
||||
|
||||
|
@ -70,12 +72,15 @@ export function RuleDetailsPage() {
|
|||
getEditAlertFlyout,
|
||||
getRuleEventLogList,
|
||||
getAlertsStateTable: AlertsStateTable,
|
||||
getRuleAlertsSummary,
|
||||
getRuleAlertsSummary: AlertSummaryWidget,
|
||||
getRuleStatusPanel,
|
||||
getRuleDefinition,
|
||||
},
|
||||
application: { capabilities, navigateToUrl },
|
||||
notifications: { toasts },
|
||||
share: {
|
||||
url: { locators },
|
||||
},
|
||||
} = useKibana<ObservabilityAppServices>().services;
|
||||
|
||||
const { ruleId } = useParams<RuleDetailsPathParams>();
|
||||
|
@ -106,6 +111,22 @@ export function RuleDetailsPage() {
|
|||
const ruleQuery = useRef([
|
||||
{ query: `kibana.alert.rule.uuid: ${ruleId}`, language: 'kuery' },
|
||||
] as Query[]);
|
||||
const tabsRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const onAlertSummaryWidgetClick = async (status: AlertStatus = ALERT_STATUS_ALL) => {
|
||||
await locators.get(ruleDetailsLocatorID)?.navigate(
|
||||
{
|
||||
ruleId,
|
||||
tabId: ALERTS_TAB,
|
||||
status,
|
||||
},
|
||||
{
|
||||
replace: true,
|
||||
}
|
||||
);
|
||||
setTabId(ALERTS_TAB);
|
||||
tabsRef.current?.scrollIntoView({ behavior: 'smooth' });
|
||||
};
|
||||
|
||||
const updateUrl = (nextQuery: { tabId: TabId }) => {
|
||||
const newTabId = nextQuery.tabId;
|
||||
|
@ -224,7 +245,7 @@ export function RuleDetailsPage() {
|
|||
<ObservabilityAlertSearchbarWithUrlSync
|
||||
appName={RULE_DETAILS_ALERTS_SEARCH_BAR_ID}
|
||||
onEsQueryChange={setEsQuery}
|
||||
urlStorageKey={URL_STORAGE_KEY}
|
||||
urlStorageKey={SEARCH_BAR_URL_STORAGE_KEY}
|
||||
defaultSearchQueries={ruleQuery.current}
|
||||
/>
|
||||
<EuiSpacer size="s" />
|
||||
|
@ -354,16 +375,18 @@ export function RuleDetailsPage() {
|
|||
</EuiFlexItem>
|
||||
<EuiSpacer size="m" />
|
||||
<EuiFlexItem style={{ minWidth: 350 }}>
|
||||
{getRuleAlertsSummary({
|
||||
rule,
|
||||
filteredRuleTypes,
|
||||
})}
|
||||
<AlertSummaryWidget
|
||||
rule={rule}
|
||||
filteredRuleTypes={filteredRuleTypes}
|
||||
onClick={(status) => onAlertSummaryWidgetClick(status)}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiSpacer size="m" />
|
||||
{getRuleDefinition({ rule, onEditRule: () => reloadRule() } as RuleDefinitionProps)}
|
||||
</EuiFlexGroup>
|
||||
|
||||
<EuiSpacer size="l" />
|
||||
<div ref={tabsRef} />
|
||||
<EuiTabbedContent
|
||||
data-test-subj="ruleDetailsTabbedContent"
|
||||
tabs={tabs}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { BehaviorSubject, from } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { SharePluginSetup, SharePluginStart } from '@kbn/share-plugin/public';
|
||||
import {
|
||||
AppDeepLink,
|
||||
AppMountParameters,
|
||||
|
@ -38,6 +39,7 @@ import {
|
|||
} from '@kbn/triggers-actions-ui-plugin/public';
|
||||
import { SecurityPluginStart } from '@kbn/security-plugin/public';
|
||||
import { GuidedOnboardingPluginStart } from '@kbn/guided-onboarding-plugin/public';
|
||||
import { RuleDetailsLocatorDefinition } from './locators/rule_details';
|
||||
import { observabilityAppId, observabilityFeatureId, casesPath } from '../common';
|
||||
import { createLazyObservabilityPageTemplate } from './components/shared';
|
||||
import { registerDataHandler } from './data_handler';
|
||||
|
@ -78,6 +80,7 @@ export type ObservabilityPublicSetup = ReturnType<Plugin['setup']>;
|
|||
|
||||
export interface ObservabilityPublicPluginsSetup {
|
||||
data: DataPublicPluginSetup;
|
||||
share: SharePluginSetup;
|
||||
triggersActionsUi: TriggersAndActionsUIPublicPluginSetup;
|
||||
home?: HomePublicPluginSetup;
|
||||
usageCollection: UsageCollectionSetup;
|
||||
|
@ -88,6 +91,7 @@ export interface ObservabilityPublicPluginsStart {
|
|||
cases: CasesUiStart;
|
||||
embeddable: EmbeddableStart;
|
||||
home?: HomePublicPluginStart;
|
||||
share: SharePluginStart;
|
||||
triggersActionsUi: TriggersAndActionsUIPublicPluginStart;
|
||||
data: DataPublicPluginStart;
|
||||
dataViews: DataViewsPublicPluginStart;
|
||||
|
@ -171,6 +175,7 @@ export class Plugin
|
|||
this.observabilityRuleTypeRegistry = createObservabilityRuleTypeRegistry(
|
||||
pluginsSetup.triggersActionsUi.ruleTypeRegistry
|
||||
);
|
||||
pluginsSetup.share.url.locators.create(new RuleDetailsLocatorDefinition());
|
||||
|
||||
const mount = async (params: AppMountParameters<unknown>) => {
|
||||
// Load application bundle
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { action } from '@storybook/addon-actions';
|
||||
import { AlertsSummaryWidgetUI as Component } from './alert_summary_widget_ui';
|
||||
|
||||
export default {
|
||||
|
@ -17,5 +18,6 @@ export const Overview = {
|
|||
active: 15,
|
||||
recovered: 53,
|
||||
timeRange: 'Last 30 days',
|
||||
onClick: action('clicked'),
|
||||
},
|
||||
};
|
||||
|
|
|
@ -5,9 +5,18 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { ALERT_STATUS_ACTIVE, ALERT_STATUS_RECOVERED, AlertStatus } from '@kbn/rule-data-utils';
|
||||
import { euiLightVars } from '@kbn/ui-theme';
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiSpacer, EuiText, EuiTitle } from '@elastic/eui';
|
||||
import React from 'react';
|
||||
import {
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiLink,
|
||||
EuiPanel,
|
||||
EuiSpacer,
|
||||
EuiText,
|
||||
EuiTitle,
|
||||
} from '@elastic/eui';
|
||||
import React, { MouseEvent } from 'react';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { AlertsSummaryWidgetUIProps } from './types';
|
||||
|
||||
|
@ -15,9 +24,26 @@ export const AlertsSummaryWidgetUI = ({
|
|||
active,
|
||||
recovered,
|
||||
timeRange,
|
||||
onClick,
|
||||
}: AlertsSummaryWidgetUIProps) => {
|
||||
const handleClick = (
|
||||
event: MouseEvent<HTMLAnchorElement | HTMLDivElement>,
|
||||
status?: AlertStatus
|
||||
) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
onClick(status);
|
||||
};
|
||||
|
||||
return (
|
||||
<EuiPanel data-test-subj="ruleAlertsSummary" hasShadow={false} hasBorder>
|
||||
<EuiPanel
|
||||
element="div"
|
||||
data-test-subj="ruleAlertsSummary"
|
||||
hasShadow={false}
|
||||
hasBorder
|
||||
onClick={handleClick}
|
||||
>
|
||||
<EuiFlexGroup direction="column">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFlexGroup direction="column">
|
||||
|
@ -43,39 +69,53 @@ export const AlertsSummaryWidgetUI = ({
|
|||
<EuiFlexItem>
|
||||
<EuiFlexGroup gutterSize="s" alignItems="flexStart" responsive={false}>
|
||||
<EuiFlexItem>
|
||||
<EuiText>
|
||||
<h3 data-test-subj="totalAlertsCount">{active + recovered}</h3>
|
||||
</EuiText>
|
||||
<EuiText size="xs" color="subdued">
|
||||
<FormattedMessage
|
||||
id="xpack.triggersActionsUI.sections.ruleDetails.alertsSummary.allAlertsLabel"
|
||||
defaultMessage="All"
|
||||
/>
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiText color={euiLightVars.euiColorSuccessText}>
|
||||
<h3 data-test-subj="recoveredAlertsCount">{recovered}</h3>
|
||||
<EuiLink onClick={handleClick}>
|
||||
<EuiText color={euiLightVars.euiTextColor}>
|
||||
<h3 data-test-subj="totalAlertsCount">{active + recovered}</h3>
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
<EuiText size="xs" color="subdued">
|
||||
<FormattedMessage
|
||||
id="xpack.triggersActionsUI.sections.ruleDetails.rule.ruleSummary.recoveredLabel"
|
||||
defaultMessage="Recovered"
|
||||
/>
|
||||
</EuiText>
|
||||
<EuiText size="xs" color="subdued">
|
||||
<FormattedMessage
|
||||
id="xpack.triggersActionsUI.sections.ruleDetails.alertsSummary.allAlertsLabel"
|
||||
defaultMessage="All"
|
||||
/>
|
||||
</EuiText>
|
||||
</EuiLink>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiText color={euiLightVars.euiColorDangerText}>
|
||||
<h3 data-test-subj="activeAlertsCount">{active}</h3>
|
||||
</EuiText>
|
||||
<EuiText size="xs" color="subdued">
|
||||
<FormattedMessage
|
||||
id="xpack.triggersActionsUI.sections.ruleDetails.alertsSummary.activeLabel"
|
||||
defaultMessage="Currently active"
|
||||
/>
|
||||
</EuiText>
|
||||
<EuiLink
|
||||
onClick={(event: React.MouseEvent<HTMLAnchorElement>) =>
|
||||
handleClick(event, ALERT_STATUS_ACTIVE)
|
||||
}
|
||||
>
|
||||
<EuiText color={euiLightVars.euiColorDangerText}>
|
||||
<h3 data-test-subj="activeAlertsCount">{active}</h3>
|
||||
</EuiText>
|
||||
<EuiText size="xs" color="subdued">
|
||||
<FormattedMessage
|
||||
id="xpack.triggersActionsUI.sections.ruleDetails.alertsSummary.activeLabel"
|
||||
defaultMessage="Currently active"
|
||||
/>
|
||||
</EuiText>
|
||||
</EuiLink>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiLink
|
||||
onClick={(event: React.MouseEvent<HTMLAnchorElement>) =>
|
||||
handleClick(event, ALERT_STATUS_RECOVERED)
|
||||
}
|
||||
>
|
||||
<EuiFlexItem>
|
||||
<EuiText color={euiLightVars.euiColorSuccessText}>
|
||||
<h3 data-test-subj="recoveredAlertsCount">{recovered}</h3>
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
<EuiText size="xs" color="subdued">
|
||||
<FormattedMessage
|
||||
id="xpack.triggersActionsUI.sections.ruleDetails.rule.ruleSummary.recoveredLabel"
|
||||
defaultMessage="Recovered"
|
||||
/>
|
||||
</EuiText>
|
||||
</EuiLink>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiFlexItem>
|
||||
|
|
|
@ -5,8 +5,11 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { AlertStatus } from '@kbn/rule-data-utils';
|
||||
|
||||
export interface AlertsSummaryWidgetUIProps {
|
||||
active: number;
|
||||
recovered: number;
|
||||
timeRange: JSX.Element | string;
|
||||
onClick: (status?: AlertStatus) => void;
|
||||
}
|
||||
|
|
|
@ -59,6 +59,7 @@ describe('Rule Alert Summary', () => {
|
|||
<RuleAlertsSummary
|
||||
rule={mockedRule}
|
||||
filteredRuleTypes={['apm', 'uptime', 'metric', 'logs']}
|
||||
onClick={jest.fn}
|
||||
/>
|
||||
</IntlProvider>
|
||||
);
|
||||
|
|
|
@ -14,7 +14,7 @@ import { useLoadRuleTypes } from '../../../../hooks/use_load_rule_types';
|
|||
import { RuleAlertsSummaryProps } from '.';
|
||||
import { AlertSummaryWidgetError, AlertsSummaryWidgetUI } from './components';
|
||||
|
||||
export const RuleAlertsSummary = ({ rule, filteredRuleTypes }: RuleAlertsSummaryProps) => {
|
||||
export const RuleAlertsSummary = ({ rule, filteredRuleTypes, onClick }: RuleAlertsSummaryProps) => {
|
||||
const [features, setFeatures] = useState<string>('');
|
||||
const { ruleTypes } = useLoadRuleTypes({
|
||||
filteredRuleTypes,
|
||||
|
@ -40,6 +40,7 @@ export const RuleAlertsSummary = ({ rule, filteredRuleTypes }: RuleAlertsSummary
|
|||
return (
|
||||
<AlertsSummaryWidgetUI
|
||||
active={active}
|
||||
onClick={onClick}
|
||||
recovered={recovered}
|
||||
timeRange={
|
||||
<FormattedMessage
|
||||
|
|
|
@ -5,9 +5,11 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { AlertStatus } from '@kbn/rule-data-utils';
|
||||
import { Rule } from '../../../../../types';
|
||||
|
||||
export interface RuleAlertsSummaryProps {
|
||||
rule: Rule;
|
||||
filteredRuleTypes: string[];
|
||||
onClick: (status?: AlertStatus) => void;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue