mirror of
https://github.com/elastic/kibana.git
synced 2025-06-27 10:40:07 -04:00
Single list of rule types in observability without grouping (#166772)
Closes #166136
## Summary
This PR removes the groups in the rules list in the observability.
|With disabled rule|Without disabled rule|
|---|---|
||
## 🧪 How to test
- Check the rule type list in observability > rules page
- Check the filter works as before
This commit is contained in:
parent
c1aabee73f
commit
566e086963
14 changed files with 268 additions and 116 deletions
|
@ -245,7 +245,7 @@ export const RULE_TYPES_CONFIG: Record<
|
|||
},
|
||||
[ApmRuleType.Anomaly]: {
|
||||
name: i18n.translate('xpack.apm.anomalyAlert.name', {
|
||||
defaultMessage: 'Anomaly',
|
||||
defaultMessage: 'APM Anomaly',
|
||||
}),
|
||||
actionGroups: [THRESHOLD_MET_GROUP],
|
||||
defaultActionGroupId: THRESHOLD_MET_GROUP_ID,
|
||||
|
|
|
@ -55,6 +55,7 @@ export function registerApmRuleTypes(
|
|||
}),
|
||||
requiresAppContext: false,
|
||||
defaultActionMessage: errorCountMessage,
|
||||
priority: 80,
|
||||
});
|
||||
|
||||
observabilityRuleTypeRegistry.register({
|
||||
|
@ -92,6 +93,7 @@ export function registerApmRuleTypes(
|
|||
),
|
||||
requiresAppContext: false,
|
||||
defaultActionMessage: transactionDurationMessage,
|
||||
priority: 60,
|
||||
});
|
||||
|
||||
observabilityRuleTypeRegistry.register({
|
||||
|
@ -124,6 +126,7 @@ export function registerApmRuleTypes(
|
|||
}),
|
||||
requiresAppContext: false,
|
||||
defaultActionMessage: transactionErrorRateMessage,
|
||||
priority: 70,
|
||||
});
|
||||
|
||||
observabilityRuleTypeRegistry.register({
|
||||
|
@ -153,5 +156,6 @@ export function registerApmRuleTypes(
|
|||
}),
|
||||
requiresAppContext: false,
|
||||
defaultActionMessage: anomalyMessage,
|
||||
priority: 90,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -66,5 +66,6 @@ export function createInventoryMetricRuleType(): ObservabilityRuleTypeModel<Inve
|
|||
defaultRecoveryMessage: inventoryDefaultRecoveryMessage,
|
||||
requiresAppContext: false,
|
||||
format: formatReason,
|
||||
priority: 20,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -72,5 +72,6 @@ export function createLogThresholdRuleType(
|
|||
defaultRecoveryMessage: logThresholdDefaultRecoveryMessage,
|
||||
requiresAppContext: false,
|
||||
format: createRuleFormatter(logsLocator),
|
||||
priority: 30,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -67,5 +67,6 @@ export function createMetricThresholdRuleType(): ObservabilityRuleTypeModel<Metr
|
|||
requiresAppContext: false,
|
||||
format: formatReason,
|
||||
alertDetailsAppSection: lazy(() => import('./components/alert_details_app_section')),
|
||||
priority: 10,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
import React from 'react';
|
||||
import { render } from '@testing-library/react';
|
||||
import { CoreStart } from '@kbn/core/public';
|
||||
import { __IntlProvider as IntlProvider } from '@kbn/i18n-react';
|
||||
import { ObservabilityPublicPluginsStart } from '../../plugin';
|
||||
import { RulesPage } from './rules';
|
||||
import { kibanaStartMock } from '../../utils/kibana_react.mock';
|
||||
|
@ -104,7 +105,11 @@ describe('RulesPage with all capabilities', () => {
|
|||
ruleTypeIndex,
|
||||
});
|
||||
|
||||
return render(<RulesPage />);
|
||||
return render(
|
||||
<IntlProvider locale="en">
|
||||
<RulesPage />
|
||||
</IntlProvider>
|
||||
);
|
||||
}
|
||||
|
||||
it('should render a page template', async () => {
|
||||
|
|
|
@ -150,7 +150,8 @@ export function RulesPage({ activeTab = RULES_TAB_NAME }: RulesPageProps) {
|
|||
setRefresh(new Date());
|
||||
return Promise.resolve();
|
||||
}}
|
||||
useRuleProducer={true}
|
||||
hideGrouping
|
||||
useRuleProducer
|
||||
/>
|
||||
)}
|
||||
</ObservabilityPageTemplate>
|
||||
|
|
|
@ -21,21 +21,27 @@ export type ObservabilityRuleTypeFormatter = (options: {
|
|||
export interface ObservabilityRuleTypeModel<Params extends RuleTypeParams = RuleTypeParams>
|
||||
extends RuleTypeModel<Params> {
|
||||
format: ObservabilityRuleTypeFormatter;
|
||||
priority?: number;
|
||||
}
|
||||
|
||||
export function createObservabilityRuleTypeRegistry(ruleTypeRegistry: RuleTypeRegistryContract) {
|
||||
const formatters: Array<{ typeId: string; fn: ObservabilityRuleTypeFormatter }> = [];
|
||||
const formatters: Array<{
|
||||
typeId: string;
|
||||
priority: number;
|
||||
fn: ObservabilityRuleTypeFormatter;
|
||||
}> = [];
|
||||
|
||||
return {
|
||||
register: (type: ObservabilityRuleTypeModel<any>) => {
|
||||
const { format, ...rest } = type;
|
||||
formatters.push({ typeId: type.id, fn: format });
|
||||
const { format, priority, ...rest } = type;
|
||||
formatters.push({ typeId: type.id, priority: priority || 0, fn: format });
|
||||
ruleTypeRegistry.register(rest);
|
||||
},
|
||||
getFormatter: (typeId: string) => {
|
||||
return formatters.find((formatter) => formatter.typeId === typeId)?.fn;
|
||||
},
|
||||
list: () => formatters.map((formatter) => formatter.typeId),
|
||||
list: () =>
|
||||
formatters.sort((a, b) => b.priority - a.priority).map((formatter) => formatter.typeId),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -97,6 +97,7 @@ export const registerObservabilityRuleTypes = (
|
|||
requiresAppContext: false,
|
||||
defaultActionMessage: sloBurnRateDefaultActionMessage,
|
||||
defaultRecoveryMessage: sloBurnRateDefaultRecoveryMessage,
|
||||
priority: 100,
|
||||
});
|
||||
|
||||
if (config.unsafe.thresholdRule.enabled) {
|
||||
|
@ -124,6 +125,7 @@ export const registerObservabilityRuleTypes = (
|
|||
alertDetailsAppSection: lazy(
|
||||
() => import('../components/custom_threshold/components/alert_details_app_section')
|
||||
),
|
||||
priority: 110,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
|
@ -6,21 +6,16 @@
|
|||
*/
|
||||
|
||||
import { RuleTypeModel } from '../../types';
|
||||
import { ruleTypeGroupCompare, ruleTypeCompare } from './rule_type_compare';
|
||||
import {
|
||||
RuleTypeGroup,
|
||||
ruleTypeGroupCompare,
|
||||
ruleTypeCompare,
|
||||
ruleTypeUngroupedCompare,
|
||||
} from './rule_type_compare';
|
||||
import { IsEnabledResult, IsDisabledResult } from './check_rule_type_enabled';
|
||||
|
||||
test('should sort groups by containing enabled rule types first and then by name', async () => {
|
||||
const ruleTypes: Array<
|
||||
[
|
||||
string,
|
||||
Array<{
|
||||
id: string;
|
||||
name: string;
|
||||
checkEnabledResult: IsEnabledResult | IsDisabledResult;
|
||||
ruleTypeItem: RuleTypeModel;
|
||||
}>
|
||||
]
|
||||
> = [
|
||||
const ruleTypes: RuleTypeGroup[] = [
|
||||
[
|
||||
'abc',
|
||||
[
|
||||
|
@ -113,6 +108,102 @@ test('should sort groups by containing enabled rule types first and then by name
|
|||
expect(result[2]).toEqual(ruleTypes[0]);
|
||||
});
|
||||
|
||||
describe('ruleTypeUngroupedCompare', () => {
|
||||
test('should maintain the order of rules', async () => {
|
||||
const ruleTypes: RuleTypeGroup[] = [
|
||||
[
|
||||
'abc',
|
||||
[
|
||||
{
|
||||
id: '1',
|
||||
name: 'test2',
|
||||
checkEnabledResult: { isEnabled: false, message: 'gold license' },
|
||||
ruleTypeItem: {
|
||||
id: 'ruleTypeItemId1',
|
||||
iconClass: 'test',
|
||||
description: 'Alert when testing',
|
||||
documentationUrl: 'https://localhost.local/docs',
|
||||
validate: () => {
|
||||
return { errors: {} };
|
||||
},
|
||||
ruleParamsExpression: () => null,
|
||||
requiresAppContext: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
[
|
||||
'bcd',
|
||||
[
|
||||
{
|
||||
id: '2',
|
||||
name: 'abc',
|
||||
checkEnabledResult: { isEnabled: false, message: 'platinum license' },
|
||||
ruleTypeItem: {
|
||||
id: 'ruleTypeItemId2',
|
||||
iconClass: 'test',
|
||||
description: 'Alert when testing',
|
||||
documentationUrl: 'https://localhost.local/docs',
|
||||
validate: () => {
|
||||
return { errors: {} };
|
||||
},
|
||||
ruleParamsExpression: () => null,
|
||||
requiresAppContext: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
name: 'cdf',
|
||||
checkEnabledResult: { isEnabled: true },
|
||||
ruleTypeItem: {
|
||||
id: 'ruleTypeItemId3',
|
||||
iconClass: 'test',
|
||||
description: 'Alert when testing',
|
||||
documentationUrl: 'https://localhost.local/docs',
|
||||
validate: () => {
|
||||
return { errors: {} };
|
||||
},
|
||||
ruleParamsExpression: () => null,
|
||||
requiresAppContext: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
[
|
||||
'cde',
|
||||
[
|
||||
{
|
||||
id: '4',
|
||||
name: 'cde',
|
||||
checkEnabledResult: { isEnabled: true },
|
||||
ruleTypeItem: {
|
||||
id: 'ruleTypeItemId4',
|
||||
iconClass: 'test',
|
||||
description: 'Alert when testing',
|
||||
documentationUrl: 'https://localhost.local/docs',
|
||||
validate: () => {
|
||||
return { errors: {} };
|
||||
},
|
||||
ruleParamsExpression: () => null,
|
||||
requiresAppContext: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
const ruleTypesOrder = ['4', '1', '2', '3'];
|
||||
|
||||
const result = [...ruleTypes].sort((left, right) =>
|
||||
ruleTypeUngroupedCompare(left, right, ruleTypesOrder)
|
||||
);
|
||||
|
||||
expect(result[0]).toEqual(ruleTypes[2]);
|
||||
expect(result[1]).toEqual(ruleTypes[1]);
|
||||
expect(result[2]).toEqual(ruleTypes[0]);
|
||||
});
|
||||
});
|
||||
|
||||
test('should sort rule types by enabled first and then by name', async () => {
|
||||
const ruleTypes: Array<{
|
||||
id: string;
|
||||
|
|
|
@ -8,25 +8,19 @@
|
|||
import { RuleTypeModel } from '../../types';
|
||||
import { IsEnabledResult, IsDisabledResult } from './check_rule_type_enabled';
|
||||
|
||||
export type RuleTypeGroup = [
|
||||
string,
|
||||
Array<{
|
||||
id: string;
|
||||
name: string;
|
||||
checkEnabledResult: IsEnabledResult | IsDisabledResult;
|
||||
ruleTypeItem: RuleTypeModel;
|
||||
}>
|
||||
];
|
||||
|
||||
export function ruleTypeGroupCompare(
|
||||
left: [
|
||||
string,
|
||||
Array<{
|
||||
id: string;
|
||||
name: string;
|
||||
checkEnabledResult: IsEnabledResult | IsDisabledResult;
|
||||
ruleTypeItem: RuleTypeModel;
|
||||
}>
|
||||
],
|
||||
right: [
|
||||
string,
|
||||
Array<{
|
||||
id: string;
|
||||
name: string;
|
||||
checkEnabledResult: IsEnabledResult | IsDisabledResult;
|
||||
ruleTypeItem: RuleTypeModel;
|
||||
}>
|
||||
],
|
||||
left: RuleTypeGroup,
|
||||
right: RuleTypeGroup,
|
||||
groupNames: Map<string, string> | undefined
|
||||
) {
|
||||
const groupNameA = left[0];
|
||||
|
@ -54,6 +48,35 @@ export function ruleTypeGroupCompare(
|
|||
: groupNameA.localeCompare(groupNameB);
|
||||
}
|
||||
|
||||
export function ruleTypeUngroupedCompare(
|
||||
left: RuleTypeGroup,
|
||||
right: RuleTypeGroup,
|
||||
ruleTypes?: string[]
|
||||
) {
|
||||
const leftRuleTypesList = left[1];
|
||||
const rightRuleTypesList = right[1];
|
||||
|
||||
const hasEnabledRuleTypeInListLeft =
|
||||
leftRuleTypesList.find((ruleTypeItem) => ruleTypeItem.checkEnabledResult.isEnabled) !==
|
||||
undefined;
|
||||
|
||||
const hasEnabledRuleTypeInListRight =
|
||||
rightRuleTypesList.find((ruleTypeItem) => ruleTypeItem.checkEnabledResult.isEnabled) !==
|
||||
undefined;
|
||||
|
||||
if (hasEnabledRuleTypeInListLeft && !hasEnabledRuleTypeInListRight) {
|
||||
return -1;
|
||||
}
|
||||
if (!hasEnabledRuleTypeInListLeft && hasEnabledRuleTypeInListRight) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return ruleTypes
|
||||
? ruleTypes.findIndex((frtA) => leftRuleTypesList.some((aRuleType) => aRuleType.id === frtA)) -
|
||||
ruleTypes.findIndex((frtB) => rightRuleTypesList.some((bRuleType) => bRuleType.id === frtB))
|
||||
: 0;
|
||||
}
|
||||
|
||||
export function ruleTypeCompare(
|
||||
a: {
|
||||
id: string;
|
||||
|
|
|
@ -49,6 +49,7 @@ const RuleAdd = ({
|
|||
initialValues,
|
||||
reloadRules,
|
||||
onSave,
|
||||
hideGrouping,
|
||||
hideInterval,
|
||||
metadata: initialMetadata,
|
||||
filteredRuleTypes,
|
||||
|
@ -286,6 +287,7 @@ const RuleAdd = ({
|
|||
ruleTypeRegistry={ruleTypeRegistry}
|
||||
metadata={metadata}
|
||||
filteredRuleTypes={filteredRuleTypes}
|
||||
hideGrouping={hideGrouping}
|
||||
hideInterval={hideInterval}
|
||||
onChangeMetaData={onChangeMetaData}
|
||||
setConsumer={setSelectedConsumer}
|
||||
|
|
|
@ -72,7 +72,11 @@ import { useKibana } from '../../../common/lib/kibana';
|
|||
import { recoveredActionGroupMessage, summaryMessage } from '../../constants';
|
||||
import { IsEnabledResult, IsDisabledResult } from '../../lib/check_rule_type_enabled';
|
||||
import { checkRuleTypeEnabled } from '../../lib/check_rule_type_enabled';
|
||||
import { ruleTypeCompare, ruleTypeGroupCompare } from '../../lib/rule_type_compare';
|
||||
import {
|
||||
ruleTypeCompare,
|
||||
ruleTypeGroupCompare,
|
||||
ruleTypeUngroupedCompare,
|
||||
} from '../../lib/rule_type_compare';
|
||||
import { VIEW_LICENSE_OPTIONS_LINK } from '../../../common/constants';
|
||||
import { MULTI_CONSUMER_RULE_TYPE_IDS } from '../../constants';
|
||||
import { SectionLoading } from '../../components/section_loading';
|
||||
|
@ -137,6 +141,7 @@ interface RuleFormProps<MetaData = Record<string, any>> {
|
|||
setConsumer?: (consumer: RuleCreationValidConsumer | null) => void;
|
||||
metadata?: MetaData;
|
||||
filteredRuleTypes?: string[];
|
||||
hideGrouping?: boolean;
|
||||
hideInterval?: boolean;
|
||||
connectorFeatureId?: string;
|
||||
validConsumers?: RuleCreationValidConsumer[];
|
||||
|
@ -159,6 +164,7 @@ export const RuleForm = ({
|
|||
actionTypeRegistry,
|
||||
metadata,
|
||||
filteredRuleTypes: ruleTypeToFilter,
|
||||
hideGrouping = false,
|
||||
hideInterval,
|
||||
connectorFeatureId = AlertingConnectorFeatureId,
|
||||
validConsumers,
|
||||
|
@ -457,85 +463,93 @@ export const RuleForm = ({
|
|||
{}
|
||||
);
|
||||
|
||||
const ruleTypeNodes = Object.entries(ruleTypesByProducer)
|
||||
.sort((a, b) => ruleTypeGroupCompare(a, b, solutions))
|
||||
.map(([solution, items], groupIndex) => (
|
||||
<Fragment key={`group${groupIndex}`}>
|
||||
<EuiFlexGroup
|
||||
gutterSize="none"
|
||||
alignItems="center"
|
||||
className="triggersActionsUI__ruleTypeNodeHeading"
|
||||
>
|
||||
<EuiFlexItem>
|
||||
<EuiTitle
|
||||
data-test-subj={`ruleType${groupIndex}Group`}
|
||||
size="xxxs"
|
||||
textTransform="uppercase"
|
||||
>
|
||||
<EuiTextColor color="subdued">
|
||||
{(kibanaFeatures
|
||||
? getProducerFeatureName(solution, kibanaFeatures)
|
||||
: capitalize(solution)) ?? capitalize(solution)}
|
||||
</EuiTextColor>
|
||||
</EuiTitle>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiNotificationBadge color="subdued">{items.length}</EuiNotificationBadge>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<EuiHorizontalRule size="full" margin="xs" />
|
||||
<EuiListGroup flush={true} gutterSize="m" size="m" maxWidth={false}>
|
||||
{items
|
||||
.sort((a, b) => ruleTypeCompare(a, b))
|
||||
.map((item, index) => {
|
||||
const ruleTypeListItemHtml = (
|
||||
<span>
|
||||
<strong>{item.name}</strong>
|
||||
<EuiText color="subdued" size="s">
|
||||
<p>{item.ruleTypeItem.description}</p>
|
||||
</EuiText>
|
||||
</span>
|
||||
);
|
||||
return (
|
||||
<EuiListGroupItem
|
||||
wrapText
|
||||
key={index}
|
||||
data-test-subj={`${item.id}-SelectOption`}
|
||||
color="primary"
|
||||
label={
|
||||
item.checkEnabledResult.isEnabled ? (
|
||||
ruleTypeListItemHtml
|
||||
) : (
|
||||
<EuiToolTip
|
||||
position="top"
|
||||
data-test-subj={`${item.id}-disabledTooltip`}
|
||||
content={item.checkEnabledResult.message}
|
||||
>
|
||||
{ruleTypeListItemHtml}
|
||||
</EuiToolTip>
|
||||
)
|
||||
}
|
||||
isDisabled={!item.checkEnabledResult.isEnabled}
|
||||
onClick={() => {
|
||||
setRuleProperty('ruleTypeId', item.id);
|
||||
setRuleTypeModel(item.ruleTypeItem);
|
||||
setActions([]);
|
||||
setRuleProperty('params', {});
|
||||
if (ruleTypeIndex && ruleTypeIndex.has(item.id)) {
|
||||
setDefaultActionGroupId(ruleTypeIndex.get(item.id)!.defaultActionGroupId);
|
||||
}
|
||||
const sortedRuleTypeNodes = hideGrouping
|
||||
? Object.entries(ruleTypesByProducer).sort((a, b) =>
|
||||
ruleTypeUngroupedCompare(a, b, ruleTypeToFilter)
|
||||
)
|
||||
: Object.entries(ruleTypesByProducer).sort((a, b) => ruleTypeGroupCompare(a, b, solutions));
|
||||
|
||||
if (useRuleProducer && !MULTI_CONSUMER_RULE_TYPE_IDS.includes(item.id)) {
|
||||
setConsumer(solution as RuleCreationValidConsumer);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</EuiListGroup>
|
||||
<EuiSpacer />
|
||||
</Fragment>
|
||||
));
|
||||
const ruleTypeNodes = sortedRuleTypeNodes.map(([solution, items], groupIndex) => (
|
||||
<Fragment key={`group${groupIndex}`}>
|
||||
{!hideGrouping && (
|
||||
<>
|
||||
<EuiFlexGroup
|
||||
gutterSize="none"
|
||||
alignItems="center"
|
||||
className="triggersActionsUI__ruleTypeNodeHeading"
|
||||
>
|
||||
<EuiFlexItem>
|
||||
<EuiTitle
|
||||
data-test-subj={`ruleType${groupIndex}Group`}
|
||||
size="xxxs"
|
||||
textTransform="uppercase"
|
||||
>
|
||||
<EuiTextColor color="subdued">
|
||||
{(kibanaFeatures
|
||||
? getProducerFeatureName(solution, kibanaFeatures)
|
||||
: capitalize(solution)) ?? capitalize(solution)}
|
||||
</EuiTextColor>
|
||||
</EuiTitle>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiNotificationBadge color="subdued">{items.length}</EuiNotificationBadge>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<EuiHorizontalRule size="full" margin="xs" />
|
||||
</>
|
||||
)}
|
||||
<EuiListGroup flush={true} gutterSize="m" size="m" maxWidth={false}>
|
||||
{items
|
||||
.sort((a, b) => ruleTypeCompare(a, b))
|
||||
.map((item, index) => {
|
||||
const ruleTypeListItemHtml = (
|
||||
<span>
|
||||
<strong>{item.name}</strong>
|
||||
<EuiText color="subdued" size="s">
|
||||
<p>{item.ruleTypeItem.description}</p>
|
||||
</EuiText>
|
||||
</span>
|
||||
);
|
||||
return (
|
||||
<EuiListGroupItem
|
||||
wrapText
|
||||
key={index}
|
||||
data-test-subj={`${item.id}-SelectOption`}
|
||||
color="primary"
|
||||
label={
|
||||
item.checkEnabledResult.isEnabled ? (
|
||||
ruleTypeListItemHtml
|
||||
) : (
|
||||
<EuiToolTip
|
||||
position="top"
|
||||
data-test-subj={`${item.id}-disabledTooltip`}
|
||||
content={item.checkEnabledResult.message}
|
||||
>
|
||||
{ruleTypeListItemHtml}
|
||||
</EuiToolTip>
|
||||
)
|
||||
}
|
||||
isDisabled={!item.checkEnabledResult.isEnabled}
|
||||
onClick={() => {
|
||||
setRuleProperty('ruleTypeId', item.id);
|
||||
setRuleTypeModel(item.ruleTypeItem);
|
||||
setActions([]);
|
||||
setRuleProperty('params', {});
|
||||
if (ruleTypeIndex && ruleTypeIndex.has(item.id)) {
|
||||
setDefaultActionGroupId(ruleTypeIndex.get(item.id)!.defaultActionGroupId);
|
||||
}
|
||||
|
||||
if (useRuleProducer && !MULTI_CONSUMER_RULE_TYPE_IDS.includes(item.id)) {
|
||||
setConsumer(solution as RuleCreationValidConsumer);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</EuiListGroup>
|
||||
<EuiSpacer size="m" />
|
||||
</Fragment>
|
||||
));
|
||||
|
||||
const labelForRuleChecked = [
|
||||
i18n.translate('xpack.triggersActionsUI.sections.ruleForm.checkFieldLabel', {
|
||||
|
|
|
@ -453,6 +453,7 @@ export interface RuleAddProps<MetaData = Record<string, any>> {
|
|||
initialValues?: Partial<Rule>;
|
||||
/** @deprecated use `onSave` as a callback after an alert is saved*/
|
||||
reloadRules?: () => Promise<void>;
|
||||
hideGrouping?: boolean;
|
||||
hideInterval?: boolean;
|
||||
onSave?: (metadata?: MetaData) => Promise<void>;
|
||||
metadata?: MetaData;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue