Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ import _ from 'lodash';
import { State } from 'ui/state_management/state';
import { FilterManager, esFilters } from '../../../../../../plugins/data/public';

import {
compareFilters,
COMPARE_FILTER_STATE,
// this whole file will soon be deprecated by new state management.
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
} from '../../../../../../plugins/data/public/query/filter_manager/lib/compare_filters';

type GetAppStateFunc = () => State | undefined | null;

/**
Expand Down Expand Up @@ -63,8 +70,16 @@ export class FilterStateManager {
const globalFilters = this.globalState.filters || [];
const appFilters = (appState && appState.filters) || [];

const globalFilterChanged = !_.isEqual(this.filterManager.getGlobalFilters(), globalFilters);
const appFilterChanged = !_.isEqual(this.filterManager.getAppFilters(), appFilters);
const globalFilterChanged = !compareFilters(
this.filterManager.getGlobalFilters(),
globalFilters,
COMPARE_FILTER_STATE
);
const appFilterChanged = !compareFilters(
this.filterManager.getAppFilters(),
appFilters,
COMPARE_FILTER_STATE
);
const filterStateChanged = globalFilterChanged || appFilterChanged;

if (!filterStateChanged) return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -637,7 +637,7 @@ function discoverController(

// fetch data when filters fire fetch event
subscriptions.add(
subscribeWithScope($scope, filterManager.getUpdates$(), {
subscribeWithScope($scope, filterManager.getFetches$(), {
next: $scope.fetch,
})
);
Expand Down
18 changes: 4 additions & 14 deletions src/plugins/data/public/query/filter_manager/filter_manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ import { Subject } from 'rxjs';

import { IUiSettingsClient } from 'src/core/public';

import { compareFilters } from './lib/compare_filters';
import { compareFilters, COMPARE_FILTER_STATE } from './lib/compare_filters';
import { sortFilters } from './lib/sort_filters';
import { mapAndFlattenFilters } from './lib/map_and_flatten_filters';
import { uniqFilters } from './lib/uniq_filters';
import { onlyDisabledFiltersChanged } from './lib/only_disabled';
Expand Down Expand Up @@ -76,20 +77,9 @@ export class FilterManager {
}

private handleStateUpdate(newFilters: esFilters.Filter[]) {
// global filters should always be first

newFilters.sort(({ $state: a }: esFilters.Filter, { $state: b }: esFilters.Filter): number => {
if (a!.store === b!.store) {
return 0;
} else {
return a!.store === esFilters.FilterStateStore.GLOBAL_STATE &&
b!.store !== esFilters.FilterStateStore.GLOBAL_STATE
? -1
: 1;
}
});
newFilters.sort(sortFilters);

const filtersUpdated = !_.isEqual(this.filters, newFilters);
const filtersUpdated = !compareFilters(this.filters, newFilters, COMPARE_FILTER_STATE);
const updatedOnlyDisabledFilters = onlyDisabledFiltersChanged(newFilters, this.filters);

this.filters = newFilters;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
* under the License.
*/

import { compareFilters } from './compare_filters';
import { compareFilters, COMPARE_FILTER_STATE } from './compare_filters';
import { esFilters } from '../../../../common';

describe('filter manager utilities', () => {
Expand Down Expand Up @@ -83,5 +83,134 @@ describe('filter manager utilities', () => {

expect(compareFilters(f1, f2)).toBeTruthy();
});

test('should compare filters array to non array', () => {
const f1 = esFilters.buildQueryFilter(
{ _type: { match: { query: 'apache', type: 'phrase' } } },
'index',
''
);

const f2 = esFilters.buildQueryFilter(
{ _type: { match: { query: 'mochi', type: 'phrase' } } },
'index',
''
);

expect(compareFilters([f1, f2], f1)).toBeFalsy();
});

test('should compare filters array to partial array', () => {
const f1 = esFilters.buildQueryFilter(
{ _type: { match: { query: 'apache', type: 'phrase' } } },
'index',
''
);

const f2 = esFilters.buildQueryFilter(
{ _type: { match: { query: 'mochi', type: 'phrase' } } },
'index',
''
);

expect(compareFilters([f1, f2], [f1])).toBeFalsy();
});

test('should compare filters array to exact array', () => {
const f1 = esFilters.buildQueryFilter(
{ _type: { match: { query: 'apache', type: 'phrase' } } },
'index',
''
);

const f2 = esFilters.buildQueryFilter(
{ _type: { match: { query: 'mochi', type: 'phrase' } } },
'index',
''
);

expect(compareFilters([f1, f2], [f1, f2])).toBeTruthy();
});

test('should compare array of duplicates, ignoring meta attributes', () => {
const f1 = esFilters.buildQueryFilter(
{ _type: { match: { query: 'apache', type: 'phrase' } } },
'index1',
''
);
const f2 = esFilters.buildQueryFilter(
{ _type: { match: { query: 'apache', type: 'phrase' } } },
'index2',
''
);

expect(compareFilters([f1], [f2])).toBeTruthy();
});

test('should compare array of duplicates, ignoring $state attributes', () => {
const f1 = {
$state: { store: esFilters.FilterStateStore.APP_STATE },
...esFilters.buildQueryFilter(
{ _type: { match: { query: 'apache', type: 'phrase' } } },
'index',
''
),
};
const f2 = {
$state: { store: esFilters.FilterStateStore.GLOBAL_STATE },
...esFilters.buildQueryFilter(
{ _type: { match: { query: 'apache', type: 'phrase' } } },
'index',
''
),
};

expect(compareFilters([f1], [f2])).toBeTruthy();
});

test('should compare duplicates with COMPARE_FILTER_STATE should check store', () => {
const f1 = {
$state: { store: esFilters.FilterStateStore.APP_STATE },
...esFilters.buildQueryFilter(
{ _type: { match: { query: 'apache', type: 'phrase' } } },
'index',
''
),
};
const f2 = {
$state: { store: esFilters.FilterStateStore.GLOBAL_STATE },
...esFilters.buildQueryFilter(
{ _type: { match: { query: 'apache', type: 'phrase' } } },
'index',
''
),
};

expect(compareFilters([f1], [f2], COMPARE_FILTER_STATE)).toBeFalsy();
});

test('should compare duplicates with COMPARE_FILTER_STATE should not check key and value ', () => {
const f1 = {
$state: { store: esFilters.FilterStateStore.GLOBAL_STATE },
...esFilters.buildQueryFilter(
{ _type: { match: { query: 'apache', type: 'phrase' } } },
'index',
''
),
};
const f2 = {
$state: { store: esFilters.FilterStateStore.GLOBAL_STATE },
...esFilters.buildQueryFilter(
{ _type: { match: { query: 'apache', type: 'phrase' } } },
'index',
''
),
};

f2.meta.key = 'wassup';
f2.meta.value = 'dog';

expect(compareFilters([f1], [f2], COMPARE_FILTER_STATE)).toBeTruthy();
});
});
});
59 changes: 46 additions & 13 deletions src/plugins/data/public/query/filter_manager/lib/compare_filters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,32 +17,53 @@
* under the License.
*/

import { defaults, isEqual, omit } from 'lodash';
import { defaults, isEqual, omit, map, sortBy } from 'lodash';
import { esFilters } from '../../../../common';

/**
* Include disabled, negate and store when comparing filters
*/
export const COMPARE_FILTER_STATE = {
disabled: true,
negate: true,
state: true,
};

const mapFilter = (filter: esFilters.Filter, comparators: any, excludedAttributes: string[]) => {
const cleaned: esFilters.FilterMeta = omit(filter, excludedAttributes);

if (comparators.negate) cleaned.negate = filter.meta && Boolean(filter.meta.negate);
if (comparators.disabled) cleaned.disabled = filter.meta && Boolean(filter.meta.disabled);

return cleaned;
};

const mapFilterArray = (
filters: esFilters.Filter[],
comparators: any,
excludedAttributes: string[]
) => {
return sortBy(
map(filters, (filter: esFilters.Filter) => mapFilter(filter, comparators, excludedAttributes))
);
};

/**
* Compare two filters to see if they match
*
* @param {object} first The first filter to compare
* @param {object} second The second filter to compare
* @param {esFilters.Filter | esFilters.Filter[]} first The first filter or filter array to compare
* @param {esFilters.Filter | esFilters.Filter[]} second The second filter or filter array to compare
* @param {object} comparatorOptions Parameters to use for comparison
*
* @returns {bool} Filters are the same
*/
export const compareFilters = (
first: esFilters.Filter,
second: esFilters.Filter,
first: esFilters.Filter | esFilters.Filter[],
second: esFilters.Filter | esFilters.Filter[],
comparatorOptions: any = {}
) => {
let comparators: any = {};
const mapFilter = (filter: esFilters.Filter) => {
const cleaned: esFilters.FilterMeta = omit(filter, excludedAttributes);

if (comparators.negate) cleaned.negate = filter.meta && Boolean(filter.meta.negate);
if (comparators.disabled) cleaned.disabled = filter.meta && Boolean(filter.meta.disabled);

return cleaned;
};
const excludedAttributes: string[] = ['$$hashKey', 'meta'];

comparators = defaults(comparatorOptions || {}, {
Expand All @@ -53,5 +74,17 @@ export const compareFilters = (

if (!comparators.state) excludedAttributes.push('$state');

return isEqual(mapFilter(first), mapFilter(second));
if (Array.isArray(first) && Array.isArray(second)) {
return isEqual(
mapFilterArray(first, comparators, excludedAttributes),
mapFilterArray(second, comparators, excludedAttributes)
);
} else if (!Array.isArray(first) && !Array.isArray(second)) {
return isEqual(
mapFilter(first, comparators, excludedAttributes),
mapFilter(second, comparators, excludedAttributes)
);
} else {
return false;
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@
* under the License.
*/

import { filter, isEqual } from 'lodash';
import { filter } from 'lodash';
import { esFilters } from '../../../../common';
import { compareFilters, COMPARE_FILTER_STATE } from './compare_filters';

const isEnabled = (f: esFilters.Filter) => f && f.meta && !f.meta.disabled;

Expand All @@ -35,5 +36,5 @@ export const onlyDisabledFiltersChanged = (
const newEnabledFilters = filter(newFilters || [], isEnabled);
const oldEnabledFilters = filter(oldFilters || [], isEnabled);

return isEqual(oldEnabledFilters, newEnabledFilters);
return compareFilters(oldEnabledFilters, newEnabledFilters, COMPARE_FILTER_STATE);
};
Loading