Merge branch 'main' into feature-list-managed-groups

This commit is contained in:
Carlos Alcaide Corvo authored and GitHub committed 2021-11-09 11:38:23 -08:00
commit 1fc0d3eae8
4 files changed
+130 -2

No files matched your search

@@ -0,0 +1,109 @@
import Service from '@ember/service';
import { inject as service } from '@ember/service';
/**
* Takes a POJO representing a query and converts it to a boolean expression
* string which is understood by the API.
*
* @example
* const filter = new ResourceFilter({
* type: 'oidc',
* status: ['active', 'pending']
* });
* console.log(filter.queryExpression);
* // ("/item/type" == "oidc") and ("/item/status" == "active" or "/item/status" == "pending")
*/
export class ResourceFilter {
// =attributes
/**
* @type {?object}
*/
#filterObject;
/**
* @type {string}
*/
get queryExpression() {
const clauses = Object.keys(this.#filterObject)
.map((key) => {
const value = this.#filterObject[key];
const valuesArray = Array.isArray(value) ? value : [value];
return this.parenthetical(
this.or(valuesArray.map((value) => this.equals(key, value)))
);
})
.flat();
return this.and(clauses);
}
// =methods
/**
* @param {object} filterObject
*/
constructor(filterObject = {}) {
this.#filterObject = Object.assign({}, filterObject);
}
/**
* @param {string} key
* @param value
* @return {string}
*/
equals(key, value) {
return `"/item/${key}" == "${value}"`;
}
/**
* @param {string[]} clauses
* @return {string}
*/
and(clauses) {
return clauses.join(' and ');
}
/**
* @param {string[]} clauses
* @return {string}
*/
or(clauses) {
return clauses.join(' or ');
}
/**
* @param {string} expression
* @return {string}
*/
parenthetical(expression) {
return `(${expression})`;
}
}
/**
*
*/
export default class ResourceFilterStoreService extends Service {
// =services
@service store;
// =methods
/**
* Similar to Ember's built-in `store.query`, except this method accepts
* an additional argument `filterObject` representing a query filter
* (see ResourceFilter class above).
* @param {string} modelName
* @param {object} filterObject
* @param {?object} storeQuery
* @return {Promise}
*/
queryBy(modelName, filterObject = {}, storeQuery = {}) {
const filter = new ResourceFilter(filterObject);
const query = Object.assign({}, storeQuery);
// Apply filters to store query when available
if (filter.queryExpression) query.filter = filter.queryExpression;
return this.store.query(modelName, query);
}
}
@@ -0,0 +1 @@
export { default } from 'api/services/resource-filter-store';
@@ -0,0 +1,18 @@
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
import { ResourceFilter } from 'api/services/resource-filter-store';
module('Unit | Service | resource-filter-store', function (hooks) {
setupTest(hooks);
test('it exports a ResourceFilter class that converts filterObjects to query expressions', function (assert) {
assert.ok(ResourceFilter);
const filter = new ResourceFilter({
type: 'oidc',
status: ['active', 'pending'],
});
const expected =
'("/item/type" == "oidc") and ("/item/status" == "active" or "/item/status" == "pending")';
assert.equal(filter.queryExpression, expected);
});
});
@@ -13,6 +13,7 @@ export default class ScopesScopeProjectsSessionsRoute extends Route {
@service ipc;
@service session;
@service resourceFilterStore;
// =attributes
@@ -52,8 +53,7 @@ export default class ScopesScopeProjectsSessionsRoute extends Route {
const { id: scope_id } = this.modelFor('scopes.scope');
const { user_id } = this.session.data.authenticated;
await this.store.query('target', { recursive: true, scope_id });
return await this.store.query('session', {
filter: `"/item/user_id" == "${user_id}"`,
return await this.resourceFilterStore.queryBy('session', { user_id }, {
recursive: true,
scope_id
});