{isEmpty(threshold.field[0])
? `${descriptionStepI18n.THRESHOLD_RESULTS_ALL} >= ${threshold.value}`
@@ -193,7 +193,7 @@ interface AnomalyThresholdProps {
anomalyThreshold: number;
}
-const AnomalyThreshold = ({ anomalyThreshold }: AnomalyThresholdProps) => (
+export const AnomalyThreshold = ({ anomalyThreshold }: AnomalyThresholdProps) => (
{anomalyThreshold}
@@ -258,7 +258,7 @@ interface RuleTypeProps {
type: Type;
}
-const RuleType = ({ type }: RuleTypeProps) => (
+export const RuleType = ({ type }: RuleTypeProps) => (
{getRuleTypeDescription(type)}
);
@@ -298,7 +298,7 @@ interface TimelineTitleProps {
timelineTitle: string;
}
-const TimelineTitle = ({ timelineTitle }: TimelineTitleProps) => (
+export const TimelineTitle = ({ timelineTitle }: TimelineTitleProps) => (
{timelineTitle}
@@ -354,7 +354,7 @@ interface SuppressAlertsByFieldProps {
fields: string[];
}
-const SuppressAlertsByField = ({ fields }: SuppressAlertsByFieldProps) => (
+export const SuppressAlertsByField = ({ fields }: SuppressAlertsByFieldProps) => (
);
@@ -362,7 +362,7 @@ interface SuppressAlertsDurationProps {
duration?: Duration;
}
-const SuppressAlertsDuration = ({ duration }: SuppressAlertsDurationProps) => {
+export const SuppressAlertsDuration = ({ duration }: SuppressAlertsDurationProps) => {
const durationDescription = duration
? `${duration.value}${duration.unit}`
: descriptionStepI18n.ALERT_SUPPRESSION_PER_RULE_EXECUTION;
@@ -378,7 +378,7 @@ interface MissingFieldsStrategyProps {
missingFieldsStrategy?: AlertSuppressionMissingFieldsStrategy;
}
-const MissingFieldsStrategy = ({ missingFieldsStrategy }: MissingFieldsStrategyProps) => {
+export const MissingFieldsStrategy = ({ missingFieldsStrategy }: MissingFieldsStrategyProps) => {
const missingFieldsDescription =
missingFieldsStrategy === AlertSuppressionMissingFieldsStrategyEnum.suppress
? descriptionStepI18n.ALERT_SUPPRESSION_SUPPRESS_ON_MISSING_FIELDS
@@ -395,7 +395,7 @@ interface NewTermsFieldsProps {
newTermsFields: string[];
}
-const NewTermsFields = ({ newTermsFields }: NewTermsFieldsProps) => (
+export const NewTermsFields = ({ newTermsFields }: NewTermsFieldsProps) => (
);
@@ -403,7 +403,7 @@ interface HistoryWindowSizeProps {
historyWindowStart?: string;
}
-const HistoryWindowSize = ({ historyWindowStart }: HistoryWindowSizeProps) => {
+export const HistoryWindowSize = ({ historyWindowStart }: HistoryWindowSizeProps) => {
const size = historyWindowStart ? convertHistoryStartToSize(historyWindowStart) : '7d';
return (
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_schedule_section.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_schedule_section.tsx
index 7d7579521c82d..5ed99e4328136 100644
--- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_schedule_section.tsx
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_schedule_section.tsx
@@ -14,14 +14,26 @@ import { getHumanizedDuration } from '../../../../detections/pages/detection_eng
import { DEFAULT_DESCRIPTION_LIST_COLUMN_WIDTHS } from './constants';
import * as i18n from './translations';
+interface AccessibleTimeValueProps {
+ timeValue: string;
+ 'data-test-subj'?: string;
+}
+
+export const AccessibleTimeValue = ({
+ timeValue,
+ 'data-test-subj': dataTestSubj,
+}: AccessibleTimeValueProps) => (
+
+
+
+);
+
interface IntervalProps {
interval: string;
}
const Interval = ({ interval }: IntervalProps) => (
-
-
-
+
);
interface FromProps {
@@ -30,9 +42,10 @@ interface FromProps {
}
const From = ({ from, interval }: FromProps) => (
-
-
-
+
);
export interface RuleScheduleSectionProps extends React.ComponentProps
{
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/common_rule_field_readonly.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/common_rule_field_readonly.tsx
index 35bde351bbeb6..9471a17b216b3 100644
--- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/common_rule_field_readonly.tsx
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/common_rule_field_readonly.tsx
@@ -19,6 +19,21 @@ import { NameReadOnly } from './fields/name/name';
import { TagsReadOnly } from './fields/tags/tags';
import { DescriptionReadOnly } from './fields/description/description';
import { assertUnreachable } from '../../../../../../../common/utility_types';
+import { AuthorReadOnly } from './fields/author/author';
+import { BuildingBlockReadOnly } from './fields/building_block/building_block';
+import { InvestigationFieldsReadOnly } from './fields/investigation_fields/investigation_fields';
+import { FalsePositivesReadOnly } from './fields/false_positives/false_positives';
+import { LicenseReadOnly } from './fields/license/license';
+import { MaxSignalsReadOnly } from './fields/max_signals/max_signals';
+import { NoteReadOnly } from './fields/note/note';
+import { RuleScheduleReadOnly } from './fields/rule_schedule/rule_schedule';
+import { ReferencesReadOnly } from './fields/references/references';
+import { RiskScoreReadOnly } from './fields/risk_score/risk_score';
+import { RuleNameOverrideReadOnly } from './fields/rule_name_override/rule_name_override';
+import { SetupReadOnly } from './fields/setup/setup';
+import { SeverityReadOnly } from './fields/severity/severity';
+import { TimestampOverrideReadOnly } from './fields/timestamp_override/timestamp_override';
+import { TimelineTemplateReadOnly } from './fields/timeline_template/timeline_template';
interface CommonRuleFieldReadOnlyProps {
fieldName: keyof DiffableCommonFields;
@@ -32,25 +47,28 @@ export function CommonRuleFieldReadOnly({
}: CommonRuleFieldReadOnlyProps) {
switch (fieldName) {
case 'author':
- return null;
+ return ;
case 'building_block':
- return null;
+ return ;
case 'description':
return ;
case 'exceptions_list':
+ /* Exceptions are not used in prebuilt rules */
return null;
case 'investigation_fields':
- return null;
+ return (
+
+ );
case 'false_positives':
- return null;
+ return ;
case 'license':
- return null;
+ return ;
case 'max_signals':
- return null;
+ return ;
case 'name':
return ;
case 'note':
- return null;
+ return ;
case 'related_integrations':
return (
@@ -60,7 +78,7 @@ export function CommonRuleFieldReadOnly({
case 'risk_score_mapping':
return ;
case 'rule_schedule':
- return null;
+ return ;
case 'severity_mapping':
return ;
case 'tags':
@@ -68,22 +86,24 @@ export function CommonRuleFieldReadOnly({
case 'threat':
return ;
case 'references':
- return null;
+ return ;
case 'risk_score':
- return null;
+ return ;
case 'rule_id':
+ /* Rule ID is not displayed in the UI */
return null;
case 'rule_name_override':
- return null;
+ return ;
case 'setup':
- return null;
+ return ;
case 'severity':
- return null;
+ return ;
case 'timestamp_override':
- return null;
+ return ;
case 'timeline_template':
- return null;
+ return ;
case 'version':
+ /* Version is not displayed in the UI */
return null;
default:
return assertUnreachable(fieldName);
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/custom_query_rule_field_readonly.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/custom_query_rule_field_readonly.tsx
index 3d22d268438c4..da435b8092cd6 100644
--- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/custom_query_rule_field_readonly.tsx
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/custom_query_rule_field_readonly.tsx
@@ -9,6 +9,9 @@ import React from 'react';
import type { DiffableCustomQueryFields } from '../../../../../../../common/api/detection_engine';
import { DataSourceReadOnly } from './fields/data_source/data_source';
import { KqlQueryReadOnly } from './fields/kql_query';
+import { assertUnreachable } from '../../../../../../../common/utility_types';
+import { TypeReadOnly } from './fields/type/type';
+import { AlertSuppressionReadOnly } from './fields/alert_suppression/alert_suppression';
interface CustomQueryRuleFieldReadOnlyProps {
fieldName: keyof DiffableCustomQueryFields;
@@ -20,6 +23,13 @@ export function CustomQueryRuleFieldReadOnly({
finalDiffableRule,
}: CustomQueryRuleFieldReadOnlyProps) {
switch (fieldName) {
+ case 'alert_suppression':
+ return (
+
+ );
case 'data_source':
return ;
case 'kql_query':
@@ -30,7 +40,9 @@ export function CustomQueryRuleFieldReadOnly({
ruleType={finalDiffableRule.type}
/>
);
+ case 'type':
+ return ;
default:
- return null; // Will replace with `assertUnreachable(fieldName)` once all fields are implemented
+ return assertUnreachable(fieldName);
}
}
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/eql_rule_field_readonly.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/eql_rule_field_readonly.tsx
index 126775965724b..b72fce91f198c 100644
--- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/eql_rule_field_readonly.tsx
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/eql_rule_field_readonly.tsx
@@ -9,6 +9,12 @@ import React from 'react';
import type { DiffableEqlFields } from '../../../../../../../common/api/detection_engine';
import { DataSourceReadOnly } from './fields/data_source/data_source';
import { EqlQueryReadOnly } from './fields/eql_query/eql_query';
+import { TypeReadOnly } from './fields/type/type';
+import { AlertSuppressionReadOnly } from './fields/alert_suppression/alert_suppression';
+import { assertUnreachable } from '../../../../../../../common/utility_types';
+import { EventCategoryOverrideReadOnly } from './fields/event_category_override/event_category_override';
+import { TimestampFieldReadOnly } from './fields/timestamp_field/timestamp_field';
+import { TiebreakerFieldReadOnly } from './fields/tiebreaker_field/tiebreaker_field';
interface EqlRuleFieldReadOnlyProps {
fieldName: keyof DiffableEqlFields;
@@ -17,6 +23,13 @@ interface EqlRuleFieldReadOnlyProps {
export function EqlRuleFieldReadOnly({ fieldName, finalDiffableRule }: EqlRuleFieldReadOnlyProps) {
switch (fieldName) {
+ case 'alert_suppression':
+ return (
+
+ );
case 'data_source':
return ;
case 'eql_query':
@@ -26,9 +39,19 @@ export function EqlRuleFieldReadOnly({ fieldName, finalDiffableRule }: EqlRuleFi
dataSource={finalDiffableRule.data_source}
/>
);
+ case 'event_category_override':
+ return (
+
+ );
+ case 'tiebreaker_field':
+ return ;
+ case 'timestamp_field':
+ return ;
case 'type':
- return null;
+ return ;
default:
- return null; // Will replace with `assertUnreachable(fieldName)` once all fields are implemented
+ return assertUnreachable(fieldName);
}
}
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/esql_rule_field_readonly.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/esql_rule_field_readonly.tsx
index 755ad6b1b4789..04280ebaacc5b 100644
--- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/esql_rule_field_readonly.tsx
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/esql_rule_field_readonly.tsx
@@ -8,6 +8,9 @@
import React from 'react';
import type { DiffableEsqlFields } from '../../../../../../../common/api/detection_engine';
import { EsqlQueryReadOnly } from './fields/esql_query/esql_query';
+import { TypeReadOnly } from './fields/type/type';
+import { AlertSuppressionReadOnly } from './fields/alert_suppression/alert_suppression';
+import { assertUnreachable } from '../../../../../../../common/utility_types';
interface EsqlRuleFieldReadOnlyProps {
fieldName: keyof DiffableEsqlFields;
@@ -19,11 +22,18 @@ export function EsqlRuleFieldReadOnly({
finalDiffableRule,
}: EsqlRuleFieldReadOnlyProps) {
switch (fieldName) {
+ case 'alert_suppression':
+ return (
+
+ );
case 'esql_query':
return ;
case 'type':
- return null;
+ return ;
default:
- return null; // Will replace with `assertUnreachable(fieldName)` once all fields are implemented
+ return assertUnreachable(fieldName);
}
}
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/alert_suppression/alert_suppression.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/alert_suppression/alert_suppression.stories.tsx
new file mode 100644
index 0000000000000..4f6739a3af481
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/alert_suppression/alert_suppression.stories.tsx
@@ -0,0 +1,44 @@
+/*
+ * 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 { Story } from '@storybook/react';
+import { AlertSuppressionReadOnly } from './alert_suppression';
+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: AlertSuppressionReadOnly,
+ title:
+ 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/alert_suppression',
+};
+
+interface TemplateProps {
+ finalDiffableRule: DiffableRule;
+}
+
+const Template: Story = (args) => {
+ return (
+
+
+
+ );
+};
+
+export const Default = Template.bind({});
+
+Default.args = {
+ finalDiffableRule: mockCustomQueryRule({
+ alert_suppression: {
+ group_by: ['host.name'],
+ duration: { value: 5, unit: 'm' },
+ missing_fields_strategy: 'suppress',
+ },
+ }),
+};
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/alert_suppression/alert_suppression.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/alert_suppression/alert_suppression.tsx
new file mode 100644
index 0000000000000..8c15347bc6d90
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/alert_suppression/alert_suppression.tsx
@@ -0,0 +1,81 @@
+/*
+ * 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 { EuiDescriptionList } from '@elastic/eui';
+import * as ruleDetailsI18n from '../../../../translations';
+import type {
+ AlertSuppression,
+ DiffableRuleTypes,
+ ThresholdAlertSuppression,
+} from '../../../../../../../../../common/api/detection_engine';
+import { AlertSuppressionLabel } from '../../../../../../../rule_creation_ui/components/description_step/alert_suppression_label';
+import {
+ MissingFieldsStrategy,
+ SuppressAlertsByField,
+ SuppressAlertsDuration,
+} from '../../../../rule_definition_section';
+
+interface AlertSuppressionReadOnlyProps {
+ alertSuppression?: AlertSuppression | ThresholdAlertSuppression;
+ ruleType: DiffableRuleTypes;
+}
+
+export function AlertSuppressionReadOnly({
+ alertSuppression,
+ ruleType,
+}: AlertSuppressionReadOnlyProps) {
+ if (!alertSuppression) {
+ return null;
+ }
+
+ const listItems = [];
+
+ if ('group_by' in alertSuppression) {
+ listItems.push({
+ title: (
+
+ ),
+ description: ,
+ });
+ }
+
+ if ('duration' in alertSuppression) {
+ listItems.push({
+ title: (
+
+
+
+ ),
+ description: ,
+ });
+ }
+
+ if ('missing_fields_strategy' in alertSuppression) {
+ listItems.push({
+ title: (
+
+
+
+ ),
+ description: (
+
+ ),
+ });
+ }
+
+ return ;
+}
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/anomaly_threshold/anomaly_threshold.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/anomaly_threshold/anomaly_threshold.stories.tsx
new file mode 100644
index 0000000000000..8203e015d11db
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/anomaly_threshold/anomaly_threshold.stories.tsx
@@ -0,0 +1,35 @@
+/*
+ * 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 { Story } from '@storybook/react';
+import { AnomalyThresholdReadOnly } from './anomaly_threshold';
+import { FieldReadOnly } from '../../field_readonly';
+import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine';
+import { mockMachineLearningRule } from '../../storybook/mocks';
+
+export default {
+ component: AnomalyThresholdReadOnly,
+ title:
+ 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/anomaly_threshold',
+};
+
+interface TemplateProps {
+ finalDiffableRule: DiffableRule;
+}
+
+const Template: Story = (args) => {
+ return ;
+};
+
+export const Default = Template.bind({});
+
+Default.args = {
+ finalDiffableRule: mockMachineLearningRule({
+ anomaly_threshold: 50,
+ }),
+};
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/anomaly_threshold/anomaly_threshold.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/anomaly_threshold/anomaly_threshold.tsx
new file mode 100644
index 0000000000000..20b9026c2a8ae
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/anomaly_threshold/anomaly_threshold.tsx
@@ -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 React from 'react';
+import { EuiDescriptionList } from '@elastic/eui';
+import * as ruleDetailsI18n from '../../../../translations';
+import type { AnomalyThreshold as AnomalyThresholdType } from '../../../../../../../../../common/api/detection_engine';
+import { AnomalyThreshold } from '../../../../rule_definition_section';
+
+interface TagsReadOnlyProps {
+ anomalyThreshold: AnomalyThresholdType;
+}
+
+export function AnomalyThresholdReadOnly({ anomalyThreshold }: TagsReadOnlyProps) {
+ return (
+ ,
+ },
+ ]}
+ />
+ );
+}
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/author/author.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/author/author.stories.tsx
new file mode 100644
index 0000000000000..2700517c1c3ec
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/author/author.stories.tsx
@@ -0,0 +1,34 @@
+/*
+ * 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 { Story } from '@storybook/react';
+import { AuthorReadOnly } from './author';
+import { FieldReadOnly } from '../../field_readonly';
+import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine';
+import { mockCustomQueryRule } from '../../storybook/mocks';
+
+export default {
+ component: AuthorReadOnly,
+ title: 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/author',
+};
+
+interface TemplateProps {
+ finalDiffableRule: DiffableRule;
+}
+
+const Template: Story = (args) => {
+ return ;
+};
+
+export const Default = Template.bind({});
+
+Default.args = {
+ finalDiffableRule: mockCustomQueryRule({
+ author: ['Elastic', 'John Doe'],
+ }),
+};
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/author/author.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/author/author.tsx
new file mode 100644
index 0000000000000..c284275bd4db4
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/author/author.tsx
@@ -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 React from 'react';
+import { EuiDescriptionList } from '@elastic/eui';
+import * as ruleDetailsI18n from '../../../../translations';
+import type { RuleAuthorArray } from '../../../../../../../../../common/api/detection_engine';
+import { Author } from '../../../../rule_about_section';
+
+interface AuthorReadOnlyProps {
+ author: RuleAuthorArray;
+}
+
+export function AuthorReadOnly({ author }: AuthorReadOnlyProps) {
+ return (
+ ,
+ },
+ ]}
+ />
+ );
+}
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/building_block/building_block.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/building_block/building_block.stories.tsx
new file mode 100644
index 0000000000000..f927b753c17ab
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/building_block/building_block.stories.tsx
@@ -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 type { Story } from '@storybook/react';
+import { BuildingBlockReadOnly } from './building_block';
+import { FieldReadOnly } from '../../field_readonly';
+import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine';
+import { mockCustomQueryRule } from '../../storybook/mocks';
+
+export default {
+ component: BuildingBlockReadOnly,
+ title: 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/building_block',
+};
+
+interface TemplateProps {
+ finalDiffableRule: DiffableRule;
+}
+
+const Template: Story = (args) => {
+ return ;
+};
+
+export const Default = Template.bind({});
+
+Default.args = {
+ finalDiffableRule: mockCustomQueryRule({
+ building_block: {
+ type: 'default',
+ },
+ }),
+};
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/building_block/building_block.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/building_block/building_block.tsx
new file mode 100644
index 0000000000000..84edd7932a2d7
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/building_block/building_block.tsx
@@ -0,0 +1,24 @@
+/*
+ * 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 { EuiDescriptionList } from '@elastic/eui';
+import * as ruleDetailsI18n from '../../../../translations';
+import { BuildingBlock } from '../../../../rule_about_section';
+
+export function BuildingBlockReadOnly() {
+ return (
+ ,
+ },
+ ]}
+ />
+ );
+}
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/data_source/data_source.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/data_source/data_source.stories.tsx
index 9deebf794c241..091a874385156 100644
--- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/data_source/data_source.stories.tsx
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/data_source/data_source.stories.tsx
@@ -24,12 +24,12 @@ export default {
interface TemplateProps {
finalDiffableRule: DiffableRule;
- kibanaServicesMock?: Record;
+ kibanaServicesOverrides?: Record;
}
const Template: Story = (args) => {
return (
-
+
);
@@ -49,7 +49,7 @@ DataSourceWithDataView.args = {
finalDiffableRule: mockCustomQueryRule({
data_source: dataSourceWithDataView,
}),
- kibanaServicesMock: {
+ kibanaServicesOverrides: {
data: {
dataViews: {
get: async () => mockDataView(),
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/eql_query/eql_query.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/eql_query/eql_query.stories.tsx
index af835c5a92779..84ea98047bcee 100644
--- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/eql_query/eql_query.stories.tsx
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/eql_query/eql_query.stories.tsx
@@ -26,12 +26,12 @@ export default {
interface TemplateProps {
finalDiffableRule: DiffableRule;
- kibanaServicesMock?: Record;
+ kibanaServicesOverrides?: Record;
}
const Template: Story = (args) => {
return (
-
+
);
@@ -44,7 +44,7 @@ EqlQueryWithIndexPatterns.args = {
eql_query: eqlQuery,
data_source: dataSourceWithIndexPatterns,
}),
- kibanaServicesMock: {
+ kibanaServicesOverrides: {
data: {
dataViews: {
create: async () => mockDataView(),
@@ -60,7 +60,7 @@ EqlQueryWithDataView.args = {
eql_query: eqlQuery,
data_source: dataSourceWithDataView,
}),
- kibanaServicesMock: {
+ kibanaServicesOverrides: {
data: {
dataViews: {
get: async () => mockDataView(),
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/event_category_override/event_category_override.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/event_category_override/event_category_override.stories.tsx
new file mode 100644
index 0000000000000..1eb29ef1084d9
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/event_category_override/event_category_override.stories.tsx
@@ -0,0 +1,37 @@
+/*
+ * 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 { Story } from '@storybook/react';
+import { EventCategoryOverrideReadOnly } from './event_category_override';
+import { FieldReadOnly } from '../../field_readonly';
+import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine';
+import { mockEqlRule } from '../../storybook/mocks';
+
+export default {
+ component: EventCategoryOverrideReadOnly,
+ title:
+ 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/event_category_override',
+};
+
+interface TemplateProps {
+ finalDiffableRule: DiffableRule;
+}
+
+const Template: Story = (args) => {
+ return (
+
+ );
+};
+
+export const Default = Template.bind({});
+
+Default.args = {
+ finalDiffableRule: mockEqlRule({
+ event_category_override: 'event.action',
+ }),
+};
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/event_category_override/event_category_override.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/event_category_override/event_category_override.tsx
new file mode 100644
index 0000000000000..910e639049f96
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/event_category_override/event_category_override.tsx
@@ -0,0 +1,42 @@
+/*
+ * 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 { EuiDescriptionList, EuiText } from '@elastic/eui';
+import * as descriptionStepI18n from '../../../../../../../rule_creation_ui/components/description_step/translations';
+import type { EventCategoryOverride as EventCategoryOverrideType } from '../../../../../../../../../common/api/detection_engine';
+
+interface EventCategoryOverrideReadOnlyProps {
+ eventCategoryOverride?: EventCategoryOverrideType;
+}
+
+export function EventCategoryOverrideReadOnly({
+ eventCategoryOverride,
+}: EventCategoryOverrideReadOnlyProps) {
+ if (!eventCategoryOverride) {
+ return null;
+ }
+
+ return (
+ ,
+ },
+ ]}
+ />
+ );
+}
+
+interface EventCategoryOverrideProps {
+ eventCategoryOverride: EventCategoryOverrideType;
+}
+
+function EventCategoryOverride({ eventCategoryOverride }: EventCategoryOverrideProps) {
+ return {eventCategoryOverride};
+}
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/false_positives/false_positives.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/false_positives/false_positives.stories.tsx
new file mode 100644
index 0000000000000..60d8a34616652
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/false_positives/false_positives.stories.tsx
@@ -0,0 +1,37 @@
+/*
+ * 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 { Story } from '@storybook/react';
+import { FalsePositivesReadOnly } from './false_positives';
+import { FieldReadOnly } from '../../field_readonly';
+import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine';
+import { mockCustomQueryRule } from '../../storybook/mocks';
+
+export default {
+ component: FalsePositivesReadOnly,
+ title: 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/false_positives',
+};
+
+interface TemplateProps {
+ finalDiffableRule: DiffableRule;
+}
+
+const Template: Story = (args) => {
+ return ;
+};
+
+export const Default = Template.bind({});
+
+Default.args = {
+ finalDiffableRule: mockCustomQueryRule({
+ false_positives: [
+ 'WAF rules or rule groups may be deleted by a system or network administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Rule deletions by unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule.',
+ 'Uncommon user command activity can be due to an engineer logging onto a server instance in order to perform manual troubleshooting or reconfiguration.',
+ ],
+ }),
+};
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/false_positives/false_positives.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/false_positives/false_positives.tsx
new file mode 100644
index 0000000000000..f026609b6c850
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/false_positives/false_positives.tsx
@@ -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 React from 'react';
+import { EuiDescriptionList } from '@elastic/eui';
+import * as ruleDetailsI18n from '../../../../translations';
+import type { RuleFalsePositiveArray } from '../../../../../../../../../common/api/detection_engine';
+import { FalsePositives } from '../../../../rule_about_section';
+
+interface FalsePositivesReadOnlyProps {
+ falsePositives: RuleFalsePositiveArray;
+}
+
+export function FalsePositivesReadOnly({ falsePositives }: FalsePositivesReadOnlyProps) {
+ return (
+ ,
+ },
+ ]}
+ />
+ );
+}
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/history_window_start/history_window_start.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/history_window_start/history_window_start.stories.tsx
new file mode 100644
index 0000000000000..c84868e97ee0c
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/history_window_start/history_window_start.stories.tsx
@@ -0,0 +1,37 @@
+/*
+ * 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 { Story } from '@storybook/react';
+import { HistoryWindowStartReadOnly } from './history_window_start';
+import { FieldReadOnly } from '../../field_readonly';
+import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine';
+import { mockNewTermsRule } from '../../storybook/mocks';
+
+export default {
+ component: HistoryWindowStartReadOnly,
+ title:
+ 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/history_window_start',
+};
+
+interface TemplateProps {
+ finalDiffableRule: DiffableRule;
+}
+
+const Template: Story = (args) => {
+ return (
+
+ );
+};
+
+export const Default = Template.bind({});
+
+Default.args = {
+ finalDiffableRule: mockNewTermsRule({
+ history_window_start: 'now-14d',
+ }),
+};
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/history_window_start/history_window_start.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/history_window_start/history_window_start.tsx
new file mode 100644
index 0000000000000..c6bd8ebf7b972
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/history_window_start/history_window_start.tsx
@@ -0,0 +1,31 @@
+/*
+ * 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 { EuiDescriptionList } from '@elastic/eui';
+import * as ruleDetailsI18n from '../../../../translations';
+import type { HistoryWindowStart as HistoryWindowStartType } from '../../../../../../../../../common/api/detection_engine';
+import { HistoryWindowSize } from '../../../../rule_definition_section';
+
+interface HistoryWindowStartReadOnlyProps {
+ historyWindowStart: HistoryWindowStartType;
+}
+
+export function HistoryWindowStartReadOnly({
+ historyWindowStart,
+}: HistoryWindowStartReadOnlyProps) {
+ return (
+ ,
+ },
+ ]}
+ />
+ );
+}
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/investigation_fields/investigation_fields.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/investigation_fields/investigation_fields.stories.tsx
new file mode 100644
index 0000000000000..e73b01a719f8a
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/investigation_fields/investigation_fields.stories.tsx
@@ -0,0 +1,39 @@
+/*
+ * 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 { Story } from '@storybook/react';
+import { InvestigationFieldsReadOnly } from './investigation_fields';
+import { FieldReadOnly } from '../../field_readonly';
+import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine';
+import { mockCustomQueryRule } from '../../storybook/mocks';
+
+export default {
+ component: InvestigationFieldsReadOnly,
+ title:
+ 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/investigation_fields',
+};
+
+interface TemplateProps {
+ finalDiffableRule: DiffableRule;
+}
+
+const Template: Story = (args) => {
+ return (
+
+ );
+};
+
+export const Default = Template.bind({});
+
+Default.args = {
+ finalDiffableRule: mockCustomQueryRule({
+ investigation_fields: {
+ field_names: ['host.name', 'source.ip'],
+ },
+ }),
+};
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/investigation_fields/investigation_fields.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/investigation_fields/investigation_fields.tsx
new file mode 100644
index 0000000000000..b567b32ada533
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/investigation_fields/investigation_fields.tsx
@@ -0,0 +1,37 @@
+/*
+ * 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 { EuiDescriptionList } from '@elastic/eui';
+import * as ruleDetailsI18n from '../../../../translations';
+import type { InvestigationFields } from '../../../../../../../../../common/api/detection_engine';
+import { InvestigationFields as InvestigationFieldsComponent } from '../../../../rule_about_section';
+
+interface InvestigationFieldsReadOnlyProps {
+ investigationFields?: InvestigationFields;
+}
+
+export function InvestigationFieldsReadOnly({
+ investigationFields,
+}: InvestigationFieldsReadOnlyProps) {
+ if (!investigationFields || !investigationFields.field_names.length) {
+ return null;
+ }
+
+ return (
+
+ ),
+ },
+ ]}
+ />
+ );
+}
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/kql_query/kql_query.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/kql_query/kql_query.stories.tsx
index 2b4844ceac5d5..4fd102fc0627f 100644
--- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/kql_query/kql_query.stories.tsx
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/kql_query/kql_query.stories.tsx
@@ -28,12 +28,12 @@ export default {
interface TemplateProps {
finalDiffableRule: DiffableRule;
- kibanaServicesMock?: Record;
+ kibanaServicesOverrides?: Record;
}
const Template: Story = (args) => {
return (
-
+
);
@@ -46,7 +46,7 @@ InlineKqlQueryWithIndexPatterns.args = {
kql_query: inlineKqlQuery,
data_source: dataSourceWithIndexPatterns,
}),
- kibanaServicesMock: {
+ kibanaServicesOverrides: {
data: {
dataViews: {
create: async () => mockDataView(),
@@ -62,7 +62,7 @@ InlineKqlQueryWithDataView.args = {
kql_query: inlineKqlQuery,
data_source: dataSourceWithDataView,
}),
- kibanaServicesMock: {
+ kibanaServicesOverrides: {
data: {
dataViews: {
get: async () => mockDataView(),
@@ -81,7 +81,7 @@ InlineKqlQueryWithoutDataSource.args = {
finalDiffableRule: mockCustomQueryRule({
kql_query: inlineKqlQuery,
}),
- kibanaServicesMock: {
+ kibanaServicesOverrides: {
data: {
dataViews: {
create: async () => mockDataView(),
@@ -98,7 +98,7 @@ SavedKqlQueryWithIndexPatterns.args = {
data_source: dataSourceWithIndexPatterns,
type: 'saved_query',
}),
- kibanaServicesMock: {
+ kibanaServicesOverrides: {
data: {
dataViews: {
create: async () => mockDataView(),
@@ -118,7 +118,7 @@ SavedKqlQueryWithDataView.args = {
data_source: dataSourceWithDataView,
type: 'saved_query',
}),
- kibanaServicesMock: {
+ kibanaServicesOverrides: {
data: {
dataViews: {
get: async () => mockDataView(),
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/license/license.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/license/license.stories.tsx
new file mode 100644
index 0000000000000..044564acd91d8
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/license/license.stories.tsx
@@ -0,0 +1,34 @@
+/*
+ * 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 { Story } from '@storybook/react';
+import { LicenseReadOnly } from './license';
+import { FieldReadOnly } from '../../field_readonly';
+import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine';
+import { mockCustomQueryRule } from '../../storybook/mocks';
+
+export default {
+ component: LicenseReadOnly,
+ title: 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/license',
+};
+
+interface TemplateProps {
+ finalDiffableRule: DiffableRule;
+}
+
+const Template: Story = (args) => {
+ return ;
+};
+
+export const Default = Template.bind({});
+
+Default.args = {
+ finalDiffableRule: mockCustomQueryRule({
+ license: 'Elastic License 2.0',
+ }),
+};
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/license/license.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/license/license.tsx
new file mode 100644
index 0000000000000..18032f66ab81d
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/license/license.tsx
@@ -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 React from 'react';
+import { EuiDescriptionList } from '@elastic/eui';
+import * as ruleDetailsI18n from '../../../../translations';
+import type { RuleLicense } from '../../../../../../../../../common/api/detection_engine';
+import { License } from '../../../../rule_about_section';
+
+interface LicenseReadOnlyProps {
+ license: RuleLicense;
+}
+
+export function LicenseReadOnly({ license }: LicenseReadOnlyProps) {
+ return (
+ ,
+ },
+ ]}
+ />
+ );
+}
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/max_signals/max_signals.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/max_signals/max_signals.stories.tsx
new file mode 100644
index 0000000000000..d6f369ff47ce6
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/max_signals/max_signals.stories.tsx
@@ -0,0 +1,34 @@
+/*
+ * 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 { Story } from '@storybook/react';
+import { MaxSignalsReadOnly } from './max_signals';
+import { FieldReadOnly } from '../../field_readonly';
+import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine';
+import { mockCustomQueryRule } from '../../storybook/mocks';
+
+export default {
+ component: MaxSignalsReadOnly,
+ title: 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/max_signals',
+};
+
+interface TemplateProps {
+ finalDiffableRule: DiffableRule;
+}
+
+const Template: Story = (args) => {
+ return ;
+};
+
+export const Default = Template.bind({});
+
+Default.args = {
+ finalDiffableRule: mockCustomQueryRule({
+ max_signals: 100,
+ }),
+};
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/max_signals/max_signals.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/max_signals/max_signals.tsx
new file mode 100644
index 0000000000000..d0bda317a416a
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/max_signals/max_signals.tsx
@@ -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 React from 'react';
+import { EuiDescriptionList } from '@elastic/eui';
+import * as ruleDetailsI18n from '../../../../translations';
+import type { MaxSignals as MaxSignalsType } from '../../../../../../../../../common/api/detection_engine';
+import { MaxSignals } from '../../../../rule_about_section';
+
+interface MaxSignalsReadOnlyProps {
+ maxSignals: MaxSignalsType;
+}
+
+export function MaxSignalsReadOnly({ maxSignals }: MaxSignalsReadOnlyProps) {
+ return (
+ ,
+ },
+ ]}
+ />
+ );
+}
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/new_terms_fields/new_terms_fields.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/new_terms_fields/new_terms_fields.stories.tsx
new file mode 100644
index 0000000000000..8f77a747fa06c
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/new_terms_fields/new_terms_fields.stories.tsx
@@ -0,0 +1,35 @@
+/*
+ * 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 { Story } from '@storybook/react';
+import { NewTermsFieldsReadOnly } from './new_terms_fields';
+import { FieldReadOnly } from '../../field_readonly';
+import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine';
+import { mockNewTermsRule } from '../../storybook/mocks';
+
+export default {
+ component: NewTermsFieldsReadOnly,
+ title:
+ 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/new_terms_fields',
+};
+
+interface TemplateProps {
+ finalDiffableRule: DiffableRule;
+}
+
+const Template: Story = (args) => {
+ return ;
+};
+
+export const Default = Template.bind({});
+
+Default.args = {
+ finalDiffableRule: mockNewTermsRule({
+ new_terms_fields: ['user.name', 'source.ip'],
+ }),
+};
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/new_terms_fields/new_terms_fields.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/new_terms_fields/new_terms_fields.tsx
new file mode 100644
index 0000000000000..b77f7b0736482
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/new_terms_fields/new_terms_fields.tsx
@@ -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 React from 'react';
+import { EuiDescriptionList } from '@elastic/eui';
+import * as ruleDetailsI18n from '../../../../translations';
+import type { NewTermsFields as NewTermsFieldsType } from '../../../../../../../../../common/api/detection_engine';
+import { NewTermsFields } from '../../../../rule_definition_section';
+
+interface NewTermsFieldsReadOnlyProps {
+ newTermsFields: NewTermsFieldsType;
+}
+
+export function NewTermsFieldsReadOnly({ newTermsFields }: NewTermsFieldsReadOnlyProps) {
+ return (
+ ,
+ },
+ ]}
+ />
+ );
+}
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/note/note.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/note/note.stories.tsx
new file mode 100644
index 0000000000000..501faeb1cfbad
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/note/note.stories.tsx
@@ -0,0 +1,34 @@
+/*
+ * 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 { Story } from '@storybook/react';
+import { NoteReadOnly } from './note';
+import { FieldReadOnly } from '../../field_readonly';
+import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine';
+import { mockCustomQueryRule } from '../../storybook/mocks';
+
+export default {
+ component: NoteReadOnly,
+ title: 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/note',
+};
+
+interface TemplateProps {
+ finalDiffableRule: DiffableRule;
+}
+
+const Template: Story = (args) => {
+ return ;
+};
+
+export const Default = Template.bind({});
+
+Default.args = {
+ finalDiffableRule: mockCustomQueryRule({
+ note: '## Triage and analysis\n\n### Investigating Unusual Network Activity\nDetection alerts from this rule indicate the presence of network activity from a Linux process for which network activity is rare and unusual. Here are some possible avenues of investigation:\n- Consider the IP addresses and ports. Are these used by normal but infrequent network workflows? Are they expected or unexpected?\n- If the destination IP address is remote or external, does it associate with an expected domain, organization or geography? Note: avoid interacting directly with suspected malicious IP addresses.\n- Consider the user as identified by the username field. Is this network activity part of an expected workflow for the user who ran the program?\n- Examine the history of execution. If this process only manifested recently, it might be part of a new software package. If it has a consistent cadence (for example if it runs monthly or quarterly), it might be part of a monthly or quarterly business or maintenance process.\n- Examine the process arguments, title and working directory. These may provide indications as to the source of the program or the nature of the tasks it is performing.',
+ }),
+};
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/note/note.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/note/note.tsx
new file mode 100644
index 0000000000000..37184df117110
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/note/note.tsx
@@ -0,0 +1,37 @@
+/*
+ * 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 { EuiDescriptionList } from '@elastic/eui';
+import * as i18n from './translations';
+import type { InvestigationGuide } from '../../../../../../../../../common/api/detection_engine';
+import { MarkdownRenderer } from '../../../../../../../../common/components/markdown_editor';
+
+interface NoteReadOnlyProps {
+ note: InvestigationGuide;
+}
+
+export function NoteReadOnly({ note }: NoteReadOnlyProps) {
+ return (
+ ,
+ },
+ ]}
+ />
+ );
+}
+
+interface NoteProps {
+ note: InvestigationGuide;
+}
+
+function Note({ note }: NoteProps) {
+ return {note};
+}
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/note/translations.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/note/translations.ts
new file mode 100644
index 0000000000000..7a36a7d117d8d
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/note/translations.ts
@@ -0,0 +1,15 @@
+/*
+ * 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 NOTE_LABEL = i18n.translate(
+ 'xpack.securitySolution.detectionEngine.rules.upgradeRules.fieldReadOnly.noteLabel',
+ {
+ defaultMessage: 'Investigation guide',
+ }
+);
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/references/references.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/references/references.stories.tsx
new file mode 100644
index 0000000000000..561d5b36cf4f3
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/references/references.stories.tsx
@@ -0,0 +1,38 @@
+/*
+ * 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 { Story } from '@storybook/react';
+import { ReferencesReadOnly } from './references';
+import { FieldReadOnly } from '../../field_readonly';
+import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine';
+import { mockCustomQueryRule } from '../../storybook/mocks';
+
+export default {
+ component: ReferencesReadOnly,
+ title: 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/references',
+};
+
+interface TemplateProps {
+ finalDiffableRule: DiffableRule;
+}
+
+const Template: Story = (args) => {
+ return ;
+};
+
+export const Default = Template.bind({});
+
+Default.args = {
+ finalDiffableRule: mockCustomQueryRule({
+ references: [
+ 'https://www.elastic.co/guide/en/security/current/prebuilt-ml-jobs.html',
+ 'https://docs.elastic.co/en/integrations/beaconing',
+ 'https://www.elastic.co/security-labs/identifying-beaconing-malware-using-elastic',
+ ],
+ }),
+};
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/references/references.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/references/references.tsx
new file mode 100644
index 0000000000000..c98c5a53bb2e8
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/references/references.tsx
@@ -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 React from 'react';
+import { EuiDescriptionList } from '@elastic/eui';
+import * as ruleDetailsI18n from '../../../../translations';
+import type { RuleReferenceArray } from '../../../../../../../../../common/api/detection_engine';
+import { References } from '../../../../rule_about_section';
+
+interface ReferencesReadOnlyProps {
+ references: RuleReferenceArray;
+}
+
+export function ReferencesReadOnly({ references }: ReferencesReadOnlyProps) {
+ return (
+ ,
+ },
+ ]}
+ />
+ );
+}
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/risk_score/risk_score.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/risk_score/risk_score.stories.tsx
new file mode 100644
index 0000000000000..c0be0fb6190f6
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/risk_score/risk_score.stories.tsx
@@ -0,0 +1,34 @@
+/*
+ * 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 { Story } from '@storybook/react';
+import { RiskScoreReadOnly } from './risk_score';
+import { FieldReadOnly } from '../../field_readonly';
+import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine';
+import { mockCustomQueryRule } from '../../storybook/mocks';
+
+export default {
+ component: RiskScoreReadOnly,
+ title: 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/risk_score',
+};
+
+interface TemplateProps {
+ finalDiffableRule: DiffableRule;
+}
+
+const Template: Story = (args) => {
+ return ;
+};
+
+export const Default = Template.bind({});
+
+Default.args = {
+ finalDiffableRule: mockCustomQueryRule({
+ risk_score: 96,
+ }),
+};
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/risk_score/risk_score.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/risk_score/risk_score.tsx
new file mode 100644
index 0000000000000..ef6ddbd7d8217
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/risk_score/risk_score.tsx
@@ -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 React from 'react';
+import { EuiDescriptionList } from '@elastic/eui';
+import * as ruleDetailsI18n from '../../../../translations';
+import type { RiskScore as RiskScoreType } from '../../../../../../../../../common/api/detection_engine';
+import { RiskScore } from '../../../../rule_about_section';
+
+interface RiskScoreReadOnlyProps {
+ riskScore: RiskScoreType;
+}
+
+export function RiskScoreReadOnly({ riskScore }: RiskScoreReadOnlyProps) {
+ return (
+ ,
+ },
+ ]}
+ />
+ );
+}
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/rule_name_override/rule_name_override.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/rule_name_override/rule_name_override.stories.tsx
new file mode 100644
index 0000000000000..fa46e313fd664
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/rule_name_override/rule_name_override.stories.tsx
@@ -0,0 +1,39 @@
+/*
+ * 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 { Story } from '@storybook/react';
+import { RuleNameOverrideReadOnly } from './rule_name_override';
+import { FieldReadOnly } from '../../field_readonly';
+import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine';
+import { mockCustomQueryRule } from '../../storybook/mocks';
+
+export default {
+ component: RuleNameOverrideReadOnly,
+ title:
+ 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/rule_name_override',
+};
+
+interface TemplateProps {
+ finalDiffableRule: DiffableRule;
+}
+
+const Template: Story = (args) => {
+ return (
+
+ );
+};
+
+export const Default = Template.bind({});
+
+Default.args = {
+ finalDiffableRule: mockCustomQueryRule({
+ rule_name_override: {
+ field_name: 'event.action',
+ },
+ }),
+};
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/rule_name_override/rule_name_override.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/rule_name_override/rule_name_override.tsx
new file mode 100644
index 0000000000000..9090138ab91ee
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/rule_name_override/rule_name_override.tsx
@@ -0,0 +1,33 @@
+/*
+ * 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 { EuiDescriptionList } from '@elastic/eui';
+import * as ruleDetailsI18n from '../../../../translations';
+import type { RuleNameOverrideObject } from '../../../../../../../../../common/api/detection_engine';
+import { RuleNameOverride } from '../../../../rule_about_section';
+
+interface RuleNameOverrideReadOnlyProps {
+ ruleNameOverride?: RuleNameOverrideObject;
+}
+
+export function RuleNameOverrideReadOnly({ ruleNameOverride }: RuleNameOverrideReadOnlyProps) {
+ if (!ruleNameOverride) {
+ return null;
+ }
+
+ return (
+ ,
+ },
+ ]}
+ />
+ );
+}
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/rule_schedule/rule_schedule.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/rule_schedule/rule_schedule.stories.tsx
new file mode 100644
index 0000000000000..9e6be8a3cbe82
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/rule_schedule/rule_schedule.stories.tsx
@@ -0,0 +1,37 @@
+/*
+ * 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 { Story } from '@storybook/react';
+import { RuleScheduleReadOnly } from './rule_schedule';
+import { FieldReadOnly } from '../../field_readonly';
+import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine';
+import { mockCustomQueryRule } from '../../storybook/mocks';
+
+export default {
+ component: RuleScheduleReadOnly,
+ title: 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/rule_schedule',
+};
+
+interface TemplateProps {
+ finalDiffableRule: DiffableRule;
+}
+
+const Template: Story = (args) => {
+ return ;
+};
+
+export const Default = Template.bind({});
+
+Default.args = {
+ finalDiffableRule: mockCustomQueryRule({
+ rule_schedule: {
+ interval: '5m',
+ lookback: '60s',
+ },
+ }),
+};
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/rule_schedule/rule_schedule.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/rule_schedule/rule_schedule.tsx
new file mode 100644
index 0000000000000..24d0e5d6e05f1
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/rule_schedule/rule_schedule.tsx
@@ -0,0 +1,38 @@
+/*
+ * 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 { EuiDescriptionList } from '@elastic/eui';
+import { parseDuration } from '@kbn/alerting-plugin/common';
+import * as i18n from '../../../../translations';
+import type { RuleSchedule } from '../../../../../../../../../common/api/detection_engine';
+import { AccessibleTimeValue } from '../../../../rule_schedule_section';
+import { secondsToDurationString } from '../../../../../../../../detections/pages/detection_engine/rules/helpers';
+
+interface RuleScheduleReadOnlyProps {
+ ruleSchedule: RuleSchedule;
+}
+
+export function RuleScheduleReadOnly({ ruleSchedule }: RuleScheduleReadOnlyProps) {
+ const lookbackSeconds = parseDuration(ruleSchedule.lookback) / 1000;
+ const lookbackHumanized = secondsToDurationString(lookbackSeconds);
+
+ return (
+ ,
+ },
+ {
+ title: i18n.FROM_FIELD_LABEL,
+ description: ,
+ },
+ ]}
+ />
+ );
+}
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/setup/setup.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/setup/setup.stories.tsx
new file mode 100644
index 0000000000000..f610cbf9eafbb
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/setup/setup.stories.tsx
@@ -0,0 +1,35 @@
+/*
+ * 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 { Story } from '@storybook/react';
+import { SetupReadOnly } from './setup';
+import { FieldReadOnly } from '../../field_readonly';
+import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine';
+import { mockCustomQueryRule } from '../../storybook/mocks';
+
+export default {
+ component: SetupReadOnly,
+ title: 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/setup',
+};
+
+interface TemplateProps {
+ finalDiffableRule: DiffableRule;
+}
+
+const Template: Story = (args) => {
+ return ;
+};
+
+export const Default = Template.bind({});
+
+Default.args = {
+ finalDiffableRule: mockCustomQueryRule({
+ setup:
+ 'The \'PowerShell Script Block Logging\' logging policy must be enabled.\nSteps to implement the logging policy with Advanced Audit Configuration:\n\n```\nComputer Configuration >\nAdministrative Templates >\nWindows PowerShell >\nTurn on PowerShell Script Block Logging (Enable)\n```\n\nSteps to implement the logging policy via registry:\n\n```\nreg add "hklm\\SOFTWARE\\Policies\\Microsoft\\Windows\\PowerShell\\ScriptBlockLogging" /v EnableScriptBlockLogging /t REG_DWORD /d 1\n```',
+ }),
+};
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/setup/setup.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/setup/setup.tsx
new file mode 100644
index 0000000000000..a4ed7ba9539f1
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/setup/setup.tsx
@@ -0,0 +1,37 @@
+/*
+ * 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 { EuiDescriptionList } from '@elastic/eui';
+import * as ruleDetailsI18n from '../../../../translations';
+import type { SetupGuide } from '../../../../../../../../../common/api/detection_engine';
+import { MarkdownRenderer } from '../../../../../../../../common/components/markdown_editor';
+
+interface SetupReadOnlyProps {
+ setup: SetupGuide;
+}
+
+export function SetupReadOnly({ setup }: SetupReadOnlyProps) {
+ return (
+ ,
+ },
+ ]}
+ />
+ );
+}
+
+interface SetupProps {
+ setup: SetupGuide;
+}
+
+function Setup({ setup }: SetupProps) {
+ return {setup};
+}
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/severity/severity.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/severity/severity.stories.tsx
new file mode 100644
index 0000000000000..51956bb27fa0e
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/severity/severity.stories.tsx
@@ -0,0 +1,34 @@
+/*
+ * 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 { Story } from '@storybook/react';
+import { SeverityReadOnly } from './severity';
+import { FieldReadOnly } from '../../field_readonly';
+import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine';
+import { mockCustomQueryRule } from '../../storybook/mocks';
+
+export default {
+ component: SeverityReadOnly,
+ title: 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/severity',
+};
+
+interface TemplateProps {
+ finalDiffableRule: DiffableRule;
+}
+
+const Template: Story = (args) => {
+ return ;
+};
+
+export const Default = Template.bind({});
+
+Default.args = {
+ finalDiffableRule: mockCustomQueryRule({
+ severity: 'high',
+ }),
+};
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/severity/severity.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/severity/severity.tsx
new file mode 100644
index 0000000000000..71ab7bf07d793
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/severity/severity.tsx
@@ -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 React from 'react';
+import { EuiDescriptionList } from '@elastic/eui';
+import * as ruleDetailsI18n from '../../../../translations';
+import type { Severity } from '../../../../../../../../../common/api/detection_engine';
+import { SeverityBadge } from '../../../../../../../../common/components/severity_badge';
+
+interface SeverityReadOnlyProps {
+ severity: Severity;
+}
+
+export function SeverityReadOnly({ severity }: SeverityReadOnlyProps) {
+ return (
+ ,
+ },
+ ]}
+ />
+ );
+}
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_language/threat_language.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_language/threat_language.stories.tsx
new file mode 100644
index 0000000000000..0e3408aae043e
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_language/threat_language.stories.tsx
@@ -0,0 +1,34 @@
+/*
+ * 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 { Story } from '@storybook/react';
+import { ThreatLanguageReadOnly } from './threat_language';
+import { FieldReadOnly } from '../../field_readonly';
+import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine';
+import { mockThreatMatchRule } from '../../storybook/mocks';
+
+export default {
+ component: ThreatLanguageReadOnly,
+ title: 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/threat_language',
+};
+
+interface TemplateProps {
+ finalDiffableRule: DiffableRule;
+}
+
+const Template: Story = (args) => {
+ return ;
+};
+
+export const Default = Template.bind({});
+
+Default.args = {
+ finalDiffableRule: mockThreatMatchRule({
+ threat_language: 'lucene',
+ }),
+};
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_language/threat_language.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_language/threat_language.tsx
new file mode 100644
index 0000000000000..df43373783b1b
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_language/threat_language.tsx
@@ -0,0 +1,33 @@
+/*
+ * 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 { EuiDescriptionList } from '@elastic/eui';
+import * as ruleDetailsI18n from '../../../../translations';
+import type { KqlQueryLanguage } from '../../../../../../../../../common/api/detection_engine';
+import { getQueryLanguageLabel } from '../../../../helpers';
+
+interface ThreatLanguageReadOnlyProps {
+ threatLanguage?: KqlQueryLanguage;
+}
+
+export function ThreatLanguageReadOnly({ threatLanguage }: ThreatLanguageReadOnlyProps) {
+ if (!threatLanguage) {
+ return null;
+ }
+
+ return (
+
+ );
+}
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_query/threat_query.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_query/threat_query.stories.tsx
index 28b4cd65ba78b..bbc5b19d7e66a 100644
--- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_query/threat_query.stories.tsx
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_query/threat_query.stories.tsx
@@ -26,12 +26,12 @@ export default {
interface TemplateProps {
finalDiffableRule: DiffableRule;
- kibanaServicesMock?: Record;
+ kibanaServicesOverrides?: Record;
}
const Template: Story = (args) => {
return (
-
+
);
@@ -44,7 +44,7 @@ ThreatQueryWithIndexPatterns.args = {
threat_query: inlineKqlQuery,
data_source: dataSourceWithIndexPatterns,
}),
- kibanaServicesMock: {
+ kibanaServicesOverrides: {
data: {
dataViews: {
create: async () => mockDataView(),
@@ -60,7 +60,7 @@ ThreatQueryWithDataView.args = {
threat_query: inlineKqlQuery,
data_source: dataSourceWithDataView,
}),
- kibanaServicesMock: {
+ kibanaServicesOverrides: {
data: {
dataViews: {
get: async () => mockDataView(),
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threshold/threshold.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threshold/threshold.stories.tsx
new file mode 100644
index 0000000000000..8dfee48ba7d23
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threshold/threshold.stories.tsx
@@ -0,0 +1,38 @@
+/*
+ * 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 { Story } from '@storybook/react';
+import { ThresholdReadOnly } from './threshold';
+import { FieldReadOnly } from '../../field_readonly';
+import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine';
+import { mockThresholdRule } from '../../storybook/mocks';
+
+export default {
+ component: ThresholdReadOnly,
+ title: 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/threshold',
+};
+
+interface TemplateProps {
+ finalDiffableRule: DiffableRule;
+}
+
+const Template: Story = (args) => {
+ return ;
+};
+
+export const Default = Template.bind({});
+
+Default.args = {
+ finalDiffableRule: mockThresholdRule({
+ threshold: {
+ field: ['Responses.process.pid'],
+ value: 100,
+ cardinality: [{ field: 'host.id', value: 2 }],
+ },
+ }),
+};
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threshold/threshold.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threshold/threshold.tsx
new file mode 100644
index 0000000000000..19e2b824a9ce5
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threshold/threshold.tsx
@@ -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 React from 'react';
+import { EuiDescriptionList } from '@elastic/eui';
+import * as ruleDetailsI18n from '../../../../translations';
+import type { Threshold as ThresholdType } from '../../../../../../../../../common/api/detection_engine';
+import { Threshold } from '../../../../rule_definition_section';
+
+interface ThresholdReadOnlyProps {
+ threshold: ThresholdType;
+}
+
+export function ThresholdReadOnly({ threshold }: ThresholdReadOnlyProps) {
+ return (
+ ,
+ },
+ ]}
+ />
+ );
+}
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/tiebreaker_field/tiebreaker_field.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/tiebreaker_field/tiebreaker_field.stories.tsx
new file mode 100644
index 0000000000000..2a41b6c928963
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/tiebreaker_field/tiebreaker_field.stories.tsx
@@ -0,0 +1,35 @@
+/*
+ * 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 { Story } from '@storybook/react';
+import { TiebreakerFieldReadOnly } from './tiebreaker_field';
+import { FieldReadOnly } from '../../field_readonly';
+import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine';
+import { mockEqlRule } from '../../storybook/mocks';
+
+export default {
+ component: TiebreakerFieldReadOnly,
+ title:
+ 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/tiebreaker_field',
+};
+
+interface TemplateProps {
+ finalDiffableRule: DiffableRule;
+}
+
+const Template: Story = (args) => {
+ return ;
+};
+
+export const Default = Template.bind({});
+
+Default.args = {
+ finalDiffableRule: mockEqlRule({
+ tiebreaker_field: 'process.name',
+ }),
+};
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/tiebreaker_field/tiebreaker_field.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/tiebreaker_field/tiebreaker_field.tsx
new file mode 100644
index 0000000000000..10e52240748c7
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/tiebreaker_field/tiebreaker_field.tsx
@@ -0,0 +1,40 @@
+/*
+ * 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 { EuiDescriptionList, EuiText } from '@elastic/eui';
+import * as descriptionStepI18n from '../../../../../../../rule_creation_ui/components/description_step/translations';
+import type { TiebreakerField as TiebreakerFieldType } from '../../../../../../../../../common/api/detection_engine';
+
+interface TiebreakerFieldReadOnlyProps {
+ tiebreakerField?: TiebreakerFieldType;
+}
+
+export function TiebreakerFieldReadOnly({ tiebreakerField }: TiebreakerFieldReadOnlyProps) {
+ if (!tiebreakerField) {
+ return null;
+ }
+
+ return (
+ ,
+ },
+ ]}
+ />
+ );
+}
+
+interface TiebreakerFieldProps {
+ tiebreakerField: TiebreakerFieldType;
+}
+
+function TiebreakerField({ tiebreakerField }: TiebreakerFieldProps) {
+ return {tiebreakerField};
+}
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timeline_template/timeline_template.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timeline_template/timeline_template.stories.tsx
new file mode 100644
index 0000000000000..e8646a562dadd
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timeline_template/timeline_template.stories.tsx
@@ -0,0 +1,38 @@
+/*
+ * 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 { Story } from '@storybook/react';
+import { TimelineTemplateReadOnly } from './timeline_template';
+import { FieldReadOnly } from '../../field_readonly';
+import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine';
+import { mockCustomQueryRule } from '../../storybook/mocks';
+
+export default {
+ component: TimelineTemplateReadOnly,
+ title:
+ 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/timeline_template',
+};
+
+interface TemplateProps {
+ finalDiffableRule: DiffableRule;
+}
+
+const Template: Story = (args) => {
+ return ;
+};
+
+export const Default = Template.bind({});
+
+Default.args = {
+ finalDiffableRule: mockCustomQueryRule({
+ timeline_template: {
+ timeline_title: 'Alerts Involving a Single User Timeline',
+ timeline_id: 'some-timeline-id-123',
+ },
+ }),
+};
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timeline_template/timeline_template.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timeline_template/timeline_template.tsx
new file mode 100644
index 0000000000000..d6cc75cec5843
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timeline_template/timeline_template.tsx
@@ -0,0 +1,33 @@
+/*
+ * 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 { EuiDescriptionList } from '@elastic/eui';
+import * as ruleDetailsI18n from '../../../../translations';
+import type { TimelineTemplateReference } from '../../../../../../../../../common/api/detection_engine';
+import { TimelineTitle } from '../../../../rule_definition_section';
+
+interface TimelineTemplateReadOnlyProps {
+ timelineTemplate?: TimelineTemplateReference;
+}
+
+export function TimelineTemplateReadOnly({ timelineTemplate }: TimelineTemplateReadOnlyProps) {
+ if (!timelineTemplate) {
+ return null;
+ }
+
+ return (
+ ,
+ },
+ ]}
+ />
+ );
+}
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timestamp_field/timestamp_field.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timestamp_field/timestamp_field.stories.tsx
new file mode 100644
index 0000000000000..5d6b6c0a7bc3a
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timestamp_field/timestamp_field.stories.tsx
@@ -0,0 +1,34 @@
+/*
+ * 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 { Story } from '@storybook/react';
+import { TimestampFieldReadOnly } from './timestamp_field';
+import { FieldReadOnly } from '../../field_readonly';
+import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine';
+import { mockEqlRule } from '../../storybook/mocks';
+
+export default {
+ component: TimestampFieldReadOnly,
+ title: 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/timestamp_field',
+};
+
+interface TemplateProps {
+ finalDiffableRule: DiffableRule;
+}
+
+const Template: Story = (args) => {
+ return ;
+};
+
+export const Default = Template.bind({});
+
+Default.args = {
+ finalDiffableRule: mockEqlRule({
+ timestamp_field: 'event.created',
+ }),
+};
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timestamp_field/timestamp_field.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timestamp_field/timestamp_field.tsx
new file mode 100644
index 0000000000000..cd27bfde3db60
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timestamp_field/timestamp_field.tsx
@@ -0,0 +1,40 @@
+/*
+ * 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 { EuiDescriptionList, EuiText } from '@elastic/eui';
+import * as descriptionStepI18n from '../../../../../../../rule_creation_ui/components/description_step/translations';
+import type { TimestampField as TimestampFieldType } from '../../../../../../../../../common/api/detection_engine';
+
+interface TimestampFieldReadOnlyProps {
+ timestampField?: TimestampFieldType;
+}
+
+export function TimestampFieldReadOnly({ timestampField }: TimestampFieldReadOnlyProps) {
+ if (!timestampField) {
+ return null;
+ }
+
+ return (
+ ,
+ },
+ ]}
+ />
+ );
+}
+
+interface TimestampFieldProps {
+ timestampField: TimestampFieldType;
+}
+
+function TimestampField({ timestampField }: TimestampFieldProps) {
+ return {timestampField};
+}
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timestamp_override/timestamp_override.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timestamp_override/timestamp_override.stories.tsx
new file mode 100644
index 0000000000000..eaba3bda0c2e7
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timestamp_override/timestamp_override.stories.tsx
@@ -0,0 +1,40 @@
+/*
+ * 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 { Story } from '@storybook/react';
+import { TimestampOverrideReadOnly } from './timestamp_override';
+import { FieldReadOnly } from '../../field_readonly';
+import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine';
+import { mockCustomQueryRule } from '../../storybook/mocks';
+
+export default {
+ component: TimestampOverrideReadOnly,
+ title:
+ 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/timestamp_override',
+};
+
+interface TemplateProps {
+ finalDiffableRule: DiffableRule;
+}
+
+const Template: Story = (args) => {
+ return (
+
+ );
+};
+
+export const Default = Template.bind({});
+
+Default.args = {
+ finalDiffableRule: mockCustomQueryRule({
+ timestamp_override: {
+ field_name: 'event.ingested',
+ fallback_disabled: true,
+ },
+ }),
+};
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timestamp_override/timestamp_override.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timestamp_override/timestamp_override.tsx
new file mode 100644
index 0000000000000..5d4c6ba3e1d2b
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timestamp_override/timestamp_override.tsx
@@ -0,0 +1,33 @@
+/*
+ * 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 { EuiDescriptionList } from '@elastic/eui';
+import * as ruleDetailsI18n from '../../../../translations';
+import type { TimestampOverrideObject } from '../../../../../../../../../common/api/detection_engine';
+import { TimestampOverride } from '../../../../rule_about_section';
+
+interface TimestampOverrideReadOnlyProps {
+ timestampOverride?: TimestampOverrideObject;
+}
+
+export function TimestampOverrideReadOnly({ timestampOverride }: TimestampOverrideReadOnlyProps) {
+ if (!timestampOverride) {
+ return null;
+ }
+
+ return (
+ ,
+ },
+ ]}
+ />
+ );
+}
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/type/type.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/type/type.stories.tsx
new file mode 100644
index 0000000000000..e3f901c958788
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/type/type.stories.tsx
@@ -0,0 +1,34 @@
+/*
+ * 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 { Story } from '@storybook/react';
+import { TypeReadOnly } from './type';
+import { FieldReadOnly } from '../../field_readonly';
+import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine';
+import { mockCustomQueryRule } from '../../storybook/mocks';
+
+export default {
+ component: TypeReadOnly,
+ title: 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/type',
+};
+
+interface TemplateProps {
+ finalDiffableRule: DiffableRule;
+}
+
+const Template: Story = (args) => {
+ return ;
+};
+
+export const Default = Template.bind({});
+
+Default.args = {
+ finalDiffableRule: mockCustomQueryRule({
+ type: 'query',
+ }),
+};
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/type/type.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/type/type.tsx
new file mode 100644
index 0000000000000..c08a77a2c1d0c
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/type/type.tsx
@@ -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 React from 'react';
+import { EuiDescriptionList } from '@elastic/eui';
+import * as ruleDetailsI18n from '../../../../translations';
+import type { DiffableRuleTypes } from '../../../../../../../../../common/api/detection_engine';
+import { RuleType } from '../../../../rule_definition_section';
+
+interface TypeReadOnlyProps {
+ type: DiffableRuleTypes;
+}
+
+export function TypeReadOnly({ type }: TypeReadOnlyProps) {
+ return (
+ ,
+ },
+ ]}
+ />
+ );
+}
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/machine_learning_rule_field_readonly.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/machine_learning_rule_field_readonly.tsx
index 5ebc6f80b13f2..1212905c930c7 100644
--- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/machine_learning_rule_field_readonly.tsx
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/machine_learning_rule_field_readonly.tsx
@@ -8,6 +8,10 @@
import React from 'react';
import type { DiffableMachineLearningFields } from '../../../../../../../common/api/detection_engine';
import { MachineLearningJobIdReadOnly } from './fields/machine_learning_job_id/machine_learning_job_id';
+import { TypeReadOnly } from './fields/type/type';
+import { AlertSuppressionReadOnly } from './fields/alert_suppression/alert_suppression';
+import { assertUnreachable } from '../../../../../../../common/utility_types';
+import { AnomalyThresholdReadOnly } from './fields/anomaly_threshold/anomaly_threshold';
interface MachineLearningRuleFieldReadOnlyProps {
fieldName: keyof DiffableMachineLearningFields;
@@ -19,6 +23,15 @@ export function MachineLearningRuleFieldReadOnly({
finalDiffableRule,
}: MachineLearningRuleFieldReadOnlyProps) {
switch (fieldName) {
+ case 'anomaly_threshold':
+ return ;
+ case 'alert_suppression':
+ return (
+
+ );
case 'machine_learning_job_id':
return (
);
case 'type':
- return null;
+ return ;
default:
- return null; // Will replace with `assertUnreachable(fieldName)` once all fields are implemented
+ return assertUnreachable(fieldName);
}
}
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/new_terms_rule_field_readonly.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/new_terms_rule_field_readonly.tsx
index 0e2b52c71ba2b..45eeb17f730fb 100644
--- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/new_terms_rule_field_readonly.tsx
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/new_terms_rule_field_readonly.tsx
@@ -9,6 +9,11 @@ import React from 'react';
import type { DiffableNewTermsFields } from '../../../../../../../common/api/detection_engine';
import { DataSourceReadOnly } from './fields/data_source/data_source';
import { KqlQueryReadOnly } from './fields/kql_query';
+import { TypeReadOnly } from './fields/type/type';
+import { AlertSuppressionReadOnly } from './fields/alert_suppression/alert_suppression';
+import { NewTermsFieldsReadOnly } from './fields/new_terms_fields/new_terms_fields';
+import { HistoryWindowStartReadOnly } from './fields/history_window_start/history_window_start';
+import { assertUnreachable } from '../../../../../../../common/utility_types';
interface NewTermsRuleFieldReadOnlyProps {
fieldName: keyof DiffableNewTermsFields;
@@ -20,8 +25,19 @@ export function NewTermsRuleFieldReadOnly({
finalDiffableRule,
}: NewTermsRuleFieldReadOnlyProps) {
switch (fieldName) {
+ case 'alert_suppression':
+ return (
+
+ );
case 'data_source':
return ;
+ case 'history_window_start':
+ return (
+
+ );
case 'kql_query':
return (
);
+ case 'new_terms_fields':
+ return ;
case 'type':
- return null;
+ return ;
default:
- return null; // Will replace with `assertUnreachable(fieldName)` once all fields are implemented
+ return assertUnreachable(fieldName);
}
}
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/saved_query_rule_field_readonly.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/saved_query_rule_field_readonly.tsx
index 41e2e0c32108b..e4a5dbf7242d1 100644
--- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/saved_query_rule_field_readonly.tsx
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/saved_query_rule_field_readonly.tsx
@@ -9,6 +9,9 @@ import React from 'react';
import type { DiffableSavedQueryFields } from '../../../../../../../common/api/detection_engine';
import { DataSourceReadOnly } from './fields/data_source/data_source';
import { KqlQueryReadOnly } from './fields/kql_query';
+import { TypeReadOnly } from './fields/type/type';
+import { AlertSuppressionReadOnly } from './fields/alert_suppression/alert_suppression';
+import { assertUnreachable } from '../../../../../../../common/utility_types';
interface SavedQueryRuleFieldReadOnlyProps {
fieldName: keyof DiffableSavedQueryFields;
@@ -20,6 +23,13 @@ export function SavedQueryRuleFieldReadOnly({
finalDiffableRule,
}: SavedQueryRuleFieldReadOnlyProps) {
switch (fieldName) {
+ case 'alert_suppression':
+ return (
+
+ );
case 'data_source':
return ;
case 'kql_query':
@@ -31,8 +41,8 @@ export function SavedQueryRuleFieldReadOnly({
/>
);
case 'type':
- return null;
+ return ;
default:
- return null; // Will replace with `assertUnreachable(fieldName)` once all fields are implemented
+ return assertUnreachable(fieldName);
}
}
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/storybook/mocks.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/storybook/mocks.ts
index 854251450809f..4612852c0ff7e 100644
--- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/storybook/mocks.ts
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/storybook/mocks.ts
@@ -16,9 +16,11 @@ import type {
DiffableEqlFields,
DiffableEsqlFields,
DiffableMachineLearningFields,
+ DiffableNewTermsFields,
DiffableRule,
DiffableSavedQueryFields,
DiffableThreatMatchFields,
+ DiffableThresholdFields,
InlineKqlQuery,
RuleEqlQuery,
SavedKqlQuery,
@@ -274,3 +276,49 @@ export function mockThreatMatchRule(
...overrides,
};
}
+
+const newTermsDiffableRuleFields: DiffableNewTermsFields = {
+ type: 'new_terms',
+ kql_query: {
+ type: KqlQueryType.inline_query,
+ query: '*',
+ language: 'kuery',
+ filters: [],
+ },
+ new_terms_fields: ['host.name'],
+ history_window_start: 'now-7d',
+};
+
+export function mockNewTermsRule(
+ overrides: Partial
+): DiffableRule {
+ return {
+ ...commonDiffableRuleFields,
+ ...newTermsDiffableRuleFields,
+ ...overrides,
+ };
+}
+
+export const thresholdDiffableRuleFields: DiffableThresholdFields = {
+ type: 'threshold',
+ kql_query: {
+ type: KqlQueryType.inline_query,
+ query: '*',
+ language: 'kuery',
+ filters: [],
+ },
+ threshold: {
+ field: ['user.name'],
+ value: 200,
+ },
+};
+
+export function mockThresholdRule(
+ overrides: Partial
+): DiffableRule {
+ return {
+ ...commonDiffableRuleFields,
+ ...thresholdDiffableRuleFields,
+ ...overrides,
+ };
+}
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/storybook/three_way_diff_storybook_providers.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/storybook/three_way_diff_storybook_providers.tsx
index 483624b6fb408..4eb14440c056c 100644
--- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/storybook/three_way_diff_storybook_providers.tsx
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/storybook/three_way_diff_storybook_providers.tsx
@@ -11,8 +11,10 @@ import { merge } from 'lodash';
import { Subject } from 'rxjs';
import { Provider as ReduxStoreProvider } from 'react-redux';
import type { CoreStart } from '@kbn/core/public';
+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';
function createKibanaServicesMock(overrides?: Partial) {
const baseMock = {
@@ -44,6 +46,10 @@ function createKibanaServicesMock(overrides?: Partial) {
},
},
uiSettings: {},
+ upsellingService: {
+ messages$: new Subject(),
+ getMessagesValue: () => new Map(),
+ } as unknown as UpsellingService,
};
return merge(baseMock, overrides);
@@ -65,21 +71,26 @@ function createMockStore() {
interface StorybookProvidersProps {
children: React.ReactNode;
- kibanaServicesMock?: Record;
+ kibanaServicesOverrides?: Record;
}
export function ThreeWayDiffStorybookProviders({
children,
- kibanaServicesMock,
+ kibanaServicesOverrides,
}: StorybookProvidersProps) {
- const KibanaReactContext = createKibanaReactContext(createKibanaServicesMock(kibanaServicesMock));
+ const kibanaServicesMock = createKibanaServicesMock(kibanaServicesOverrides);
+ const KibanaReactContext = createKibanaReactContext(kibanaServicesMock);
const store = createMockStore();
return (
- {children}
+
+
+ {children}
+
+
);
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/threat_match_rule_field_readonly.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/threat_match_rule_field_readonly.tsx
index 11fd941601922..3e23a064d14f2 100644
--- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/threat_match_rule_field_readonly.tsx
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/threat_match_rule_field_readonly.tsx
@@ -13,6 +13,10 @@ import { ThreatIndexReadOnly } from './fields/threat_index/threat_index';
import { ThreatIndicatorPathReadOnly } from './fields/threat_indicator_path/threat_indicator_path';
import { ThreatMappingReadOnly } from './fields/threat_mapping/threat_mapping';
import { ThreatQueryReadOnly } from './fields/threat_query/threat_query';
+import { TypeReadOnly } from './fields/type/type';
+import { AlertSuppressionReadOnly } from './fields/alert_suppression/alert_suppression';
+import { assertUnreachable } from '../../../../../../../common/utility_types';
+import { ThreatLanguageReadOnly } from './fields/threat_language/threat_language';
interface ThreatMatchRuleFieldReadOnlyProps {
fieldName: keyof DiffableThreatMatchFields;
@@ -24,6 +28,13 @@ export function ThreatMatchRuleFieldReadOnly({
finalDiffableRule,
}: ThreatMatchRuleFieldReadOnlyProps) {
switch (fieldName) {
+ case 'alert_suppression':
+ return (
+
+ );
case 'data_source':
return ;
case 'kql_query':
@@ -42,6 +53,8 @@ export function ThreatMatchRuleFieldReadOnly({
threatIndicatorPath={finalDiffableRule.threat_indicator_path}
/>
);
+ case 'threat_language':
+ return ;
case 'threat_mapping':
return ;
case 'threat_query':
@@ -52,8 +65,8 @@ export function ThreatMatchRuleFieldReadOnly({
/>
);
case 'type':
- return null;
+ return ;
default:
- return null; // Will replace with `assertUnreachable(fieldName)` once all fields are implemented
+ return assertUnreachable(fieldName);
}
}
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/threshold_rule_field_readonly.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/threshold_rule_field_readonly.tsx
index da7d3984d7ccb..d3208a055fa48 100644
--- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/threshold_rule_field_readonly.tsx
+++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/threshold_rule_field_readonly.tsx
@@ -9,6 +9,10 @@ import React from 'react';
import type { DiffableThresholdFields } from '../../../../../../../common/api/detection_engine';
import { DataSourceReadOnly } from './fields/data_source/data_source';
import { KqlQueryReadOnly } from './fields/kql_query';
+import { TypeReadOnly } from './fields/type/type';
+import { AlertSuppressionReadOnly } from './fields/alert_suppression/alert_suppression';
+import { assertUnreachable } from '../../../../../../../common/utility_types';
+import { ThresholdReadOnly } from './fields/threshold/threshold';
interface ThresholdRuleFieldReadOnlyProps {
fieldName: keyof DiffableThresholdFields;
@@ -20,6 +24,13 @@ export function ThresholdRuleFieldReadOnly({
finalDiffableRule,
}: ThresholdRuleFieldReadOnlyProps) {
switch (fieldName) {
+ case 'alert_suppression':
+ return (
+
+ );
case 'data_source':
return ;
case 'kql_query':
@@ -30,9 +41,11 @@ export function ThresholdRuleFieldReadOnly({
ruleType={finalDiffableRule.type}
/>
);
+ case 'threshold':
+ return ;
case 'type':
- return null;
+ return ;
default:
- return null; // Will replace with `assertUnreachable(fieldName)` once all fields are implemented
+ return assertUnreachable(fieldName);
}
}
diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/helpers.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/helpers.tsx
index 24f871125ce4d..8fccd1fb8ac73 100644
--- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/helpers.tsx
+++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/helpers.tsx
@@ -199,6 +199,23 @@ export const getScheduleStepsData = (rule: RuleResponse): ScheduleStepRule => {
};
};
+/**
+ * Converts seconds to duration string, like "1h", "30m" or "15s"
+ */
+export const secondsToDurationString = (seconds: number): string => {
+ if (seconds === 0) {
+ return `0s`;
+ }
+
+ if (seconds % 3600 === 0) {
+ return `${seconds / 3600}h`;
+ } else if (seconds % 60 === 0) {
+ return `${seconds / 60}m`;
+ } else {
+ return `${seconds}s`;
+ }
+};
+
export const getHumanizedDuration = (from: string, interval: string): string => {
const fromValue = dateMath.parse(from) ?? moment();
const intervalValue = dateMath.parse(`now-${interval}`) ?? moment();
@@ -208,17 +225,8 @@ export const getHumanizedDuration = (from: string, interval: string): string =>
// Basing calculations off floored seconds count as moment durations weren't precise
const intervalDuration = Math.floor(fromDuration.asSeconds());
// For consistency of display value
- if (intervalDuration === 0) {
- return `0s`;
- }
- if (intervalDuration % 3600 === 0) {
- return `${intervalDuration / 3600}h`;
- } else if (intervalDuration % 60 === 0) {
- return `${intervalDuration / 60}m`;
- } else {
- return `${intervalDuration}s`;
- }
+ return secondsToDurationString(intervalDuration);
};
export const getAboutStepsData = (rule: RuleResponse, detailsView: boolean): AboutStepRule => {