@adaptabletools/adaptable
Version:
Powerful data-agnostic HTML5 AG Grid extension which provides advanced, cutting-edge functionality to meet all DataGrid requirements
123 lines (122 loc) • 4.47 kB
JavaScript
import { mapColumnDataTypeToExpressionFunctionType } from '../../../Utilities/adaptableQlUtils';
import { isQlLogicalOperator } from '../../../parser/src/predicate';
import { booleanExpressionFunctions } from '../../../Utilities/ExpressionFunctions/booleanExpressionFunctions';
import { deepClone } from '../../../Utilities/Extensions/ObjectExtensions';
import { booleanExpressionsAvailableInQueryBuilder } from './booleanExpressions';
export const reorder = (predicate, from, to) => {
const predicateCopy = deepClone(predicate);
// we start from the root so no need to traverse first level
const [_, ...fromPath] = from.split('/');
const [__, ...toPath] = to.split('/');
// remove from old position and get the item
// path = '0/1/2'
let itemToMove = predicateCopy;
let prev = null;
for (const index of fromPath) {
prev = itemToMove;
itemToMove = itemToMove.args[parseInt(index)];
}
prev.args.splice(parseInt(fromPath[fromPath.length - 1]), 1);
// find the parent into wich we want to insert the item
let cursor = predicateCopy;
let parent = null;
for (const index of toPath) {
parent = cursor;
cursor = cursor.args[parseInt(index)];
}
parent.args.splice(parseInt(toPath[toPath.length - 1]), 0, itemToMove);
return predicateCopy;
};
export const getOperatorMatchingInputs = (columnType, inputs, includeAllInputs = false) => {
if (Array.isArray(inputs[0])) {
const matchingInput = inputs.find((input) => input[0] === columnType);
const [_, ...restOfArgs] = matchingInput ?? [];
return restOfArgs;
}
const [_, ...restOfArgs] = inputs;
return includeAllInputs
? inputs
: restOfArgs;
};
export const getFunctionsForColumnType = (dataType, availableBooleanFunctions) => {
const columnType = mapColumnDataTypeToExpressionFunctionType(dataType);
return booleanExpressionsAvailableInQueryBuilder.filter((boolFnName) => {
if (!availableBooleanFunctions.includes(boolFnName)) {
return false;
}
const functionDef = booleanExpressionFunctions[boolFnName];
const inputs = functionDef.inputs;
let matchingInputTypes = [];
if (inputs && Array.isArray(inputs[0])) {
matchingInputTypes = inputs.find((input) => input[0] === columnType);
}
else {
matchingInputTypes = inputs;
}
return matchingInputTypes?.[0] === columnType;
});
};
export const getUnsuportedExpressionFromQlPredicate = (predicate, context) => {
if (!predicate) {
return null;
}
if (typeof predicate === 'string' && isFieldValue(predicate)) {
const field = mapExpressionToFieldValue(predicate);
if (!context.supportedFields?.some((field) => field?.value === mapExpressionToFieldValue(predicate))) {
return `Expression uses an unregistered field: "${field}"`;
}
else {
return null;
}
}
if (typeof predicate === 'object' && 'errorMessage' in predicate) {
return null;
}
if (typeof predicate !== 'object' || !('operator' in predicate) || !predicate.operator) {
return null;
}
if (!isQlLogicalOperator(predicate.operator) &&
!booleanExpressionsAvailableInQueryBuilder.includes(predicate.operator)) {
return `${predicate.operator} is not supported in the Query Builder`;
}
if (predicate.args.length === 0) {
return null;
}
let firstInvalidArg = null;
for (let arg of predicate.args) {
firstInvalidArg = getUnsuportedExpressionFromQlPredicate(arg, context);
if (firstInvalidArg) {
break;
}
}
if (firstInvalidArg) {
return firstInvalidArg;
}
return null;
};
export const mapFieldValueToExpression = (field) => `FIELD('${field}')`;
export const mapExpressionToFieldValue = (expression) => {
if (!expression) {
return '';
}
try {
return expression.match(/FIELD\(['"](.+)['"]\)/)?.[1];
}
catch (e) {
return '';
}
};
export const mapColumnExpressionToColumnId = (expression) => {
if (!expression) {
return null;
}
try {
return expression.match(/\[(.+)\]/)?.[1];
}
catch (e) {
return expression;
}
};
export const isFieldValue = (expression) => {
return typeof expression === 'string' && expression.includes('FIELD');
};