Skip to content

Commit

Permalink
refactor action filter creation utils (elastic#62969)
Browse files Browse the repository at this point in the history
  • Loading branch information
ppisljar committed Apr 22, 2020
1 parent 2f794e6 commit 222fdc5
Show file tree
Hide file tree
Showing 27 changed files with 184 additions and 172 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

```typescript
actions: {
createFiltersFromEvent: typeof createFiltersFromEvent;
createFiltersFromValueClickAction: typeof createFiltersFromValueClickAction;
createFiltersFromRangeSelectAction: typeof createFiltersFromRangeSelectAction;
};
```
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export interface DataPublicPluginStart

| Property | Type | Description |
| --- | --- | --- |
| [actions](./kibana-plugin-plugins-data-public.datapublicpluginstart.actions.md) | <code>{</code><br/><code> createFiltersFromEvent: typeof createFiltersFromEvent;</code><br/><code> }</code> | |
| [actions](./kibana-plugin-plugins-data-public.datapublicpluginstart.actions.md) | <code>{</code><br/><code> createFiltersFromValueClickAction: typeof createFiltersFromValueClickAction;</code><br/><code> createFiltersFromRangeSelectAction: typeof createFiltersFromRangeSelectAction;</code><br/><code> }</code> | |
| [autocomplete](./kibana-plugin-plugins-data-public.datapublicpluginstart.autocomplete.md) | <code>AutocompleteStart</code> | |
| [fieldFormats](./kibana-plugin-plugins-data-public.datapublicpluginstart.fieldformats.md) | <code>FieldFormatsStart</code> | |
| [indexPatterns](./kibana-plugin-plugins-data-public.datapublicpluginstart.indexpatterns.md) | <code>IndexPatternsContract</code> | |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
fieldFormats: {
FieldFormat: typeof FieldFormat;
FieldFormatsRegistry: typeof FieldFormatsRegistry;
serialize: (agg: import("./search").AggConfig) => import("../../expressions/common").SerializedFieldFormat<object>;
serialize: (agg: import("./search").AggConfig) => import("../../expressions").SerializedFieldFormat<object>;
DEFAULT_CONVERTER_COLOR: {
range: string;
regex: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
fieldFormats: {
FieldFormatsRegistry: typeof FieldFormatsRegistry;
FieldFormat: typeof FieldFormat;
serializeFieldFormat: (agg: import("../public/search").AggConfig) => import("../../expressions/common").SerializedFieldFormat<object>;
serializeFieldFormat: (agg: import("../public/search").AggConfig) => import("../../expressions").SerializedFieldFormat<object>;
BoolFormat: typeof BoolFormat;
BytesFormat: typeof BytesFormat;
ColorFormat: typeof ColorFormat;
Expand Down
2 changes: 1 addition & 1 deletion src/legacy/core_plugins/vis_type_vislib/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,6 @@ export class VisTypeVislibPlugin implements Plugin<void, void> {

public start(core: CoreStart, { data }: VisTypeVislibPluginStartDependencies) {
setFormatService(data.fieldFormats);
setDataActions({ createFiltersFromEvent: data.actions.createFiltersFromEvent });
setDataActions(data.actions);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ jest.mock('../../../legacy_imports', () => ({
}));

jest.mock('../../../services', () => ({
getDataActions: () => ({ createFiltersFromEvent: jest.fn().mockResolvedValue(['yes']) }),
getDataActions: () => ({
createFiltersFromValueClickAction: jest.fn().mockResolvedValue(['yes']),
}),
}));

const vis = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ export class VisLegend extends PureComponent<VisLegendProps, VisLegendState> {
return false;
}

const filters = await getDataActions().createFiltersFromEvent(item.values);
const filters = await getDataActions().createFiltersFromValueClickAction({ data: item.values });
return Boolean(filters.length);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,21 @@ export class Handler {

// memoize so that the same function is returned every time,
// allowing us to remove/re-add the same function
this.getProxyHandler = _.memoize(function(event) {
this.getProxyHandler = _.memoize(function(eventType) {
const self = this;
return function(e) {
self.vis.emit(event, e);
return function(eventPayload) {
switch (eventType) {
case 'brush':
const xRaw = _.get(eventPayload.data, 'series[0].values[0].xRaw');
if (!xRaw) return; // not sure if this is possible?
return self.vis.emit(eventType, {
table: xRaw.table,
range: eventPayload.range,
column: xRaw.column,
});
case 'click':
return self.vis.emit(eventType, eventPayload);
}
};
});

Expand Down
3 changes: 2 additions & 1 deletion src/legacy/ui/public/new_platform/new_platform.karma_mock.js
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,8 @@ export const npStart = {
},
data: {
actions: {
createFiltersFromEvent: Promise.resolve(['yes']),
createFiltersFromValueClickAction: Promise.resolve(['yes']),
createFiltersFromRangeSelectAction: sinon.fake(),
},
autocomplete: {
getProvider: sinon.fake(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,87 +19,72 @@

import moment from 'moment';

import { onBrushEvent, BrushEvent } from './brush_event';
import { createFiltersFromRangeSelectAction } from './create_filters_from_range_select';

import { IndexPatternsContract } from '../../../public';
import { IndexPatternsContract, RangeFilter } from '../../../public';
import { dataPluginMock } from '../../../public/mocks';
import { setIndexPatterns } from '../../../public/services';
import { mockDataServices } from '../../../public/search/aggs/test_helpers';
import { TriggerContextMapping } from '../../../../ui_actions/public';

describe('brushEvent', () => {
const DAY_IN_MS = 24 * 60 * 60 * 1000;
const JAN_01_2014 = 1388559600000;
let baseEvent: BrushEvent;
let baseEvent: TriggerContextMapping['SELECT_RANGE_TRIGGER']['data'];

const indexPattern = {
id: 'indexPatternId',
timeFieldName: 'time',
fields: {
getByName: () => undefined,
filter: () => [],
},
};

const aggConfigs = [
{
params: {
field: {},
},
getIndexPattern: () => ({
timeFieldName: 'time',
fields: {
getByName: () => undefined,
filter: () => [],
},
}),
getIndexPattern: () => indexPattern,
},
];

beforeEach(() => {
mockDataServices();
setIndexPatterns(({
...dataPluginMock.createStartContract().indexPatterns,
get: async () => ({
id: 'indexPatternId',
timeFieldName: 'time',
fields: {
getByName: () => undefined,
filter: () => [],
},
}),
get: async () => indexPattern,
} as unknown) as IndexPatternsContract);

baseEvent = {
data: {
ordered: {
date: false,
},
series: [
column: 0,
table: {
type: 'kibana_datatable',
columns: [
{
values: [
{
xRaw: {
column: 0,
table: {
columns: [
{
id: '1',
meta: {
type: 'histogram',
indexPatternId: 'indexPatternId',
aggConfigParams: aggConfigs[0].params,
},
},
],
},
},
},
],
id: '1',
name: '1',
meta: {
type: 'histogram',
indexPatternId: 'indexPatternId',
aggConfigParams: aggConfigs[0].params,
},
},
],
rows: [],
},
range: [],
};
});

test('should be a function', () => {
expect(typeof onBrushEvent).toBe('function');
expect(typeof createFiltersFromRangeSelectAction).toBe('function');
});

test('ignores event when data.xAxisField not provided', async () => {
const filter = await onBrushEvent(baseEvent);
expect(filter).toBeUndefined();
const filter = await createFiltersFromRangeSelectAction(baseEvent);
expect(filter).toEqual([]);
});

describe('handles an event when the x-axis field is a date field', () => {
Expand All @@ -109,29 +94,29 @@ describe('brushEvent', () => {
name: 'time',
type: 'date',
};
baseEvent.data.ordered = { date: true };
});

afterAll(() => {
baseEvent.range = [];
baseEvent.data.ordered = { date: false };
aggConfigs[0].params.field = {};
});

test('by ignoring the event when range spans zero time', async () => {
baseEvent.range = [JAN_01_2014, JAN_01_2014];
const filter = await onBrushEvent(baseEvent);
expect(filter).toBeUndefined();
const filter = await createFiltersFromRangeSelectAction(baseEvent);
expect(filter).toEqual([]);
});

test('by updating the timefilter', async () => {
baseEvent.range = [JAN_01_2014, JAN_01_2014 + DAY_IN_MS];
const filter = await onBrushEvent(baseEvent);
const filter = await createFiltersFromRangeSelectAction(baseEvent);
expect(filter).toBeDefined();

if (filter) {
expect(filter.range.time.gte).toBe(new Date(JAN_01_2014).toISOString());
if (filter.length) {
const rangeFilter = filter[0] as RangeFilter;
expect(rangeFilter.range.time.gte).toBe(new Date(JAN_01_2014).toISOString());
// Set to a baseline timezone for comparison.
expect(filter.range.time.lt).toBe(new Date(JAN_01_2014 + DAY_IN_MS).toISOString());
expect(rangeFilter.range.time.lt).toBe(new Date(JAN_01_2014 + DAY_IN_MS).toISOString());
}
});
});
Expand All @@ -142,26 +127,26 @@ describe('brushEvent', () => {
name: 'anotherTimeField',
type: 'date',
};
baseEvent.data.ordered = { date: true };
});

afterAll(() => {
baseEvent.range = [];
baseEvent.data.ordered = { date: false };
aggConfigs[0].params.field = {};
});

test('creates a new range filter', async () => {
const rangeBegin = JAN_01_2014;
const rangeEnd = rangeBegin + DAY_IN_MS;
baseEvent.range = [rangeBegin, rangeEnd];
const filter = await onBrushEvent(baseEvent);
const filter = await createFiltersFromRangeSelectAction(baseEvent);

expect(filter).toBeDefined();

if (filter) {
expect(filter.range.anotherTimeField.gte).toBe(moment(rangeBegin).toISOString());
expect(filter.range.anotherTimeField.lt).toBe(moment(rangeEnd).toISOString());
expect(filter.range.anotherTimeField).toHaveProperty(
if (filter.length) {
const rangeFilter = filter[0] as RangeFilter;
expect(rangeFilter.range.anotherTimeField.gte).toBe(moment(rangeBegin).toISOString());
expect(rangeFilter.range.anotherTimeField.lt).toBe(moment(rangeEnd).toISOString());
expect(rangeFilter.range.anotherTimeField).toHaveProperty(
'format',
'strict_date_optional_time'
);
Expand All @@ -184,20 +169,21 @@ describe('brushEvent', () => {

test('by ignoring the event when range does not span at least 2 values', async () => {
baseEvent.range = [1];
const filter = await onBrushEvent(baseEvent);
expect(filter).toBeUndefined();
const filter = await createFiltersFromRangeSelectAction(baseEvent);
expect(filter).toEqual([]);
});

test('by creating a new filter', async () => {
baseEvent.range = [1, 2, 3, 4];
const filter = await onBrushEvent(baseEvent);
const filter = await createFiltersFromRangeSelectAction(baseEvent);

expect(filter).toBeDefined();

if (filter) {
expect(filter.range.numberField.gte).toBe(1);
expect(filter.range.numberField.lt).toBe(4);
expect(filter.range.numberField).not.toHaveProperty('format');
if (filter.length) {
const rangeFilter = filter[0] as RangeFilter;
expect(rangeFilter.range.numberField.gte).toBe(1);
expect(rangeFilter.range.numberField.lt).toBe(4);
expect(rangeFilter.range.numberField).not.toHaveProperty('format');
}
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,34 +17,18 @@
* under the License.
*/

import { get, last } from 'lodash';
import { last } from 'lodash';
import moment from 'moment';
import { esFilters, IFieldType, RangeFilterParams } from '../../../public';
import { getIndexPatterns } from '../../../public/services';
import { deserializeAggConfig } from '../../search/expressions/utils';
import { RangeSelectTriggerContext } from '../../../../embeddable/public';

export interface BrushEvent {
data: {
ordered: {
date: boolean;
};
series: Array<Record<string, any>>;
};
range: number[];
}

export async function onBrushEvent(event: BrushEvent) {
const isDate = get(event.data, 'ordered.date');
const xRaw: Record<string, any> = get(event.data, 'series[0].values[0].xRaw');

if (!xRaw) {
return;
}

const column: Record<string, any> = xRaw.table.columns[xRaw.column];
export async function createFiltersFromRangeSelectAction(event: RangeSelectTriggerContext['data']) {
const column: Record<string, any> = event.table.columns[event.column];

if (!column || !column.meta) {
return;
return [];
}

const indexPattern = await getIndexPatterns().get(column.meta.indexPatternId);
Expand All @@ -55,16 +39,18 @@ export async function onBrushEvent(event: BrushEvent) {
const field: IFieldType = aggConfig.params.field;

if (!field || event.range.length <= 1) {
return;
return [];
}

const min = event.range[0];
const max = last(event.range);

if (min === max) {
return;
return [];
}

const isDate = field.type === 'date';

const range: RangeFilterParams = {
gte: isDate ? moment(min).toISOString() : min,
lt: isDate ? moment(max).toISOString() : max,
Expand All @@ -74,5 +60,5 @@ export async function onBrushEvent(event: BrushEvent) {
range.format = 'strict_date_optional_time';
}

return esFilters.buildRangeFilter(field, range, indexPattern);
return esFilters.mapAndFlattenFilters([esFilters.buildRangeFilter(field, range, indexPattern)]);
}
Loading

0 comments on commit 222fdc5

Please sign in to comment.