* refactor: 💡 rename Filter -> ExpressionValueFilter

* refactor: 💡 use new filter type in Canvas

* fix: 🐛 fix tests after refactor

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
Vadim Dalecky 2020-05-04 18:39:09 +02:00 committed by GitHub
parent 86c64af553
commit 496f492474
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 165 additions and 89 deletions

View file

@ -17,29 +17,31 @@
* under the License.
*/
import { ExpressionTypeDefinition } from '../types';
const name = 'filter';
import { ExpressionTypeDefinition, ExpressionValueBoxed } from '../types';
/**
* Represents an object that is a Filter.
*/
export interface Filter {
type?: string;
value?: string;
column?: string;
and: Filter[];
to?: string;
from?: string;
query?: string | null;
}
export type ExpressionValueFilter = ExpressionValueBoxed<
'filter',
{
filterType?: string;
value?: string;
column?: string;
and: ExpressionValueFilter[];
to?: string;
from?: string;
query?: string | null;
}
>;
export const filter: ExpressionTypeDefinition<typeof name, Filter> = {
name,
export const filter: ExpressionTypeDefinition<'filter', ExpressionValueFilter> = {
name: 'filter',
from: {
null: () => {
return {
type: name,
type: 'filter',
filterType: 'filter',
// Any meta data you wish to pass along.
meta: {},
// And filters. If you need an "or", create a filter type for it.

View file

@ -78,7 +78,7 @@ export {
ExpressionValueRender,
ExpressionValueSearchContext,
ExpressionValueUnboxed,
Filter,
ExpressionValueFilter,
Font,
FontLabel,
FontStyle,

View file

@ -69,7 +69,7 @@ export {
ExpressionValueRender,
ExpressionValueSearchContext,
ExpressionValueUnboxed,
Filter,
ExpressionValueFilter,
Font,
FontLabel,
FontStyle,

View file

@ -18,7 +18,7 @@ describe('exactly', () => {
it("adds an exactly object to 'and'", () => {
const result = fn(emptyFilter, { column: 'name', value: 'product2' });
expect(result.and[0]).toHaveProperty('type', 'exactly');
expect(result.and[0]).toHaveProperty('filterType', 'exactly');
});
describe('args', () => {

View file

@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { Filter, ExpressionFunctionDefinition } from '../../../types';
import { ExpressionValueFilter, ExpressionFunctionDefinition } from '../../../types';
import { getFunctionHelp } from '../../../i18n';
interface Arguments {
@ -13,7 +13,12 @@ interface Arguments {
filterGroup: string;
}
export function exactly(): ExpressionFunctionDefinition<'exactly', Filter, Arguments, Filter> {
export function exactly(): ExpressionFunctionDefinition<
'exactly',
ExpressionValueFilter,
Arguments,
ExpressionValueFilter
> {
const { help, args: argHelp } = getFunctionHelp().exactly;
return {
@ -43,8 +48,9 @@ export function exactly(): ExpressionFunctionDefinition<'exactly', Filter, Argum
fn: (input, args) => {
const { value, column } = args;
const filter = {
type: 'exactly',
const filter: ExpressionValueFilter = {
type: 'filter',
filterType: 'exactly',
value,
column,
and: [],

View file

@ -6,14 +6,23 @@
jest.mock('ui/new_platform');
import { savedLens } from './saved_lens';
import { getQueryFilters } from '../../../public/lib/build_embeddable_filters';
import { ExpressionValueFilter } from '../../../types';
const filterContext = {
const filterContext: ExpressionValueFilter = {
type: 'filter',
and: [
{ and: [], value: 'filter-value', column: 'filter-column', type: 'exactly' },
{
type: 'filter',
and: [],
value: 'filter-value',
column: 'filter-column',
filterType: 'exactly',
},
{
type: 'filter',
and: [],
column: 'time-column',
type: 'time',
filterType: 'time',
from: '2019-06-04T04:00:00.000Z',
to: '2019-06-05T04:00:00.000Z',
},

View file

@ -8,7 +8,7 @@ import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common';
import { TimeRange, Filter as DataFilter } from 'src/plugins/data/public';
import { EmbeddableInput } from 'src/plugins/embeddable/public';
import { getQueryFilters } from '../../../public/lib/build_embeddable_filters';
import { Filter, TimeRange as TimeRangeArg } from '../../../types';
import { ExpressionValueFilter, TimeRange as TimeRangeArg } from '../../../types';
import {
EmbeddableTypes,
EmbeddableExpressionType,
@ -37,7 +37,7 @@ type Return = EmbeddableExpression<SavedLensInput>;
export function savedLens(): ExpressionFunctionDefinition<
'savedLens',
Filter | null,
ExpressionValueFilter | null,
Arguments,
Return
> {
@ -63,8 +63,8 @@ export function savedLens(): ExpressionFunctionDefinition<
},
},
type: EmbeddableExpressionType,
fn: (context, args) => {
const filters = context ? context.and : [];
fn: (input, args) => {
const filters = input ? input.and : [];
return {
type: EmbeddableExpressionType,

View file

@ -6,14 +6,23 @@
jest.mock('ui/new_platform');
import { savedMap } from './saved_map';
import { getQueryFilters } from '../../../public/lib/build_embeddable_filters';
import { ExpressionValueFilter } from '../../../types';
const filterContext = {
const filterContext: ExpressionValueFilter = {
type: 'filter',
and: [
{ and: [], value: 'filter-value', column: 'filter-column', type: 'exactly' },
{
type: 'filter',
and: [],
value: 'filter-value',
column: 'filter-column',
filterType: 'exactly',
},
{
type: 'filter',
and: [],
column: 'time-column',
type: 'time',
filterType: 'time',
from: '2019-06-04T04:00:00.000Z',
to: '2019-06-05T04:00:00.000Z',
},

View file

@ -6,7 +6,7 @@
import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common';
import { getQueryFilters } from '../../../public/lib/build_embeddable_filters';
import { Filter, MapCenter, TimeRange as TimeRangeArg } from '../../../types';
import { ExpressionValueFilter, MapCenter, TimeRange as TimeRangeArg } from '../../../types';
import {
EmbeddableTypes,
EmbeddableExpressionType,
@ -32,7 +32,7 @@ type Output = EmbeddableExpression<MapEmbeddableInput>;
export function savedMap(): ExpressionFunctionDefinition<
'savedMap',
Filter | null,
ExpressionValueFilter | null,
Arguments,
Output
> {

View file

@ -6,14 +6,23 @@
jest.mock('ui/new_platform');
import { savedSearch } from './saved_search';
import { buildEmbeddableFilters } from '../../../public/lib/build_embeddable_filters';
import { ExpressionValueFilter } from '../../../types';
const filterContext = {
const filterContext: ExpressionValueFilter = {
type: 'filter',
and: [
{ and: [], value: 'filter-value', column: 'filter-column', type: 'exactly' },
{
type: 'filter',
and: [],
value: 'filter-value',
column: 'filter-column',
filterType: 'exactly',
},
{
type: 'filter',
and: [],
column: 'time-column',
type: 'time',
filterType: 'time',
from: '2019-06-04T04:00:00.000Z',
to: '2019-06-05T04:00:00.000Z',
},

View file

@ -13,7 +13,7 @@ import {
} from '../../expression_types';
import { buildEmbeddableFilters } from '../../../public/lib/build_embeddable_filters';
import { Filter } from '../../../types';
import { ExpressionValueFilter } from '../../../types';
import { getFunctionHelp } from '../../../i18n';
interface Arguments {
@ -24,7 +24,7 @@ type Output = EmbeddableExpression<Partial<SearchInput> & { id: SearchInput['id'
export function savedSearch(): ExpressionFunctionDefinition<
'savedSearch',
Filter | null,
ExpressionValueFilter | null,
Arguments,
Output
> {

View file

@ -6,14 +6,23 @@
jest.mock('ui/new_platform');
import { savedVisualization } from './saved_visualization';
import { getQueryFilters } from '../../../public/lib/build_embeddable_filters';
import { ExpressionValueFilter } from '../../../types';
const filterContext = {
const filterContext: ExpressionValueFilter = {
type: 'filter',
and: [
{ and: [], value: 'filter-value', column: 'filter-column', type: 'exactly' },
{
type: 'filter',
and: [],
value: 'filter-value',
column: 'filter-column',
filterType: 'exactly',
},
{
type: 'filter',
and: [],
column: 'time-column',
type: 'time',
filterType: 'time',
from: '2019-06-04T04:00:00.000Z',
to: '2019-06-05T04:00:00.000Z',
},

View file

@ -12,7 +12,7 @@ import {
EmbeddableExpression,
} from '../../expression_types';
import { getQueryFilters } from '../../../public/lib/build_embeddable_filters';
import { Filter, TimeRange as TimeRangeArg, SeriesStyle } from '../../../types';
import { ExpressionValueFilter, TimeRange as TimeRangeArg, SeriesStyle } from '../../../types';
import { getFunctionHelp } from '../../../i18n';
interface Arguments {
@ -31,7 +31,7 @@ const defaultTimeRange = {
export function savedVisualization(): ExpressionFunctionDefinition<
'savedVisualization',
Filter | null,
ExpressionValueFilter | null,
Arguments,
Output
> {

View file

@ -44,7 +44,7 @@ describe('timefilter', () => {
from: fromDate,
to: toDate,
}).and[0]
).toHaveProperty('type', 'time');
).toHaveProperty('filterType', 'time');
});
describe('args', () => {

View file

@ -5,7 +5,7 @@
*/
import dateMath from '@elastic/datemath';
import { Filter, ExpressionFunctionDefinition } from '../../../types';
import { ExpressionValueFilter, ExpressionFunctionDefinition } from '../../../types';
import { getFunctionHelp, getFunctionErrors } from '../../../i18n';
interface Arguments {
@ -17,9 +17,9 @@ interface Arguments {
export function timefilter(): ExpressionFunctionDefinition<
'timefilter',
Filter,
ExpressionValueFilter,
Arguments,
Filter
ExpressionValueFilter
> {
const { help, args: argHelp } = getFunctionHelp().timefilter;
const errors = getFunctionErrors().timefilter;
@ -58,8 +58,9 @@ export function timefilter(): ExpressionFunctionDefinition<
}
const { from, to, column } = args;
const filter: Filter = {
type: 'time',
const filter: ExpressionValueFilter = {
type: 'filter',
filterType: 'time',
column,
and: [],
};

View file

@ -5,12 +5,11 @@
*/
import { demodata } from './demodata';
import { ExpressionValueFilter } from '../../../types';
const nullFilter = {
const nullFilter: ExpressionValueFilter = {
type: 'filter',
meta: {},
size: null,
sort: [],
filterType: 'filter',
and: [],
};

View file

@ -10,14 +10,19 @@ import { ExpressionFunctionDefinition } from 'src/plugins/expressions';
import { queryDatatable } from '../../../../common/lib/datatable/query';
import { DemoRows } from './demo_rows_types';
import { getDemoRows } from './get_demo_rows';
import { Filter, Datatable, DatatableColumn, DatatableRow } from '../../../../types';
import { ExpressionValueFilter, Datatable, DatatableColumn, DatatableRow } from '../../../../types';
import { getFunctionHelp } from '../../../../i18n';
interface Arguments {
type: string;
}
export function demodata(): ExpressionFunctionDefinition<'demodata', Filter, Arguments, Datatable> {
export function demodata(): ExpressionFunctionDefinition<
'demodata',
ExpressionValueFilter,
Arguments,
Datatable
> {
const { help, args: argHelp } = getFunctionHelp().demodata;
return {

View file

@ -4,7 +4,10 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { ExpressionFunctionDefinition, Filter } from 'src/plugins/expressions/common';
import {
ExpressionFunctionDefinition,
ExpressionValueFilter,
} from 'src/plugins/expressions/common';
// @ts-ignore untyped local
import { buildESRequest } from '../../../server/lib/build_es_request';
import { getFunctionHelp } from '../../../i18n';
@ -14,7 +17,12 @@ interface Arguments {
query: string;
}
export function escount(): ExpressionFunctionDefinition<'escount', Filter, Arguments, any> {
export function escount(): ExpressionFunctionDefinition<
'escount',
ExpressionValueFilter,
Arguments,
any
> {
const { help, args: argHelp } = getFunctionHelp().escount;
return {
@ -40,7 +48,8 @@ export function escount(): ExpressionFunctionDefinition<'escount', Filter, Argum
fn: (input, args, handlers) => {
input.and = input.and.concat([
{
type: 'luceneQueryString',
type: 'filter',
filterType: 'luceneQueryString',
query: args.query,
and: [],
},

View file

@ -8,7 +8,7 @@ import squel from 'squel';
import { ExpressionFunctionDefinition } from 'src/plugins/expressions';
// @ts-ignore untyped local
import { queryEsSQL } from '../../../server/lib/query_es_sql';
import { Filter } from '../../../types';
import { ExpressionValueFilter } from '../../../types';
import { getFunctionHelp } from '../../../i18n';
interface Arguments {
@ -20,7 +20,12 @@ interface Arguments {
count: number;
}
export function esdocs(): ExpressionFunctionDefinition<'esdocs', Filter, Arguments, any> {
export function esdocs(): ExpressionFunctionDefinition<
'esdocs',
ExpressionValueFilter,
Arguments,
any
> {
const { help, args: argHelp } = getFunctionHelp().esdocs;
return {
@ -67,7 +72,8 @@ export function esdocs(): ExpressionFunctionDefinition<'esdocs', Filter, Argumen
input.and = input.and.concat([
{
type: 'luceneQueryString',
type: 'filter',
filterType: 'luceneQueryString',
query: args.query,
and: [],
},

View file

@ -7,7 +7,7 @@
import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common';
// @ts-ignore untyped local
import { queryEsSQL } from '../../../server/lib/query_es_sql';
import { Filter } from '../../../types';
import { ExpressionValueFilter } from '../../../types';
import { getFunctionHelp } from '../../../i18n';
interface Arguments {
@ -16,7 +16,12 @@ interface Arguments {
timezone: string;
}
export function essql(): ExpressionFunctionDefinition<'essql', Filter, Arguments, any> {
export function essql(): ExpressionFunctionDefinition<
'essql',
ExpressionValueFilter,
Arguments,
any
> {
const { help, args: argHelp } = getFunctionHelp().essql;
return {

View file

@ -15,14 +15,14 @@ export function queryDatatable(datatable, query) {
if (query.and) {
query.and.forEach(filter => {
// handle exact matches
if (filter.type === 'exactly') {
if (filter.filterType === 'exactly') {
datatable.rows = datatable.rows.filter(row => {
return row[filter.column] === filter.value;
});
}
// handle time filters
if (filter.type === 'time') {
if (filter.filterType === 'time') {
const columnNames = datatable.columns.map(col => col.name);
// remove row if no column match

View file

@ -11,7 +11,7 @@ import { interpretAst } from '../lib/run_interpreter';
// @ts-ignore untyped local
import { getState } from '../state/store';
import { getGlobalFilters } from '../state/selectors/workpad';
import { Filter } from '../../types';
import { ExpressionValueFilter } from '../../types';
import { getFunctionHelp } from '../../i18n';
import { InitializeArguments } from '.';
@ -41,7 +41,12 @@ function getFiltersByGroup(allFilters: string[], groups?: string[], ungrouped =
});
}
type FiltersFunction = ExpressionFunctionDefinition<'filters', null, Arguments, Filter>;
type FiltersFunction = ExpressionFunctionDefinition<
'filters',
null,
Arguments,
ExpressionValueFilter
>;
export function filtersFunctionFactory(initialize: InitializeArguments): () => FiltersFunction {
return function filters(): FiltersFunction {

View file

@ -11,7 +11,7 @@ import { ExpressionFunctionDefinition, DatatableRow } from 'src/plugins/expressi
import { fetch } from '../../common/lib/fetch';
// @ts-ignore untyped local
import { buildBoolArray } from '../../server/lib/build_bool_array';
import { Datatable, Filter } from '../../types';
import { Datatable, ExpressionValueFilter } from '../../types';
import { getFunctionHelp } from '../../i18n';
import { InitializeArguments } from './';
@ -49,7 +49,7 @@ function parseDateMath(
type TimelionFunction = ExpressionFunctionDefinition<
'timelion',
Filter,
ExpressionValueFilter,
Arguments,
Promise<Datatable>
>;
@ -94,11 +94,10 @@ export function timelionFunctionFactory(initialize: InitializeArguments): () =>
fn: (input, args): Promise<Datatable> => {
// Timelion requires a time range. Use the time range from the timefilter element in the
// workpad, if it exists. Otherwise fall back on the function args.
const timeFilter = input.and.find(and => and.type === 'time');
const timeFilter = input.and.find(and => and.filterType === 'time');
const range = timeFilter
? { min: timeFilter.from, max: timeFilter.to }
: parseDateMath({ from: args.from, to: args.to }, args.timezone, initialize.timefilter);
const body = {
extended: {
es: {

View file

@ -5,19 +5,21 @@
*/
import { buildEmbeddableFilters } from './build_embeddable_filters';
import { Filter } from '../../types';
import { ExpressionValueFilter } from '../../types';
const columnFilter: Filter = {
const columnFilter: ExpressionValueFilter = {
type: 'filter',
and: [],
value: 'filter-value',
column: 'filter-column',
type: 'exactly',
filterType: 'exactly',
};
const timeFilter: Filter = {
const timeFilter: ExpressionValueFilter = {
type: 'filter',
and: [],
column: 'time-column',
type: 'time',
filterType: 'time',
from: '2019-06-04T04:00:00.000Z',
to: '2019-06-05T04:00:00.000Z',
};

View file

@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { Filter } from '../../types';
import { ExpressionValueFilter } from '../../types';
// @ts-ignore Untyped Local
import { buildBoolArray } from './build_bool_array';
import {
@ -20,9 +20,9 @@ export interface EmbeddableFilterInput {
const TimeFilterType = 'time';
function getTimeRangeFromFilters(filters: Filter[]): TimeRange | undefined {
function getTimeRangeFromFilters(filters: ExpressionValueFilter[]): TimeRange | undefined {
const timeFilter = filters.find(
filter => filter.type !== undefined && filter.type === TimeFilterType
filter => filter.filterType !== undefined && filter.filterType === TimeFilterType
);
return timeFilter !== undefined && timeFilter.from !== undefined && timeFilter.to !== undefined
@ -33,11 +33,12 @@ function getTimeRangeFromFilters(filters: Filter[]): TimeRange | undefined {
: undefined;
}
export function getQueryFilters(filters: Filter[]): DataFilter[] {
return buildBoolArray(filters).map(esFilters.buildQueryFilter);
export function getQueryFilters(filters: ExpressionValueFilter[]): DataFilter[] {
const dataFilters = filters.map(filter => ({ ...filter, type: filter.filterType }));
return buildBoolArray(dataFilters).map(esFilters.buildQueryFilter);
}
export function buildEmbeddableFilters(filters: Filter[]): EmbeddableFilterInput {
export function buildEmbeddableFilters(filters: ExpressionValueFilter[]): EmbeddableFilterInput {
return {
timeRange: getTimeRangeFromFilters(filters),
filters: getQueryFilters(filters),

View file

@ -14,13 +14,13 @@
import * as filters from './filters';
export function getESFilter(filter) {
if (!filters[filter.type]) {
throw new Error(`Unknown filter type: ${filter.type}`);
if (!filters[filter.filterType]) {
throw new Error(`Unknown filter type: ${filter.filterType}`);
}
try {
return filters[filter.type](filter);
return filters[filter.filterType](filter);
} catch (e) {
throw new Error(`Could not create elasticsearch filter from ${filter.type}`);
throw new Error(`Could not create elasticsearch filter from ${filter.filterType}`);
}
}

View file

@ -6,7 +6,7 @@
import {
Datatable,
Filter,
ExpressionValueFilter,
ExpressionImage,
ExpressionFunction,
KibanaContext,
@ -46,7 +46,7 @@ interface ElementStatsType {
type ExpressionType =
| Datatable
| Filter
| ExpressionValueFilter
| ExpressionImage
| KibanaContext
| KibanaDatatable