feat: 🎸 tweak resource-filter service and apply to sessions

This commit is contained in:
Randall Morey committed 2021-11-09 12:42:39 -05:00
1 parent cd6f87b796
commit 751a72a2d8
7 files changed
+108 -85

No files matched your search

@@ -0,0 +1,87 @@
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
#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
*/
equals(key, value) {
return `"/item/${key}" == "${value}"`;
}
/**
* @param {string[]} clauses
*/
and(clauses) {
return clauses.join(' and ');
}
/**
* @param {string[]} clauses
*/
or(clauses) {
return clauses.join(' or ');
}
/**
* @param {string} expression
*/
parenthetical(expression) {
return `(${expression})`;
}
}
export default class ResourceFilterStoreService extends Service {
@service store;
queryBy(modelName, filterObject = {}, storeQuery = {}) {
console.log(filterObject);
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);
}
}
@@ -1,53 +0,0 @@
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);
}
}