diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/comparison_side/comparison_side.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/comparison_side/comparison_side.tsx index 2592469beaabb..e5ec6a8dfc540 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/comparison_side/comparison_side.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/comparison_side/comparison_side.tsx @@ -24,7 +24,7 @@ import * as i18n from './translations'; interface ComparisonSideProps { fieldName: FieldName; fieldThreeWayDiff: ThreeWayDiff; - resolvedValue?: DiffableAllFields[FieldName]; + resolvedValue: DiffableAllFields[FieldName]; } export function ComparisonSide({ @@ -39,6 +39,7 @@ export function ComparisonSide({ const [oldVersionType, newVersionType] = selectedVersions.split('_') as [Version, Version]; const oldFieldValue = pickFieldValueForVersion(oldVersionType, fieldThreeWayDiff, resolvedValue); + const newFieldValue = pickFieldValueForVersion(newVersionType, fieldThreeWayDiff, resolvedValue); const subfieldChanges = getSubfieldChanges(fieldName, oldFieldValue, newFieldValue); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/comparison_side/utils.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/comparison_side/utils.ts index dd52da04982f3..d0673c460a1d5 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/comparison_side/utils.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/comparison_side/utils.ts @@ -17,13 +17,13 @@ import type { * * @param version - The version for which the field value is to be picked. * @param fieldThreeWayDiff - The three-way diff object containing the field values for different versions. - * @param resolvedValue - The user-set resolved value resolved value. Used if it is set and the version is final. + * @param resolvedValue - A value field will be upgraded to. * @returns - The field value for the specified version */ export function pickFieldValueForVersion( version: Version, fieldThreeWayDiff: ThreeWayDiff, - resolvedValue?: DiffableAllFields[FieldName] + resolvedValue: DiffableAllFields[FieldName] ): DiffableAllFields[FieldName] | undefined { if (version === Version.Final) { return resolvedValue; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/components/constants.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/components/constants.ts new file mode 100644 index 0000000000000..ad348c85148b2 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/components/constants.ts @@ -0,0 +1,19 @@ +/* + * 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 type { DiffableAllFields } from '../../../../../../../common/api/detection_engine'; + +type NonEditableFields = Readonly>; + +/* These fields are not visible in the comparison UI and are not editable */ +export const HIDDEN_FIELDS: NonEditableFields = new Set([ + 'alert_suppression', + 'author', + 'rule_id', + 'license', + 'version', +]); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/components/field_upgrade_conflicts_resolver.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/components/field_upgrade_conflicts_resolver.tsx index a750c163814a0..6a2ad17f45f26 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/components/field_upgrade_conflicts_resolver.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/components/field_upgrade_conflicts_resolver.tsx @@ -11,7 +11,6 @@ import { css } from '@emotion/css'; import { SplitAccordion } from '../../../../../../common/components/split_accordion'; import type { DiffableAllFields, - DiffableRule, RuleFieldsDiff, ThreeWayDiff, } from '../../../../../../../common/api/detection_engine'; @@ -20,23 +19,25 @@ import type { FieldUpgradeState } from '../../../../model/prebuilt_rule_upgrade' import { ComparisonSide } from '../comparison_side/comparison_side'; import { FinalSide } from '../final_side/final_side'; import { FieldUpgradeConflictsResolverHeader } from './field_upgrade_conflicts_resolver_header'; +import { useDiffableRuleContext } from '../diffable_rule_context'; +import type { UpgradeableDiffableFields } from '../../../../model/prebuilt_rule_upgrade/fields'; -interface FieldUpgradeConflictsResolverProps { +interface FieldUpgradeConflictsResolverProps { fieldName: FieldName; fieldUpgradeState: FieldUpgradeState; fieldThreeWayDiff: RuleFieldsDiff[FieldName]; - finalDiffableRule: DiffableRule; } -export function FieldUpgradeConflictsResolver({ +export function FieldUpgradeConflictsResolver({ fieldName, fieldUpgradeState, fieldThreeWayDiff, - finalDiffableRule, }: FieldUpgradeConflictsResolverProps): JSX.Element { const { euiTheme } = useEuiTheme(); const hasConflict = fieldThreeWayDiff.conflict !== ThreeWayDiffConflict.NONE; + const { finalDiffableRule } = useDiffableRuleContext(); + return ( <> - + diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/components/rule_upgrade_callout/rule_upgrade_callout.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/components/rule_upgrade_callout/rule_upgrade_callout.tsx index 852ab0c91c58e..8ab2674524952 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/components/rule_upgrade_callout/rule_upgrade_callout.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/components/rule_upgrade_callout/rule_upgrade_callout.tsx @@ -64,7 +64,12 @@ export function RuleUpgradeCallout({ ruleUpgradeState }: RuleUpgradeCalloutProps } return ( - +

{i18n.RULE_IS_READY_FOR_UPGRADE_DESCRIPTION}

); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/components/rule_upgrade_callout/translations.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/components/rule_upgrade_callout/translations.tsx index be9ee761388d0..319884746dbc2 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/components/rule_upgrade_callout/translations.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/components/rule_upgrade_callout/translations.tsx @@ -13,7 +13,7 @@ export const RULE_HAS_NON_SOLVABLE_CONFLICTS = (count: number) => { values: { count }, defaultMessage: - '{count} of the fields has a unsolved conflict. Please review and modify accordingly.', + '{count} of the fields {count, plural, one {has} other {have}} an unsolved conflict. Please review and modify accordingly.', } ); @@ -31,7 +31,7 @@ export const RULE_HAS_SOLVABLE_CONFLICTS = (count: number) => { values: { count }, defaultMessage: - '{count} of the fields has an update conflict, please review the suggested update being updating.', + '{count} of the fields {count, plural, one {has} other {have}} an update conflict, please review the suggested update being updating.', } ); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/components/rule_upgrade_conflicts_resolver.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/components/rule_upgrade_conflicts_resolver.tsx index f60af70c808f5..3379cf2ab3e96 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/components/rule_upgrade_conflicts_resolver.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/components/rule_upgrade_conflicts_resolver.tsx @@ -6,36 +6,39 @@ */ import React from 'react'; -import type { - RuleUpgradeState, - SetRuleFieldResolvedValueFn, -} from '../../../../model/prebuilt_rule_upgrade'; +import type { RuleUpgradeState } from '../../../../model/prebuilt_rule_upgrade'; import { FieldUpgradeConflictsResolver } from './field_upgrade_conflicts_resolver'; +import type { NonUpgradeableDiffableFields } from '../../../../model/prebuilt_rule_upgrade/fields'; +import { isNonUpgradeableFieldName } from '../../../../model/prebuilt_rule_upgrade/fields'; + +type FieldDiffEntries = Array< + [ + Exclude, + Required[Exclude] + ] +>; interface RuleUpgradeConflictsResolverProps { ruleUpgradeState: RuleUpgradeState; - setRuleFieldResolvedValue: SetRuleFieldResolvedValueFn; } export function RuleUpgradeConflictsResolver({ ruleUpgradeState, - setRuleFieldResolvedValue, -}: RuleUpgradeConflictsResolverProps): JSX.Element { - const fieldDiffEntries = Object.entries(ruleUpgradeState.diff.fields) as Array< - [ - keyof typeof ruleUpgradeState.diff.fields, - Required[keyof typeof ruleUpgradeState.diff.fields] - ] +}: RuleUpgradeConflictsResolverProps): React.ReactNode { + const fieldDiffEntries = Object.entries(ruleUpgradeState.diff.fields) as FieldDiffEntries< + typeof ruleUpgradeState.diff.fields >; - const fields = fieldDiffEntries.map(([fieldName, fieldDiff]) => ( + + const fields = fieldDiffEntries.filter(([fieldName]) => { + return isNonUpgradeableFieldName(fieldName) === false; + }) as FieldDiffEntries; + + return fields.map(([fieldName, fieldDiff]) => ( )); - - return <>{fields}; } diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/diffable_rule_context.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/diffable_rule_context.tsx new file mode 100644 index 0000000000000..4210b394c7618 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/diffable_rule_context.tsx @@ -0,0 +1,50 @@ +/* + * 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, { createContext, useContext } from 'react'; +import type { DiffableRule } from '../../../../../../common/api/detection_engine'; +import { invariant } from '../../../../../../common/utils/invariant'; +import type { SetRuleFieldResolvedValueFn } from '../../../model/prebuilt_rule_upgrade/set_rule_field_resolved_value'; + +interface DiffableRuleContextType { + finalDiffableRule: DiffableRule; + setRuleFieldResolvedValue: SetRuleFieldResolvedValueFn; +} + +const DiffableRuleContext = createContext(null); + +interface DiffableRuleContextProviderProps { + finalDiffableRule: DiffableRule; + setRuleFieldResolvedValue: SetRuleFieldResolvedValueFn; + children: React.ReactNode; +} + +export function DiffableRuleContextProvider({ + finalDiffableRule, + setRuleFieldResolvedValue, + children, +}: DiffableRuleContextProviderProps) { + const contextValue = { + finalDiffableRule, + setRuleFieldResolvedValue, + }; + + return ( + {children} + ); +} + +export function useDiffableRuleContext() { + const context = useContext(DiffableRuleContext); + + invariant( + context !== null, + 'useDiffableRuleContext must be used inside a DiffableRuleContextProvider' + ); + + return context; +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/common_rule_field_edit.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/common_rule_field_edit.tsx new file mode 100644 index 0000000000000..0cb7ce3982868 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/common_rule_field_edit.tsx @@ -0,0 +1,23 @@ +/* + * 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 { FieldFormWrapper } from './field_form_wrapper'; +import { NameEdit, nameSchema } from './fields/name'; +import type { UpgradeableCommonFields } from '../../../../model/prebuilt_rule_upgrade/fields'; +interface CommonRuleFieldEditProps { + fieldName: UpgradeableCommonFields; +} + +export function CommonRuleFieldEdit({ fieldName }: CommonRuleFieldEditProps) { + switch (fieldName) { + case 'name': + return ; + default: + return null; // Will be replaced with `assertUnreachable(fieldName)` once all fields are implemented + } +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/custom_query_rule_field_edit.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/custom_query_rule_field_edit.tsx new file mode 100644 index 0000000000000..3dc3cc5b87023 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/custom_query_rule_field_edit.tsx @@ -0,0 +1,36 @@ +/* + * 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 { FieldFormWrapper } from './field_form_wrapper'; +import { + KqlQueryEdit, + kqlQuerySchema, + kqlQuerySerializer, + kqlQueryDeserializer, +} from './fields/kql_query'; +import type { UpgradeableCustomQueryFields } from '../../../../model/prebuilt_rule_upgrade/fields'; + +interface CustomQueryRuleFieldEditProps { + fieldName: UpgradeableCustomQueryFields; +} + +export function CustomQueryRuleFieldEdit({ fieldName }: CustomQueryRuleFieldEditProps) { + switch (fieldName) { + case 'kql_query': + return ( + + ); + default: + return null; // Will be replaced with `assertUnreachable(fieldName)` once all fields are implemented + } +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/field_form_wrapper.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/field_form_wrapper.tsx new file mode 100644 index 0000000000000..b4a53ee7aea0a --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/field_form_wrapper.tsx @@ -0,0 +1,115 @@ +/* + * 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, { useCallback, useState } from 'react'; +import { EuiButtonEmpty, EuiFlexGroup } from '@elastic/eui'; +import { useForm, Form } from '../../../../../../shared_imports'; +import type { FormSchema, FormData } from '../../../../../../shared_imports'; +import type { + DiffableAllFields, + DiffableRule, +} from '../../../../../../../common/api/detection_engine'; +import { useFinalSideContext } from '../final_side/final_side_context'; +import { useDiffableRuleContext } from '../diffable_rule_context'; +import * as i18n from '../translations'; + +type FieldComponent = React.ComponentType<{ + finalDiffableRule: DiffableRule; + setValidity: (isValid: boolean) => void; + setFieldValue: (fieldName: string, fieldValue: unknown) => void; +}>; + +interface FieldFormWrapperProps { + component: FieldComponent; + fieldFormSchema: FormSchema; + deserializer?: (fieldValue: FormData, finalDiffableRule: DiffableRule) => FormData; + serializer?: (formData: FormData) => FormData; +} + +/** + * FieldFormWrapper component manages form state and renders "Save" and "Cancel" buttons. + * + * @param {Object} props - Component props. + * @param {React.ComponentType} props.component - Field component to be wrapped. + * @param {FormSchema} props.fieldFormSchema - Configuration schema for the field. + * @param {Function} props.deserializer - Deserializer prepares initial form data. It converts field value from a DiffableRule format to a format used by the form. + * @param {Function} props.serializer - Serializer prepares form data for submission. It converts form data back to a DiffableRule format. + */ +export function FieldFormWrapper({ + component: FieldComponent, + fieldFormSchema, + deserializer, + serializer, +}: FieldFormWrapperProps) { + const { fieldName, setReadOnlyMode } = useFinalSideContext(); + const { finalDiffableRule, setRuleFieldResolvedValue } = useDiffableRuleContext(); + + const deserialize = useCallback( + (defaultValue: FormData): FormData => { + if (!deserializer) { + return defaultValue; + } + + const rule = finalDiffableRule as Record; + const fieldValue = rule[fieldName] as FormData; + return deserializer(fieldValue, finalDiffableRule); + }, + [deserializer, fieldName, finalDiffableRule] + ); + + const handleSubmit = useCallback( + async (formData: FormData, isValid: boolean) => { + if (!isValid) { + return; + } + + setRuleFieldResolvedValue({ + ruleId: finalDiffableRule.rule_id, + fieldName: fieldName as keyof DiffableAllFields, + resolvedValue: formData[fieldName], + }); + setReadOnlyMode(); + }, + [fieldName, finalDiffableRule.rule_id, setReadOnlyMode, setRuleFieldResolvedValue] + ); + + const { form } = useForm({ + schema: fieldFormSchema, + defaultValue: getDefaultValue(fieldName, finalDiffableRule), + deserializer: deserialize, + serializer, + onSubmit: handleSubmit, + }); + + const [validity, setValidity] = useState(undefined); + + const isValid = validity === undefined ? form.isValid : validity; + + return ( + <> + + + {i18n.CANCEL_BUTTON_LABEL} + + + {i18n.SAVE_BUTTON_LABEL} + + +
+ + + + ); +} + +function getDefaultValue(fieldName: string, finalDiffableRule: Record): FormData { + return { [fieldName]: finalDiffableRule[fieldName] }; +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/fields/kql_query.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/fields/kql_query.tsx new file mode 100644 index 0000000000000..abd3c93550694 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/fields/kql_query.tsx @@ -0,0 +1,239 @@ +/* + * 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, { useCallback } from 'react'; +import { useToggle } from 'react-use'; +import { css } from '@emotion/css'; +import { EuiButtonEmpty } from '@elastic/eui'; +import type { Type } from '@kbn/securitysolution-io-ts-alerting-types'; +import type { FormSchema, FormData } from '../../../../../../../shared_imports'; +import { HiddenField, UseField } from '../../../../../../../shared_imports'; +import { schema } from '../../../../../../rule_creation_ui/components/step_define_rule/schema'; +import { QueryBarDefineRule } from '../../../../../../rule_creation_ui/components/query_bar'; +import type { FieldValueQueryBar } from '../../../../../../rule_creation_ui/components/query_bar'; +import * as stepDefineRuleI18n from '../../../../../../rule_creation_ui/components/step_define_rule/translations'; +import { useRuleIndexPattern } from '../../../../../../rule_creation_ui/pages/form'; +import { + DataSourceType as DataSourceTypeSnakeCase, + KqlQueryLanguage, + KqlQueryType, + RuleQuery, + SavedQueryId, + RuleKqlQuery, +} from '../../../../../../../../common/api/detection_engine'; +import type { + DiffableRule, + DiffableRuleTypes, + InlineKqlQuery, + SavedKqlQuery, +} from '../../../../../../../../common/api/detection_engine'; +import { useDefaultIndexPattern } from '../../../use_default_index_pattern'; +import { DataSourceType } from '../../../../../../../detections/pages/detection_engine/rules/types'; +import { isFilters } from '../../../helpers'; +import type { SetRuleQuery } from '../../../../../../../detections/containers/detection_engine/rules/use_rule_from_timeline'; +import { useRuleFromTimeline } from '../../../../../../../detections/containers/detection_engine/rules/use_rule_from_timeline'; +import { useGetSavedQuery } from '../../../../../../../detections/pages/detection_engine/rules/use_get_saved_query'; + +export const kqlQuerySchema = { + ruleType: schema.ruleType, + queryBar: schema.queryBar, +} as FormSchema<{ + ruleType: DiffableRuleTypes; + queryBar: FieldValueQueryBar; +}>; + +interface KqlQueryEditProps { + finalDiffableRule: DiffableRule; + setValidity: (isValid: boolean) => void; + setFieldValue: (fieldName: string, fieldValue: unknown) => void; +} + +export function KqlQueryEdit({ + finalDiffableRule, + setValidity, + setFieldValue, +}: KqlQueryEditProps): JSX.Element { + const defaultIndexPattern = useDefaultIndexPattern(); + const indexPatternParameters = getUseRuleIndexPatternParameters( + finalDiffableRule, + defaultIndexPattern + ); + const { indexPattern, isIndexPatternLoading } = useRuleIndexPattern(indexPatternParameters); + + const [isTimelineSearchOpen, toggleIsTimelineSearchOpen] = useToggle(false); + + const handleSetRuleFromTimeline = useCallback( + ({ queryBar: timelineQueryBar }) => { + setFieldValue('queryBar', timelineQueryBar); + }, + [setFieldValue] + ); + + const { onOpenTimeline } = useRuleFromTimeline(handleSetRuleFromTimeline); + + const isSavedQueryRule = finalDiffableRule.type === 'saved_query'; + + const { savedQuery } = useGetSavedQuery({ + savedQueryId: getSavedQueryId(finalDiffableRule), + ruleType: finalDiffableRule.type, + }); + + return ( + <> + + + ), + }} + component={QueryBarDefineRule} + componentProps={{ + indexPattern, + isLoading: isIndexPatternLoading, + openTimelineSearch: isTimelineSearchOpen, + onCloseTimelineSearch: toggleIsTimelineSearchOpen, + onValidityChange: setValidity, + onOpenTimeline, + isDisabled: isSavedQueryRule, + defaultSavedQuery: savedQuery, + resetToSavedQuery: isSavedQueryRule, + }} + /> + + ); +} + +const timelineButtonClassName = css` + height: 18px; + font-size: 12px; +`; + +function ImportTimelineQueryButton({ + handleOpenTimelineSearch, +}: { + handleOpenTimelineSearch: () => void; +}) { + return ( + + {stepDefineRuleI18n.IMPORT_TIMELINE_QUERY} + + ); +} + +export function kqlQuerySerializer(formData: FormData): { + kql_query: RuleKqlQuery; +} { + const formValue = formData as { ruleType: Type; queryBar: FieldValueQueryBar }; + + if (formValue.ruleType === 'saved_query') { + const savedQueryId = SavedQueryId.parse(formValue.queryBar.saved_id); + + const savedKqlQuery: SavedKqlQuery = { + type: KqlQueryType.saved_query, + saved_query_id: savedQueryId, + }; + + return { + kql_query: savedKqlQuery, + }; + } + + const query = RuleQuery.parse(formValue.queryBar.query.query); + const language = KqlQueryLanguage.parse(formValue.queryBar.query.language); + + const inlineKqlQuery: InlineKqlQuery = { + type: KqlQueryType.inline_query, + query, + language, + filters: formValue.queryBar.filters, + }; + + return { kql_query: inlineKqlQuery }; +} + +export function kqlQueryDeserializer( + fieldValue: FormData, + finalDiffableRule: DiffableRule +): { + ruleType: Type; + queryBar: FieldValueQueryBar; +} { + const parsedFieldValue = RuleKqlQuery.parse(fieldValue); + + if (parsedFieldValue.type === KqlQueryType.inline_query) { + const returnValue = { + ruleType: finalDiffableRule.type, + queryBar: { + query: { + query: parsedFieldValue.query, + language: parsedFieldValue.language, + }, + filters: isFilters(parsedFieldValue.filters) ? parsedFieldValue.filters : [], + saved_id: null, + }, + }; + + return returnValue; + } + + const returnValue = { + ruleType: finalDiffableRule.type, + queryBar: { + query: { + query: '', + language: '', + }, + filters: [], + saved_id: parsedFieldValue.saved_query_id, + }, + }; + + return returnValue; +} + +interface UseRuleIndexPatternParameters { + dataSourceType: DataSourceType; + index: string[]; + dataViewId: string | undefined; +} + +function getUseRuleIndexPatternParameters( + finalDiffableRule: DiffableRule, + defaultIndexPattern: string[] +): UseRuleIndexPatternParameters { + if (!('data_source' in finalDiffableRule) || !finalDiffableRule.data_source) { + return { + dataSourceType: DataSourceType.IndexPatterns, + index: defaultIndexPattern, + dataViewId: undefined, + }; + } + if (finalDiffableRule.data_source.type === DataSourceTypeSnakeCase.data_view) { + return { + dataSourceType: DataSourceType.DataView, + index: [], + dataViewId: finalDiffableRule.data_source.data_view_id, + }; + } + return { + dataSourceType: DataSourceType.IndexPatterns, + index: finalDiffableRule.data_source.index_patterns, + dataViewId: undefined, + }; +} + +function getSavedQueryId(diffableRule: DiffableRule): string | undefined { + if (diffableRule.type === 'saved_query' && 'saved_query_id' in diffableRule.kql_query) { + return diffableRule.kql_query.saved_query_id; + } + + return undefined; +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/fields/name.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/fields/name.tsx new file mode 100644 index 0000000000000..10ae6cffbe50d --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/fields/name.tsx @@ -0,0 +1,28 @@ +/* + * 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 type { FormSchema } from '../../../../../../../shared_imports'; +import { Field, UseField } from '../../../../../../../shared_imports'; +import { schema } from '../../../../../../rule_creation_ui/components/step_about_rule/schema'; +import type { RuleName } from '../../../../../../../../common/api/detection_engine'; + +export const nameSchema = { name: schema.name } as FormSchema<{ name: RuleName }>; + +export function NameEdit(): JSX.Element { + return ( + + ); +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/final_edit.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/final_edit.tsx new file mode 100644 index 0000000000000..698d138208d70 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/final_edit.tsx @@ -0,0 +1,57 @@ +/* + * 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 { assertUnreachable } from '../../../../../../../common/utility_types'; +import { useDiffableRuleContext } from '../diffable_rule_context'; +import { CommonRuleFieldEdit } from './common_rule_field_edit'; +import { CustomQueryRuleFieldEdit } from './custom_query_rule_field_edit'; +import { SavedQueryRuleFieldEdit } from './saved_query_rule_field_edit'; +import { ThreatMatchRuleFieldEdit } from './threat_match_rule_field_edit'; +import { ThresholdRuleFieldEdit } from './threshold_rule_field_edit'; +import { NewTermsRuleFieldEdit } from './new_terms_rule_field_edit'; +import type { + UpgradeableCustomQueryFields, + UpgradeableSavedQueryFields, + UpgradeableThreatMatchFields, + UpgradeableThresholdFields, + UpgradeableNewTermsFields, +} from '../../../../model/prebuilt_rule_upgrade/fields'; +import { isCommonFieldName } from '../../../../model/prebuilt_rule_upgrade/fields'; +import { useFinalSideContext } from '../final_side/final_side_context'; + +export function FinalEdit() { + const { finalDiffableRule } = useDiffableRuleContext(); + const { type } = finalDiffableRule; + + const { fieldName } = useFinalSideContext(); + + if (isCommonFieldName(fieldName)) { + return ; + } + + switch (type) { + case 'query': + return ; + case 'saved_query': + return ; + case 'eql': + return {'Rule type not yet implemented'}; + case 'esql': + return {'Rule type not yet implemented'}; + case 'threat_match': + return ; + case 'threshold': + return ; + case 'machine_learning': + return {'Rule type not yet implemented'}; + case 'new_terms': + return ; + default: + return assertUnreachable(type); + } +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/new_terms_rule_field_edit.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/new_terms_rule_field_edit.tsx new file mode 100644 index 0000000000000..183200aef1c43 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/new_terms_rule_field_edit.tsx @@ -0,0 +1,36 @@ +/* + * 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 { FieldFormWrapper } from './field_form_wrapper'; +import { + KqlQueryEdit, + kqlQuerySchema, + kqlQuerySerializer, + kqlQueryDeserializer, +} from './fields/kql_query'; +import type { UpgradeableNewTermsFields } from '../../../../model/prebuilt_rule_upgrade/fields'; + +interface NewTermsRuleFieldEditProps { + fieldName: UpgradeableNewTermsFields; +} + +export function NewTermsRuleFieldEdit({ fieldName }: NewTermsRuleFieldEditProps) { + switch (fieldName) { + case 'kql_query': + return ( + + ); + default: + return null; // Will be replaced with `assertUnreachable(fieldName)` once all fields are implemented + } +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/saved_query_rule_field_edit.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/saved_query_rule_field_edit.tsx new file mode 100644 index 0000000000000..fa573e6339e9f --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/saved_query_rule_field_edit.tsx @@ -0,0 +1,36 @@ +/* + * 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 { FieldFormWrapper } from './field_form_wrapper'; +import { + KqlQueryEdit, + kqlQuerySchema, + kqlQuerySerializer, + kqlQueryDeserializer, +} from './fields/kql_query'; +import type { UpgradeableSavedQueryFields } from '../../../../model/prebuilt_rule_upgrade/fields'; + +interface SavedQueryRuleFieldEditProps { + fieldName: UpgradeableSavedQueryFields; +} + +export function SavedQueryRuleFieldEdit({ fieldName }: SavedQueryRuleFieldEditProps) { + switch (fieldName) { + case 'kql_query': + return ( + + ); + default: + return null; // Will be replaced with `assertUnreachable(fieldName)` once all fields are implemented + } +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/threat_match_rule_field_edit.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/threat_match_rule_field_edit.tsx new file mode 100644 index 0000000000000..5f2adbb113fd5 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/threat_match_rule_field_edit.tsx @@ -0,0 +1,36 @@ +/* + * 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 { FieldFormWrapper } from './field_form_wrapper'; +import { + KqlQueryEdit, + kqlQuerySchema, + kqlQuerySerializer, + kqlQueryDeserializer, +} from './fields/kql_query'; +import type { UpgradeableThreatMatchFields } from '../../../../model/prebuilt_rule_upgrade/fields'; + +interface ThreatMatchRuleFieldEditProps { + fieldName: UpgradeableThreatMatchFields; +} + +export function ThreatMatchRuleFieldEdit({ fieldName }: ThreatMatchRuleFieldEditProps) { + switch (fieldName) { + case 'kql_query': + return ( + + ); + default: + return null; // Will be replaced with `assertUnreachable(fieldName)` once all fields are implemented + } +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/threshold_rule_field_edit.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/threshold_rule_field_edit.tsx new file mode 100644 index 0000000000000..4975ca49205e7 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/threshold_rule_field_edit.tsx @@ -0,0 +1,36 @@ +/* + * 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 { FieldFormWrapper } from './field_form_wrapper'; +import { + KqlQueryEdit, + kqlQuerySchema, + kqlQuerySerializer, + kqlQueryDeserializer, +} from './fields/kql_query'; +import type { UpgradeableThresholdFields } from '../../../../model/prebuilt_rule_upgrade/fields'; + +interface ThresholdRuleFieldEditProps { + fieldName: UpgradeableThresholdFields; +} + +export function ThresholdRuleFieldEdit({ fieldName }: ThresholdRuleFieldEditProps) { + switch (fieldName) { + case 'kql_query': + return ( + + ); + default: + return null; // Will be replaced with `assertUnreachable(fieldName)` once all fields are implemented + } +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/field_readonly.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/field_readonly.tsx index d8d31e343278b..ecaec5af0f54a 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/field_readonly.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/field_readonly.tsx @@ -8,7 +8,6 @@ import React, { useMemo } from 'react'; import { DiffableCommonFields } from '../../../../../../../common/api/detection_engine'; import type { - DiffableRule, DiffableCustomQueryFields, DiffableSavedQueryFields, DiffableEqlFields, @@ -28,13 +27,15 @@ import { ThresholdRuleFieldReadOnly } from './threshold_rule_field_readonly'; import { MachineLearningRuleFieldReadOnly } from './machine_learning_rule_field_readonly'; import { NewTermsRuleFieldReadOnly } from './new_terms_rule_field_readonly'; import { CommonRuleFieldReadOnly } from './common_rule_field_readonly'; +import { useDiffableRuleContext } from '../diffable_rule_context'; interface FieldReadOnlyProps { fieldName: string; - finalDiffableRule: DiffableRule; } -export function FieldReadOnly({ fieldName, finalDiffableRule }: FieldReadOnlyProps) { +export function FieldReadOnly({ fieldName }: FieldReadOnlyProps) { + const { finalDiffableRule } = useDiffableRuleContext(); + const { data: commonField } = useMemo( () => DiffableCommonFields.keyof().safeParse(fieldName), [fieldName] diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/alert_suppression/alert_suppression.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/alert_suppression/alert_suppression.stories.tsx index 4f6739a3af481..9aeeee25983d3 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/alert_suppression/alert_suppression.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/alert_suppression/alert_suppression.stories.tsx @@ -25,8 +25,8 @@ interface TemplateProps { const Template: Story = (args) => { return ( - - + + ); }; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/anomaly_threshold/anomaly_threshold.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/anomaly_threshold/anomaly_threshold.stories.tsx index 8203e015d11db..392187941046c 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/anomaly_threshold/anomaly_threshold.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/anomaly_threshold/anomaly_threshold.stories.tsx @@ -11,6 +11,7 @@ import { AnomalyThresholdReadOnly } from './anomaly_threshold'; import { FieldReadOnly } from '../../field_readonly'; import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { mockMachineLearningRule } from '../../storybook/mocks'; +import { ThreeWayDiffStorybookProviders } from '../../storybook/three_way_diff_storybook_providers'; export default { component: AnomalyThresholdReadOnly, @@ -23,7 +24,11 @@ interface TemplateProps { } const Template: Story = (args) => { - return ; + return ( + + + + ); }; export const Default = Template.bind({}); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/author/author.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/author/author.stories.tsx index 2700517c1c3ec..97526ec0290b9 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/author/author.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/author/author.stories.tsx @@ -11,6 +11,7 @@ import { AuthorReadOnly } from './author'; import { FieldReadOnly } from '../../field_readonly'; import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { mockCustomQueryRule } from '../../storybook/mocks'; +import { ThreeWayDiffStorybookProviders } from '../../storybook/three_way_diff_storybook_providers'; export default { component: AuthorReadOnly, @@ -22,7 +23,11 @@ interface TemplateProps { } const Template: Story = (args) => { - return ; + return ( + + + + ); }; export const Default = Template.bind({}); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/building_block/building_block.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/building_block/building_block.stories.tsx index f927b753c17ab..6bace209f283b 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/building_block/building_block.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/building_block/building_block.stories.tsx @@ -11,6 +11,7 @@ import { BuildingBlockReadOnly } from './building_block'; import { FieldReadOnly } from '../../field_readonly'; import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { mockCustomQueryRule } from '../../storybook/mocks'; +import { ThreeWayDiffStorybookProviders } from '../../storybook/three_way_diff_storybook_providers'; export default { component: BuildingBlockReadOnly, @@ -22,7 +23,11 @@ interface TemplateProps { } const Template: Story = (args) => { - return ; + return ( + + + + ); }; export const Default = Template.bind({}); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/data_source/data_source.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/data_source/data_source.stories.tsx index 091a874385156..d7bf26bc7d9ba 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/data_source/data_source.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/data_source/data_source.stories.tsx @@ -29,8 +29,11 @@ interface TemplateProps { const Template: Story = (args) => { return ( - - + + ); }; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/description/description.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/description/description.stories.tsx index ba094ecfe54f9..079c327fb29ef 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/description/description.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/description/description.stories.tsx @@ -11,6 +11,7 @@ import { DescriptionReadOnly } from './description'; import { FieldReadOnly } from '../../field_readonly'; import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { mockCustomQueryRule } from '../../storybook/mocks'; +import { ThreeWayDiffStorybookProviders } from '../../storybook/three_way_diff_storybook_providers'; export default { component: DescriptionReadOnly, @@ -22,7 +23,11 @@ interface TemplateProps { } const Template: Story = (args) => { - return ; + return ( + + + + ); }; export const Default = Template.bind({}); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/eql_query/eql_query.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/eql_query/eql_query.stories.tsx index 84ea98047bcee..8ee0ac1511784 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/eql_query/eql_query.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/eql_query/eql_query.stories.tsx @@ -31,8 +31,11 @@ interface TemplateProps { const Template: Story = (args) => { return ( - - + + ); }; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/esql_query/esql_query.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/esql_query/esql_query.stories.tsx index 664294dbe768c..70f37106842e1 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/esql_query/esql_query.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/esql_query/esql_query.stories.tsx @@ -10,6 +10,7 @@ import type { Story } from '@storybook/react'; import { FieldReadOnly } from '../../field_readonly'; import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { mockEsqlRule } from '../../storybook/mocks'; +import { ThreeWayDiffStorybookProviders } from '../../storybook/three_way_diff_storybook_providers'; export default { component: FieldReadOnly, @@ -21,7 +22,11 @@ interface TemplateProps { } const Template: Story = (args) => { - return ; + return ( + + + + ); }; export const Default = Template.bind({}); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/event_category_override/event_category_override.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/event_category_override/event_category_override.stories.tsx index 1eb29ef1084d9..1f5987287f665 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/event_category_override/event_category_override.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/event_category_override/event_category_override.stories.tsx @@ -11,6 +11,7 @@ import { EventCategoryOverrideReadOnly } from './event_category_override'; import { FieldReadOnly } from '../../field_readonly'; import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { mockEqlRule } from '../../storybook/mocks'; +import { ThreeWayDiffStorybookProviders } from '../../storybook/three_way_diff_storybook_providers'; export default { component: EventCategoryOverrideReadOnly, @@ -24,7 +25,9 @@ interface TemplateProps { const Template: Story = (args) => { return ( - + + + ); }; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/false_positives/false_positives.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/false_positives/false_positives.stories.tsx index 60d8a34616652..a5884b340e32b 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/false_positives/false_positives.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/false_positives/false_positives.stories.tsx @@ -11,6 +11,7 @@ import { FalsePositivesReadOnly } from './false_positives'; import { FieldReadOnly } from '../../field_readonly'; import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { mockCustomQueryRule } from '../../storybook/mocks'; +import { ThreeWayDiffStorybookProviders } from '../../storybook/three_way_diff_storybook_providers'; export default { component: FalsePositivesReadOnly, @@ -22,7 +23,11 @@ interface TemplateProps { } const Template: Story = (args) => { - return ; + return ( + + + + ); }; export const Default = Template.bind({}); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/history_window_start/history_window_start.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/history_window_start/history_window_start.stories.tsx index c84868e97ee0c..12e0f086ecec9 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/history_window_start/history_window_start.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/history_window_start/history_window_start.stories.tsx @@ -11,6 +11,7 @@ import { HistoryWindowStartReadOnly } from './history_window_start'; import { FieldReadOnly } from '../../field_readonly'; import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { mockNewTermsRule } from '../../storybook/mocks'; +import { ThreeWayDiffStorybookProviders } from '../../storybook/three_way_diff_storybook_providers'; export default { component: HistoryWindowStartReadOnly, @@ -24,7 +25,9 @@ interface TemplateProps { const Template: Story = (args) => { return ( - + + + ); }; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/investigation_fields/investigation_fields.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/investigation_fields/investigation_fields.stories.tsx index e73b01a719f8a..a32c79076a03d 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/investigation_fields/investigation_fields.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/investigation_fields/investigation_fields.stories.tsx @@ -11,6 +11,7 @@ import { InvestigationFieldsReadOnly } from './investigation_fields'; import { FieldReadOnly } from '../../field_readonly'; import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { mockCustomQueryRule } from '../../storybook/mocks'; +import { ThreeWayDiffStorybookProviders } from '../../storybook/three_way_diff_storybook_providers'; export default { component: InvestigationFieldsReadOnly, @@ -24,7 +25,9 @@ interface TemplateProps { const Template: Story = (args) => { return ( - + + + ); }; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/kql_query/kql_query.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/kql_query/kql_query.stories.tsx index 4fd102fc0627f..16731ec498162 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/kql_query/kql_query.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/kql_query/kql_query.stories.tsx @@ -33,8 +33,11 @@ interface TemplateProps { const Template: Story = (args) => { return ( - - + + ); }; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/kql_query/saved_kql_query.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/kql_query/saved_kql_query.tsx index 5f50a9c1b9eae..6db78a20082d9 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/kql_query/saved_kql_query.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/kql_query/saved_kql_query.tsx @@ -17,7 +17,7 @@ import { Query, SavedQueryName, Filters } from '../../../../rule_definition_sect import * as ruleDetailsI18n from '../../../../translations'; import * as descriptionStepI18n from '../../../../../../../rule_creation_ui/components/description_step/translations'; import { useGetSavedQuery } from '../../../../../../../../detections/pages/detection_engine/rules/use_get_saved_query'; -import { getDataSourceProps, getQueryLanguageLabel } from '../../../../helpers'; +import { getDataSourceProps, getQueryLanguageLabel, isFilters } from '../../../../helpers'; interface SavedQueryProps { kqlQuery: SavedKqlQuery; @@ -53,12 +53,14 @@ export function SavedKqlQueryReadOnly({ kqlQuery, dataSource, ruleType }: SavedQ }); } - if (savedQuery.attributes.filters) { + const filters = savedQuery.attributes.filters ?? []; + + if (isFilters(filters) && filters.length > 0) { const dataSourceProps = getDataSourceProps(dataSource); listItems.push({ title: descriptionStepI18n.SAVED_QUERY_FILTERS_LABEL, - description: , + description: , }); } diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/license/license.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/license/license.stories.tsx index 044564acd91d8..666f4b6507798 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/license/license.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/license/license.stories.tsx @@ -11,6 +11,7 @@ import { LicenseReadOnly } from './license'; import { FieldReadOnly } from '../../field_readonly'; import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { mockCustomQueryRule } from '../../storybook/mocks'; +import { ThreeWayDiffStorybookProviders } from '../../storybook/three_way_diff_storybook_providers'; export default { component: LicenseReadOnly, @@ -22,7 +23,11 @@ interface TemplateProps { } const Template: Story = (args) => { - return ; + return ( + + + + ); }; export const Default = Template.bind({}); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/machine_learning_job_id/machine_learning_job_id.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/machine_learning_job_id/machine_learning_job_id.stories.tsx index 8dc504b737e00..ea23aa5984106 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/machine_learning_job_id/machine_learning_job_id.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/machine_learning_job_id/machine_learning_job_id.stories.tsx @@ -64,12 +64,9 @@ interface TemplateProps { const Template: Story = (args) => { return ( - + - + ); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/max_signals/max_signals.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/max_signals/max_signals.stories.tsx index d6f369ff47ce6..3c7945366a174 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/max_signals/max_signals.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/max_signals/max_signals.stories.tsx @@ -11,6 +11,7 @@ import { MaxSignalsReadOnly } from './max_signals'; import { FieldReadOnly } from '../../field_readonly'; import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { mockCustomQueryRule } from '../../storybook/mocks'; +import { ThreeWayDiffStorybookProviders } from '../../storybook/three_way_diff_storybook_providers'; export default { component: MaxSignalsReadOnly, @@ -22,7 +23,11 @@ interface TemplateProps { } const Template: Story = (args) => { - return ; + return ( + + + + ); }; export const Default = Template.bind({}); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/name/name.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/name/name.stories.tsx index 1451d3b70ef8b..d97f71b4df0ac 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/name/name.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/name/name.stories.tsx @@ -11,6 +11,7 @@ import { NameReadOnly } from './name'; import { FieldReadOnly } from '../../field_readonly'; import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { mockCustomQueryRule } from '../../storybook/mocks'; +import { ThreeWayDiffStorybookProviders } from '../../storybook/three_way_diff_storybook_providers'; export default { component: NameReadOnly, @@ -22,7 +23,11 @@ interface TemplateProps { } const Template: Story = (args) => { - return ; + return ( + + + + ); }; export const Default = Template.bind({}); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/new_terms_fields/new_terms_fields.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/new_terms_fields/new_terms_fields.stories.tsx index 8f77a747fa06c..f3dc5a1e3da9b 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/new_terms_fields/new_terms_fields.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/new_terms_fields/new_terms_fields.stories.tsx @@ -11,6 +11,7 @@ import { NewTermsFieldsReadOnly } from './new_terms_fields'; import { FieldReadOnly } from '../../field_readonly'; import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { mockNewTermsRule } from '../../storybook/mocks'; +import { ThreeWayDiffStorybookProviders } from '../../storybook/three_way_diff_storybook_providers'; export default { component: NewTermsFieldsReadOnly, @@ -23,7 +24,11 @@ interface TemplateProps { } const Template: Story = (args) => { - return ; + return ( + + + + ); }; export const Default = Template.bind({}); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/note/note.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/note/note.stories.tsx index 501faeb1cfbad..4a62c5e58dc28 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/note/note.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/note/note.stories.tsx @@ -11,6 +11,7 @@ import { NoteReadOnly } from './note'; import { FieldReadOnly } from '../../field_readonly'; import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { mockCustomQueryRule } from '../../storybook/mocks'; +import { ThreeWayDiffStorybookProviders } from '../../storybook/three_way_diff_storybook_providers'; export default { component: NoteReadOnly, @@ -22,7 +23,11 @@ interface TemplateProps { } const Template: Story = (args) => { - return ; + return ( + + + + ); }; export const Default = Template.bind({}); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/references/references.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/references/references.stories.tsx index 561d5b36cf4f3..ea8ee856099dd 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/references/references.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/references/references.stories.tsx @@ -11,6 +11,7 @@ import { ReferencesReadOnly } from './references'; import { FieldReadOnly } from '../../field_readonly'; import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { mockCustomQueryRule } from '../../storybook/mocks'; +import { ThreeWayDiffStorybookProviders } from '../../storybook/three_way_diff_storybook_providers'; export default { component: ReferencesReadOnly, @@ -22,7 +23,11 @@ interface TemplateProps { } const Template: Story = (args) => { - return ; + return ( + + + + ); }; export const Default = Template.bind({}); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/related_integrations/related_integrations.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/related_integrations/related_integrations.stories.tsx index 4657b21b0c64e..b810eaa1fbb8f 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/related_integrations/related_integrations.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/related_integrations/related_integrations.stories.tsx @@ -45,12 +45,9 @@ interface TemplateProps { const Template: Story = (args) => { return ( - + - + ); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/required_fields/required_fields.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/required_fields/required_fields.stories.tsx index 44d3383ae8227..ee926fc7ed561 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/required_fields/required_fields.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/required_fields/required_fields.stories.tsx @@ -10,6 +10,7 @@ import { RequiredFieldsReadOnly } from './required_fields'; import { FieldReadOnly } from '../../field_readonly'; import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { mockCustomQueryRule } from '../../storybook/mocks'; +import { ThreeWayDiffStorybookProviders } from '../../storybook/three_way_diff_storybook_providers'; export default { component: RequiredFieldsReadOnly, @@ -21,7 +22,11 @@ interface TemplateProps { } const Template: Story = (args) => { - return ; + return ( + + + + ); }; export const Default = Template.bind({}); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/risk_score/risk_score.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/risk_score/risk_score.stories.tsx index c0be0fb6190f6..cb640e31090cc 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/risk_score/risk_score.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/risk_score/risk_score.stories.tsx @@ -11,6 +11,7 @@ import { RiskScoreReadOnly } from './risk_score'; import { FieldReadOnly } from '../../field_readonly'; import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { mockCustomQueryRule } from '../../storybook/mocks'; +import { ThreeWayDiffStorybookProviders } from '../../storybook/three_way_diff_storybook_providers'; export default { component: RiskScoreReadOnly, @@ -22,7 +23,11 @@ interface TemplateProps { } const Template: Story = (args) => { - return ; + return ( + + + + ); }; export const Default = Template.bind({}); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/risk_score_mapping/risk_score_mapping.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/risk_score_mapping/risk_score_mapping.stories.tsx index 40c8644ffd3ea..90dbe7f981f64 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/risk_score_mapping/risk_score_mapping.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/risk_score_mapping/risk_score_mapping.stories.tsx @@ -11,6 +11,7 @@ import { FieldReadOnly } from '../../field_readonly'; import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { RiskScoreMappingReadOnly } from './risk_score_mapping'; import { mockCustomQueryRule } from '../../storybook/mocks'; +import { ThreeWayDiffStorybookProviders } from '../../storybook/three_way_diff_storybook_providers'; export default { component: RiskScoreMappingReadOnly, @@ -24,7 +25,9 @@ interface TemplateProps { const Template: Story = (args) => { return ( - + + + ); }; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/rule_name_override/rule_name_override.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/rule_name_override/rule_name_override.stories.tsx index fa46e313fd664..d0d596f15af42 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/rule_name_override/rule_name_override.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/rule_name_override/rule_name_override.stories.tsx @@ -11,6 +11,7 @@ import { RuleNameOverrideReadOnly } from './rule_name_override'; import { FieldReadOnly } from '../../field_readonly'; import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { mockCustomQueryRule } from '../../storybook/mocks'; +import { ThreeWayDiffStorybookProviders } from '../../storybook/three_way_diff_storybook_providers'; export default { component: RuleNameOverrideReadOnly, @@ -24,7 +25,9 @@ interface TemplateProps { const Template: Story = (args) => { return ( - + + + ); }; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/rule_schedule/rule_schedule.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/rule_schedule/rule_schedule.stories.tsx index 9e6be8a3cbe82..30f2170a30f31 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/rule_schedule/rule_schedule.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/rule_schedule/rule_schedule.stories.tsx @@ -11,6 +11,7 @@ import { RuleScheduleReadOnly } from './rule_schedule'; import { FieldReadOnly } from '../../field_readonly'; import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { mockCustomQueryRule } from '../../storybook/mocks'; +import { ThreeWayDiffStorybookProviders } from '../../storybook/three_way_diff_storybook_providers'; export default { component: RuleScheduleReadOnly, @@ -22,7 +23,11 @@ interface TemplateProps { } const Template: Story = (args) => { - return ; + return ( + + + + ); }; export const Default = Template.bind({}); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/setup/setup.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/setup/setup.stories.tsx index f610cbf9eafbb..34410c7c6f638 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/setup/setup.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/setup/setup.stories.tsx @@ -11,6 +11,7 @@ import { SetupReadOnly } from './setup'; import { FieldReadOnly } from '../../field_readonly'; import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { mockCustomQueryRule } from '../../storybook/mocks'; +import { ThreeWayDiffStorybookProviders } from '../../storybook/three_way_diff_storybook_providers'; export default { component: SetupReadOnly, @@ -22,7 +23,11 @@ interface TemplateProps { } const Template: Story = (args) => { - return ; + return ( + + + + ); }; export const Default = Template.bind({}); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/severity/severity.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/severity/severity.stories.tsx index 51956bb27fa0e..b51547d1655e0 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/severity/severity.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/severity/severity.stories.tsx @@ -11,6 +11,7 @@ import { SeverityReadOnly } from './severity'; import { FieldReadOnly } from '../../field_readonly'; import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { mockCustomQueryRule } from '../../storybook/mocks'; +import { ThreeWayDiffStorybookProviders } from '../../storybook/three_way_diff_storybook_providers'; export default { component: SeverityReadOnly, @@ -22,7 +23,11 @@ interface TemplateProps { } const Template: Story = (args) => { - return ; + return ( + + + + ); }; export const Default = Template.bind({}); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/severity_mapping/severity_mapping.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/severity_mapping/severity_mapping.stories.tsx index 6a4b365a86db5..b4ecb70ce66cd 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/severity_mapping/severity_mapping.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/severity_mapping/severity_mapping.stories.tsx @@ -11,6 +11,7 @@ import { FieldReadOnly } from '../../field_readonly'; import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { SeverityMappingReadOnly } from './severity_mapping'; import { mockCustomQueryRule } from '../../storybook/mocks'; +import { ThreeWayDiffStorybookProviders } from '../../storybook/three_way_diff_storybook_providers'; export default { component: SeverityMappingReadOnly, @@ -23,7 +24,11 @@ interface TemplateProps { } const Template: Story = (args) => { - return ; + return ( + + + + ); }; export const Default = Template.bind({}); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/tags/tags.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/tags/tags.stories.tsx index b2c483cbc8c97..c8129dd989d24 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/tags/tags.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/tags/tags.stories.tsx @@ -11,6 +11,7 @@ import { TagsReadOnly } from './tags'; import { FieldReadOnly } from '../../field_readonly'; import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { mockCustomQueryRule } from '../../storybook/mocks'; +import { ThreeWayDiffStorybookProviders } from '../../storybook/three_way_diff_storybook_providers'; export default { component: TagsReadOnly, @@ -22,7 +23,11 @@ interface TemplateProps { } const Template: Story = (args) => { - return ; + return ( + + + + ); }; export const Default = Template.bind({}); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat/threat.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat/threat.stories.tsx index aa95633349260..de8c15f29e0cc 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat/threat.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat/threat.stories.tsx @@ -11,6 +11,7 @@ import { FieldReadOnly } from '../../field_readonly'; import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { ThreatReadOnly } from './threat'; import { mockCustomQueryRule } from '../../storybook/mocks'; +import { ThreeWayDiffStorybookProviders } from '../../storybook/three_way_diff_storybook_providers'; export default { component: ThreatReadOnly, @@ -22,7 +23,11 @@ interface TemplateProps { } const Template: Story = (args) => { - return ; + return ( + + + + ); }; export const Default = Template.bind({}); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_index/threat_index.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_index/threat_index.stories.tsx index 4f10cb8932ab1..aeb1b6491bba6 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_index/threat_index.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_index/threat_index.stories.tsx @@ -11,6 +11,7 @@ import { FieldReadOnly } from '../../field_readonly'; import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { ThreatIndexReadOnly } from './threat_index'; import { mockThreatMatchRule } from '../../storybook/mocks'; +import { ThreeWayDiffStorybookProviders } from '../../storybook/three_way_diff_storybook_providers'; export default { component: ThreatIndexReadOnly, @@ -22,7 +23,11 @@ interface TemplateProps { } const Template: Story = (args) => { - return ; + return ( + + + + ); }; export const Default = Template.bind({}); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_indicator_path/threat_indicator_path.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_indicator_path/threat_indicator_path.stories.tsx index be8906d76eb6b..bb91b29fffe11 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_indicator_path/threat_indicator_path.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_indicator_path/threat_indicator_path.stories.tsx @@ -11,6 +11,7 @@ import { FieldReadOnly } from '../../field_readonly'; import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { ThreatIndicatorPathReadOnly } from './threat_indicator_path'; import { mockThreatMatchRule } from '../../storybook/mocks'; +import { ThreeWayDiffStorybookProviders } from '../../storybook/three_way_diff_storybook_providers'; export default { component: ThreatIndicatorPathReadOnly, @@ -24,7 +25,9 @@ interface TemplateProps { const Template: Story = (args) => { return ( - + + + ); }; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_language/threat_language.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_language/threat_language.stories.tsx index 0e3408aae043e..bae9f596de750 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_language/threat_language.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_language/threat_language.stories.tsx @@ -11,6 +11,7 @@ import { ThreatLanguageReadOnly } from './threat_language'; import { FieldReadOnly } from '../../field_readonly'; import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { mockThreatMatchRule } from '../../storybook/mocks'; +import { ThreeWayDiffStorybookProviders } from '../../storybook/three_way_diff_storybook_providers'; export default { component: ThreatLanguageReadOnly, @@ -22,7 +23,11 @@ interface TemplateProps { } const Template: Story = (args) => { - return ; + return ( + + + + ); }; export const Default = Template.bind({}); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_mapping/threat_mapping.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_mapping/threat_mapping.stories.tsx index 4f5b8f608c4bf..35c4bba4544a7 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_mapping/threat_mapping.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_mapping/threat_mapping.stories.tsx @@ -11,6 +11,7 @@ import { FieldReadOnly } from '../../field_readonly'; import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { ThreatMappingReadOnly } from './threat_mapping'; import { mockThreatMatchRule } from '../../storybook/mocks'; +import { ThreeWayDiffStorybookProviders } from '../../storybook/three_way_diff_storybook_providers'; export default { component: ThreatMappingReadOnly, @@ -22,7 +23,11 @@ interface TemplateProps { } const Template: Story = (args) => { - return ; + return ( + + + + ); }; export const Default = Template.bind({}); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_query/threat_query.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_query/threat_query.stories.tsx index bbc5b19d7e66a..625226ab4f9f5 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_query/threat_query.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_query/threat_query.stories.tsx @@ -31,8 +31,11 @@ interface TemplateProps { const Template: Story = (args) => { return ( - - + + ); }; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threshold/threshold.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threshold/threshold.stories.tsx index 8dfee48ba7d23..0541d5f9a9b47 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threshold/threshold.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threshold/threshold.stories.tsx @@ -11,6 +11,7 @@ import { ThresholdReadOnly } from './threshold'; import { FieldReadOnly } from '../../field_readonly'; import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { mockThresholdRule } from '../../storybook/mocks'; +import { ThreeWayDiffStorybookProviders } from '../../storybook/three_way_diff_storybook_providers'; export default { component: ThresholdReadOnly, @@ -22,7 +23,11 @@ interface TemplateProps { } const Template: Story = (args) => { - return ; + return ( + + + + ); }; export const Default = Template.bind({}); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/tiebreaker_field/tiebreaker_field.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/tiebreaker_field/tiebreaker_field.stories.tsx index 2a41b6c928963..3e73afda8f4eb 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/tiebreaker_field/tiebreaker_field.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/tiebreaker_field/tiebreaker_field.stories.tsx @@ -11,6 +11,7 @@ import { TiebreakerFieldReadOnly } from './tiebreaker_field'; import { FieldReadOnly } from '../../field_readonly'; import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { mockEqlRule } from '../../storybook/mocks'; +import { ThreeWayDiffStorybookProviders } from '../../storybook/three_way_diff_storybook_providers'; export default { component: TiebreakerFieldReadOnly, @@ -23,7 +24,11 @@ interface TemplateProps { } const Template: Story = (args) => { - return ; + return ( + + + + ); }; export const Default = Template.bind({}); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timeline_template/timeline_template.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timeline_template/timeline_template.stories.tsx index e8646a562dadd..e4c3a2043ff24 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timeline_template/timeline_template.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timeline_template/timeline_template.stories.tsx @@ -11,6 +11,7 @@ import { TimelineTemplateReadOnly } from './timeline_template'; import { FieldReadOnly } from '../../field_readonly'; import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { mockCustomQueryRule } from '../../storybook/mocks'; +import { ThreeWayDiffStorybookProviders } from '../../storybook/three_way_diff_storybook_providers'; export default { component: TimelineTemplateReadOnly, @@ -23,7 +24,11 @@ interface TemplateProps { } const Template: Story = (args) => { - return ; + return ( + + + + ); }; export const Default = Template.bind({}); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timestamp_field/timestamp_field.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timestamp_field/timestamp_field.stories.tsx index 5d6b6c0a7bc3a..9b3977c3deeb2 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timestamp_field/timestamp_field.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timestamp_field/timestamp_field.stories.tsx @@ -11,6 +11,7 @@ import { TimestampFieldReadOnly } from './timestamp_field'; import { FieldReadOnly } from '../../field_readonly'; import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { mockEqlRule } from '../../storybook/mocks'; +import { ThreeWayDiffStorybookProviders } from '../../storybook/three_way_diff_storybook_providers'; export default { component: TimestampFieldReadOnly, @@ -22,7 +23,11 @@ interface TemplateProps { } const Template: Story = (args) => { - return ; + return ( + + + + ); }; export const Default = Template.bind({}); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timestamp_override/timestamp_override.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timestamp_override/timestamp_override.stories.tsx index eaba3bda0c2e7..5828ba156d9d2 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timestamp_override/timestamp_override.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timestamp_override/timestamp_override.stories.tsx @@ -11,6 +11,7 @@ import { TimestampOverrideReadOnly } from './timestamp_override'; import { FieldReadOnly } from '../../field_readonly'; import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { mockCustomQueryRule } from '../../storybook/mocks'; +import { ThreeWayDiffStorybookProviders } from '../../storybook/three_way_diff_storybook_providers'; export default { component: TimestampOverrideReadOnly, @@ -24,7 +25,9 @@ interface TemplateProps { const Template: Story = (args) => { return ( - + + + ); }; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/type/type.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/type/type.stories.tsx index e3f901c958788..ba252a8a80b88 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/type/type.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/type/type.stories.tsx @@ -11,6 +11,7 @@ import { TypeReadOnly } from './type'; import { FieldReadOnly } from '../../field_readonly'; import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { mockCustomQueryRule } from '../../storybook/mocks'; +import { ThreeWayDiffStorybookProviders } from '../../storybook/three_way_diff_storybook_providers'; export default { component: TypeReadOnly, @@ -22,7 +23,11 @@ interface TemplateProps { } const Template: Story = (args) => { - return ; + return ( + + + + ); }; export const Default = Template.bind({}); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/final_readonly.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/final_readonly.tsx new file mode 100644 index 0000000000000..21b8475fe3002 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/final_readonly.tsx @@ -0,0 +1,25 @@ +/* + * 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 { EuiButtonEmpty } from '@elastic/eui'; +import React from 'react'; +import { FieldReadOnly } from './field_readonly'; +import * as i18n from '../translations'; +import { useFinalSideContext } from '../final_side/final_side_context'; + +export function FinalReadOnly() { + const { setEditMode, fieldName } = useFinalSideContext(); + + return ( + <> + + {i18n.EDIT_BUTTON_LABEL} + + + + ); +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/storybook/mocks.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/storybook/mocks.ts index 4612852c0ff7e..e940f1ba52a40 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/storybook/mocks.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/storybook/mocks.ts @@ -159,7 +159,7 @@ const customQueryDiffableRuleFields: DiffableCustomQueryFields = { }; export function mockCustomQueryRule( - overrides: Partial + overrides: Partial = {} ): DiffableRule { return { ...commonDiffableRuleFields, @@ -177,7 +177,7 @@ const savedQueryDiffableRuleFields: DiffableSavedQueryFields = { }; export function mockSavedQueryRule( - overrides: Partial + overrides: Partial = {} ): DiffableRule { return { ...commonDiffableRuleFields, @@ -196,7 +196,7 @@ const eqlDiffableRuleFields: DiffableEqlFields = { }; export function mockEqlRule( - overrides: Partial + overrides: Partial = {} ): DiffableRule { return { ...commonDiffableRuleFields, @@ -214,7 +214,7 @@ const esqlDiffableRuleFields: DiffableEsqlFields = { }; export function mockEsqlRule( - overrides: Partial + overrides: Partial = {} ): DiffableRule { return { ...commonDiffableRuleFields, @@ -230,7 +230,7 @@ const machineLearningDiffableRuleFields: DiffableMachineLearningFields = { }; export function mockMachineLearningRule( - overrides: Partial + overrides: Partial = {} ): DiffableRule { return { ...commonDiffableRuleFields, @@ -268,7 +268,7 @@ const threatMatchDiffableRuleFields: DiffableThreatMatchFields = { }; export function mockThreatMatchRule( - overrides: Partial + overrides: Partial = {} ): DiffableRule { return { ...commonDiffableRuleFields, @@ -290,7 +290,7 @@ const newTermsDiffableRuleFields: DiffableNewTermsFields = { }; export function mockNewTermsRule( - overrides: Partial + overrides: Partial = {} ): DiffableRule { return { ...commonDiffableRuleFields, @@ -314,7 +314,7 @@ export const thresholdDiffableRuleFields: DiffableThresholdFields = { }; export function mockThresholdRule( - overrides: Partial + overrides: Partial = {} ): DiffableRule { return { ...commonDiffableRuleFields, diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/storybook/three_way_diff_storybook_providers.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/storybook/three_way_diff_storybook_providers.tsx index 4eb14440c056c..722f5ac9f6ada 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/storybook/three_way_diff_storybook_providers.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/storybook/three_way_diff_storybook_providers.tsx @@ -15,6 +15,9 @@ import type { UpsellingService } from '@kbn/security-solution-upselling/service' import { createKibanaReactContext } from '@kbn/kibana-react-plugin/public'; import { ReactQueryClientProvider } from '../../../../../../../common/containers/query_client/query_client_provider'; import { UpsellingProvider } from '../../../../../../../common/components/upselling_provider'; +import { DiffableRuleContextProvider } from '../../diffable_rule_context'; +import type { DiffableRule } from '../../../../../../../../common/api/detection_engine'; +import { mockCustomQueryRule } from './mocks'; function createKibanaServicesMock(overrides?: Partial) { const baseMock = { @@ -69,14 +72,18 @@ function createMockStore() { return store; } +const setRuleFieldResolvedValueMock = () => {}; + interface StorybookProvidersProps { children: React.ReactNode; kibanaServicesOverrides?: Record; + finalDiffableRule?: DiffableRule; } export function ThreeWayDiffStorybookProviders({ children, kibanaServicesOverrides, + finalDiffableRule = mockCustomQueryRule(), }: StorybookProvidersProps) { const kibanaServicesMock = createKibanaServicesMock(kibanaServicesOverrides); const KibanaReactContext = createKibanaReactContext(kibanaServicesMock); @@ -88,7 +95,12 @@ export function ThreeWayDiffStorybookProviders({ - {children} + + {children} + diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_side/constants.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_side/constants.ts new file mode 100644 index 0000000000000..6316abcae48a3 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_side/constants.ts @@ -0,0 +1,11 @@ +/* + * 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. + */ + +export enum FinalSideMode { + READONLY = 'readonly', + EDIT = 'edit', +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_side/final_side.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_side/final_side.tsx index 83190015ebc6d..30e3f4461195a 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_side/final_side.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_side/final_side.tsx @@ -7,18 +7,21 @@ import React from 'react'; import { EuiTitle } from '@elastic/eui'; -import type { DiffableRule } from '../../../../../../../common/api/detection_engine'; -import { FieldReadOnly } from '../final_readonly/field_readonly'; import { SideHeader } from '../components/side_header'; import { FinalSideHelpInfo } from './final_side_help_info'; import * as i18n from './translations'; +import { FinalReadOnly } from '../final_readonly/final_readonly'; +import { FinalEdit } from '../final_edit/final_edit'; +import { FinalSideMode } from './constants'; +import type { UpgradeableDiffableFields } from '../../../../model/prebuilt_rule_upgrade/fields'; +import { assertUnreachable } from '../../../../../../../common/utility_types'; +import { FinalSideContextProvider, useFinalSideContext } from './final_side_context'; interface FinalSideProps { - fieldName: string; - finalDiffableRule: DiffableRule; + fieldName: UpgradeableDiffableFields; } -export function FinalSide({ fieldName, finalDiffableRule }: FinalSideProps): JSX.Element { +export function FinalSide({ fieldName }: FinalSideProps): JSX.Element { return ( <> @@ -29,7 +32,22 @@ export function FinalSide({ fieldName, finalDiffableRule }: FinalSideProps): JSX - + + + ); } + +function FinalSideContent(): JSX.Element { + const { mode } = useFinalSideContext(); + + switch (mode) { + case FinalSideMode.READONLY: + return ; + case FinalSideMode.EDIT: + return ; + default: + return assertUnreachable(mode); + } +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_side/final_side_context.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_side/final_side_context.tsx new file mode 100644 index 0000000000000..6beb0535e5e27 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_side/final_side_context.tsx @@ -0,0 +1,50 @@ +/* + * 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, { createContext, useContext, type PropsWithChildren, useCallback } from 'react'; +import { invariant } from '../../../../../../../common/utils/invariant'; +import { FinalSideMode } from './constants'; +import type { UpgradeableDiffableFields } from '../../../../model/prebuilt_rule_upgrade/fields'; + +interface FinalSideContextType { + fieldName: UpgradeableDiffableFields; + mode: FinalSideMode; + setReadOnlyMode: () => void; + setEditMode: () => void; +} + +const FinalSideContext = createContext(null); + +interface FinalSideContextProviderProps { + fieldName: UpgradeableDiffableFields; +} + +export function FinalSideContextProvider({ + children, + fieldName, +}: PropsWithChildren) { + const [mode, setMode] = React.useState(FinalSideMode.READONLY); + const setReadOnlyMode = useCallback(() => setMode(FinalSideMode.READONLY), []); + const setEditMode = useCallback(() => setMode(FinalSideMode.EDIT), []); + + const contextValue = { + fieldName, + setReadOnlyMode, + setEditMode, + mode, + }; + + return {children}; +} + +export function useFinalSideContext() { + const context = useContext(FinalSideContext); + + invariant(context !== null, 'useFinalSideContext must be used inside a FinalSideContextProvider'); + + return context; +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/rule_upgrade_conflicts_resolver_tab.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/rule_upgrade_conflicts_resolver_tab.tsx index 547cd23c7e86e..95fa407fb7ca2 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/rule_upgrade_conflicts_resolver_tab.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/rule_upgrade_conflicts_resolver_tab.tsx @@ -13,6 +13,7 @@ import type { } from '../../../model/prebuilt_rule_upgrade'; import { RuleUpgradeInfoBar } from './components/rule_upgrade_info_bar'; import { RuleUpgradeConflictsResolver } from './components/rule_upgrade_conflicts_resolver'; +import { DiffableRuleContextProvider } from './diffable_rule_context'; import { RuleUpgradeCallout } from './components/rule_upgrade_callout'; interface RuleUpgradeConflictsResolverTabProps { @@ -25,16 +26,16 @@ export function RuleUpgradeConflictsResolverTab({ setRuleFieldResolvedValue, }: RuleUpgradeConflictsResolverTabProps): JSX.Element { return ( - <> + - - + + ); } diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/translations.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/translations.ts new file mode 100644 index 0000000000000..ced733d87ff6e --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/translations.ts @@ -0,0 +1,29 @@ +/* + * 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 { i18n } from '@kbn/i18n'; + +export const CANCEL_BUTTON_LABEL = i18n.translate( + 'xpack.securitySolution.detectionEngine.rules.upgradeRules.cancelButtonLabel', + { + defaultMessage: 'Cancel', + } +); + +export const SAVE_BUTTON_LABEL = i18n.translate( + 'xpack.securitySolution.detectionEngine.rules.upgradeRules.saveButtonLabel', + { + defaultMessage: 'Save', + } +); + +export const EDIT_BUTTON_LABEL = i18n.translate( + 'xpack.securitySolution.detectionEngine.rules.upgradeRules.editButtonLabel', + { + defaultMessage: 'Edit', + } +); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/model/prebuilt_rule_upgrade/fields.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management/model/prebuilt_rule_upgrade/fields.ts new file mode 100644 index 0000000000000..c384b48a79d4f --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/model/prebuilt_rule_upgrade/fields.ts @@ -0,0 +1,82 @@ +/* + * 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 { DiffableCommonFields } from '../../../../../common/api/detection_engine'; +import type { + DiffableCustomQueryFields, + DiffableEqlFields, + DiffableEsqlFields, + DiffableMachineLearningFields, + DiffableNewTermsFields, + DiffableSavedQueryFields, + DiffableThreatMatchFields, + DiffableThresholdFields, + RuleFieldsDiff, +} from '../../../../../common/api/detection_engine'; + +export type NonUpgradeableDiffableFields = (typeof NON_UPGRADEABLE_DIFFABLE_FIELDS)[number]; + +export type UpgradeableDiffableFields = Exclude; + +export type UpgradeableCommonFields = Exclude< + keyof DiffableCommonFields, + NonUpgradeableDiffableFields +>; + +export type UpgradeableCustomQueryFields = Exclude< + keyof DiffableCustomQueryFields, + NonUpgradeableDiffableFields +>; + +export type UpgradeableSavedQueryFields = Exclude< + keyof DiffableSavedQueryFields, + NonUpgradeableDiffableFields +>; + +export type UpgradeableEqlFields = Exclude; + +export type UpgradeableEsqlFields = Exclude; + +export type UpgradeableThreatMatchFields = Exclude< + keyof DiffableThreatMatchFields, + NonUpgradeableDiffableFields +>; + +export type UpgradeableThresholdFields = Exclude< + keyof DiffableThresholdFields, + NonUpgradeableDiffableFields +>; + +export type UpgradeableMachineLearningFields = Exclude< + keyof DiffableMachineLearningFields, + NonUpgradeableDiffableFields +>; + +export type UpgradeableNewTermsFields = Exclude< + keyof DiffableNewTermsFields, + NonUpgradeableDiffableFields +>; + +export const NON_UPGRADEABLE_DIFFABLE_FIELDS = [ + 'author', + 'license', + 'rule_id', + 'type', + 'version', +] as const; + +export const COMMON_FIELD_NAMES = DiffableCommonFields.keyof().options; + +export function isCommonFieldName(fieldName: string): fieldName is keyof DiffableCommonFields { + return (COMMON_FIELD_NAMES as string[]).includes(fieldName); +} + +export function isNonUpgradeableFieldName( + fieldName: string +): fieldName is NonUpgradeableDiffableFields { + return (NON_UPGRADEABLE_DIFFABLE_FIELDS as Readonly).includes(fieldName); +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/model/prebuilt_rule_upgrade/set_rule_field_resolved_value.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management/model/prebuilt_rule_upgrade/set_rule_field_resolved_value.ts index c4bb65f162394..6040e471435fe 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/model/prebuilt_rule_upgrade/set_rule_field_resolved_value.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/model/prebuilt_rule_upgrade/set_rule_field_resolved_value.ts @@ -5,12 +5,15 @@ * 2.0. */ -import type { DiffableAllFields, RuleObjectId } from '../../../../../common/api/detection_engine'; +import type { + DiffableAllFields, + RuleSignatureId, +} from '../../../../../common/api/detection_engine'; export type SetRuleFieldResolvedValueFn< FieldName extends keyof DiffableAllFields = keyof DiffableAllFields > = (params: { - ruleId: RuleObjectId; + ruleId: RuleSignatureId; fieldName: FieldName; resolvedValue: DiffableAllFields[FieldName]; }) => void; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/use_prebuilt_rules_upgrade_state.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/use_prebuilt_rules_upgrade_state.ts index 202019b394cd0..d44f9738b1fd6 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/use_prebuilt_rules_upgrade_state.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/use_prebuilt_rules_upgrade_state.ts @@ -12,12 +12,12 @@ import type { SetRuleFieldResolvedValueFn, } from '../../../../rule_management/model/prebuilt_rule_upgrade'; import { FieldUpgradeState } from '../../../../rule_management/model/prebuilt_rule_upgrade'; -import type { FieldsDiff } from '../../../../../../common/api/detection_engine'; import { - ThreeWayDiffConflict, + type FieldsDiff, type DiffableAllFields, type DiffableRule, type RuleUpgradeInfoForReview, + ThreeWayDiffConflict, } from '../../../../../../common/api/detection_engine'; import { convertRuleToDiffable } from '../../../../../../common/detection_engine/prebuilt_rules/diff/convert_rule_to_diffable'; @@ -33,6 +33,7 @@ export function usePrebuiltRulesUpgradeState( ruleUpgradeInfos: RuleUpgradeInfoForReview[] ): UseRulesUpgradeStateResult { const [rulesResolvedConflicts, setRulesResolvedConflicts] = useState({}); + const setRuleFieldResolvedValue = useCallback( (...[params]: Parameters) => { setRulesResolvedConflicts((prevRulesResolvedConflicts) => ({ @@ -45,6 +46,7 @@ export function usePrebuiltRulesUpgradeState( }, [] ); + const rulesUpgradeState = useMemo(() => { const state: RulesUpgradeState = {}; @@ -88,7 +90,7 @@ function calcFinalDiffableRule( } /** - * Assembles a `DiffableRule` from rule fields diff `merge_value`s. + * Assembles a `DiffableRule` from rule fields diff `merged_version`s. */ function convertRuleFieldsDiffToDiffable( ruleFieldsDiff: FieldsDiff> diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/use_rule_preview_flyout.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/use_rule_preview_flyout.tsx index ccdfd5c39177e..d6dcdd0592b85 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/use_rule_preview_flyout.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/use_rule_preview_flyout.tsx @@ -9,7 +9,7 @@ import type { ReactNode } from 'react'; import React, { useCallback, useState, useMemo } from 'react'; import type { EuiTabbedContentTab } from '@elastic/eui'; import { invariant } from '../../../../../common/utils/invariant'; -import type { RuleObjectId } from '../../../../../common/api/detection_engine'; +import type { RuleSignatureId } from '../../../../../common/api/detection_engine'; import type { RuleResponse } from '../../../../../common/api/detection_engine/model/rule_schema'; import { RuleDetailsFlyout } from '../../../rule_management/components/rule_details/rule_details_flyout'; @@ -30,7 +30,7 @@ interface RulePreviewFlyoutProps { interface UseRulePreviewFlyoutResult { rulePreviewFlyout: ReactNode; - openRulePreview: (ruleId: RuleObjectId) => void; + openRulePreview: (ruleId: RuleSignatureId) => void; closeRulePreview: () => void; } @@ -64,7 +64,7 @@ export function useRulePreviewFlyout({ /> ), openRulePreview: useCallback( - (ruleId: RuleObjectId) => { + (ruleId: RuleSignatureId) => { const ruleToShowInFlyout = rules.find((x) => x.id === ruleId); invariant(ruleToShowInFlyout, `Rule with id ${ruleId} not found`);