mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[Security Solution] FinalEdit
: Add name
and kql_query
fields + shared components (#193828)
**Partially addresses: https://github.com/elastic/kibana/issues/171520** **Is a follow-up PR to: https://github.com/elastic/kibana/pull/192342** ## Summary Changes: - Adds editable components for `name` and `kql_query` fields - Adds a `FieldFormWrapper` component that abstracts away form creation and data preparation for each field - Adds local context providers to pass data between the main context and field components - Adds some basic layout components to make the "edit" functionality work <img width="1392" alt="Schermafbeelding 2024-10-04 om 17 17 44" src="https://github.com/user-attachments/assets/6272ac84-8159-4b8a-a0d4-88b458f4bc5f"> --------- Co-authored-by: Maxim Palenov <maxim.palenov@elastic.co>
This commit is contained in:
parent
37c1bb1e9d
commit
424ffbaffc
74 changed files with 1242 additions and 118 deletions
|
@ -24,7 +24,7 @@ import * as i18n from './translations';
|
|||
interface ComparisonSideProps<FieldName extends keyof DiffableAllFields> {
|
||||
fieldName: FieldName;
|
||||
fieldThreeWayDiff: ThreeWayDiff<DiffableAllFields[FieldName]>;
|
||||
resolvedValue?: DiffableAllFields[FieldName];
|
||||
resolvedValue: DiffableAllFields[FieldName];
|
||||
}
|
||||
|
||||
export function ComparisonSide<FieldName extends keyof DiffableAllFields>({
|
||||
|
@ -39,6 +39,7 @@ export function ComparisonSide<FieldName extends keyof DiffableAllFields>({
|
|||
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);
|
||||
|
|
|
@ -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<FieldName extends keyof DiffableAllFields>(
|
||||
version: Version,
|
||||
fieldThreeWayDiff: ThreeWayDiff<DiffableAllFields[FieldName]>,
|
||||
resolvedValue?: DiffableAllFields[FieldName]
|
||||
resolvedValue: DiffableAllFields[FieldName]
|
||||
): DiffableAllFields[FieldName] | undefined {
|
||||
if (version === Version.Final) {
|
||||
return resolvedValue;
|
||||
|
|
|
@ -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<Set<keyof DiffableAllFields>>;
|
||||
|
||||
/* 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',
|
||||
]);
|
|
@ -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<FieldName extends keyof RuleFieldsDiff> {
|
||||
interface FieldUpgradeConflictsResolverProps<FieldName extends UpgradeableDiffableFields> {
|
||||
fieldName: FieldName;
|
||||
fieldUpgradeState: FieldUpgradeState;
|
||||
fieldThreeWayDiff: RuleFieldsDiff[FieldName];
|
||||
finalDiffableRule: DiffableRule;
|
||||
}
|
||||
|
||||
export function FieldUpgradeConflictsResolver<FieldName extends keyof RuleFieldsDiff>({
|
||||
export function FieldUpgradeConflictsResolver<FieldName extends UpgradeableDiffableFields>({
|
||||
fieldName,
|
||||
fieldUpgradeState,
|
||||
fieldThreeWayDiff,
|
||||
finalDiffableRule,
|
||||
}: FieldUpgradeConflictsResolverProps<FieldName>): JSX.Element {
|
||||
const { euiTheme } = useEuiTheme();
|
||||
const hasConflict = fieldThreeWayDiff.conflict !== ThreeWayDiffConflict.NONE;
|
||||
|
||||
const { finalDiffableRule } = useDiffableRuleContext();
|
||||
|
||||
return (
|
||||
<>
|
||||
<SplitAccordion
|
||||
|
@ -65,7 +66,7 @@ export function FieldUpgradeConflictsResolver<FieldName extends keyof RuleFields
|
|||
`}
|
||||
/>
|
||||
<EuiFlexItem grow={1}>
|
||||
<FinalSide fieldName={fieldName} finalDiffableRule={finalDiffableRule} />
|
||||
<FinalSide fieldName={fieldName} />
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</SplitAccordion>
|
||||
|
|
|
@ -64,7 +64,12 @@ export function RuleUpgradeCallout({ ruleUpgradeState }: RuleUpgradeCalloutProps
|
|||
}
|
||||
|
||||
return (
|
||||
<EuiCallOut title={i18n.RULE_IS_READY_FOR_UPGRADE} iconType="warning" color="success" size="s">
|
||||
<EuiCallOut
|
||||
title={i18n.RULE_IS_READY_FOR_UPGRADE}
|
||||
iconType="checkInCircleFilled"
|
||||
color="success"
|
||||
size="s"
|
||||
>
|
||||
<p>{i18n.RULE_IS_READY_FOR_UPGRADE_DESCRIPTION}</p>
|
||||
</EuiCallOut>
|
||||
);
|
||||
|
|
|
@ -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.',
|
||||
}
|
||||
);
|
||||
|
||||
|
|
|
@ -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<FieldsDiff, ExcludedFields extends keyof FieldsDiff = never> = Array<
|
||||
[
|
||||
Exclude<keyof FieldsDiff, ExcludedFields>,
|
||||
Required<FieldsDiff>[Exclude<keyof FieldsDiff, ExcludedFields>]
|
||||
]
|
||||
>;
|
||||
|
||||
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<typeof ruleUpgradeState.diff.fields>[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<typeof ruleUpgradeState.diff.fields, NonUpgradeableDiffableFields>;
|
||||
|
||||
return fields.map(([fieldName, fieldDiff]) => (
|
||||
<FieldUpgradeConflictsResolver
|
||||
key={fieldName}
|
||||
fieldName={fieldName}
|
||||
fieldUpgradeState={ruleUpgradeState.fieldsUpgradeState[fieldName]}
|
||||
fieldThreeWayDiff={fieldDiff}
|
||||
finalDiffableRule={ruleUpgradeState.finalRule}
|
||||
/>
|
||||
));
|
||||
|
||||
return <>{fields}</>;
|
||||
}
|
||||
|
|
|
@ -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<DiffableRuleContextType | null>(null);
|
||||
|
||||
interface DiffableRuleContextProviderProps {
|
||||
finalDiffableRule: DiffableRule;
|
||||
setRuleFieldResolvedValue: SetRuleFieldResolvedValueFn;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export function DiffableRuleContextProvider({
|
||||
finalDiffableRule,
|
||||
setRuleFieldResolvedValue,
|
||||
children,
|
||||
}: DiffableRuleContextProviderProps) {
|
||||
const contextValue = {
|
||||
finalDiffableRule,
|
||||
setRuleFieldResolvedValue,
|
||||
};
|
||||
|
||||
return (
|
||||
<DiffableRuleContext.Provider value={contextValue}>{children}</DiffableRuleContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export function useDiffableRuleContext() {
|
||||
const context = useContext(DiffableRuleContext);
|
||||
|
||||
invariant(
|
||||
context !== null,
|
||||
'useDiffableRuleContext must be used inside a DiffableRuleContextProvider'
|
||||
);
|
||||
|
||||
return context;
|
||||
}
|
|
@ -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 <FieldFormWrapper component={NameEdit} fieldFormSchema={nameSchema} />;
|
||||
default:
|
||||
return null; // Will be replaced with `assertUnreachable(fieldName)` once all fields are implemented
|
||||
}
|
||||
}
|
|
@ -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 (
|
||||
<FieldFormWrapper
|
||||
component={KqlQueryEdit}
|
||||
fieldFormSchema={kqlQuerySchema}
|
||||
serializer={kqlQuerySerializer}
|
||||
deserializer={kqlQueryDeserializer}
|
||||
/>
|
||||
);
|
||||
default:
|
||||
return null; // Will be replaced with `assertUnreachable(fieldName)` once all fields are implemented
|
||||
}
|
||||
}
|
|
@ -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<string, unknown>;
|
||||
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<boolean | undefined>(undefined);
|
||||
|
||||
const isValid = validity === undefined ? form.isValid : validity;
|
||||
|
||||
return (
|
||||
<>
|
||||
<EuiFlexGroup justifyContent="flexEnd">
|
||||
<EuiButtonEmpty iconType="cross" onClick={setReadOnlyMode}>
|
||||
{i18n.CANCEL_BUTTON_LABEL}
|
||||
</EuiButtonEmpty>
|
||||
<EuiButtonEmpty iconType="save" onClick={form.submit} disabled={isValid === false}>
|
||||
{i18n.SAVE_BUTTON_LABEL}
|
||||
</EuiButtonEmpty>
|
||||
</EuiFlexGroup>
|
||||
<Form form={form}>
|
||||
<FieldComponent
|
||||
finalDiffableRule={finalDiffableRule}
|
||||
setValidity={setValidity}
|
||||
setFieldValue={form.setFieldValue}
|
||||
/>
|
||||
</Form>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function getDefaultValue(fieldName: string, finalDiffableRule: Record<string, unknown>): FormData {
|
||||
return { [fieldName]: finalDiffableRule[fieldName] };
|
||||
}
|
|
@ -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<SetRuleQuery>(
|
||||
({ 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 (
|
||||
<>
|
||||
<UseField path="ruleType" component={HiddenField} />
|
||||
<UseField
|
||||
path="queryBar"
|
||||
config={{
|
||||
...kqlQuerySchema.queryBar,
|
||||
label: stepDefineRuleI18n.QUERY_BAR_LABEL,
|
||||
labelAppend: isSavedQueryRule ? null : (
|
||||
<ImportTimelineQueryButton handleOpenTimelineSearch={toggleIsTimelineSearchOpen} />
|
||||
),
|
||||
}}
|
||||
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 (
|
||||
<EuiButtonEmpty className={timelineButtonClassName} onClick={handleOpenTimelineSearch}>
|
||||
{stepDefineRuleI18n.IMPORT_TIMELINE_QUERY}
|
||||
</EuiButtonEmpty>
|
||||
);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
|
@ -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 (
|
||||
<UseField
|
||||
path="name"
|
||||
component={Field}
|
||||
componentProps={{
|
||||
euiFieldProps: {
|
||||
fullWidth: true,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
|
@ -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 <CommonRuleFieldEdit fieldName={fieldName} />;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case 'query':
|
||||
return <CustomQueryRuleFieldEdit fieldName={fieldName as UpgradeableCustomQueryFields} />;
|
||||
case 'saved_query':
|
||||
return <SavedQueryRuleFieldEdit fieldName={fieldName as UpgradeableSavedQueryFields} />;
|
||||
case 'eql':
|
||||
return <span>{'Rule type not yet implemented'}</span>;
|
||||
case 'esql':
|
||||
return <span>{'Rule type not yet implemented'}</span>;
|
||||
case 'threat_match':
|
||||
return <ThreatMatchRuleFieldEdit fieldName={fieldName as UpgradeableThreatMatchFields} />;
|
||||
case 'threshold':
|
||||
return <ThresholdRuleFieldEdit fieldName={fieldName as UpgradeableThresholdFields} />;
|
||||
case 'machine_learning':
|
||||
return <span>{'Rule type not yet implemented'}</span>;
|
||||
case 'new_terms':
|
||||
return <NewTermsRuleFieldEdit fieldName={fieldName as UpgradeableNewTermsFields} />;
|
||||
default:
|
||||
return assertUnreachable(type);
|
||||
}
|
||||
}
|
|
@ -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 (
|
||||
<FieldFormWrapper
|
||||
component={KqlQueryEdit}
|
||||
fieldFormSchema={kqlQuerySchema}
|
||||
serializer={kqlQuerySerializer}
|
||||
deserializer={kqlQueryDeserializer}
|
||||
/>
|
||||
);
|
||||
default:
|
||||
return null; // Will be replaced with `assertUnreachable(fieldName)` once all fields are implemented
|
||||
}
|
||||
}
|
|
@ -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 (
|
||||
<FieldFormWrapper
|
||||
component={KqlQueryEdit}
|
||||
fieldFormSchema={kqlQuerySchema}
|
||||
serializer={kqlQuerySerializer}
|
||||
deserializer={kqlQueryDeserializer}
|
||||
/>
|
||||
);
|
||||
default:
|
||||
return null; // Will be replaced with `assertUnreachable(fieldName)` once all fields are implemented
|
||||
}
|
||||
}
|
|
@ -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 (
|
||||
<FieldFormWrapper
|
||||
component={KqlQueryEdit}
|
||||
fieldFormSchema={kqlQuerySchema}
|
||||
serializer={kqlQuerySerializer}
|
||||
deserializer={kqlQueryDeserializer}
|
||||
/>
|
||||
);
|
||||
default:
|
||||
return null; // Will be replaced with `assertUnreachable(fieldName)` once all fields are implemented
|
||||
}
|
||||
}
|
|
@ -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 (
|
||||
<FieldFormWrapper
|
||||
component={KqlQueryEdit}
|
||||
fieldFormSchema={kqlQuerySchema}
|
||||
serializer={kqlQuerySerializer}
|
||||
deserializer={kqlQueryDeserializer}
|
||||
/>
|
||||
);
|
||||
default:
|
||||
return null; // Will be replaced with `assertUnreachable(fieldName)` once all fields are implemented
|
||||
}
|
||||
}
|
|
@ -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]
|
||||
|
|
|
@ -25,8 +25,8 @@ interface TemplateProps {
|
|||
|
||||
const Template: Story<TemplateProps> = (args) => {
|
||||
return (
|
||||
<ThreeWayDiffStorybookProviders>
|
||||
<FieldReadOnly fieldName="alert_suppression" finalDiffableRule={args.finalDiffableRule} />
|
||||
<ThreeWayDiffStorybookProviders finalDiffableRule={args.finalDiffableRule}>
|
||||
<FieldReadOnly fieldName="alert_suppression" />
|
||||
</ThreeWayDiffStorybookProviders>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -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<TemplateProps> = (args) => {
|
||||
return <FieldReadOnly fieldName="anomaly_threshold" finalDiffableRule={args.finalDiffableRule} />;
|
||||
return (
|
||||
<ThreeWayDiffStorybookProviders finalDiffableRule={args.finalDiffableRule}>
|
||||
<FieldReadOnly fieldName="anomaly_threshold" />
|
||||
</ThreeWayDiffStorybookProviders>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
|
|
|
@ -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<TemplateProps> = (args) => {
|
||||
return <FieldReadOnly fieldName="author" finalDiffableRule={args.finalDiffableRule} />;
|
||||
return (
|
||||
<ThreeWayDiffStorybookProviders finalDiffableRule={args.finalDiffableRule}>
|
||||
<FieldReadOnly fieldName="author" />
|
||||
</ThreeWayDiffStorybookProviders>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
|
|
|
@ -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<TemplateProps> = (args) => {
|
||||
return <FieldReadOnly fieldName="building_block" finalDiffableRule={args.finalDiffableRule} />;
|
||||
return (
|
||||
<ThreeWayDiffStorybookProviders finalDiffableRule={args.finalDiffableRule}>
|
||||
<FieldReadOnly fieldName="building_block" />
|
||||
</ThreeWayDiffStorybookProviders>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
|
|
|
@ -29,8 +29,11 @@ interface TemplateProps {
|
|||
|
||||
const Template: Story<TemplateProps> = (args) => {
|
||||
return (
|
||||
<ThreeWayDiffStorybookProviders kibanaServicesOverrides={args.kibanaServicesOverrides}>
|
||||
<FieldReadOnly fieldName="data_source" finalDiffableRule={args.finalDiffableRule} />
|
||||
<ThreeWayDiffStorybookProviders
|
||||
kibanaServicesOverrides={args.kibanaServicesOverrides}
|
||||
finalDiffableRule={args.finalDiffableRule}
|
||||
>
|
||||
<FieldReadOnly fieldName="data_source" />
|
||||
</ThreeWayDiffStorybookProviders>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -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<TemplateProps> = (args) => {
|
||||
return <FieldReadOnly fieldName="description" finalDiffableRule={args.finalDiffableRule} />;
|
||||
return (
|
||||
<ThreeWayDiffStorybookProviders finalDiffableRule={args.finalDiffableRule}>
|
||||
<FieldReadOnly fieldName="description" />
|
||||
</ThreeWayDiffStorybookProviders>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
|
|
|
@ -31,8 +31,11 @@ interface TemplateProps {
|
|||
|
||||
const Template: Story<TemplateProps> = (args) => {
|
||||
return (
|
||||
<ThreeWayDiffStorybookProviders kibanaServicesOverrides={args.kibanaServicesOverrides}>
|
||||
<FieldReadOnly fieldName="eql_query" finalDiffableRule={args.finalDiffableRule} />
|
||||
<ThreeWayDiffStorybookProviders
|
||||
kibanaServicesOverrides={args.kibanaServicesOverrides}
|
||||
finalDiffableRule={args.finalDiffableRule}
|
||||
>
|
||||
<FieldReadOnly fieldName="eql_query" />
|
||||
</ThreeWayDiffStorybookProviders>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -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<TemplateProps> = (args) => {
|
||||
return <FieldReadOnly fieldName="esql_query" finalDiffableRule={args.finalDiffableRule} />;
|
||||
return (
|
||||
<ThreeWayDiffStorybookProviders finalDiffableRule={args.finalDiffableRule}>
|
||||
<FieldReadOnly fieldName="esql_query" />
|
||||
</ThreeWayDiffStorybookProviders>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
|
|
|
@ -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<TemplateProps> = (args) => {
|
||||
return (
|
||||
<FieldReadOnly fieldName="event_category_override" finalDiffableRule={args.finalDiffableRule} />
|
||||
<ThreeWayDiffStorybookProviders finalDiffableRule={args.finalDiffableRule}>
|
||||
<FieldReadOnly fieldName="event_category_override" />
|
||||
</ThreeWayDiffStorybookProviders>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -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<TemplateProps> = (args) => {
|
||||
return <FieldReadOnly fieldName="false_positives" finalDiffableRule={args.finalDiffableRule} />;
|
||||
return (
|
||||
<ThreeWayDiffStorybookProviders finalDiffableRule={args.finalDiffableRule}>
|
||||
<FieldReadOnly fieldName="false_positives" />
|
||||
</ThreeWayDiffStorybookProviders>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
|
|
|
@ -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<TemplateProps> = (args) => {
|
||||
return (
|
||||
<FieldReadOnly fieldName="history_window_start" finalDiffableRule={args.finalDiffableRule} />
|
||||
<ThreeWayDiffStorybookProviders finalDiffableRule={args.finalDiffableRule}>
|
||||
<FieldReadOnly fieldName="history_window_start" />
|
||||
</ThreeWayDiffStorybookProviders>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -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<TemplateProps> = (args) => {
|
||||
return (
|
||||
<FieldReadOnly fieldName="investigation_fields" finalDiffableRule={args.finalDiffableRule} />
|
||||
<ThreeWayDiffStorybookProviders finalDiffableRule={args.finalDiffableRule}>
|
||||
<FieldReadOnly fieldName="investigation_fields" />
|
||||
</ThreeWayDiffStorybookProviders>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -33,8 +33,11 @@ interface TemplateProps {
|
|||
|
||||
const Template: Story<TemplateProps> = (args) => {
|
||||
return (
|
||||
<ThreeWayDiffStorybookProviders kibanaServicesOverrides={args.kibanaServicesOverrides}>
|
||||
<FieldReadOnly fieldName="kql_query" finalDiffableRule={args.finalDiffableRule} />
|
||||
<ThreeWayDiffStorybookProviders
|
||||
kibanaServicesOverrides={args.kibanaServicesOverrides}
|
||||
finalDiffableRule={args.finalDiffableRule}
|
||||
>
|
||||
<FieldReadOnly fieldName="kql_query" />
|
||||
</ThreeWayDiffStorybookProviders>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -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: <Filters filters={savedQuery.attributes.filters} {...dataSourceProps} />,
|
||||
description: <Filters filters={filters} {...dataSourceProps} />,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -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<TemplateProps> = (args) => {
|
||||
return <FieldReadOnly fieldName="license" finalDiffableRule={args.finalDiffableRule} />;
|
||||
return (
|
||||
<ThreeWayDiffStorybookProviders finalDiffableRule={args.finalDiffableRule}>
|
||||
<FieldReadOnly fieldName="license" />
|
||||
</ThreeWayDiffStorybookProviders>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
|
|
|
@ -64,12 +64,9 @@ interface TemplateProps {
|
|||
|
||||
const Template: Story<TemplateProps> = (args) => {
|
||||
return (
|
||||
<ThreeWayDiffStorybookProviders>
|
||||
<ThreeWayDiffStorybookProviders finalDiffableRule={args.finalDiffableRule}>
|
||||
<MockMlData>
|
||||
<FieldReadOnly
|
||||
fieldName="machine_learning_job_id"
|
||||
finalDiffableRule={args.finalDiffableRule}
|
||||
/>
|
||||
<FieldReadOnly fieldName="machine_learning_job_id" />
|
||||
</MockMlData>
|
||||
</ThreeWayDiffStorybookProviders>
|
||||
);
|
||||
|
|
|
@ -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<TemplateProps> = (args) => {
|
||||
return <FieldReadOnly fieldName="max_signals" finalDiffableRule={args.finalDiffableRule} />;
|
||||
return (
|
||||
<ThreeWayDiffStorybookProviders finalDiffableRule={args.finalDiffableRule}>
|
||||
<FieldReadOnly fieldName="max_signals" />
|
||||
</ThreeWayDiffStorybookProviders>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
|
|
|
@ -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<TemplateProps> = (args) => {
|
||||
return <FieldReadOnly fieldName="name" finalDiffableRule={args.finalDiffableRule} />;
|
||||
return (
|
||||
<ThreeWayDiffStorybookProviders finalDiffableRule={args.finalDiffableRule}>
|
||||
<FieldReadOnly fieldName="name" />
|
||||
</ThreeWayDiffStorybookProviders>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
|
|
|
@ -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<TemplateProps> = (args) => {
|
||||
return <FieldReadOnly fieldName="new_terms_fields" finalDiffableRule={args.finalDiffableRule} />;
|
||||
return (
|
||||
<ThreeWayDiffStorybookProviders finalDiffableRule={args.finalDiffableRule}>
|
||||
<FieldReadOnly fieldName="new_terms_fields" />
|
||||
</ThreeWayDiffStorybookProviders>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
|
|
|
@ -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<TemplateProps> = (args) => {
|
||||
return <FieldReadOnly fieldName="note" finalDiffableRule={args.finalDiffableRule} />;
|
||||
return (
|
||||
<ThreeWayDiffStorybookProviders finalDiffableRule={args.finalDiffableRule}>
|
||||
<FieldReadOnly fieldName="note" />
|
||||
</ThreeWayDiffStorybookProviders>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
|
|
|
@ -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<TemplateProps> = (args) => {
|
||||
return <FieldReadOnly fieldName="references" finalDiffableRule={args.finalDiffableRule} />;
|
||||
return (
|
||||
<ThreeWayDiffStorybookProviders finalDiffableRule={args.finalDiffableRule}>
|
||||
<FieldReadOnly fieldName="references" />
|
||||
</ThreeWayDiffStorybookProviders>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
|
|
|
@ -45,12 +45,9 @@ interface TemplateProps {
|
|||
|
||||
const Template: Story<TemplateProps> = (args) => {
|
||||
return (
|
||||
<ThreeWayDiffStorybookProviders>
|
||||
<ThreeWayDiffStorybookProviders finalDiffableRule={args.finalDiffableRule}>
|
||||
<MockRelatedIntegrationsData>
|
||||
<FieldReadOnly
|
||||
fieldName="related_integrations"
|
||||
finalDiffableRule={args.finalDiffableRule}
|
||||
/>
|
||||
<FieldReadOnly fieldName="related_integrations" />
|
||||
</MockRelatedIntegrationsData>
|
||||
</ThreeWayDiffStorybookProviders>
|
||||
);
|
||||
|
|
|
@ -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<TemplateProps> = (args) => {
|
||||
return <FieldReadOnly fieldName="required_fields" finalDiffableRule={args.finalDiffableRule} />;
|
||||
return (
|
||||
<ThreeWayDiffStorybookProviders finalDiffableRule={args.finalDiffableRule}>
|
||||
<FieldReadOnly fieldName="required_fields" />
|
||||
</ThreeWayDiffStorybookProviders>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
|
|
|
@ -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<TemplateProps> = (args) => {
|
||||
return <FieldReadOnly fieldName="risk_score" finalDiffableRule={args.finalDiffableRule} />;
|
||||
return (
|
||||
<ThreeWayDiffStorybookProviders finalDiffableRule={args.finalDiffableRule}>
|
||||
<FieldReadOnly fieldName="risk_score" />
|
||||
</ThreeWayDiffStorybookProviders>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
|
|
|
@ -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<TemplateProps> = (args) => {
|
||||
return (
|
||||
<FieldReadOnly fieldName="risk_score_mapping" finalDiffableRule={args.finalDiffableRule} />
|
||||
<ThreeWayDiffStorybookProviders finalDiffableRule={args.finalDiffableRule}>
|
||||
<FieldReadOnly fieldName="risk_score_mapping" />
|
||||
</ThreeWayDiffStorybookProviders>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -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<TemplateProps> = (args) => {
|
||||
return (
|
||||
<FieldReadOnly fieldName="rule_name_override" finalDiffableRule={args.finalDiffableRule} />
|
||||
<ThreeWayDiffStorybookProviders finalDiffableRule={args.finalDiffableRule}>
|
||||
<FieldReadOnly fieldName="rule_name_override" />
|
||||
</ThreeWayDiffStorybookProviders>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -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<TemplateProps> = (args) => {
|
||||
return <FieldReadOnly fieldName="rule_schedule" finalDiffableRule={args.finalDiffableRule} />;
|
||||
return (
|
||||
<ThreeWayDiffStorybookProviders finalDiffableRule={args.finalDiffableRule}>
|
||||
<FieldReadOnly fieldName="rule_schedule" />
|
||||
</ThreeWayDiffStorybookProviders>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
|
|
|
@ -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<TemplateProps> = (args) => {
|
||||
return <FieldReadOnly fieldName="setup" finalDiffableRule={args.finalDiffableRule} />;
|
||||
return (
|
||||
<ThreeWayDiffStorybookProviders finalDiffableRule={args.finalDiffableRule}>
|
||||
<FieldReadOnly fieldName="setup" />
|
||||
</ThreeWayDiffStorybookProviders>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
|
|
|
@ -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<TemplateProps> = (args) => {
|
||||
return <FieldReadOnly fieldName="severity" finalDiffableRule={args.finalDiffableRule} />;
|
||||
return (
|
||||
<ThreeWayDiffStorybookProviders finalDiffableRule={args.finalDiffableRule}>
|
||||
<FieldReadOnly fieldName="severity" />
|
||||
</ThreeWayDiffStorybookProviders>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
|
|
|
@ -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<TemplateProps> = (args) => {
|
||||
return <FieldReadOnly fieldName="severity_mapping" finalDiffableRule={args.finalDiffableRule} />;
|
||||
return (
|
||||
<ThreeWayDiffStorybookProviders finalDiffableRule={args.finalDiffableRule}>
|
||||
<FieldReadOnly fieldName="severity_mapping" />
|
||||
</ThreeWayDiffStorybookProviders>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
|
|
|
@ -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<TemplateProps> = (args) => {
|
||||
return <FieldReadOnly fieldName="tags" finalDiffableRule={args.finalDiffableRule} />;
|
||||
return (
|
||||
<ThreeWayDiffStorybookProviders finalDiffableRule={args.finalDiffableRule}>
|
||||
<FieldReadOnly fieldName="tags" />
|
||||
</ThreeWayDiffStorybookProviders>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
|
|
|
@ -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<TemplateProps> = (args) => {
|
||||
return <FieldReadOnly fieldName="threat" finalDiffableRule={args.finalDiffableRule} />;
|
||||
return (
|
||||
<ThreeWayDiffStorybookProviders finalDiffableRule={args.finalDiffableRule}>
|
||||
<FieldReadOnly fieldName="threat" />
|
||||
</ThreeWayDiffStorybookProviders>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
|
|
|
@ -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<TemplateProps> = (args) => {
|
||||
return <FieldReadOnly fieldName="threat_index" finalDiffableRule={args.finalDiffableRule} />;
|
||||
return (
|
||||
<ThreeWayDiffStorybookProviders finalDiffableRule={args.finalDiffableRule}>
|
||||
<FieldReadOnly fieldName="threat_index" />
|
||||
</ThreeWayDiffStorybookProviders>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
|
|
|
@ -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<TemplateProps> = (args) => {
|
||||
return (
|
||||
<FieldReadOnly fieldName="threat_indicator_path" finalDiffableRule={args.finalDiffableRule} />
|
||||
<ThreeWayDiffStorybookProviders finalDiffableRule={args.finalDiffableRule}>
|
||||
<FieldReadOnly fieldName="threat_indicator_path" />
|
||||
</ThreeWayDiffStorybookProviders>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -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<TemplateProps> = (args) => {
|
||||
return <FieldReadOnly fieldName="threat_language" finalDiffableRule={args.finalDiffableRule} />;
|
||||
return (
|
||||
<ThreeWayDiffStorybookProviders finalDiffableRule={args.finalDiffableRule}>
|
||||
<FieldReadOnly fieldName="threat_language" />
|
||||
</ThreeWayDiffStorybookProviders>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
|
|
|
@ -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<TemplateProps> = (args) => {
|
||||
return <FieldReadOnly fieldName="threat_mapping" finalDiffableRule={args.finalDiffableRule} />;
|
||||
return (
|
||||
<ThreeWayDiffStorybookProviders finalDiffableRule={args.finalDiffableRule}>
|
||||
<FieldReadOnly fieldName="threat_mapping" />
|
||||
</ThreeWayDiffStorybookProviders>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
|
|
|
@ -31,8 +31,11 @@ interface TemplateProps {
|
|||
|
||||
const Template: Story<TemplateProps> = (args) => {
|
||||
return (
|
||||
<ThreeWayDiffStorybookProviders kibanaServicesOverrides={args.kibanaServicesOverrides}>
|
||||
<FieldReadOnly fieldName="threat_query" finalDiffableRule={args.finalDiffableRule} />
|
||||
<ThreeWayDiffStorybookProviders
|
||||
kibanaServicesOverrides={args.kibanaServicesOverrides}
|
||||
finalDiffableRule={args.finalDiffableRule}
|
||||
>
|
||||
<FieldReadOnly fieldName="threat_query" />
|
||||
</ThreeWayDiffStorybookProviders>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -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<TemplateProps> = (args) => {
|
||||
return <FieldReadOnly fieldName="threshold" finalDiffableRule={args.finalDiffableRule} />;
|
||||
return (
|
||||
<ThreeWayDiffStorybookProviders finalDiffableRule={args.finalDiffableRule}>
|
||||
<FieldReadOnly fieldName="threshold" />
|
||||
</ThreeWayDiffStorybookProviders>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
|
|
|
@ -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<TemplateProps> = (args) => {
|
||||
return <FieldReadOnly fieldName="tiebreaker_field" finalDiffableRule={args.finalDiffableRule} />;
|
||||
return (
|
||||
<ThreeWayDiffStorybookProviders finalDiffableRule={args.finalDiffableRule}>
|
||||
<FieldReadOnly fieldName="tiebreaker_field" />
|
||||
</ThreeWayDiffStorybookProviders>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
|
|
|
@ -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<TemplateProps> = (args) => {
|
||||
return <FieldReadOnly fieldName="timeline_template" finalDiffableRule={args.finalDiffableRule} />;
|
||||
return (
|
||||
<ThreeWayDiffStorybookProviders finalDiffableRule={args.finalDiffableRule}>
|
||||
<FieldReadOnly fieldName="timeline_template" />
|
||||
</ThreeWayDiffStorybookProviders>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
|
|
|
@ -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<TemplateProps> = (args) => {
|
||||
return <FieldReadOnly fieldName="timestamp_field" finalDiffableRule={args.finalDiffableRule} />;
|
||||
return (
|
||||
<ThreeWayDiffStorybookProviders finalDiffableRule={args.finalDiffableRule}>
|
||||
<FieldReadOnly fieldName="timestamp_field" />
|
||||
</ThreeWayDiffStorybookProviders>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
|
|
|
@ -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<TemplateProps> = (args) => {
|
||||
return (
|
||||
<FieldReadOnly fieldName="timestamp_override" finalDiffableRule={args.finalDiffableRule} />
|
||||
<ThreeWayDiffStorybookProviders finalDiffableRule={args.finalDiffableRule}>
|
||||
<FieldReadOnly fieldName="timestamp_override" />
|
||||
</ThreeWayDiffStorybookProviders>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -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<TemplateProps> = (args) => {
|
||||
return <FieldReadOnly fieldName="type" finalDiffableRule={args.finalDiffableRule} />;
|
||||
return (
|
||||
<ThreeWayDiffStorybookProviders finalDiffableRule={args.finalDiffableRule}>
|
||||
<FieldReadOnly fieldName="type" />
|
||||
</ThreeWayDiffStorybookProviders>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
|
|
|
@ -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 (
|
||||
<>
|
||||
<EuiButtonEmpty iconType="pencil" onClick={setEditMode}>
|
||||
{i18n.EDIT_BUTTON_LABEL}
|
||||
</EuiButtonEmpty>
|
||||
<FieldReadOnly fieldName={fieldName} />
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -159,7 +159,7 @@ const customQueryDiffableRuleFields: DiffableCustomQueryFields = {
|
|||
};
|
||||
|
||||
export function mockCustomQueryRule(
|
||||
overrides: Partial<DiffableCommonFields & DiffableCustomQueryFields>
|
||||
overrides: Partial<DiffableCommonFields & DiffableCustomQueryFields> = {}
|
||||
): DiffableRule {
|
||||
return {
|
||||
...commonDiffableRuleFields,
|
||||
|
@ -177,7 +177,7 @@ const savedQueryDiffableRuleFields: DiffableSavedQueryFields = {
|
|||
};
|
||||
|
||||
export function mockSavedQueryRule(
|
||||
overrides: Partial<DiffableCommonFields & DiffableSavedQueryFields>
|
||||
overrides: Partial<DiffableCommonFields & DiffableSavedQueryFields> = {}
|
||||
): DiffableRule {
|
||||
return {
|
||||
...commonDiffableRuleFields,
|
||||
|
@ -196,7 +196,7 @@ const eqlDiffableRuleFields: DiffableEqlFields = {
|
|||
};
|
||||
|
||||
export function mockEqlRule(
|
||||
overrides: Partial<DiffableCommonFields & DiffableEqlFields>
|
||||
overrides: Partial<DiffableCommonFields & DiffableEqlFields> = {}
|
||||
): DiffableRule {
|
||||
return {
|
||||
...commonDiffableRuleFields,
|
||||
|
@ -214,7 +214,7 @@ const esqlDiffableRuleFields: DiffableEsqlFields = {
|
|||
};
|
||||
|
||||
export function mockEsqlRule(
|
||||
overrides: Partial<DiffableCommonFields & DiffableEsqlFields>
|
||||
overrides: Partial<DiffableCommonFields & DiffableEsqlFields> = {}
|
||||
): DiffableRule {
|
||||
return {
|
||||
...commonDiffableRuleFields,
|
||||
|
@ -230,7 +230,7 @@ const machineLearningDiffableRuleFields: DiffableMachineLearningFields = {
|
|||
};
|
||||
|
||||
export function mockMachineLearningRule(
|
||||
overrides: Partial<DiffableCommonFields & DiffableMachineLearningFields>
|
||||
overrides: Partial<DiffableCommonFields & DiffableMachineLearningFields> = {}
|
||||
): DiffableRule {
|
||||
return {
|
||||
...commonDiffableRuleFields,
|
||||
|
@ -268,7 +268,7 @@ const threatMatchDiffableRuleFields: DiffableThreatMatchFields = {
|
|||
};
|
||||
|
||||
export function mockThreatMatchRule(
|
||||
overrides: Partial<DiffableCommonFields & DiffableThreatMatchFields>
|
||||
overrides: Partial<DiffableCommonFields & DiffableThreatMatchFields> = {}
|
||||
): DiffableRule {
|
||||
return {
|
||||
...commonDiffableRuleFields,
|
||||
|
@ -290,7 +290,7 @@ const newTermsDiffableRuleFields: DiffableNewTermsFields = {
|
|||
};
|
||||
|
||||
export function mockNewTermsRule(
|
||||
overrides: Partial<DiffableCommonFields & DiffableNewTermsFields>
|
||||
overrides: Partial<DiffableCommonFields & DiffableNewTermsFields> = {}
|
||||
): DiffableRule {
|
||||
return {
|
||||
...commonDiffableRuleFields,
|
||||
|
@ -314,7 +314,7 @@ export const thresholdDiffableRuleFields: DiffableThresholdFields = {
|
|||
};
|
||||
|
||||
export function mockThresholdRule(
|
||||
overrides: Partial<DiffableCommonFields & DiffableThresholdFields>
|
||||
overrides: Partial<DiffableCommonFields & DiffableThresholdFields> = {}
|
||||
): DiffableRule {
|
||||
return {
|
||||
...commonDiffableRuleFields,
|
||||
|
|
|
@ -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<CoreStart>) {
|
||||
const baseMock = {
|
||||
|
@ -69,14 +72,18 @@ function createMockStore() {
|
|||
return store;
|
||||
}
|
||||
|
||||
const setRuleFieldResolvedValueMock = () => {};
|
||||
|
||||
interface StorybookProvidersProps {
|
||||
children: React.ReactNode;
|
||||
kibanaServicesOverrides?: Record<string, unknown>;
|
||||
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({
|
|||
<ReactQueryClientProvider>
|
||||
<ReduxStoreProvider store={store}>
|
||||
<UpsellingProvider upsellingService={kibanaServicesMock.upsellingService}>
|
||||
{children}
|
||||
<DiffableRuleContextProvider
|
||||
finalDiffableRule={finalDiffableRule}
|
||||
setRuleFieldResolvedValue={setRuleFieldResolvedValueMock}
|
||||
>
|
||||
{children}
|
||||
</DiffableRuleContextProvider>
|
||||
</UpsellingProvider>
|
||||
</ReduxStoreProvider>
|
||||
</ReactQueryClientProvider>
|
||||
|
|
|
@ -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',
|
||||
}
|
|
@ -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 (
|
||||
<>
|
||||
<SideHeader>
|
||||
|
@ -29,7 +32,22 @@ export function FinalSide({ fieldName, finalDiffableRule }: FinalSideProps): JSX
|
|||
</h3>
|
||||
</EuiTitle>
|
||||
</SideHeader>
|
||||
<FieldReadOnly fieldName={fieldName} finalDiffableRule={finalDiffableRule} />
|
||||
<FinalSideContextProvider fieldName={fieldName}>
|
||||
<FinalSideContent />
|
||||
</FinalSideContextProvider>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function FinalSideContent(): JSX.Element {
|
||||
const { mode } = useFinalSideContext();
|
||||
|
||||
switch (mode) {
|
||||
case FinalSideMode.READONLY:
|
||||
return <FinalReadOnly />;
|
||||
case FinalSideMode.EDIT:
|
||||
return <FinalEdit />;
|
||||
default:
|
||||
return assertUnreachable(mode);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<FinalSideContextType | null>(null);
|
||||
|
||||
interface FinalSideContextProviderProps {
|
||||
fieldName: UpgradeableDiffableFields;
|
||||
}
|
||||
|
||||
export function FinalSideContextProvider({
|
||||
children,
|
||||
fieldName,
|
||||
}: PropsWithChildren<FinalSideContextProviderProps>) {
|
||||
const [mode, setMode] = React.useState<FinalSideMode>(FinalSideMode.READONLY);
|
||||
const setReadOnlyMode = useCallback(() => setMode(FinalSideMode.READONLY), []);
|
||||
const setEditMode = useCallback(() => setMode(FinalSideMode.EDIT), []);
|
||||
|
||||
const contextValue = {
|
||||
fieldName,
|
||||
setReadOnlyMode,
|
||||
setEditMode,
|
||||
mode,
|
||||
};
|
||||
|
||||
return <FinalSideContext.Provider value={contextValue}>{children}</FinalSideContext.Provider>;
|
||||
}
|
||||
|
||||
export function useFinalSideContext() {
|
||||
const context = useContext(FinalSideContext);
|
||||
|
||||
invariant(context !== null, 'useFinalSideContext must be used inside a FinalSideContextProvider');
|
||||
|
||||
return context;
|
||||
}
|
|
@ -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 (
|
||||
<>
|
||||
<DiffableRuleContextProvider
|
||||
finalDiffableRule={ruleUpgradeState.finalRule}
|
||||
setRuleFieldResolvedValue={setRuleFieldResolvedValue}
|
||||
>
|
||||
<EuiSpacer size="s" />
|
||||
<RuleUpgradeInfoBar ruleUpgradeState={ruleUpgradeState} />
|
||||
<EuiSpacer size="s" />
|
||||
<RuleUpgradeCallout ruleUpgradeState={ruleUpgradeState} />
|
||||
<EuiSpacer size="s" />
|
||||
<RuleUpgradeConflictsResolver
|
||||
ruleUpgradeState={ruleUpgradeState}
|
||||
setRuleFieldResolvedValue={setRuleFieldResolvedValue}
|
||||
/>
|
||||
</>
|
||||
<RuleUpgradeConflictsResolver ruleUpgradeState={ruleUpgradeState} />
|
||||
</DiffableRuleContextProvider>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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',
|
||||
}
|
||||
);
|
|
@ -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<keyof RuleFieldsDiff, NonUpgradeableDiffableFields>;
|
||||
|
||||
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<keyof DiffableEqlFields, NonUpgradeableDiffableFields>;
|
||||
|
||||
export type UpgradeableEsqlFields = Exclude<keyof DiffableEsqlFields, NonUpgradeableDiffableFields>;
|
||||
|
||||
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<string[]>).includes(fieldName);
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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<RulesResolvedConflicts>({});
|
||||
|
||||
const setRuleFieldResolvedValue = useCallback(
|
||||
(...[params]: Parameters<SetRuleFieldResolvedValueFn>) => {
|
||||
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<Record<string, unknown>>
|
||||
|
|
|
@ -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`);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue