Skip to content

Commit

Permalink
[Vis] Move propFilter from ui/filter to ui/agg_types/filter (#36875) (#…
Browse files Browse the repository at this point in the history
…37090)

* Move propFilter from ui/filter to ui/agg_types/filter

* Return default value

* Make propFilter generic

* Convert propFilter from a mocha test to a jest test
  • Loading branch information
maryia-lapata authored May 25, 2019
1 parent 72060b1 commit 6825df6
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 63 deletions.
1 change: 1 addition & 0 deletions src/legacy/ui/public/agg_types/filter/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@
*/

export { aggTypeFilters } from './agg_type_filters';
export { propFilter } from './prop_filter';
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,16 @@
*/

import expect from '@kbn/expect';
import { propFilter } from '../_prop_filter';
import { propFilter } from './prop_filter';

describe('prop filter', function () {
let nameFilter;
describe('prop filter', () => {
let nameFilter: Function;

beforeEach(function () {
beforeEach(() => {
nameFilter = propFilter('name');
});

function getObjects(...names) {
function getObjects(...names: string[]) {
const count = new Map();
const objects = [];

Expand All @@ -36,56 +36,56 @@ describe('prop filter', function () {
count.set(name, 1);
}
objects.push({
name: name,
title: `${name} ${count.get(name)}`
name,
title: `${name} ${count.get(name)}`,
});
count.set(name, count.get(name) + 1);
}
return objects;
}

it('returns list when no filters are provided', function () {
it('returns list when no filters are provided', () => {
const objects = getObjects('table', 'table', 'pie');
expect(nameFilter(objects)).to.eql(objects);
});

it('returns list when empty list of filters is provided', function () {
it('returns list when empty list of filters is provided', () => {
const objects = getObjects('table', 'table', 'pie');
expect(nameFilter(objects, [])).to.eql(objects);
});

it('should keep only the tables', function () {
it('should keep only the tables', () => {
const objects = getObjects('table', 'table', 'pie');
expect(nameFilter(objects, 'table')).to.eql(getObjects('table', 'table'));
});

it('should support comma-separated values', function () {
it('should support comma-separated values', () => {
const objects = getObjects('table', 'line', 'pie');
expect(nameFilter(objects, 'table,line')).to.eql(getObjects('table', 'line'));
});

it('should support an array of values', function () {
it('should support an array of values', () => {
const objects = getObjects('table', 'line', 'pie');
expect(nameFilter(objects, [ 'table', 'line' ])).to.eql(getObjects('table', 'line'));
expect(nameFilter(objects, ['table', 'line'])).to.eql(getObjects('table', 'line'));
});

it('should return all objects', function () {
it('should return all objects', () => {
const objects = getObjects('table', 'line', 'pie');
expect(nameFilter(objects, '*')).to.eql(objects);
});

it('should allow negation', function () {
it('should allow negation', () => {
const objects = getObjects('table', 'line', 'pie');
expect(nameFilter(objects, [ '!line' ])).to.eql(getObjects('table', 'pie'));
expect(nameFilter(objects, ['!line'])).to.eql(getObjects('table', 'pie'));
});

it('should support a function for specifying what should be kept', function () {
it('should support a function for specifying what should be kept', () => {
const objects = getObjects('table', 'line', 'pie');
const line = (value) => value === 'line';
const line = (value: string) => value === 'line';
expect(nameFilter(objects, line)).to.eql(getObjects('line'));
});

it('gracefully handles a filter function with zero arity', function () {
it('gracefully handles a filter function with zero arity', () => {
const objects = getObjects('table', 'line', 'pie');
const rejectEverything = () => false;
expect(nameFilter(objects, rejectEverything)).to.eql([]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,16 @@

import { isFunction } from 'lodash';

type FilterFunc<P extends keyof T, T> = (item: T[P]) => boolean;

/**
* Filters out a list by a given filter. This is currently used to implement:
* - fieldType filters a list of fields by their type property
* - aggFilter filters a list of aggs by their name property
*
* @returns {function} - the filter function which can be registered with angular
* @returns the filter function which can be registered with angular
*/
export function propFilter(prop) {
function propFilter<P extends string>(prop: P) {
/**
* List filtering function which accepts an array or list of values that a property
* must contain
Expand All @@ -37,9 +39,12 @@ export function propFilter(prop) {
* - Can be also an array, a single value as a string, or a comma-separated list of items
* @return {array} - the filtered list
*/
return function (list, filters = []) {
return function filterByName<T extends { [key in P]: T[P] }>(
list: T[],
filters: string[] | string | FilterFunc<P, T> = []
): T[] {
if (isFunction(filters)) {
return list.filter((item) => filters(item[prop]));
return list.filter(item => (filters as FilterFunc<P, T>)(item[prop]));
}

if (!Array.isArray(filters)) {
Expand All @@ -54,21 +59,26 @@ export function propFilter(prop) {
return list;
}

const options = filters.reduce(function (options, filter) {
let type = 'include';
let value = filter;
const options = filters.reduce(
(acc, filter) => {
let type = 'include';
let value = filter;

if (filter.charAt(0) === '!') {
type = 'exclude';
value = filter.substr(1);
}
if (filter.charAt(0) === '!') {
type = 'exclude';
value = filter.substr(1);
}

if (!options[type]) options[type] = [];
options[type].push(value);
return options;
}, {});
if (!acc[type]) {
acc[type] = [];
}
acc[type].push(value);
return acc;
},
{} as { [type: string]: string[] }
);

return list.filter(function (item) {
return list.filter(item => {
const value = item[prop];

const excluded = options.exclude && options.exclude.includes(value);
Expand All @@ -85,3 +95,5 @@ export function propFilter(prop) {
});
};
}

export { propFilter };
2 changes: 1 addition & 1 deletion src/legacy/ui/public/agg_types/param_types/field.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import '../filters/sort_prefix_first';
import { IndexedArray } from '../../indexed_array';
import { toastNotifications } from '../../notify';
import { createLegacyClass } from '../../utils/legacy_class';
import { propFilter } from '../../filters/_prop_filter';
import { propFilter } from '../filter';
import { i18n } from '@kbn/i18n';

const filterByType = propFilter('type');
Expand Down
24 changes: 0 additions & 24 deletions src/legacy/ui/public/filters/_prop_filter.d.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,10 @@
* under the License.
*/
import { AggType } from '../../../agg_types';
import { aggTypeFilters } from '../../../agg_types/filter';
import { aggTypeFilters, propFilter } from '../../../agg_types/filter';
import { IndexPattern } from '../../../index_patterns';
import { AggConfig } from '../../../vis';

import { propFilter } from '../../../filters/_prop_filter';

const filterByName = propFilter('name');

/**
Expand Down

0 comments on commit 6825df6

Please sign in to comment.