diff --git a/addons/api/addon/services/filterable-store.js b/addons/api/addon/services/filterable-store.js deleted file mode 100644 index 579e06178..000000000 --- a/addons/api/addon/services/filterable-store.js +++ /dev/null @@ -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); - } -} diff --git a/addons/api/addon/services/resource-filtering-store.js b/addons/api/addon/services/resource-filtering-store.js new file mode 100644 index 000000000..4f7537c10 --- /dev/null +++ b/addons/api/addon/services/resource-filtering-store.js @@ -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); + } +} diff --git a/addons/api/app/services/filterable-store.js b/addons/api/app/services/filterable-store.js deleted file mode 100644 index c35db1dfc..000000000 --- a/addons/api/app/services/filterable-store.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from 'api/services/filterable-store'; diff --git a/addons/api/app/services/resource-filtering-store.js b/addons/api/app/services/resource-filtering-store.js new file mode 100644 index 000000000..13fe8a0c8 --- /dev/null +++ b/addons/api/app/services/resource-filtering-store.js @@ -0,0 +1 @@ +export { default } from 'api/services/resource-filtering-store'; diff --git a/addons/api/tests/unit/services/filterable-store-test.js b/addons/api/tests/unit/services/filterable-store-test.js deleted file mode 100644 index 83bc17681..000000000 --- a/addons/api/tests/unit/services/filterable-store-test.js +++ /dev/null @@ -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); - }); -}); diff --git a/addons/api/tests/unit/services/resource-filtering-store-test.js b/addons/api/tests/unit/services/resource-filtering-store-test.js new file mode 100644 index 000000000..3e1852d6e --- /dev/null +++ b/addons/api/tests/unit/services/resource-filtering-store-test.js @@ -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); + // }); +});