Skip to content

Commit

Permalink
[Unified Search] Show error message for invalid date filter value (el…
Browse files Browse the repository at this point in the history
…astic#131290)

* feat: added show error message for invalid date

* refact: move logic in HOC

* feat: refactoring code and added translation

* refact show error

* refact: show error message

* refact: remove translation

* refactor: changed menu for show FilterEdit

* fix: open/close popover

* feat: field.type => KBN_FIELD_TYPES

* feat: remove extra code with with input check and refactored filter item

* feat: added tests and refactoring code

* refact: getFieldValidityAndErrorMessage

* feat: return isInvalid checking in valur input type for string, ip
  • Loading branch information
nlatipov authored and Esteban Beltran committed May 17, 2022
1 parent a06e781 commit 59ffe0d
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { withKibana } from '@kbn/kibana-react-plugin/public';
import { GenericComboBox, GenericComboBoxProps } from './generic_combo_box';
import { PhraseSuggestorUI, PhraseSuggestorProps } from './phrase_suggestor';
import { ValueInputType } from './value_input_type';
import { getFieldValidityAndErrorMessage } from '../../utils/helpers';

interface Props extends PhraseSuggestorProps {
value?: string;
Expand All @@ -24,13 +25,20 @@ interface Props extends PhraseSuggestorProps {

class PhraseValueInputUI extends PhraseSuggestorUI<Props> {
public render() {
const { isInvalid, errorMessage } = getFieldValidityAndErrorMessage(
this.props.field,
this.props.value
);

return (
<EuiFormRow
fullWidth={this.props.fullWidth}
label={this.props.intl.formatMessage({
id: 'unifiedSearch.filter.filterEditor.valueInputLabel',
defaultMessage: 'Value',
})}
isInvalid={isInvalid}
error={errorMessage}
>
{this.isSuggestingValues() ? (
this.renderWithSuggestions()
Expand All @@ -44,6 +52,7 @@ class PhraseValueInputUI extends PhraseSuggestorUI<Props> {
value={this.props.value}
onChange={this.props.onChange}
field={this.props.field}
isInvalid={isInvalid}
/>
)}
</EuiFormRow>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ interface Props {
controlOnly?: boolean;
className?: string;
fullWidth?: boolean;
isInvalid?: boolean;
}

class ValueInputTypeUI extends Component<Props> {
Expand All @@ -33,6 +34,7 @@ class ValueInputTypeUI extends Component<Props> {
}
return value;
};

public render() {
const value = this.props.value;
const type = this.props.field.type;
Expand Down Expand Up @@ -73,7 +75,7 @@ class ValueInputTypeUI extends Component<Props> {
value={value}
onChange={this.onChange}
onBlur={this.onBlur}
isInvalid={!isEmpty(value) && !validateParams(value, this.props.field)}
isInvalid={this.props.isInvalid}
controlOnly={this.props.controlOnly}
className={this.props.className}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import './filter_item.scss';

import { EuiContextMenu, EuiPopover, EuiPopoverProps } from '@elastic/eui';
import { EuiContextMenu, EuiContextMenuPanel, EuiPopover, EuiPopoverProps } from '@elastic/eui';
import { InjectedIntl } from '@kbn/i18n-react';
import {
Filter,
Expand Down Expand Up @@ -67,8 +67,15 @@ export const FILTER_EDITOR_WIDTH = 800;
export function FilterItem(props: FilterItemProps) {
const [isPopoverOpen, setIsPopoverOpen] = useState<boolean>(false);
const [indexPatternExists, setIndexPatternExists] = useState<boolean | undefined>(undefined);
const [renderedComponent, setRenderedComponent] = useState('menu');
const { id, filter, indexPatterns, hiddenPanelOptions } = props;

useEffect(() => {
if (isPopoverOpen) {
setRenderedComponent('menu');
}
}, [isPopoverOpen]);

useEffect(() => {
const index = props.filter.meta.index;
let isSubscribed = true;
Expand Down Expand Up @@ -194,8 +201,10 @@ export function FilterItem(props: FilterItemProps) {
defaultMessage: 'Edit filter',
}),
icon: 'pencil',
panel: 1,
'data-test-subj': 'editFilter',
onClick: () => {
setRenderedComponent('editFilter');
},
},
{
name: negate
Expand Down Expand Up @@ -255,23 +264,6 @@ export function FilterItem(props: FilterItemProps) {
id: 0,
items: mainPanelItems,
},
{
id: 1,
width: FILTER_EDITOR_WIDTH,
content: (
<div>
<FilterEditor
filter={filter}
indexPatterns={indexPatterns}
onSubmit={onSubmit}
onCancel={() => {
setIsPopoverOpen(false);
}}
timeRangeForSuggestionsOverride={props.timeRangeForSuggestionsOverride}
/>
</div>
),
},
];
}

Expand Down Expand Up @@ -401,7 +393,25 @@ export function FilterItem(props: FilterItemProps) {

return (
<EuiPopover anchorPosition="downLeft" {...popoverProps}>
<EuiContextMenu initialPanelId={0} panels={getPanels()} />
{renderedComponent === 'menu' ? (
<EuiContextMenu initialPanelId={0} panels={getPanels()} />
) : (
<EuiContextMenuPanel
items={[
<div style={{ width: FILTER_EDITOR_WIDTH }}>
<FilterEditor
filter={filter}
indexPatterns={indexPatterns}
onSubmit={onSubmit}
onCancel={() => {
setIsPopoverOpen(false);
}}
timeRangeForSuggestionsOverride={props.timeRangeForSuggestionsOverride}
/>
</div>,
]}
/>
)}
</EuiPopover>
);
}
Expand Down
33 changes: 33 additions & 0 deletions src/plugins/unified_search/public/utils/helpers.test.ts
Original file line number Diff line number Diff line change
@@ -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 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import { getFieldValidityAndErrorMessage } from './helpers';
import { IFieldType } from '@kbn/data-views-plugin/common';

const mockField = {
type: 'date',
} as IFieldType;

describe('Check field validity and error message', () => {
it('should return a message that the entered date is not incorrect', () => {
const output = getFieldValidityAndErrorMessage(mockField, Date());

expect(output).toEqual({
isInvalid: false,
});
});

it('should show error', () => {
const output = getFieldValidityAndErrorMessage(mockField, 'Date');

expect(output).toEqual({
isInvalid: true,
errorMessage: 'Invalid date format provided',
});
});
});
47 changes: 47 additions & 0 deletions src/plugins/unified_search/public/utils/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* 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 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import type { IFieldType } from '@kbn/data-views-plugin/common';
import { i18n } from '@kbn/i18n';
import { KBN_FIELD_TYPES } from '@kbn/data-plugin/public';
import { isEmpty } from 'lodash';
import { validateParams } from '../filter_bar/filter_editor/lib/filter_editor_utils';

export const getFieldValidityAndErrorMessage = (
field: IFieldType,
value?: string | undefined
): { isInvalid: boolean; errorMessage?: string } => {
const type = field.type;
switch (type) {
case KBN_FIELD_TYPES.DATE:
case KBN_FIELD_TYPES.DATE_RANGE:
if (!isEmpty(value) && !validateParams(value, field)) {
return invalidFormatError();
}
break;
default:
break;
}
return noError();
};

const noError = (): { isInvalid: boolean } => {
return { isInvalid: false };
};

const invalidFormatError = (): { isInvalid: boolean; errorMessage?: string } => {
return {
isInvalid: true,
errorMessage: i18n.translate(
'unifiedSearch.filter.filterBar.invalidDateFormatProvidedErrorMessage',
{
defaultMessage: 'Invalid date format provided',
}
),
};
};

0 comments on commit 59ffe0d

Please sign in to comment.