Skip to content

Commit

Permalink
Add history_window_start and refactor new_terms_fields
Browse files Browse the repository at this point in the history
  • Loading branch information
nikitaindik committed Nov 15, 2024
1 parent d79f204 commit 8f9cc18
Show file tree
Hide file tree
Showing 23 changed files with 238 additions and 100 deletions.
2 changes: 2 additions & 0 deletions x-pack/plugins/security_solution/public/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,5 @@ export const RISK_SCORE_HIGH = 73;
export const RISK_SCORE_CRITICAL = 99;

export const ONBOARDING_VIDEO_SOURCE = '//play.vidyard.com/K6kKDBbP9SpXife9s2tHNP.html?';

export const DEFAULT_HISTORY_WINDOW_SIZE = '7d';
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

/**
* Converts a history start string to a history size string by removing the 'now-' prefix.
*
* @param historyStart - History start string to convert. For example, "now-30d".
* @returns Converted size string. For example, "30d".
*/
export const convertHistoryStartToSize = (historyStart: string) => {
if (historyStart.startsWith('now-')) {
return historyStart.substring(4);
} else {
return historyStart;
}
};

/**
* Converts a history size string to a history start string by adding the 'now-' prefix.
*
* @param historySize - History size string to convert. For example, "30d".
* @returns Converted start string. For example, "now-30d".
*/
export const convertHistorySizeToStart = (historySize: string) => `now-${historySize}`;
Original file line number Diff line number Diff line change
@@ -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 { ScheduleItemField } from '../schedule_item_field';
import { UseField } from '../../../../shared_imports';

const componentProps = {
idAria: 'historyWindowSize',
dataTestSubj: 'historyWindowSize',
timeTypes: ['m', 'h', 'd'],
};

interface HistoryWindowStartEditProps {
path: string;
}

export function HistoryWindowStartEdit({ path }: HistoryWindowStartEditProps): JSX.Element {
return <UseField path={path} component={ScheduleItemField} componentProps={componentProps} />;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

export { HistoryWindowStartEdit } from './history_window_start_edit';
Original file line number Diff line number Diff line change
Expand Up @@ -5,38 +5,4 @@
* 2.0.
*/

import React, { useMemo } from 'react';

import type { DataViewFieldBase } from '@kbn/es-query';
import type { FieldHook } from '../../../../shared_imports';
import { Field } from '../../../../shared_imports';
import { NEW_TERMS_FIELD_PLACEHOLDER } from './translations';

interface NewTermsFieldsProps {
browserFields: DataViewFieldBase[];
field: FieldHook;
}

const FIELD_COMBO_BOX_WIDTH = 410;

const fieldDescribedByIds = 'newTermsFieldEdit';

export const NewTermsFieldsEditComponent: React.FC<NewTermsFieldsProps> = ({
browserFields,
field,
}: NewTermsFieldsProps) => {
const fieldEuiFieldProps = useMemo(
() => ({
fullWidth: true,
noSuggestions: false,
options: browserFields.map((browserField) => ({ label: browserField.name })),
placeholder: NEW_TERMS_FIELD_PLACEHOLDER,
onCreateOption: undefined,
style: { width: `${FIELD_COMBO_BOX_WIDTH}px` },
}),
[browserFields]
);
return <Field field={field} idAria={fieldDescribedByIds} euiFieldProps={fieldEuiFieldProps} />;
};

export const NewTermsFieldsEdit = React.memo(NewTermsFieldsEditComponent);
export { NewTermsFieldsEdit } from './new_terms_fields_edit';
Original file line number Diff line number Diff line change
@@ -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, { useMemo } from 'react';
import type { DataViewFieldBase } from '@kbn/es-query';
import { UseField } from '../../../../shared_imports';
import { NewTermsFieldsEditField } from './new_terms_fields_edit_field';

interface NewTermsFieldsEditProps {
path: string;
browserFields: DataViewFieldBase[];
}

export function NewTermsFieldsEdit({ path, browserFields }: NewTermsFieldsEditProps): JSX.Element {
const componentProps = useMemo(() => ({ browserFields }), [browserFields]);

return (
<UseField path={path} component={NewTermsFieldsEditField} componentProps={componentProps} />
);
}
Original file line number Diff line number Diff line change
@@ -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, { useMemo } from 'react';

import type { DataViewFieldBase } from '@kbn/es-query';
import type { FieldHook } from '../../../../shared_imports';
import { Field } from '../../../../shared_imports';
import { NEW_TERMS_FIELD_PLACEHOLDER } from './translations';

interface NewTermsFieldsProps {
browserFields: DataViewFieldBase[];
field: FieldHook;
}

const FIELD_COMBO_BOX_WIDTH = 410;

const fieldDescribedByIds = 'newTermsFieldEdit';

export const NewTermsFieldsEditFieldComponent: React.FC<NewTermsFieldsProps> = ({
browserFields,
field,
}: NewTermsFieldsProps) => {
const fieldEuiFieldProps = useMemo(
() => ({
fullWidth: true,
noSuggestions: false,
options: browserFields.map((browserField) => ({ label: browserField.name })),
placeholder: NEW_TERMS_FIELD_PLACEHOLDER,
onCreateOption: undefined,
style: { width: `${FIELD_COMBO_BOX_WIDTH}px` },
}),
[browserFields]
);
return <Field field={field} idAria={fieldDescribedByIds} euiFieldProps={fieldEuiFieldProps} />;
};

export const NewTermsFieldsEditField = React.memo(NewTermsFieldsEditFieldComponent);
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

export { ScheduleItemField } from './schedule_item_field';
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@
import React from 'react';
import { mount, shallow } from 'enzyme';

import { ScheduleItem } from '.';
import { ScheduleItemField } from './schedule_item_field';
import { TestProviders, useFormFieldMock } from '../../../../common/mock';

describe('ScheduleItem', () => {
describe('ScheduleItemField', () => {
it('renders correctly', () => {
const mockField = useFormFieldMock<string>();
const wrapper = shallow(
<ScheduleItem
<ScheduleItemField
dataTestSubj="schedule-item"
idAria="idAria"
isDisabled={false}
Expand All @@ -30,7 +30,7 @@ describe('ScheduleItem', () => {
const mockField = useFormFieldMock<string>();
const wrapper = mount(
<TestProviders>
<ScheduleItem
<ScheduleItemField
dataTestSubj="schedule-item"
idAria="idAria"
isDisabled={false}
Expand All @@ -53,7 +53,7 @@ describe('ScheduleItem', () => {
const mockField = useFormFieldMock<string>();
const wrapper = mount(
<TestProviders>
<ScheduleItem
<ScheduleItemField
dataTestSubj="schedule-item"
idAria="idAria"
isDisabled={false}
Expand All @@ -77,7 +77,7 @@ describe('ScheduleItem', () => {
const mockField = useFormFieldMock<string>();
const wrapper = mount(
<TestProviders>
<ScheduleItem
<ScheduleItemField
dataTestSubj="schedule-item"
idAria="idAria"
isDisabled={false}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ const getNumberFromUserInput = (input: string, minimumValue = 0): number => {
}
};

export const ScheduleItem = ({
export const ScheduleItemField = ({
dataTestSubj,
field,
idAria,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,6 @@ import { EqlQueryBar } from '../eql_query_bar';
import { DataViewSelectorField } from '../data_view_selector_field';
import { ThreatMatchInput } from '../threatmatch_input';
import { useFetchIndex } from '../../../../common/containers/source';
import { NewTermsFieldsEdit } from '../../../rule_creation/components/new_terms_fields_edit';
import { ScheduleItem } from '../../../rule_creation/components/schedule_item_form';
import { RequiredFields } from '../../../rule_creation/components/required_fields';
import { DocLink } from '../../../../common/components/links_to_docs/doc_link';
import { defaultCustomQuery } from '../../../../detections/pages/detection_engine/rules/utils';
Expand All @@ -94,6 +92,8 @@ import { AlertSuppressionEdit } from '../../../rule_creation/components/alert_su
import { ThresholdAlertSuppressionEdit } from '../../../rule_creation/components/threshold_alert_suppression_edit';
import { usePersistentAlertSuppressionState } from './use_persistent_alert_suppression_state';
import { useTermsAggregationFields } from '../../../../common/hooks/use_terms_aggregation_fields';
import { HistoryWindowStartEdit } from '../../../rule_creation/components/history_window_start_edit';
import { NewTermsFieldsEdit } from '../../../rule_creation/components/new_terms_fields_edit';

const CommonUseField = getUseField({ component: Field });

Expand Down Expand Up @@ -925,22 +925,8 @@ const StepDefineRuleComponent: FC<StepDefineRuleProps> = ({
fullWidth
>
<>
<UseField
path="newTermsFields"
component={NewTermsFieldsEdit}
componentProps={{
browserFields: termsAggregationFields,
}}
/>
<UseField
path="historyWindowSize"
component={ScheduleItem}
componentProps={{
idAria: 'detectionEngineStepDefineRuleHistoryWindowSize',
dataTestSubj: 'detectionEngineStepDefineRuleHistoryWindowSize',
timeTypes: ['m', 'h', 'd'],
}}
/>
<NewTermsFieldsEdit path="newTermsFields" browserFields={termsAggregationFields} />
<HistoryWindowStartEdit path="historyWindowSize" />
</>
</RuleTypeEuiFormRow>
<EuiSpacer size="m" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ import type {
ScheduleStepRule,
} from '../../../../detections/pages/detection_engine/rules/types';
import { StepRuleDescription } from '../description_step';
import { ScheduleItem } from '../../../rule_creation/components/schedule_item_form';
import { Form, UseField } from '../../../../shared_imports';
import type { FormHook } from '../../../../shared_imports';
import { StepContentWrapper } from '../../../rule_creation/components/step_content_wrapper';
import { schema } from './schema';
import { ScheduleItemField } from '../../../rule_creation/components/schedule_item_field';

const StyledForm = styled(Form)`
max-width: 235px !important;
Expand All @@ -43,7 +43,7 @@ const StepScheduleRuleComponent: FC<StepScheduleRuleProps> = ({
<StyledForm form={form} data-test-subj="stepScheduleRule">
<UseField
path="interval"
component={ScheduleItem}
component={ScheduleItemField}
componentProps={{
idAria: 'detectionEngineStepScheduleRuleInterval',
isDisabled: isLoading,
Expand All @@ -53,7 +53,7 @@ const StepScheduleRuleComponent: FC<StepScheduleRuleProps> = ({
/>
<UseField
path="from"
component={ScheduleItem}
component={ScheduleItemField}
componentProps={{
idAria: 'detectionEngineStepScheduleRuleFrom',
isDisabled: isLoading,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ import {
ALERT_SUPPRESSION_MISSING_FIELDS_FIELD_NAME,
} from '../../../rule_creation/components/alert_suppression_edit';
import { THRESHOLD_ALERT_SUPPRESSION_ENABLED } from '../../../rule_creation/components/threshold_alert_suppression_edit';
import { convertHistorySizeToStart } from '../../../../common/utils/history_window';

export const getTimeTypeValue = (time: string): { unit: Unit; value: number } => {
const timeObj: { unit: Unit; value: number } = {
Expand Down Expand Up @@ -528,7 +529,7 @@ export const formatDefineStepData = (defineStepData: DefineStepRule): DefineStep
query: ruleFields.queryBar?.query?.query as string,
required_fields: requiredFields,
new_terms_fields: ruleFields.newTermsFields,
history_window_start: `now-${ruleFields.historyWindowSize}`,
history_window_start: convertHistorySizeToStart(ruleFields.historyWindowSize),
...alertSuppressionFields,
}
: isEsqlFields(ruleFields) && !('index' in ruleFields)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ import * as timelinesI18n from '../../../../timelines/components/timeline/transl
import { useRuleIndexPattern } from '../../../rule_creation_ui/pages/form';
import { DataSourceType } from '../../../../detections/pages/detection_engine/rules/types';
import type { Duration } from '../../../../detections/pages/detection_engine/rules/types';
import { convertHistoryStartToSize } from '../../../../detections/pages/detection_engine/rules/helpers';
import { MlJobsDescription } from '../../../rule_creation/components/ml_jobs_description/ml_jobs_description';
import { MlJobLink } from '../../../rule_creation/components/ml_job_link/ml_job_link';
import { useSecurityJobs } from '../../../../common/components/ml_popover/hooks/use_security_jobs';
Expand All @@ -59,6 +58,7 @@ import {
} from './rule_definition_section.styles';
import { getQueryLanguageLabel } from './helpers';
import { useDefaultIndexPattern } from '../../hooks/use_default_index_pattern';
import { convertHistoryStartToSize } from '../../../../common/utils/history_window';

interface SavedQueryNameProps {
savedQueryName: string;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* 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 { HistoryWindowStartEdit } from '../../../../../../../rule_creation/components/history_window_start_edit';

export function HistoryWindowStartEditAdapter(): JSX.Element {
return <HistoryWindowStartEdit path="historyWindowSize" />;
}
Loading

0 comments on commit 8f9cc18

Please sign in to comment.