[8.12] [RAM] Allow initialization of the scope form the rule list component (#173795) (#173877)

# Backport

This will backport the following commits from `main` to `8.12`:
- [[RAM] Allow initialization of the scope form the rule list component
(#173795)](https://github.com/elastic/kibana/pull/173795)

<!--- Backport version: 8.9.7 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Xavier
Mouligneau","email":"xavier.mouligneau@elastic.co"},"sourceCommit":{"committedDate":"2023-12-21T20:20:59Z","message":"[RAM]
Allow initialization of the scope form the rule list component
(#173795)\n\n## Summary\r\n\r\nFIx _>
https://github.com/elastic/kibana/issues/172785\r\n\r\n\r\n###
Checklist\r\n\r\n- [x] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common
scenarios","sha":"833eebf6107b37ac1fc505b0b619587851479d70","branchLabelMapping":{"^v8.13.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["bug","release_note:skip","impact:high","Team:ResponseOps","v8.12.0","Team:obs-ux-management","v8.13.0"],"number":173795,"url":"https://github.com/elastic/kibana/pull/173795","mergeCommit":{"message":"[RAM]
Allow initialization of the scope form the rule list component
(#173795)\n\n## Summary\r\n\r\nFIx _>
https://github.com/elastic/kibana/issues/172785\r\n\r\n\r\n###
Checklist\r\n\r\n- [x] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common
scenarios","sha":"833eebf6107b37ac1fc505b0b619587851479d70"}},"sourceBranch":"main","suggestedTargetBranches":["8.12"],"targetPullRequestStates":[{"branch":"8.12","label":"v8.12.0","labelRegex":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v8.13.0","labelRegex":"^v8.13.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/173795","number":173795,"mergeCommit":{"message":"[RAM]
Allow initialization of the scope form the rule list component
(#173795)\n\n## Summary\r\n\r\nFIx _>
https://github.com/elastic/kibana/issues/172785\r\n\r\n\r\n###
Checklist\r\n\r\n- [x] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common
scenarios","sha":"833eebf6107b37ac1fc505b0b619587851479d70"}}]}]
BACKPORT-->

Co-authored-by: Xavier Mouligneau <xavier.mouligneau@elastic.co>
This commit is contained in:
Kibana Machine 2023-12-21 16:32:18 -05:00 committed by GitHub
parent 2bef2a5152
commit 4e7566d534
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 91 additions and 6 deletions

View file

@ -9,6 +9,7 @@ import React, { useState } from 'react';
import { useHistory } from 'react-router-dom';
import { createKbnUrlStateStorage } from '@kbn/kibana-utils-plugin/public';
import { RuleStatus } from '@kbn/triggers-actions-ui-plugin/public';
import { AlertConsumers } from '@kbn/rule-data-utils';
import { useKibana } from '../../utils/kibana_react';
import { useGetFilteredRuleTypes } from '../../hooks/use_get_filtered_rule_types';
import { observabilityAlertFeatureIds } from '../../../common/constants';
@ -97,6 +98,7 @@ export function RulesTab({ setRefresh, stateRefresh }: RulesTabProps) {
onSearchFilterChange={handleSearchFilterChange}
onStatusFilterChange={handleStatusFilterChange}
onTypeFilterChange={handleTypeFilterChange}
initialSelectedConsumer={AlertConsumers.LOGS}
/>
);
}

View file

@ -315,6 +315,7 @@ const RuleAdd = ({
onChangeMetaData={onChangeMetaData}
setConsumer={setSelectedConsumer}
useRuleProducer={useRuleProducer}
initialSelectedConsumer={initialSelectedConsumer}
/>
</EuiFlyoutBody>
<RuleAddFooter

View file

@ -157,6 +157,7 @@ interface RuleFormProps<MetaData = Record<string, any>> {
validConsumers?: RuleCreationValidConsumer[];
onChangeMetaData: (metadata: MetaData) => void;
useRuleProducer?: boolean;
initialSelectedConsumer?: RuleCreationValidConsumer | null;
}
const EMPTY_ARRAY: string[] = [];
@ -183,6 +184,7 @@ export const RuleForm = ({
validConsumers,
onChangeMetaData,
useRuleProducer,
initialSelectedConsumer,
}: RuleFormProps) => {
const {
notifications: { toasts },
@ -818,6 +820,7 @@ export const RuleForm = ({
onChange={setConsumer}
errors={errors}
selectedConsumer={selectedConsumer}
initialSelectedConsumer={initialSelectedConsumer}
/>
</EuiFlexItem>
</>

View file

@ -37,6 +37,71 @@ describe('RuleFormConsumerSelectionModal', () => {
expect(screen.getByText('Stack Rules')).toBeInTheDocument();
});
it('should be able to initialize to the prop initialSelectedConsumer', () => {
render(
<RuleFormConsumerSelection
selectedConsumer={null}
consumers={mockConsumers}
onChange={mockOnChange}
initialSelectedConsumer={'logs'}
errors={{}}
/>
);
expect(mockOnChange).toHaveBeenLastCalledWith('logs');
});
it('should NOT initialize if initialSelectedConsumer is equal to null', () => {
render(
<RuleFormConsumerSelection
selectedConsumer={null}
consumers={mockConsumers}
onChange={mockOnChange}
initialSelectedConsumer={null}
errors={{}}
/>
);
expect(mockOnChange).not.toBeCalled();
});
it('should initialize to the first valid consumers if initialSelectedConsumer is not valid', () => {
render(
<RuleFormConsumerSelection
selectedConsumer={null}
consumers={['logs', 'infrastructure']}
onChange={mockOnChange}
initialSelectedConsumer={'apm' as RuleCreationValidConsumer}
errors={{}}
/>
);
expect(mockOnChange).toHaveBeenLastCalledWith('logs');
});
it('should initialize to stackAlerts if the initialSelectedConsumer is not a valid and consumers has stackAlerts', () => {
render(
<RuleFormConsumerSelection
selectedConsumer={null}
consumers={['infrastructure', 'stackAlerts']}
onChange={mockOnChange}
initialSelectedConsumer={'logs'}
errors={{}}
/>
);
expect(mockOnChange).toHaveBeenLastCalledWith('stackAlerts');
});
it('should initialize to stackAlerts if the initialSelectedConsumer is undefined and consumers has stackAlerts', () => {
render(
<RuleFormConsumerSelection
selectedConsumer={null}
consumers={['infrastructure', 'stackAlerts']}
onChange={mockOnChange}
initialSelectedConsumer={undefined}
errors={{}}
/>
);
expect(mockOnChange).toHaveBeenLastCalledWith('stackAlerts');
});
it('should be able to select infrastructure and call onChange', () => {
render(
<RuleFormConsumerSelection

View file

@ -67,13 +67,19 @@ export interface RuleFormConsumerSelectionProps {
consumers: RuleCreationValidConsumer[];
onChange: (consumer: RuleCreationValidConsumer | null) => void;
errors: IErrorObject;
selectedConsumer: RuleCreationValidConsumer | null | undefined;
selectedConsumer?: RuleCreationValidConsumer | null;
/* FUTURE ENGINEER
* if this prop is set to null then we wont initialize the value and the user will have to set it
* if this prop is set to a valid consumers then we will set it up to what was passed
* if this prop is not valid or undefined but the valid consumers has stackAlerts then we will default it to stackAlerts
*/
initialSelectedConsumer?: RuleCreationValidConsumer | null;
}
const SINGLE_SELECTION = { asPlainText: true };
export const RuleFormConsumerSelection = (props: RuleFormConsumerSelectionProps) => {
const { consumers, errors, onChange, selectedConsumer } = props;
const { consumers, errors, onChange, selectedConsumer, initialSelectedConsumer } = props;
const isInvalid = errors?.consumer?.length > 0;
const handleOnChange = useCallback(
(selected: Array<EuiComboBoxOptionOption<RuleCreationValidConsumer>>) => {
@ -123,13 +129,18 @@ export const RuleFormConsumerSelection = (props: RuleFormConsumerSelectionProps)
}, [consumers]);
useEffect(() => {
// At initialization, select Stack Alerts, or the first value
// At initialization, select initialSelectedConsumer or the first value
if (!validatedSelectedConsumer) {
if (consumers.includes(STACK_ALERTS_FEATURE_ID)) {
if (initialSelectedConsumer === null) {
return;
} else if (initialSelectedConsumer && consumers.includes(initialSelectedConsumer)) {
onChange(initialSelectedConsumer);
return;
} else if (consumers.includes(STACK_ALERTS_FEATURE_ID)) {
onChange(STACK_ALERTS_FEATURE_ID);
return;
}
onChange(consumers[0] as RuleCreationValidConsumer);
onChange(consumers[0]);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

View file

@ -41,6 +41,7 @@ import {
RuleLastRunOutcomeValues,
} from '@kbn/alerting-plugin/common';
import {
RuleCreationValidConsumer,
ruleDetailsRoute as commonRuleDetailsRoute,
STACK_ALERTS_FEATURE_ID,
} from '@kbn/rule-data-utils';
@ -136,6 +137,7 @@ export interface RulesListProps {
onTypeFilterChange?: (type: string[]) => void;
onRefresh?: (refresh: Date) => void;
setHeaderActions?: (components?: React.ReactNode[]) => void;
initialSelectedConsumer?: RuleCreationValidConsumer | null;
}
export const percentileFields = {
@ -176,6 +178,7 @@ export const RulesList = ({
onTypeFilterChange,
onRefresh,
setHeaderActions,
initialSelectedConsumer = STACK_ALERTS_FEATURE_ID,
}: RulesListProps) => {
const history = useHistory();
const kibanaServices = useKibana().services;
@ -1007,7 +1010,7 @@ export const RulesList = ({
ruleTypeRegistry={ruleTypeRegistry}
ruleTypeIndex={ruleTypesState.data}
onSave={refreshRules}
initialSelectedConsumer={STACK_ALERTS_FEATURE_ID}
initialSelectedConsumer={initialSelectedConsumer}
/>
</Suspense>
)}