diff --git a/src/plugins/data/common/es_query/filters/get_display_value.ts b/src/plugins/data/common/es_query/filters/get_display_value.ts
index 4bf7e1c9c6ba7..03167f3080419 100644
--- a/src/plugins/data/common/es_query/filters/get_display_value.ts
+++ b/src/plugins/data/common/es_query/filters/get_display_value.ts
@@ -18,6 +18,7 @@
*/
import { get } from 'lodash';
+import { i18n } from '@kbn/i18n';
import { IIndexPattern, IFieldType } from '../..';
import { getIndexPatternFromFilter } from './get_index_pattern_from_filter';
import { Filter } from '../filters';
@@ -27,7 +28,16 @@ function getValueFormatter(indexPattern?: IIndexPattern, key?: string) {
let format = get(indexPattern, ['fields', 'byName', key, 'format']);
if (!format && (indexPattern.fields as any).getByName) {
// TODO: Why is indexPatterns sometimes a map and sometimes an array?
- format = ((indexPattern.fields as any).getByName(key) as IFieldType).format;
+ const field: IFieldType = (indexPattern.fields as any).getByName(key);
+ if (!field) {
+ throw new Error(
+ i18n.translate('data.filter.filterBar.fieldNotFound', {
+ defaultMessage: 'Field {key} not found in index pattern {indexPattern}',
+ values: { key, indexPattern: indexPattern.title },
+ })
+ );
+ }
+ format = field.format;
}
return format;
}
diff --git a/src/plugins/data/public/ui/filter_bar/_global_filter_item.scss b/src/plugins/data/public/ui/filter_bar/_global_filter_item.scss
index 51204e2a61168..24adf0093af95 100644
--- a/src/plugins/data/public/ui/filter_bar/_global_filter_item.scss
+++ b/src/plugins/data/public/ui/filter_bar/_global_filter_item.scss
@@ -32,6 +32,15 @@
font-style: italic;
}
+.globalFilterItem-isInvalid {
+ text-decoration: none;
+
+ .globalFilterLabel__value {
+ color: $euiColorDanger;
+ font-weight: $euiFontWeightBold;
+ }
+}
+
.globalFilterItem-isPinned {
position: relative;
diff --git a/src/plugins/data/public/ui/filter_bar/filter_editor/lib/filter_label.tsx b/src/plugins/data/public/ui/filter_bar/filter_editor/lib/filter_label.tsx
index 49a0d6f2ab3bd..503650d13c5f8 100644
--- a/src/plugins/data/public/ui/filter_bar/filter_editor/lib/filter_label.tsx
+++ b/src/plugins/data/public/ui/filter_bar/filter_editor/lib/filter_label.tsx
@@ -41,6 +41,10 @@ export function FilterLabel({ filter, valueLabel }: Props) {
prefixText
);
+ const getValue = (text?: string) => {
+ return {text};
+ };
+
if (filter.meta.alias !== null) {
return (
@@ -55,35 +59,35 @@ export function FilterLabel({ filter, valueLabel }: Props) {
return (
{prefix}
- {filter.meta.key} {existsOperator.message}
+ {filter.meta.key}: {getValue(`${existsOperator.message}`)}
);
case esFilters.FILTERS.GEO_BOUNDING_BOX:
return (
{prefix}
- {filter.meta.key}: {valueLabel}
+ {filter.meta.key}: {getValue(valueLabel)}
);
case esFilters.FILTERS.GEO_POLYGON:
return (
{prefix}
- {filter.meta.key}: {valueLabel}
+ {filter.meta.key}: {getValue(valueLabel)}
);
case esFilters.FILTERS.PHRASES:
return (
{prefix}
- {filter.meta.key} {isOneOfOperator.message} {valueLabel}
+ {filter.meta.key}: {getValue(`${isOneOfOperator.message} ${valueLabel}`)}
);
case esFilters.FILTERS.QUERY_STRING:
return (
{prefix}
- {valueLabel}
+ {getValue(`${valueLabel}`)}
);
case esFilters.FILTERS.PHRASE:
@@ -91,14 +95,14 @@ export function FilterLabel({ filter, valueLabel }: Props) {
return (
{prefix}
- {filter.meta.key}: {valueLabel}
+ {filter.meta.key}: {getValue(valueLabel)}
);
default:
return (
{prefix}
- {JSON.stringify(filter.query)}
+ {getValue(`${JSON.stringify(filter.query) || filter.meta.value}`)}
);
}
diff --git a/src/plugins/data/public/ui/filter_bar/filter_item.tsx b/src/plugins/data/public/ui/filter_bar/filter_item.tsx
index 788663041fd03..f24befff9a9a8 100644
--- a/src/plugins/data/public/ui/filter_bar/filter_item.tsx
+++ b/src/plugins/data/public/ui/filter_bar/filter_item.tsx
@@ -25,6 +25,7 @@ import { IUiSettingsClient } from 'src/core/public';
import { FilterEditor } from './filter_editor';
import { FilterView } from './filter_view';
import { esFilters, IIndexPattern } from '../..';
+import { getNotifications } from '../../services';
interface Props {
id: string;
@@ -56,24 +57,41 @@ class FilterItemUI extends Component {
public render() {
const { filter, id } = this.props;
const { negate, disabled } = filter.meta;
+ let hasError: boolean = false;
+
+ let valueLabel;
+ try {
+ valueLabel = esFilters.getDisplayValueFromFilter(filter, this.props.indexPatterns);
+ } catch (e) {
+ getNotifications().toasts.addError(e, {
+ title: this.props.intl.formatMessage({
+ id: 'data.filter.filterBar.labelErrorMessage',
+ defaultMessage: 'Failed to display filter',
+ }),
+ });
+ valueLabel = this.props.intl.formatMessage({
+ id: 'data.filter.filterBar.labelErrorText',
+ defaultMessage: 'Error',
+ });
+ hasError = true;
+ }
+ const dataTestSubjKey = filter.meta.key ? `filter-key-${filter.meta.key}` : '';
+ const dataTestSubjValue = filter.meta.value ? `filter-value-${valueLabel}` : '';
+ const dataTestSubjDisabled = `filter-${
+ this.props.filter.meta.disabled ? 'disabled' : 'enabled'
+ }`;
const classes = classNames(
'globalFilterItem',
{
- 'globalFilterItem-isDisabled': disabled,
+ 'globalFilterItem-isDisabled': disabled || hasError,
+ 'globalFilterItem-isInvalid': hasError,
'globalFilterItem-isPinned': esFilters.isFilterPinned(filter),
'globalFilterItem-isExcluded': negate,
},
this.props.className
);
- const valueLabel = esFilters.getDisplayValueFromFilter(filter, this.props.indexPatterns);
- const dataTestSubjKey = filter.meta.key ? `filter-key-${filter.meta.key}` : '';
- const dataTestSubjValue = filter.meta.value ? `filter-value-${valueLabel}` : '';
- const dataTestSubjDisabled = `filter-${
- this.props.filter.meta.disabled ? 'disabled' : 'enabled'
- }`;
-
const badge = (