- {isDetails && !!fieldMapping ? (
+ {isDetails && !!dataViewField ? (
@@ -68,11 +78,14 @@ export const TableCell: React.FC
= React.memo(
if (columnId === 'value') {
return (
);
}
diff --git a/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table_cell_actions.test.tsx b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table_cell_actions.test.tsx
index f2829a96b95d3..9dd4305cd4b00 100644
--- a/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table_cell_actions.test.tsx
+++ b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table_cell_actions.test.tsx
@@ -8,36 +8,33 @@
*/
import React from 'react';
-import { getFieldCellActions, getFieldValueCellActions, TableRow } from './table_cell_actions';
-import { DataViewField } from '@kbn/data-views-plugin/common';
+import { getFieldCellActions, getFieldValueCellActions } from './table_cell_actions';
+import { FieldRow } from './field_row';
+import { buildDataTableRecord } from '@kbn/discover-utils';
+import { stubLogstashDataView as dataView } from '@kbn/data-views-plugin/common/data_view.stub';
+import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
describe('TableActions', () => {
- const rows: TableRow[] = [
- {
- action: {
- onFilter: jest.fn(),
- flattenedField: 'flattenedField',
- onToggleColumn: jest.fn(),
- },
- field: {
- pinned: true,
- onTogglePinned: jest.fn(),
- field: 'message',
- fieldMapping: new DataViewField({
- type: 'keyword',
- name: 'message',
- searchable: true,
- aggregatable: true,
- }),
- fieldType: 'keyword',
- displayName: 'message',
- scripted: false,
- },
- value: {
- ignored: undefined,
- formattedValue: 'test',
- },
- },
+ const rows: FieldRow[] = [
+ new FieldRow({
+ name: 'message',
+ flattenedValue: 'flattenedField',
+ hit: buildDataTableRecord(
+ {
+ _ignored: [],
+ _index: 'test',
+ _id: '1',
+ _source: {
+ message: 'test',
+ },
+ },
+ dataView
+ ),
+ dataView,
+ fieldFormats: {} as FieldFormatsStart,
+ isPinned: false,
+ columnsMeta: undefined,
+ }),
];
const Component = () => Component
;
@@ -52,13 +49,13 @@ describe('TableActions', () => {
describe('getFieldCellActions', () => {
it('should render correctly for undefined functions', () => {
expect(
- getFieldCellActions({ rows, filter: undefined, onToggleColumn: jest.fn() }).map((item) =>
+ getFieldCellActions({ rows, onFilter: undefined, onToggleColumn: jest.fn() }).map((item) =>
item(EuiCellParams)
)
).toMatchSnapshot();
expect(
- getFieldCellActions({ rows, filter: undefined, onToggleColumn: undefined }).map((item) =>
+ getFieldCellActions({ rows, onFilter: undefined, onToggleColumn: undefined }).map((item) =>
item(EuiCellParams)
)
).toMatchSnapshot();
@@ -66,7 +63,7 @@ describe('TableActions', () => {
it('should render the panels correctly for defined onFilter function', () => {
expect(
- getFieldCellActions({ rows, filter: jest.fn(), onToggleColumn: jest.fn() }).map((item) =>
+ getFieldCellActions({ rows, onFilter: jest.fn(), onToggleColumn: jest.fn() }).map((item) =>
item(EuiCellParams)
)
).toMatchSnapshot();
@@ -76,13 +73,13 @@ describe('TableActions', () => {
describe('getFieldValueCellActions', () => {
it('should render correctly for undefined functions', () => {
expect(
- getFieldValueCellActions({ rows, filter: undefined }).map((item) => item(EuiCellParams))
+ getFieldValueCellActions({ rows, onFilter: undefined }).map((item) => item(EuiCellParams))
).toMatchSnapshot();
});
it('should render the panels correctly for defined onFilter function', () => {
expect(
- getFieldValueCellActions({ rows, filter: jest.fn() }).map((item) => item(EuiCellParams))
+ getFieldValueCellActions({ rows, onFilter: jest.fn() }).map((item) => item(EuiCellParams))
).toMatchSnapshot();
});
});
diff --git a/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table_cell_actions.tsx b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table_cell_actions.tsx
index 408708f674153..e9c5a70770ca5 100644
--- a/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table_cell_actions.tsx
+++ b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table_cell_actions.tsx
@@ -10,45 +10,36 @@
import React from 'react';
import { EuiDataGridColumnCellActionProps } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
-import { DocViewFilterFn, FieldRecordLegacy } from '@kbn/unified-doc-viewer/types';
-
-export interface TableRow {
- action: Omit;
- field: {
- pinned: boolean;
- onTogglePinned: (field: string) => void;
- } & FieldRecordLegacy['field'];
- value: FieldRecordLegacy['value'];
-}
+import { DocViewFilterFn } from '@kbn/unified-doc-viewer/types';
+import { FieldRow } from './field_row';
interface TableActionsProps {
Component: EuiDataGridColumnCellActionProps['Component'];
- row: TableRow | undefined; // as we pass `rows[rowIndex]` it's safer to assume that `row` prop can be undefined
+ row: FieldRow | undefined; // as we pass `rows[rowIndex]` it's safer to assume that `row` prop can be undefined
}
-export function isFilterInOutPairDisabled(row: TableRow | undefined): boolean {
+export function isFilterInOutPairDisabled(
+ row: FieldRow | undefined,
+ onFilter: DocViewFilterFn | undefined
+): boolean {
if (!row) {
return false;
}
- const {
- action: { onFilter },
- field: { fieldMapping },
- value: { ignored },
- } = row;
+ const { dataViewField, ignoredReason } = row;
- return Boolean(onFilter && (!fieldMapping || !fieldMapping.filterable || ignored));
+ return Boolean(onFilter && (!dataViewField || !dataViewField.filterable || ignoredReason));
}
-export function getFilterInOutPairDisabledWarning(row: TableRow | undefined): string | undefined {
- if (!row || !isFilterInOutPairDisabled(row)) {
+export function getFilterInOutPairDisabledWarning(
+ row: FieldRow | undefined,
+ onFilter: DocViewFilterFn | undefined
+): string | undefined {
+ if (!row || !isFilterInOutPairDisabled(row, onFilter)) {
return undefined;
}
- const {
- field: { fieldMapping },
- value: { ignored },
- } = row;
+ const { dataViewField, ignoredReason } = row;
- if (ignored) {
+ if (ignoredReason) {
return i18n.translate(
'unifiedDocViewer.docViews.table.ignoredValuesCanNotBeSearchedWarningMessage',
{
@@ -57,7 +48,7 @@ export function getFilterInOutPairDisabledWarning(row: TableRow | undefined): st
);
}
- return !fieldMapping
+ return !dataViewField
? i18n.translate(
'unifiedDocViewer.docViews.table.unindexedFieldsCanNotBeSearchedWarningMessage',
{
@@ -67,15 +58,16 @@ export function getFilterInOutPairDisabledWarning(row: TableRow | undefined): st
: undefined;
}
-export const FilterIn: React.FC = ({ Component, row }) => {
+export const FilterIn: React.FC = ({
+ Component,
+ row,
+ onFilter,
+}) => {
if (!row) {
return null;
}
- const {
- action: { onFilter, flattenedField },
- field: { field, fieldMapping },
- } = row;
+ const { dataViewField, name, flattenedValue } = row;
// Filters pair
const filterAddLabel = i18n.translate(
@@ -91,27 +83,28 @@ export const FilterIn: React.FC = ({ Component, row }) => {
return (
onFilter(fieldMapping, flattenedField, '+')}
+ onClick={() => onFilter(dataViewField, flattenedValue, '+')}
>
{filterAddLabel}
);
};
-export const FilterOut: React.FC = ({ Component, row }) => {
+export const FilterOut: React.FC = ({
+ Component,
+ row,
+ onFilter,
+}) => {
if (!row) {
return null;
}
- const {
- action: { onFilter, flattenedField },
- field: { field, fieldMapping },
- } = row;
+ const { dataViewField, name, flattenedValue } = row;
// Filters pair
const filterOutLabel = i18n.translate(
@@ -127,39 +120,42 @@ export const FilterOut: React.FC = ({ Component, row }) => {
return (
onFilter(fieldMapping, flattenedField, '-')}
+ onClick={() => onFilter(dataViewField, flattenedValue, '-')}
>
{filterOutLabel}
);
};
-export function isFilterExistsDisabled(row: TableRow | undefined): boolean {
+export function isFilterExistsDisabled(
+ row: FieldRow | undefined,
+ onFilter: DocViewFilterFn | undefined
+): boolean {
if (!row) {
return false;
}
- const {
- action: { onFilter },
- field: { fieldMapping },
- } = row;
+ const { dataViewField } = row;
- return Boolean(onFilter && (!fieldMapping || !fieldMapping.filterable || fieldMapping.scripted));
+ return Boolean(
+ onFilter && (!dataViewField || !dataViewField.filterable || dataViewField.scripted)
+ );
}
-export function getFilterExistsDisabledWarning(row: TableRow | undefined): string | undefined {
- if (!row || !isFilterExistsDisabled(row)) {
+export function getFilterExistsDisabledWarning(
+ row: FieldRow | undefined,
+ onFilter: DocViewFilterFn | undefined
+): string | undefined {
+ if (!row || !isFilterExistsDisabled(row, onFilter)) {
return undefined;
}
- const {
- field: { fieldMapping },
- } = row;
+ const { dataViewField } = row;
- return fieldMapping?.scripted
+ return dataViewField?.scripted
? i18n.translate(
'unifiedDocViewer.docViews.table.unableToFilterForPresenceOfScriptedFieldsWarningMessage',
{
@@ -169,15 +165,14 @@ export function getFilterExistsDisabledWarning(row: TableRow | undefined): strin
: undefined;
}
-export const FilterExist: React.FC = ({ Component, row }) => {
+export const FilterExist: React.FC<
+ TableActionsProps & { onFilter: DocViewFilterFn | undefined }
+> = ({ Component, row, onFilter }) => {
if (!row) {
return null;
}
- const {
- action: { onFilter },
- field: { field },
- } = row;
+ const { name } = row;
// Filter exists
const filterExistsLabel = i18n.translate(
@@ -191,27 +186,28 @@ export const FilterExist: React.FC = ({ Component, row }) =>
return (
onFilter('_exists_', field, '+')}
+ onClick={() => onFilter('_exists_', name, '+')}
>
{filterExistsLabel}
);
};
-export const ToggleColumn: React.FC = ({ Component, row }) => {
+export const ToggleColumn: React.FC<
+ TableActionsProps & {
+ onToggleColumn: ((field: string) => void) | undefined;
+ }
+> = ({ Component, row, onToggleColumn }) => {
if (!row) {
return null;
}
- const {
- action: { onToggleColumn },
- field: { field },
- } = row;
+ const { name } = row;
if (!onToggleColumn) {
return null;
@@ -227,11 +223,11 @@ export const ToggleColumn: React.FC = ({ Component, row }) =>
return (
onToggleColumn(field)}
+ onClick={() => onToggleColumn(name)}
>
{toggleColumnLabel}
@@ -240,25 +236,31 @@ export const ToggleColumn: React.FC = ({ Component, row }) =>
export function getFieldCellActions({
rows,
- filter,
+ onFilter,
onToggleColumn,
}: {
- rows: TableRow[];
- filter?: DocViewFilterFn;
+ rows: FieldRow[];
+ onFilter?: DocViewFilterFn;
onToggleColumn: ((field: string) => void) | undefined;
}) {
return [
- ...(filter
+ ...(onFilter
? [
({ Component, rowIndex }: EuiDataGridColumnCellActionProps) => {
- return ;
+ return ;
},
]
: []),
...(onToggleColumn
? [
({ Component, rowIndex }: EuiDataGridColumnCellActionProps) => {
- return ;
+ return (
+
+ );
},
]
: []),
@@ -267,18 +269,18 @@ export function getFieldCellActions({
export function getFieldValueCellActions({
rows,
- filter,
+ onFilter,
}: {
- rows: TableRow[];
- filter?: DocViewFilterFn;
+ rows: FieldRow[];
+ onFilter?: DocViewFilterFn;
}) {
- return filter
+ return onFilter
? [
({ Component, rowIndex }: EuiDataGridColumnCellActionProps) => {
- return ;
+ return ;
},
({ Component, rowIndex }: EuiDataGridColumnCellActionProps) => {
- return ;
+ return ;
},
]
: [];
diff --git a/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table_cell_value.tsx b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table_cell_value.tsx
index dea6010441308..3afe935307ab2 100644
--- a/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table_cell_value.tsx
+++ b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table_cell_value.tsx
@@ -22,7 +22,7 @@ import classnames from 'classnames';
import React, { Fragment, useCallback, useState } from 'react';
import { i18n } from '@kbn/i18n';
import { IgnoredReason, TRUNCATE_MAX_HEIGHT } from '@kbn/discover-utils';
-import { FieldRecord } from './table';
+import { FieldRecordLegacy } from '@kbn/unified-doc-viewer/types';
import { getUnifiedDocViewerServices } from '../../plugin';
const DOC_VIEWER_DEFAULT_TRUNCATE_MAX_HEIGHT = 110;
@@ -96,12 +96,13 @@ const IgnoreWarning: React.FC = React.memo(({ rawValue, reas
);
});
-type TableFieldValueProps = Pick & {
- formattedValue: FieldRecord['value']['formattedValue'];
+type TableFieldValueProps = Pick & {
+ formattedValue: FieldRecordLegacy['value']['formattedValue'];
rawValue: unknown;
ignoreReason?: IgnoredReason;
isDetails?: boolean; // true when inside EuiDataGrid cell popover
isLegacy?: boolean; // true when inside legacy table
+ isHighlighted?: boolean; // whether it's matching a search term
};
export const TableFieldValue = ({
@@ -111,6 +112,7 @@ export const TableFieldValue = ({
ignoreReason,
isDetails,
isLegacy,
+ isHighlighted,
}: TableFieldValueProps) => {
const { euiTheme } = useEuiTheme();
const { uiSettings } = getUnifiedDocViewerServices();
@@ -158,6 +160,7 @@ export const TableFieldValue = ({
const valueClasses = classnames('kbnDocViewer__value', {
'kbnDocViewer__value--truncated': shouldTruncate,
+ 'kbnDocViewer__value--highlighted': isHighlighted && !isDetails,
});
return (
diff --git a/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table_filters.tsx b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table_filters.tsx
index 5c3e7862ea6c8..50a3064b0df4d 100644
--- a/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table_filters.tsx
+++ b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table_filters.tsx
@@ -19,14 +19,21 @@ import {
type FieldTypeFilterProps,
} from '@kbn/unified-field-list/src/components/field_list_filters/field_type_filter';
import { getUnifiedDocViewerServices } from '../../plugin';
+import { FieldRow } from './field_row';
export const LOCAL_STORAGE_KEY_SEARCH_TERM = 'discover:searchText';
export const LOCAL_STORAGE_KEY_SELECTED_FIELD_TYPES = 'unifiedDocViewer:selectedFieldTypes';
const searchPlaceholder = i18n.translate('unifiedDocViewer.docView.table.searchPlaceHolder', {
- defaultMessage: 'Search field names',
+ defaultMessage: 'Search field names or values',
});
+export enum TermMatch {
+ name = 'name',
+ value = 'value',
+ both = 'both',
+}
+
interface TableFiltersCommonProps {
// search
searchTerm: string;
@@ -108,12 +115,9 @@ const getStoredFieldTypes = (storage: Storage) => {
return Array.isArray(parsedFieldTypes) ? parsedFieldTypes : [];
};
-interface UseTableFiltersReturn extends TableFiltersCommonProps {
- onFilterField: (
- fieldName: string,
- fieldDisplayName: string | undefined,
- fieldType: string | undefined
- ) => boolean;
+export interface UseTableFiltersReturn extends TableFiltersCommonProps {
+ onFilterField: (row: FieldRow) => boolean;
+ onFindSearchTermMatch: (row: FieldRow, term: string) => TermMatch | null;
}
export const useTableFilters = (storage: Storage): UseTableFiltersReturn => {
@@ -138,13 +142,34 @@ export const useTableFilters = (storage: Storage): UseTableFiltersReturn => {
[storage, setSelectedFieldTypes]
);
- const onFilterField: UseTableFiltersReturn['onFilterField'] = useCallback(
- (fieldName, fieldDisplayName, fieldType) => {
- const term = searchTerm?.trim();
+ const onFindSearchTermMatch: UseTableFiltersReturn['onFindSearchTermMatch'] = useCallback(
+ (row, term) => {
+ const { name, dataViewField } = row;
+
+ let termMatch: TermMatch | null = null;
+
+ if (fieldNameWildcardMatcher({ name, displayName: dataViewField?.customLabel }, term)) {
+ termMatch = TermMatch.name;
+ }
+
if (
- term &&
- !fieldNameWildcardMatcher({ name: fieldName, displayName: fieldDisplayName }, term)
+ (row.formattedAsText || '').toLowerCase().includes(term.toLowerCase()) ||
+ (JSON.stringify(row.flattenedValue) || '').toLowerCase().includes(term.toLowerCase())
) {
+ termMatch = termMatch ? TermMatch.both : TermMatch.value;
+ }
+
+ return termMatch;
+ },
+ []
+ );
+
+ const onFilterField: UseTableFiltersReturn['onFilterField'] = useCallback(
+ (row) => {
+ const { fieldType } = row;
+ const term = searchTerm?.trim();
+
+ if (term && !onFindSearchTermMatch(row, term)) {
return false;
}
@@ -154,7 +179,7 @@ export const useTableFilters = (storage: Storage): UseTableFiltersReturn => {
return true;
},
- [searchTerm, selectedFieldTypes]
+ [searchTerm, selectedFieldTypes, onFindSearchTermMatch]
);
return useMemo(
@@ -166,7 +191,15 @@ export const useTableFilters = (storage: Storage): UseTableFiltersReturn => {
onChangeFieldTypes,
// the actual filtering function
onFilterField,
+ onFindSearchTermMatch,
}),
- [searchTerm, onChangeSearchTerm, selectedFieldTypes, onChangeFieldTypes, onFilterField]
+ [
+ searchTerm,
+ onChangeSearchTerm,
+ selectedFieldTypes,
+ onChangeFieldTypes,
+ onFilterField,
+ onFindSearchTermMatch,
+ ]
);
};
diff --git a/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/test_filters.test.ts b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/test_filters.test.ts
index 546c7fb3a0d09..6d0a8c5dfc96c 100644
--- a/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/test_filters.test.ts
+++ b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/test_filters.test.ts
@@ -14,9 +14,54 @@ import {
LOCAL_STORAGE_KEY_SEARCH_TERM,
LOCAL_STORAGE_KEY_SELECTED_FIELD_TYPES,
} from './table_filters';
+import { FieldRow } from './field_row';
+import { buildDataTableRecord } from '@kbn/discover-utils';
+import { stubLogstashDataView as dataView } from '@kbn/data-views-plugin/common/data_view.stub';
+import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
const storage = new Storage(window.localStorage);
+const hit = buildDataTableRecord(
+ {
+ _ignored: [],
+ _index: 'test',
+ _id: '1',
+ _source: {
+ 'extension.keyword': 'zip',
+ bytes: 500,
+ '@timestamp': '2021-01-01T00:00:00',
+ },
+ },
+ dataView
+);
+const rowExtensionKeyword = new FieldRow({
+ name: 'extension.keyword',
+ flattenedValue: 'zip',
+ hit,
+ dataView,
+ fieldFormats: {} as FieldFormatsStart,
+ isPinned: false,
+ columnsMeta: undefined,
+});
+const rowBytes = new FieldRow({
+ name: 'bytes',
+ flattenedValue: 500,
+ hit,
+ dataView,
+ fieldFormats: {} as FieldFormatsStart,
+ isPinned: false,
+ columnsMeta: undefined,
+});
+const rowTimestamp = new FieldRow({
+ name: '@timestamp',
+ flattenedValue: '2021-01-01T00:00:00',
+ hit,
+ dataView,
+ fieldFormats: {} as FieldFormatsStart,
+ isPinned: false,
+ columnsMeta: undefined,
+});
+
describe('useTableFilters', () => {
beforeAll(() => {
jest.useFakeTimers();
@@ -34,8 +79,8 @@ describe('useTableFilters', () => {
expect(result.current.searchTerm).toBe('');
expect(result.current.selectedFieldTypes).toEqual([]);
- expect(result.current.onFilterField('extension', undefined, 'keyword')).toBe(true);
- expect(result.current.onFilterField('bytes', undefined, 'number')).toBe(true);
+ expect(result.current.onFilterField(rowExtensionKeyword)).toBe(true);
+ expect(result.current.onFilterField(rowBytes)).toBe(true);
expect(storage.get(LOCAL_STORAGE_KEY_SEARCH_TERM)).toBeNull();
});
@@ -47,8 +92,8 @@ describe('useTableFilters', () => {
result.current.onChangeSearchTerm('ext');
});
- expect(result.current.onFilterField('extension', undefined, 'keyword')).toBe(true);
- expect(result.current.onFilterField('bytes', undefined, 'number')).toBe(false);
+ expect(result.current.onFilterField(rowExtensionKeyword)).toBe(true);
+ expect(result.current.onFilterField(rowBytes)).toBe(false);
expect(storage.get(LOCAL_STORAGE_KEY_SEARCH_TERM)).toBe('ext');
});
@@ -60,22 +105,22 @@ describe('useTableFilters', () => {
result.current.onChangeFieldTypes(['number']);
});
- expect(result.current.onFilterField('extension', undefined, 'keyword')).toBe(false);
- expect(result.current.onFilterField('bytes', undefined, 'number')).toBe(true);
+ expect(result.current.onFilterField(rowExtensionKeyword)).toBe(false);
+ expect(result.current.onFilterField(rowBytes)).toBe(true);
act(() => {
result.current.onChangeFieldTypes(['keyword']);
});
- expect(result.current.onFilterField('extension', undefined, 'keyword')).toBe(true);
- expect(result.current.onFilterField('bytes', undefined, 'number')).toBe(false);
+ expect(result.current.onFilterField(rowExtensionKeyword)).toBe(true);
+ expect(result.current.onFilterField(rowBytes)).toBe(false);
act(() => {
result.current.onChangeFieldTypes(['number', 'keyword']);
});
- expect(result.current.onFilterField('extension', undefined, 'keyword')).toBe(true);
- expect(result.current.onFilterField('bytes', undefined, 'number')).toBe(true);
+ expect(result.current.onFilterField(rowExtensionKeyword)).toBe(true);
+ expect(result.current.onFilterField(rowBytes)).toBe(true);
jest.advanceTimersByTime(600);
expect(storage.get(LOCAL_STORAGE_KEY_SELECTED_FIELD_TYPES)).toBe('["number","keyword"]');
@@ -89,30 +134,69 @@ describe('useTableFilters', () => {
result.current.onChangeFieldTypes(['keyword']);
});
- expect(result.current.onFilterField('extension', undefined, 'keyword')).toBe(true);
- expect(result.current.onFilterField('bytes', undefined, 'number')).toBe(false);
+ expect(result.current.onFilterField(rowExtensionKeyword)).toBe(true);
+ expect(result.current.onFilterField(rowBytes)).toBe(false);
act(() => {
result.current.onChangeSearchTerm('ext');
result.current.onChangeFieldTypes(['number']);
});
- expect(result.current.onFilterField('extension', undefined, 'keyword')).toBe(false);
- expect(result.current.onFilterField('bytes', undefined, 'number')).toBe(false);
+ expect(result.current.onFilterField(rowExtensionKeyword)).toBe(false);
+ expect(result.current.onFilterField(rowBytes)).toBe(false);
act(() => {
result.current.onChangeSearchTerm('bytes');
result.current.onChangeFieldTypes(['number']);
});
- expect(result.current.onFilterField('extension', undefined, 'keyword')).toBe(false);
- expect(result.current.onFilterField('bytes', undefined, 'number')).toBe(true);
+ expect(result.current.onFilterField(rowExtensionKeyword)).toBe(false);
+ expect(result.current.onFilterField(rowBytes)).toBe(true);
jest.advanceTimersByTime(600);
expect(storage.get(LOCAL_STORAGE_KEY_SEARCH_TERM)).toBe('bytes');
expect(storage.get(LOCAL_STORAGE_KEY_SELECTED_FIELD_TYPES)).toBe('["number"]');
});
+ it('should filter by field value and field type', () => {
+ const { result } = renderHook(() => useTableFilters(storage));
+
+ expect(result.current.onFilterField(rowTimestamp)).toBe(true);
+ expect(result.current.onFilterField(rowExtensionKeyword)).toBe(true);
+ expect(result.current.onFilterField(rowBytes)).toBe(true);
+
+ act(() => {
+ result.current.onChangeSearchTerm('500');
+ result.current.onChangeFieldTypes(['number']);
+ });
+
+ expect(result.current.onFilterField(rowTimestamp)).toBe(false);
+ expect(result.current.onFilterField(rowExtensionKeyword)).toBe(false);
+ expect(result.current.onFilterField(rowBytes)).toBe(true);
+
+ act(() => {
+ result.current.onChangeSearchTerm('2021');
+ result.current.onChangeFieldTypes(['number']);
+ });
+
+ expect(result.current.onFilterField(rowTimestamp)).toBe(false);
+ expect(result.current.onFilterField(rowExtensionKeyword)).toBe(false);
+ expect(result.current.onFilterField(rowBytes)).toBe(false);
+
+ act(() => {
+ result.current.onChangeSearchTerm('2021');
+ result.current.onChangeFieldTypes(['date']);
+ });
+
+ expect(result.current.onFilterField(rowTimestamp)).toBe(true);
+ expect(result.current.onFilterField(rowExtensionKeyword)).toBe(false);
+ expect(result.current.onFilterField(rowBytes)).toBe(false);
+
+ jest.advanceTimersByTime(600);
+ expect(storage.get(LOCAL_STORAGE_KEY_SEARCH_TERM)).toBe('2021');
+ expect(storage.get(LOCAL_STORAGE_KEY_SELECTED_FIELD_TYPES)).toBe('["date"]');
+ });
+
it('should restore previous filters', () => {
storage.set(LOCAL_STORAGE_KEY_SEARCH_TERM, 'bytes');
storage.set(LOCAL_STORAGE_KEY_SELECTED_FIELD_TYPES, '["number"]');
@@ -122,8 +206,8 @@ describe('useTableFilters', () => {
expect(result.current.searchTerm).toBe('bytes');
expect(result.current.selectedFieldTypes).toEqual(['number']);
- expect(result.current.onFilterField('extension', undefined, 'keyword')).toBe(false);
- expect(result.current.onFilterField('bytes', undefined, 'number')).toBe(true);
- expect(result.current.onFilterField('bytes_counter', undefined, 'counter')).toBe(false);
+ expect(result.current.onFilterField(rowExtensionKeyword)).toBe(false);
+ expect(result.current.onFilterField(rowBytes)).toBe(true);
+ expect(result.current.onFilterField(rowTimestamp)).toBe(false);
});
});
diff --git a/test/functional/apps/context/_filters.ts b/test/functional/apps/context/_filters.ts
index bc404b45f22c0..4a3f8b3a9998f 100644
--- a/test/functional/apps/context/_filters.ts
+++ b/test/functional/apps/context/_filters.ts
@@ -42,7 +42,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
it('inclusive filter should be addable via expanded data grid rows', async function () {
await retry.waitFor(`filter ${TEST_ANCHOR_FILTER_FIELD} in filterbar`, async () => {
await dataGrid.clickRowToggle({ isAnchorRow: true, renderMoreRows: true });
- await PageObjects.discover.findFieldByNameInDocViewer(TEST_ANCHOR_FILTER_FIELD);
+ await PageObjects.discover.findFieldByNameOrValueInDocViewer(TEST_ANCHOR_FILTER_FIELD);
await dataGrid.clickFieldActionInFlyout(
TEST_ANCHOR_FILTER_FIELD,
'addFilterForValueButton'
diff --git a/test/functional/apps/discover/group3/_doc_viewer.ts b/test/functional/apps/discover/group3/_doc_viewer.ts
index 3d3562e10beb4..bc71c82289071 100644
--- a/test/functional/apps/discover/group3/_doc_viewer.ts
+++ b/test/functional/apps/discover/group3/_doc_viewer.ts
@@ -66,13 +66,13 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
});
it('should be able to search by string', async function () {
- await discover.findFieldByNameInDocViewer('geo');
+ await discover.findFieldByNameOrValueInDocViewer('geo');
await retry.waitFor('first updates', async () => {
return (await find.allByCssSelector('.kbnDocViewer__fieldName')).length === 4;
});
- await discover.findFieldByNameInDocViewer('.sr');
+ await discover.findFieldByNameOrValueInDocViewer('.sr');
await retry.waitFor('second updates', async () => {
return (await find.allByCssSelector('.kbnDocViewer__fieldName')).length === 2;
@@ -80,21 +80,21 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
});
it('should be able to search by wildcard', async function () {
- await discover.findFieldByNameInDocViewer('relatedContent*image');
+ await discover.findFieldByNameOrValueInDocViewer('relatedContent*image');
await retry.waitFor('updates', async () => {
return (await find.allByCssSelector('.kbnDocViewer__fieldName')).length === 2;
});
});
it('should be able to search with spaces as wildcard', async function () {
- await discover.findFieldByNameInDocViewer('relatedContent image');
+ await discover.findFieldByNameOrValueInDocViewer('relatedContent image');
await retry.waitFor('updates', async () => {
return (await find.allByCssSelector('.kbnDocViewer__fieldName')).length === 4;
});
});
it('should be able to search with fuzzy search (1 typo)', async function () {
- await discover.findFieldByNameInDocViewer('rel4tedContent.art');
+ await discover.findFieldByNameOrValueInDocViewer('rel4tedContent.art');
await retry.waitFor('updates', async () => {
return (await find.allByCssSelector('.kbnDocViewer__fieldName')).length === 3;
@@ -102,7 +102,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
});
it('should ignore empty search', async function () {
- await discover.findFieldByNameInDocViewer(' '); // only spaces
+ await discover.findFieldByNameOrValueInDocViewer(' '); // only spaces
await retry.waitFor('the clear button', async () => {
return await testSubjects.exists('clearSearchButton');
@@ -113,6 +113,22 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
return (await find.allByCssSelector('.kbnDocViewer__fieldName')).length > 0;
});
});
+
+ it('should be able to search by field value', async function () {
+ await discover.findFieldByNameOrValueInDocViewer('time');
+
+ await retry.waitFor('updates', async () => {
+ return (await find.allByCssSelector('.kbnDocViewer__fieldName')).length === 5;
+ });
+ });
+
+ it('should be able to search by field raw value', async function () {
+ await discover.findFieldByNameOrValueInDocViewer('2015-09-22T23:50:13.253Z');
+
+ await retry.waitFor('updates', async () => {
+ return (await find.allByCssSelector('.kbnDocViewer__fieldName')).length === 3;
+ });
+ });
});
describe('filter by field type', function () {
@@ -220,7 +236,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
});
it('should hide fields with null values ', async function () {
- await discover.findFieldByNameInDocViewer('machine');
+ await discover.findFieldByNameOrValueInDocViewer('machine');
const results = (await find.allByCssSelector('.kbnDocViewer__fieldName')).length;
const hideNullValuesSwitch = await testSubjects.find(
'unifiedDocViewerHideNullValuesSwitch'
diff --git a/test/functional/page_objects/discover_page.ts b/test/functional/page_objects/discover_page.ts
index 54dae77ff3839..1474e9d315538 100644
--- a/test/functional/page_objects/discover_page.ts
+++ b/test/functional/page_objects/discover_page.ts
@@ -444,7 +444,7 @@ export class DiscoverPageObject extends FtrService {
return await this.find.byClassName('monaco-editor');
}
- public async findFieldByNameInDocViewer(name: string) {
+ public async findFieldByNameOrValueInDocViewer(name: string) {
const fieldSearch = await this.testSubjects.find('unifiedDocViewerFieldsSearchInput');
await fieldSearch.type(name);
}
diff --git a/x-pack/test_serverless/functional/test_suites/common/context/_filters.ts b/x-pack/test_serverless/functional/test_suites/common/context/_filters.ts
index 672e13052f7d8..3dc28217ca7ed 100644
--- a/x-pack/test_serverless/functional/test_suites/common/context/_filters.ts
+++ b/x-pack/test_serverless/functional/test_suites/common/context/_filters.ts
@@ -42,7 +42,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
it('inclusive filter should be addable via expanded data grid rows', async function () {
await retry.waitFor(`filter ${TEST_ANCHOR_FILTER_FIELD} in filterbar`, async () => {
await dataGrid.clickRowToggle({ isAnchorRow: true, renderMoreRows: true });
- await PageObjects.discover.findFieldByNameInDocViewer(TEST_ANCHOR_FILTER_FIELD);
+ await PageObjects.discover.findFieldByNameOrValueInDocViewer(TEST_ANCHOR_FILTER_FIELD);
await dataGrid.clickFieldActionInFlyout(
TEST_ANCHOR_FILTER_FIELD,
'addFilterForValueButton'