feat: Refactor to ResourceFilteringStore service
This commit is contained in:
6 files changed
+83
-106
No files matched your search
@@ -1,68 +0,0 @@
|
||||
import Store from '@ember-data/store';
|
||||
|
||||
class FilterQuery {
|
||||
_config;
|
||||
constructor(config) {
|
||||
this._config = config;
|
||||
}
|
||||
|
||||
get query() {
|
||||
const filters = this._buildFilters(this._config);
|
||||
return this._joinFilters(filters, { inclusive: false });
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate through filter config to generate array of filter strings
|
||||
* @param {object} config
|
||||
*/
|
||||
_buildFilters(config) {
|
||||
let filters = [];
|
||||
for (const key in config) {
|
||||
filters.push(this._generateQuery(`/item/${key}`, config[`${key}`]));
|
||||
}
|
||||
return filters;
|
||||
}
|
||||
|
||||
/**
|
||||
* For a single filter, build filter query
|
||||
* @param {string} selector
|
||||
* @param {*} values
|
||||
*/
|
||||
_generateQuery(selector, values) {
|
||||
// TODO: Check for value type
|
||||
const filters = values.map((value) => `"${selector}" == "${value}"`);
|
||||
return this._joinFilters(filters, { inclusive: true });
|
||||
}
|
||||
|
||||
/**
|
||||
* Combine filter strings
|
||||
* @param {array} filters
|
||||
* @param {object} inclusive
|
||||
*/
|
||||
_joinFilters(filters, { inclusive }) {
|
||||
return filters.join(inclusive ? ' or ' : ' and ');
|
||||
}
|
||||
}
|
||||
export default class FilterableStoreService extends Store {
|
||||
/**
|
||||
* Filterable store queries using IDs
|
||||
* Usage:
|
||||
* // Filter for a user in sessions
|
||||
* this.store.filterByIds('session', { scope_id, recursive: true }, { user: ['u_0987654321']})
|
||||
* // Filter for status in pending or terminated state and for a session id
|
||||
* this.store.filterByIds('session', { scope_id },
|
||||
* { status: ['pending', 'terminated' ], target: ['s_U5EoFe4Jba']}
|
||||
* )
|
||||
* // To remove filters
|
||||
* this.store.filterByIds('session', { scope_id })
|
||||
* @param {string} modelName
|
||||
* @param {object} queryOptions
|
||||
* @param {string} filterQuery
|
||||
*/
|
||||
filterByIds(modelName, queryOptions, filterOptions) {
|
||||
const filterQuery = new FilterQuery(filterOptions);
|
||||
// Apply filters, if available
|
||||
if (filterQuery.query) queryOptions.filter = filterQuery;
|
||||
return this.query(modelName, queryOptions);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
import Service from '@ember/service';
|
||||
import { inject as service } from '@ember/service';
|
||||
|
||||
class ResourceFilters {
|
||||
buildQuery(resourceFilters) {
|
||||
const filters = this._buildFilters(resourceFilters);
|
||||
return this._joinFilters(filters, { inclusive: false });
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate through filter config to generate array of filter strings
|
||||
* @param {object} config
|
||||
*/
|
||||
_buildFilters(config) {
|
||||
let filters = [];
|
||||
for (const key in config) {
|
||||
filters.push(this._generateQuery(`/item/${key}`, config[`${key}`]));
|
||||
}
|
||||
return filters;
|
||||
}
|
||||
|
||||
/**
|
||||
* For a single filter, build filter query
|
||||
* @param {string} selector
|
||||
* @param {*} values
|
||||
*/
|
||||
_generateQuery(selector, values) {
|
||||
// Coerce single string filters into an array for easy mapping
|
||||
if (!Array.isArray(values)) values = [values];
|
||||
const filters = values.map((value) => `"${selector}" == "${value}"`);
|
||||
return this._joinFilters(filters, { inclusive: true });
|
||||
}
|
||||
|
||||
/**
|
||||
* Combine filter strings
|
||||
* @param {array} filters
|
||||
* @param {object} inclusive
|
||||
*/
|
||||
_joinFilters(filters, { inclusive }) {
|
||||
return filters.join(inclusive ? ' or ' : ' and ');
|
||||
}
|
||||
}
|
||||
|
||||
export default class ResourceFilteringStoreService extends Service {
|
||||
@service store;
|
||||
|
||||
queryBy(modelName, resourceParams, resourceFilters) {
|
||||
const filterQuery = new ResourceFilters().buildQuery(resourceFilters);
|
||||
// Apply filters to store query when available
|
||||
if (filterQuery) resourceParams.filter = filterQuery;
|
||||
return this.store.query(modelName, resourceParams);
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
export { default } from 'api/services/filterable-store';
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from 'api/services/resource-filtering-store';
|
||||
@@ -1,37 +0,0 @@
|
||||
import { module, test } from 'qunit';
|
||||
import { setupTest } from 'ember-qunit';
|
||||
import { Response } from 'miragejs';
|
||||
import setupMirage from 'ember-cli-mirage/test-support/setup-mirage';
|
||||
|
||||
module('Unit | Service | filterable-store', function (hooks) {
|
||||
setupTest(hooks);
|
||||
setupMirage(hooks);
|
||||
let store;
|
||||
|
||||
hooks.beforeEach(function () {
|
||||
store = this.owner.lookup('service:filterable-store');
|
||||
|
||||
store.createRecord('session', {
|
||||
id: 'i_1234567890',
|
||||
scope: {
|
||||
id: '123',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test('it supports query filtering', function (assert) {
|
||||
this.server.get('/v1/sessions?scope_id=123', () => {
|
||||
new Response({});
|
||||
});
|
||||
store.filterByIds('session', { scope_id: '123' });
|
||||
assert.ok(store);
|
||||
});
|
||||
|
||||
test('it supports single attribute filters', function (assert) {
|
||||
assert.ok(store);
|
||||
});
|
||||
|
||||
test('it supports multiple attribute filters', function (assert) {
|
||||
assert.ok(store);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,29 @@
|
||||
import { module, test } from 'qunit';
|
||||
import { setupTest } from 'ember-qunit';
|
||||
|
||||
module('Unit | Service | resource-filtering-store', function (hooks) {
|
||||
setupTest(hooks);
|
||||
let service, store;
|
||||
hooks.beforeEach(function () {
|
||||
service = this.owner.lookup('service:resource-filtering-store');
|
||||
store = this.owner.lookup('service:store');
|
||||
|
||||
store.createRecord('session', {
|
||||
id: 's_1',
|
||||
scope: {
|
||||
id: '123',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// TODO: Replace this with your real tests.
|
||||
test('it exists', function (assert) {
|
||||
assert.ok(service);
|
||||
});
|
||||
|
||||
// TODO: Is it possible to capture mirage API requests in this test?
|
||||
// test('it supports query filters', function (assert) {
|
||||
// const models = service.queryBy('session', {}, { scope_id: '123' });
|
||||
// assert.ok(service);
|
||||
// });
|
||||
});
|
||||
Reference in new issue
Block a user