Skip to content

Commit

Permalink
fix multi consumer
Browse files Browse the repository at this point in the history
  • Loading branch information
JiaweiWu committed May 23, 2024
1 parent 4560553 commit d174f6a
Show file tree
Hide file tree
Showing 20 changed files with 474 additions and 164 deletions.
26 changes: 25 additions & 1 deletion packages/kbn-alerts-ui-shared/src/rule_form/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,52 @@
* Side Public License, v 1.
*/

import {
ES_QUERY_ID,
OBSERVABILITY_THRESHOLD_RULE_TYPE_ID,
ML_ANOMALY_DETECTION_RULE_TYPE_ID,
RuleCreationValidConsumer,
AlertConsumers,
} from '@kbn/rule-data-utils';
import { RuleFormData } from './types';

export const DEFAULT_RULE_INTERVAL = '1m';

export const ALERTING_FEATURE_ID = 'alerts';

export const GET_DEFAULT_FORM_DATA = ({
ruleTypeId,
name,
consumer,
}: {
ruleTypeId: RuleFormData['ruleTypeId'];
name: RuleFormData['name'];
consumer: RuleFormData['consumer'];
}) => {
return {
tags: [],
params: {},
schedule: {
interval: DEFAULT_RULE_INTERVAL,
},
consumer: 'alerts',
consumer,
ruleTypeId,
name,
};
};

export const MULTI_CONSUMER_RULE_TYPE_IDS = [
OBSERVABILITY_THRESHOLD_RULE_TYPE_ID,
ES_QUERY_ID,
ML_ANOMALY_DETECTION_RULE_TYPE_ID,
];

export const DEFAULT_VALID_CONSUMERS: RuleCreationValidConsumer[] = [
AlertConsumers.LOGS,
AlertConsumers.INFRASTRUCTURE,
'stackAlerts',
'alerts',
];

export const createRuleRoute = '/rule/create/:ruleTypeId' as const;
export const editRuleRoute = '/rule/edit/:id' as const;
75 changes: 40 additions & 35 deletions packages/kbn-alerts-ui-shared/src/rule_form/create_rule_form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,46 +7,57 @@
*/

import React, { useCallback } from 'react';
import { EuiEmptyPrompt, EuiLoadingSpinner, EuiText } from '@elastic/eui';
// import type { RuleCreationValidConsumer } from '@kbn/rule-data-utils';
import { EuiLoadingSpinner } from '@elastic/eui';
import type { RuleCreationValidConsumer } from '@kbn/rule-data-utils';
import type { RuleFormData, RuleFormPlugins } from './types';
import { GET_DEFAULT_FORM_DATA } from './constants';
import { ALERTING_FEATURE_ID, DEFAULT_VALID_CONSUMERS, GET_DEFAULT_FORM_DATA } from './constants';
import { RuleFormStateProvider } from './rule_form_state';
import { useCreateRule } from '../common/hooks';

import { RulePage } from './rule_page';
import { RuleFormHealthCheckError } from './rule_form_health_check_error';
import {
RULE_FORM_RULE_NOT_FOUND_ERROR_TITLE,
RULE_FORM_RULE_NOT_FOUND_ERROR_TEXT,
} from './translations';
import { RuleFormHealthCheckError, RuleFormRuleOrRuleTypeError } from './rule_form_errors';
import { useLoadDependencies } from './hooks/use_load_dependencies';
import { getInitialMultiConsumer } from './utils';
import { RULE_CREATE_SUCCESS_TEXT } from './translations';

export interface CreateRuleFormProps {
ruleTypeId: string;
plugins: RuleFormPlugins;
// formData?: RuleFormData;
// consumer: RuleCreationValidConsumer;
// canChangeTrigger?: boolean;
// hideGrouping?: boolean;
// filteredRuleTypes?: string[];
// validConsumers?: RuleCreationValidConsumer[];
// useRuleProducer?: boolean;
// initialSelectedConsumer?: RuleCreationValidConsumer | null;
consumer?: string;
multiConsumerSelection?: RuleCreationValidConsumer | null;
hideInterval?: boolean;
validConsumers?: RuleCreationValidConsumer[];
filteredRuleTypes?: string[];
useRuleProducer?: boolean;
}

export const CreateRuleForm = (props: CreateRuleFormProps) => {
// const { formData, plugins, ruleTypeModel, ruleType, validConsumers } = props;
const { ruleTypeId, plugins } = props;
const {
ruleTypeId,
plugins,
consumer = ALERTING_FEATURE_ID,
multiConsumerSelection,
validConsumers = DEFAULT_VALID_CONSUMERS,
filteredRuleTypes = [],
} = props;

const { http, docLinks, notification, ruleTypeRegistry } = plugins;
const { toasts } = notification;

const { mutate, isLoading: isSaving } = useCreateRule({ http });
const { mutate, isLoading: isSaving } = useCreateRule({
http,
onSuccess: ({ name }) => {
toasts.addSuccess(RULE_CREATE_SUCCESS_TEXT(name));
},
});

const { isLoading, ruleType, ruleTypeModel, uiConfig, healthCheckError } = useLoadDependencies({
http,
toasts: notification.toasts,
ruleTypeRegistry,
ruleTypeId,
consumer,
validConsumers,
filteredRuleTypes,
});

const onSave = useCallback(
Expand All @@ -61,18 +72,7 @@ export const CreateRuleForm = (props: CreateRuleFormProps) => {
}

if (!ruleType || !ruleTypeModel) {
return (
<EuiEmptyPrompt
color="danger"
iconType="error"
title={<h2>{RULE_FORM_RULE_NOT_FOUND_ERROR_TITLE}</h2>}
body={
<EuiText>
<p>{RULE_FORM_RULE_NOT_FOUND_ERROR_TEXT}</p>
</EuiText>
}
/>
);
return <RuleFormRuleOrRuleTypeError />;
}

if (healthCheckError) {
Expand All @@ -85,17 +85,22 @@ export const CreateRuleForm = (props: CreateRuleFormProps) => {
formData: GET_DEFAULT_FORM_DATA({
ruleTypeId,
name: `${ruleType.name} rule`,
consumer,
}),
plugins,
minimumScheduleInterval: uiConfig?.minimumScheduleInterval,
selectedRuleTypeModel: ruleTypeModel,
selectedRuleType: ruleType,
multiConsumerSelection: getInitialMultiConsumer({
multiConsumerSelection,
validConsumers,
ruleType,
}),
}}
>
<RulePage
canShowConsumerSelection
selectedRuleTypeModel={ruleTypeModel}
selectedRuleType={ruleType}
// validConsumers={validConsumers}
validConsumers={validConsumers}
isSaving={isSaving}
onSave={onSave}
/>
Expand Down
41 changes: 14 additions & 27 deletions packages/kbn-alerts-ui-shared/src/rule_form/edit_rule_form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,15 @@
*/

import React, { useCallback } from 'react';
import { EuiEmptyPrompt, EuiLoadingSpinner, EuiText } from '@elastic/eui';
import { EuiLoadingSpinner } from '@elastic/eui';
import type { RuleFormData, RuleFormPlugins } from './types';
import { RuleFormStateProvider } from './rule_form_state';
import { useUpdateRule } from '../common/hooks';

import { RulePage } from './rule_page';
import { RuleFormHealthCheckError } from './rule_form_health_check_error';
import {
RULE_FORM_RULE_NOT_FOUND_ERROR_TITLE,
RULE_FORM_RULE_NOT_FOUND_ERROR_TEXT,
} from './translations';
import { RuleFormHealthCheckError } from './rule_form_errors/rule_form_health_check_error';
import { useLoadDependencies } from './hooks/use_load_dependencies';
import { RuleFormRuleOrRuleTypeError } from './rule_form_errors';
import { RULE_EDIT_SUCCESS_TEXT } from './translations';

export interface EditRuleFormProps {
id: string;
Expand All @@ -28,8 +25,14 @@ export interface EditRuleFormProps {
export const EditRuleForm = (props: EditRuleFormProps) => {
const { id, plugins } = props;
const { http, notification, docLinks, ruleTypeRegistry } = plugins;
const { toasts } = notification;

const { mutate, isLoading: isSaving } = useUpdateRule({ http });
const { mutate, isLoading: isSaving } = useUpdateRule({
http,
onSuccess: ({ name }) => {
toasts.addSuccess(RULE_EDIT_SUCCESS_TEXT(name));
},
});

const { isLoading, ruleType, ruleTypeModel, uiConfig, healthCheckError, fetchedFormData } =
useLoadDependencies({
Expand All @@ -54,18 +57,7 @@ export const EditRuleForm = (props: EditRuleFormProps) => {
}

if (!ruleType || !ruleTypeModel || !fetchedFormData) {
return (
<EuiEmptyPrompt
color="danger"
iconType="error"
title={<h2>{RULE_FORM_RULE_NOT_FOUND_ERROR_TITLE}</h2>}
body={
<EuiText>
<p>{RULE_FORM_RULE_NOT_FOUND_ERROR_TEXT}</p>
</EuiText>
}
/>
);
return <RuleFormRuleOrRuleTypeError />;
}

if (healthCheckError) {
Expand All @@ -80,16 +72,11 @@ export const EditRuleForm = (props: EditRuleFormProps) => {
id,
plugins,
minimumScheduleInterval: uiConfig?.minimumScheduleInterval,
selectedRuleType: ruleType,
selectedRuleTypeModel: ruleTypeModel,
}}
>
<RulePage
isEdit
selectedRuleTypeModel={ruleTypeModel}
selectedRuleType={ruleType}
isSaving={isSaving}
onSave={onSave}
/>
<RulePage isEdit isSaving={isSaving} onSave={onSave} />
</RuleFormStateProvider>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import { HttpStart } from '@kbn/core-http-browser';
import type { ToastsStart } from '@kbn/core-notifications-browser';
import { RuleCreationValidConsumer } from '@kbn/rule-data-utils';
import { useMemo } from 'react';
import {
useHealthCheck,
Expand All @@ -16,17 +17,30 @@ import {
useResolveRule,
} from '../../common/hooks';
import { RuleTypeRegistryContract } from '../types';
import { getAvailableRuleTypes } from '../utils';

export interface UseLoadDependencies {
http: HttpStart;
toasts: ToastsStart;
ruleTypeRegistry: RuleTypeRegistryContract;
consumer?: string;
id?: string;
ruleTypeId?: string;
validConsumers?: RuleCreationValidConsumer[];
filteredRuleTypes?: string[];
}

export const useLoadDependencies = (props: UseLoadDependencies) => {
const { http, toasts, ruleTypeRegistry, id, ruleTypeId } = props;
const {
http,
toasts,
ruleTypeRegistry,
consumer,
validConsumers,
id,
ruleTypeId,
filteredRuleTypes = [],
} = props;

const { data: uiConfig, isLoading: isLoadingUiConfig } = useLoadUiConfig({ http });

Expand All @@ -39,28 +53,36 @@ export const useLoadDependencies = (props: UseLoadDependencies) => {
} = useLoadRuleTypesQuery({
http,
toasts,
filteredRuleTypes,
});

const computedRuleTypeId = useMemo(() => {
return fetchedFormData?.ruleTypeId || ruleTypeId;
}, [fetchedFormData, ruleTypeId]);

const ruleTypes = [...ruleTypeIndex.values()];
const authorizedRuleTypeItems = useMemo(() => {
const computedConsumer = consumer || fetchedFormData?.consumer;
if (!computedConsumer) {
return [];
}
return getAvailableRuleTypes({
consumer: computedConsumer,
ruleTypes: [...ruleTypeIndex.values()],
ruleTypeRegistry,
validConsumers,
});
}, [consumer, ruleTypeIndex, ruleTypeRegistry, validConsumers, fetchedFormData]);

const ruleType = ruleTypes.find((rt) => rt.id === computedRuleTypeId);
const [ruleType, ruleTypeModel] = useMemo(() => {
const item = authorizedRuleTypeItems.find(({ ruleType: rt }) => {
return rt.id === computedRuleTypeId;
});

const ruleTypeModel = useMemo(() => {
let model;
try {
model = ruleTypeRegistry.get(computedRuleTypeId!);
} catch (e) {
return null;
}
return model;
}, [ruleTypeRegistry, computedRuleTypeId]);
return [item?.ruleType, item?.ruleTypeModel];
}, [authorizedRuleTypeItems, computedRuleTypeId]);

const isLoading = useMemo(() => {
if (typeof id === 'undefined') {
if (id === undefined) {
return isLoadingUiConfig || isLoadingHealthCheck || isLoadingRuleTypes;
}
return isLoadingUiConfig || isLoadingHealthCheck || isLoadingRule || isLoadingRuleTypes;
Expand Down
Loading

0 comments on commit d174f6a

Please sign in to comment.