diff --git a/public/pages/Rules/components/RuleEditor/components/SelectionExpField.tsx b/public/pages/Rules/components/RuleEditor/components/SelectionExpField.tsx index d7d555f22..bea0e6af5 100644 --- a/public/pages/Rules/components/RuleEditor/components/SelectionExpField.tsx +++ b/public/pages/Rules/components/RuleEditor/components/SelectionExpField.tsx @@ -8,7 +8,7 @@ import { EuiButtonIcon, EuiExpression, } from '@elastic/eui'; -import * as _ from 'lodash'; +import _ from 'lodash'; import { Selection } from '../DetectionVisualEditor'; export interface SelectionExpFieldProps { @@ -24,6 +24,19 @@ interface UsedSelection { description: string; } +const operationOptionsFirstExpression = [ + { value: '', text: '' }, + { value: 'not', text: 'NOT' }, +]; + +const operatorOptions = [ + { value: '', text: '' }, + { value: 'and', text: 'AND' }, + { value: 'or', text: 'OR' }, + { value: 'and not', text: 'AND NOT' }, + { value: 'or not', text: 'OR NOT' }, +]; + export const SelectionExpField: React.FC = ({ selections, dataTestSubj, @@ -31,13 +44,26 @@ export const SelectionExpField: React.FC = ({ value, }) => { const DEFAULT_DESCRIPTION = 'Select'; - const OPERATORS = ['and', 'or', 'not']; + const OPERATORS = ['and', 'or', 'and not', 'or not', 'not']; const [usedExpressions, setUsedExpressions] = useState([]); useEffect(() => { let expressions: UsedSelection[] = []; if (value?.length) { - let values = value.split(' '); + const temp = value.split('and not'); + let values = temp + .map((_) => { + return _.trim() + .split('or not') + .map((leaf) => leaf.split(' ')) + .reduce((prev, curr) => { + return [...prev, 'or not', ...curr]; + }); + }) + .reduce((prev, curr) => { + return [...prev, 'and not', ...curr]; + }); + if (OPERATORS.indexOf(values[0]) === -1) values = ['', ...values]; let counter = 0; @@ -110,12 +136,7 @@ export const SelectionExpField: React.FC = ({ compressed value={exp.description} onChange={(e) => changeExtDescription(e, exp, idx)} - options={[ - { value: '', text: '' }, - { value: 'and', text: 'AND' }, - { value: 'or', text: 'OR' }, - { value: 'not', text: 'NOT' }, - ]} + options={idx === 0 ? operationOptionsFirstExpression : operatorOptions} /> {selections.length > usedExpressions.length && ( @@ -212,7 +233,7 @@ export const SelectionExpField: React.FC = ({ description={exp.description} value={exp.name} isActive={exp.isOpen} - onClick={(e) => onSelectionPopup(e, idx)} + onClick={(e: any) => onSelectionPopup(e, idx)} /> } isOpen={exp.isOpen} diff --git a/public/utils/validation.ts b/public/utils/validation.ts index 35b70a9c5..83361e848 100644 --- a/public/utils/validation.ts +++ b/public/utils/validation.ts @@ -15,7 +15,7 @@ export const NAME_REGEX = new RegExp(/^[a-zA-Z0-9 _-]{5,50}$/); export const DETECTION_NAME_REGEX = new RegExp(/^[a-zA-Z0-9_.-]{5,50}$/); export const DETECTION_CONDITION_REGEX = new RegExp( - /^((not )?[a-zA-Z0-9_]+)?( (and|or|not) ?([a-zA-Z0-9_]+))*(?