feat: Sorting by dynamic query.

This commit is contained in:
Ahmed Bouhuolia
2020-04-18 23:33:41 +02:00
parent c0c4e5af4a
commit cdee562ae7
17 changed files with 566 additions and 130 deletions

View File

@@ -0,0 +1,44 @@
import { uniqBy } from 'lodash';
import {
buildFilterRolesJoins,
} from '@/lib/ViewRolesBuilder';
export default class DynamicFilter {
/**
* Constructor.
* @param {String} tableName -
*/
constructor(tableName) {
this.tableName = tableName;
this.filters = [];
}
/**
* Set filter.
* @param {*} filterRole -
*/
setFilter(filterRole) {
filterRole.setTableName(this.tableName);
this.filters.push(filterRole);
}
/**
* Builds queries of filter roles.
*/
buildQuery() {
const buildersCallbacks = [];
const tableColumns = [];
this.filters.forEach((filter) => {
const { filterRoles } = filter;
buildersCallbacks.push(filter.buildQuery());
tableColumns.push(...(Array.isArray(filterRoles)) ? filterRoles : [filterRoles]);
});
return (builder) => {
buildersCallbacks.forEach((builderCallback) => {
builderCallback(builder);
});
buildFilterRolesJoins(this.tableName, uniqBy(tableColumns, 'columnKey'))(builder);
};
}
}

View File

@@ -1,22 +1,25 @@
import { difference } from 'lodash';
import DynamicFilterRoleAbstructor from '@/lib/DynamicFilter/DynamicFilterRoleAbstructor';
import {
buildFilterQuery,
} from '../ViewRolesBuilder';
} from '@/lib/ViewRolesBuilder';
export default class FilterRoles {
export default class FilterRoles extends DynamicFilterRoleAbstructor {
/**
* Constructor method.
* @param {Array} filterRoles -
* @param {Array} resourceFields -
*/
constructor(tableName, filterRoles, resourceFields) {
constructor(filterRoles, resourceFields) {
super();
this.filterRoles = filterRoles.map((role, index) => ({
...role,
index: index + 1,
columnKey: role.field_key,
comparator: role.comparator === 'AND' ? '&&' : '||',
}));
this.resourceFields = resourceFields;
this.tableName = tableName;
}
validateFilterRoles() {
@@ -36,10 +39,12 @@ export default class FilterRoles {
return expression.trim();
}
// @public
/**
* Builds database query of view roles.
*/
buildQuery() {
const logicExpression = this.buildLogicExpression();
return (builder) => {
const logicExpression = this.buildLogicExpression();
buildFilterQuery(this.tableName, this.filterRoles, logicExpression)(builder);
};
}

View File

@@ -0,0 +1,18 @@
export default class DynamicFilterAbstructor {
constructor() {
this.filterRoles = [];
this.tableName = '';
}
setTableName(tableName) {
this.tableName = tableName;
}
buildLogicExpression() {}
validateFilterRoles() {}
buildQuery() {}
}

View File

@@ -0,0 +1,31 @@
import DynamicFilterRoleAbstructor from '@/lib/DynamicFilter/DynamicFilterRoleAbstructor';
import {
getRoleFieldColumn,
} from '@/lib/ViewRolesBuilder';
export default class DynamicFilterSortBy extends DynamicFilterRoleAbstructor {
constructor(sortByFieldKey, sortDirection) {
super();
this.filterRoles = {
columnKey: sortByFieldKey,
value: sortDirection,
comparator: 'sort_by',
};
}
/**
* Builds database query of sort by column on the given direction.
*/
buildQuery() {
const { columnKey = null, value = null } = this.filterRoles;
return (builder) => {
const fieldRelation = getRoleFieldColumn(this.tableName, columnKey);
if (columnKey) {
builder.orderBy(`${this.tableName}.${fieldRelation.column}`, value.toLowerCase());
}
};
}
}

View File

@@ -0,0 +1,46 @@
import DynamicFilterRoleAbstructor from '@/lib/DynamicFilter/DynamicFilterRoleAbstructor';
import {
validateViewRoles,
buildFilterQuery,
} from '@/lib/ViewRolesBuilder';
export default class DynamicFilterViews extends DynamicFilterRoleAbstructor {
/**
* Constructor method.
* @param {*} filterRoles -
* @param {*} logicExpression -
*/
constructor(filterRoles, logicExpression) {
super();
this.filterRoles = filterRoles;
this.logicExpression = logicExpression
.replace('AND', '&&')
.replace('OR', '||');
this.tableName = '';
}
/**
* Retrieve logic expression.
*/
buildLogicExpression() {
return this.logicExpression;
}
/**
* Validates filter roles.
*/
validateFilterRoles() {
return validateViewRoles(this.filterRoles, this.logicExpression);
}
/**
* Builds database query of view roles.
*/
buildQuery() {
return (builder) => {
buildFilterQuery(this.tableName, this.filterRoles, this.logicExpression)(builder);
};
}
}

View File

@@ -0,0 +1,13 @@
import DynamicFilter from './DynamicFilter';
import DynamicFilterSortBy from './DynamicFilterSortBy';
import DynamicFilterViews from './DynamicFilterViews';
import DynamicFilterFilterRoles from './DynamicFilterFilterRoles';
export {
DynamicFilter,
DynamicFilterSortBy,
DynamicFilterViews,
DynamicFilterFilterRoles,
};

View File

@@ -0,0 +1,44 @@
import DynamicFilterRoleAbstructor from '@/lib/DynamicFilter/DynamicFilterRoleAbstructor';
import {
validateViewRoles,
buildFilterQuery,
} from '@/lib/ViewRolesBuilder';
export default class ViewRolesDynamicFilter extends DynamicFilterRoleAbstructor {
/**
* Constructor method.
* @param {*} filterRoles
* @param {*} logicExpression
*/
constructor(filterRoles, logicExpression) {
super();
this.filterRoles = filterRoles;
this.logicExpression = logicExpression;
this.tableName = '';
}
/**
* Retrieve logic expression.
*/
buildLogicExpression() {
return this.logicExpression;
}
/**
* Validates filter roles.
*/
validateFilterRoles() {
return validateViewRoles(this.filterRoles, this.logicExpression);
}
/**
* Builds database query of view roles.
*/
buildQuery() {
return (builder) => {
buildFilterQuery(this.tableName, this.filterRoles, this.logicExpression)(builder);
};
}
}

View File

@@ -29,9 +29,8 @@ export function getRoleFieldColumn(tableName, columnKey) {
*/
export function buildRoleQuery(tableName, role) {
const fieldRelation = getRoleFieldColumn(tableName, role.columnKey);
const comparatorColumn = fieldRelation.relation || `${tableName}.${fieldRelation.column}`;
const comparatorColumn = fieldRelation.relationColumn || `${tableName}.${fieldRelation.column}`;
console.log(comparatorColumn, role.value);
switch (role.comparator) {
case 'equals':
default:
@@ -44,6 +43,7 @@ export function buildRoleQuery(tableName, role) {
builder.whereNot(comparatorColumn, role.value);
};
case 'contain':
case 'contains':
return (builder) => {
builder.where(comparatorColumn, 'LIKE', `%${role.value}%`);
};
@@ -78,6 +78,17 @@ export function buildFilterRolesJoins(tableName, roles) {
};
}
export function buildSortColumnJoin(tableName, sortColumnKey) {
return (builder) => {
const fieldColumn = getRoleFieldColumn(tableName, sortColumnKey);
if (fieldColumn.relation) {
const joinTable = getTableFromRelationColumn(fieldColumn.relation);
builder.join(joinTable, `${tableName}.${fieldColumn.column}`, '=', fieldColumn.relation);
}
}
}
/**
* Builds database query from stored view roles.
*
@@ -110,7 +121,6 @@ export function buildFilterRolesQuery(tableName, roles, logicExpression = '') {
*/
export const buildFilterQuery = (tableName, roles, logicExpression) => {
return (builder) => {
buildFilterRolesJoins(tableName, roles)(builder);
buildFilterRolesQuery(tableName, roles, logicExpression)(builder);
};
};
@@ -148,4 +158,28 @@ export function mapViewRolesToConditionals(viewRoles) {
slug: viewRole.field.slug,
index: viewRole.index,
}));
}
export function mapFilterRolesToDynamicFilter(roles) {
return roles.map((role) => ({
...role,
columnKey: role.fieldKey,
}));
}
/**
* Builds sort column query.
* @param {String} tableName -
* @param {String} columnKey -
* @param {String} sortDirection -
*/
export function buildSortColumnQuery(tableName, columnKey, sortDirection) {
const fieldRelation = getRoleFieldColumn(tableName, columnKey);
const sortColumn = fieldRelation.relation || `${tableName}.${fieldRelation.column}`;
return (builder) => {
builder.orderBy(sortColumn, sortDirection);
buildSortColumnJoin(tableName, columnKey)(builder);
};
}