WIP: dynamic list filtering.

This commit is contained in:
a.bouhuolia
2021-07-31 17:07:37 +02:00
parent 9186076676
commit 3546b6b7ae
34 changed files with 569 additions and 314 deletions

View File

@@ -25,6 +25,9 @@ export default class DynamicFilter extends DynamicFilterAbstructor{
*/
public setFilter = (dynamicFilter: IDynamicFilter) => {
dynamicFilter.setModel(this.model);
dynamicFilter.onInitialize();
this.dynamicFilters.push(dynamicFilter);
}
@@ -66,11 +69,7 @@ export default class DynamicFilter extends DynamicFilterAbstructor{
buildersCallbacks.forEach((builderCallback) => {
builderCallback(builder);
});
this.buildFilterRolesJoins(
this.model,
uniqBy(tableColumns, 'columnKey')
)(builder);
this.buildFilterRolesJoins(builder);
};
}

View File

@@ -1,4 +1,5 @@
import { IModel, IFilterRole } from 'interfaces';
import { FIELD_TYPE } from './constants';
export default class DynamicFilterAbstructor {
/**
@@ -16,22 +17,24 @@ export default class DynamicFilterAbstructor {
* @param {String} tableName - Table name.
* @param {Array} roles - Roles.
*/
protected buildFilterRolesJoins = (model: IModel, roles: IFilterRole[]) => {
return (builder) => {
roles.forEach((role) => {
const field = model.getField(role.fieldKey);
protected buildFilterRolesJoins = (builder) => {
this.dynamicFilters.forEach((dynamicFilter) => {
const relationsFields = dynamicFilter.relationFields;
if (field.relation) {
const joinTable = this.getTableFromRelationColumn(field.relation);
this.buildFieldsJoinQueries(builder, relationsFields);
});
};
builder.join(
joinTable,
`${model.tableName}.${field.column}`,
'=',
field.relation
);
}
});
};
private buildFieldsJoinQueries = (builder, fieldsRelations: string[]) => {
fieldsRelations.forEach((fieldRelation) => {
const relation = this.model.relationMappings[fieldRelation];
if (relation) {
const splitToRelation = relation.join.to.split('.');
const relationTable = splitToRelation[0] || '';
builder.join(relationTable, relation.join.from, '=', relation.join.to);
}
});
};
}

View File

@@ -13,9 +13,14 @@ export default class FilterRoles extends DynamicFilterRoleAbstructor {
super();
this.filterRoles = filterRoles;
this.setResponseMeta();
}
public onInitialize() {
this.setFilterRolesRelations();
}
/**
* Builds filter roles logic expression.
* @return {string}
@@ -53,4 +58,13 @@ export default class FilterRoles extends DynamicFilterRoleAbstructor {
filterRoles: this.filterRoles,
};
}
/**
* Sets filter roles relations if field was relation type.
*/
private setFilterRolesRelations() {
this.filterRoles.forEach((relationRole) => {
this.setRelationIfRelationField(relationRole.fieldKey);
});
}
}

View File

@@ -12,6 +12,7 @@ export default abstract class DynamicFilterAbstructor
protected tableName: string;
protected model: IModel;
protected responseMeta: { [key: string]: any } = {};
public relationFields = [];
/**
* Sets model the dynamic filter service.
@@ -78,22 +79,50 @@ export default abstract class DynamicFilterAbstructor
};
};
/**
* Retrieve relation column of comparator fieldز
*/
private getFieldComparatorRelationColumn(field) {
const relation = this.model.relationMappings[field.relationKey];
if (relation) {
const relationModel = relation.modelClass;
const relationColumn =
field.relationEntityKey === 'id'
? 'id'
: relationModel.getField(field.relationEntityKey, 'column');
return `${relationModel.tableName}.${relationColumn}`;
}
}
/**
* Retrieve the comparator field column.
* @param {IModel} model -
* @param {} -
*/
private getFieldComparatorColumn = (field) => {
return field.fieldType === FIELD_TYPE.RELATION
? this.getFieldComparatorRelationColumn(field)
: `${this.tableName}.${field.column}`;
};
/**
* Builds roles queries.
* @param {IModel} model -
* @param {Object} role -
*/
protected buildRoleQuery = (model: IModel, role: IFilterRole) => {
const fieldRelation = model.getField(role.fieldKey);
const comparatorColumn = `${model.tableName}.${fieldRelation.column}`;
const field = model.getField(role.fieldKey);
const comparatorColumn = this.getFieldComparatorColumn(field);
// Field relation custom query.
if (typeof fieldRelation.customQuery !== 'undefined') {
if (typeof field.filterCustomQuery !== 'undefined') {
return (builder) => {
fieldRelation.customQuery(builder, role);
field.filterCustomQuery(builder, role);
};
}
switch (fieldRelation.fieldType) {
switch (field.fieldType) {
case FIELD_TYPE.BOOLEAN:
case FIELD_TYPE.ENUMERATION:
return this.booleanRoleQueryBuilder(role, comparatorColumn);
@@ -265,7 +294,7 @@ export default abstract class DynamicFilterAbstructor
builder.where(comparatorColumn, '>=', startDate.format(dateFormat));
builder.where(comparatorColumn, '<=', endDate.format(dateFormat));
}
}
};
/**
* Date query after/before comparator type.
@@ -296,5 +325,25 @@ export default abstract class DynamicFilterAbstructor
}
const comparatorValue = targetDate.format(dateFormat);
builder.where(comparatorColumn, comparator, comparatorValue);
}
};
/**
* Registers relation field if the given field was relation type
* and not registered.
* @param {string} fieldKey - Field key.
*/
protected setRelationIfRelationField = (fieldKey: string): void => {
const field = this.model.getField(fieldKey);
const isAlreadyRegistered = this.relationFields.some(
(field) => field === fieldKey
);
if (
!isAlreadyRegistered &&
field &&
field.fieldType === FIELD_TYPE.RELATION
) {
this.relationFields.push(field.relationKey);
}
};
}

View File

@@ -1,9 +1,5 @@
import DynamicFilterRoleAbstructor from 'lib/DynamicFilter/DynamicFilterRoleAbstructor';
import {
getRoleFieldColumn,
validateFieldKeyExistance,
getTableFromRelationColumn,
} from 'lib/ViewRolesBuilder';
import { FIELD_TYPE } from './constants';
interface ISortRole {
fieldKey: string;
@@ -28,17 +24,52 @@ export default class DynamicFilterSortBy extends DynamicFilterRoleAbstructor {
this.setResponseMeta();
}
/**
* On initialize the dyanmic sort by.
*/
public onInitialize() {
this.setRelationIfRelationField(this.sortRole.fieldKey);
}
/**
* Retrieve field comparator relatin column.
* @param field
* @returns {string}
*/
private getFieldComparatorRelationColumn = (field): string => {
const relation = this.model.relationMappings[field.relationKey];
if (relation) {
const relationModel = relation.modelClass;
const relationField = relationModel.getField(field.relationEntityLabel);
return `${relationModel.tableName}.${relationField.column}`;
}
return '';
};
/**
* Retrieve the comparator field column.
* @param {IModel} field
* @returns {string}
*/
private getFieldComparatorColumn = (field): string => {
return field.fieldType === FIELD_TYPE.RELATION
? this.getFieldComparatorRelationColumn(field)
: `${this.tableName}.${field.column}`;
};
/**
* Builds database query of sort by column on the given direction.
*/
public buildQuery() {
public buildQuery = () => {
const field = this.model.getField(this.sortRole.fieldKey);
const comparatorColumn = `${this.tableName}.${field.column}`;
const comparatorColumn = this.getFieldComparatorColumn(field);
if (typeof field.customSortQuery !== 'undefined') {
// Sort custom query.
if (typeof field.sortCustomQuery !== 'undefined') {
return (builder) => {
field.customSortQuery(builder, this.sortRole);
field.sortCustomQuery(builder, this.sortRole);
};
}
@@ -47,24 +78,7 @@ export default class DynamicFilterSortBy extends DynamicFilterRoleAbstructor {
builder.orderBy(`${comparatorColumn}`, this.sortRole.order);
}
};
}
private joinBuildQuery() {
const fieldColumn = getRoleFieldColumn(this.model, this.sortRole.fieldKey);
return (builder) => {
if (fieldColumn.relation) {
const joinTable = getTableFromRelationColumn(fieldColumn.relation);
builder.join(
joinTable,
`${this.model.tableName}.${fieldColumn.column}`,
'=',
fieldColumn.relation
);
}
};
}
};
/**
* Sets response meta.

View File

@@ -33,4 +33,5 @@ export const FIELD_TYPE = {
BOOLEAN: 'boolean',
RELATION: 'relation',
DATE: 'date',
COMPUTED: 'computed'
};