Skip to content

Commit

Permalink
[Security Solution][Exceptions] - Updates autocomplete validation for…
Browse files Browse the repository at this point in the history
… numbers and boolean (elastic#74561)

## Summary

This PR chips  a bit at some stricter value validations that have been discussed. Further validation is needed, but this adds some more basic validation.

- **Current:** if selected field is of type `boolean` users can add custom values in combo box
  - **Now:** if selected field is of type `boolean` users can only select `true` or `false`
- **Current:** if selected field is of type `number` (that is kibana type number) user can input any values
  - **Now:** if selected field is of type `number` and no autocomplete suggestions are available, number input is used to restrict users
- **Current:** for operator `match_any` it's conducting an autocomplete search after each selection resulting in some jumpy/weird behavior
  - **Now:** only conducts autocomplete search on initial field selection and if user enters value to search
- **Current:** only validations on type date
  - **Now:** validation on type (Kibana type) date, number
- **Current:** input would show red when there was an error but user could still submit
  - **Now:** submit button is disabled if error exists
  • Loading branch information
yctercero authored Oct 7, 2020
1 parent e60cfa0 commit 30695fb
Show file tree
Hide file tree
Showing 25 changed files with 1,392 additions and 388 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,28 @@
* you may not use this file except in compliance with the Elastic License.
*/
import React from 'react';
import { EuiComboBox } from '@elastic/eui';
import { EuiFormRow, EuiComboBox } from '@elastic/eui';

interface AutocompleteFieldExistsProps {
placeholder: string;
rowLabel?: string;
}

export const AutocompleteFieldExistsComponent: React.FC<AutocompleteFieldExistsProps> = ({
placeholder,
rowLabel,
}): JSX.Element => (
<EuiComboBox
placeholder={placeholder}
options={[]}
selectedOptions={[]}
onChange={undefined}
isDisabled
data-test-subj="valuesAutocompleteComboBox existsComboxBox"
fullWidth
/>
<EuiFormRow label={rowLabel} fullWidth>
<EuiComboBox
placeholder={placeholder}
options={[]}
selectedOptions={[]}
onChange={undefined}
isDisabled
data-test-subj="valuesAutocompleteComboBox existsComboxBox"
fullWidth
/>
</EuiFormRow>
);

AutocompleteFieldExistsComponent.displayName = 'AutocompleteFieldExists';
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@
* you may not use this file except in compliance with the Elastic License.
*/
import React, { useState, useEffect, useCallback, useMemo } from 'react';
import { EuiComboBoxOptionOption, EuiComboBox } from '@elastic/eui';
import { EuiFormRow, EuiComboBoxOptionOption, EuiComboBox } from '@elastic/eui';

import { IFieldType } from '../../../../../../../src/plugins/data/common';
import { useFindLists, ListSchema } from '../../../lists_plugin_deps';
import { useKibana } from '../../../common/lib/kibana';
import { getGenericComboBoxProps, paramIsValid } from './helpers';
import { getGenericComboBoxProps } from './helpers';
import * as i18n from './translations';

interface AutocompleteFieldListsProps {
placeholder: string;
Expand All @@ -19,11 +20,13 @@ interface AutocompleteFieldListsProps {
isDisabled: boolean;
isClearable: boolean;
isRequired?: boolean;
rowLabel?: string;
onChange: (arg: ListSchema) => void;
}

export const AutocompleteFieldListsComponent: React.FC<AutocompleteFieldListsProps> = ({
placeholder,
rowLabel,
selectedField,
selectedValue,
isLoading = false,
Expand All @@ -32,7 +35,7 @@ export const AutocompleteFieldListsComponent: React.FC<AutocompleteFieldListsPro
isRequired = false,
onChange,
}): JSX.Element => {
const [touched, setIsTouched] = useState(false);
const [error, setError] = useState<string | undefined>(undefined);
const { http } = useKibana().services;
const [lists, setLists] = useState<ListSchema[]>([]);
const { loading, result, start } = useFindLists();
Expand Down Expand Up @@ -75,7 +78,9 @@ export const AutocompleteFieldListsComponent: React.FC<AutocompleteFieldListsPro
[labels, optionsMemo, onChange]
);

const setIsTouchedValue = useCallback(() => setIsTouched(true), [setIsTouched]);
const setIsTouchedValue = useCallback((): void => {
setError(selectedValue == null ? i18n.FIELD_REQUIRED_ERR : undefined);
}, [selectedValue]);

useEffect(() => {
if (result != null) {
Expand All @@ -93,30 +98,27 @@ export const AutocompleteFieldListsComponent: React.FC<AutocompleteFieldListsPro
}
}, [selectedField, start, http]);

const isValid = useMemo(
(): boolean => paramIsValid(selectedValue, selectedField, isRequired, touched),
[selectedField, selectedValue, isRequired, touched]
);

const isLoadingState = useMemo((): boolean => isLoading || loading, [isLoading, loading]);

return (
<EuiComboBox
placeholder={placeholder}
isDisabled={isDisabled}
isLoading={isLoadingState}
isClearable={isClearable}
options={comboOptions}
selectedOptions={selectedComboOptions}
onChange={handleValuesChange}
isInvalid={!isValid}
onFocus={setIsTouchedValue}
singleSelection={{ asPlainText: true }}
sortMatchesBy="startsWith"
data-test-subj="valuesAutocompleteComboBox listsComboxBox"
fullWidth
async
/>
<EuiFormRow label={rowLabel} error={error} isInvalid={error != null} fullWidth>
<EuiComboBox
placeholder={placeholder}
isDisabled={isDisabled}
isLoading={isLoadingState}
isClearable={isClearable}
options={comboOptions}
selectedOptions={selectedComboOptions}
onChange={handleValuesChange}
isInvalid={error != null}
onBlur={setIsTouchedValue}
singleSelection={{ asPlainText: true }}
sortMatchesBy="startsWith"
data-test-subj="valuesAutocompleteComboBox listsComboxBox"
fullWidth
async
/>
</EuiFormRow>
);
};

Expand Down
Loading

0 comments on commit 30695fb

Please sign in to comment.