UNPKG

@adaptabletools/adaptable

Version:

Powerful data-agnostic HTML5 AG Grid extension which provides advanced, cutting-edge functionality to meet all DataGrid requirements

359 lines (358 loc) 13.3 kB
import { isAfter } from 'date-fns'; import { isBefore } from 'date-fns'; import { isEqual } from 'date-fns'; import { ExpressionEvaluationError } from '../../parser/src/ExpressionEvaluationError'; import { getStringValue, getStringValues } from './expressionFunctionUtils'; import { getTypedKeys } from '../Extensions/TypeExtensions'; import { normalizeDateParam } from './dateUtils'; export const booleanExpressionFunctions = { TRUE: { handler: () => { return true; }, description: 'Returns the boolean value TRUE', category: 'logical', returnType: 'boolean', signatures: ['TRUE'], examples: ['[column] = TRUE'], }, FALSE: { handler: () => { return false; }, description: 'Returns the boolean value FALSE', category: 'logical', returnType: 'boolean', signatures: ['FALSE'], examples: ['[column] = FALSE'], }, AND: { handler(args) { return Boolean(args[0] && args[1]); }, isHiddenFromMenu: true, category: 'logical', description: 'Returns true if both statements are true', signatures: ['statement AND statement'], examples: ['[col1] > 5 AND [col2] > 10'], returnType: 'boolean', inputs: ['boolean', 'boolean'], }, OR: { handler(args) { return Boolean(args[0] || args[1]); }, isHiddenFromMenu: true, category: 'logical', description: 'Returns true if either statement is true', signatures: ['statement OR statement'], examples: ['[col1] > 5 OR [col2] > 10'], returnType: 'boolean', inputs: ['boolean', 'boolean'], }, NOT: { handler(args) { return Boolean(!args[0]); }, isHiddenFromMenu: true, category: 'logical', description: 'Returns the negation of a statement', signatures: ['!statement'], examples: ['!([col1] > 5 AND [col2] > 10)'], returnType: 'boolean', inputs: ['boolean'], }, EQ: { handler(args, context) { if (args[0] instanceof Date && args[1] instanceof Date) { return isEqual(args[0], args[1]); } if (typeof args[0] === 'string' || typeof args[1] === 'string') { const [first, second] = getStringValues(context, String(args[0]), String(args[1])); return first == second; } return args[0] == args[1]; }, isHiddenFromMenu: true, category: 'comparison', description: 'Returns true if the 2 (input) values are equal', signatures: ['value = value', 'EQ(a: value, b: value)'], examples: ['[col1] = 5', 'EQ([col1], 5)'], returnType: 'boolean', inputs: [ ['number', 'number'], ['date', 'date'], ['text', 'text'], ['boolean', 'boolean'], ], }, NEQ: { handler(args, context) { if (args[0] instanceof Date && args[1] instanceof Date) { return !isEqual(args[0], args[1]); } if (typeof args[0] === 'string' || typeof args[1] === 'string') { const [first, second] = getStringValues(context, String(args[0]), String(args[1])); return first != second; } return args[0] != args[1]; }, isHiddenFromMenu: true, category: 'comparison', description: 'Returns true if the 2 (input) values are NOT equal', signatures: ['value != value', 'NEQ(a: value, b: value)'], examples: ['[col1] != 5', 'NEQ([col1], 5)'], returnType: 'boolean', inputs: [ ['number', 'number'], ['date', 'date'], ['text', 'text'], ['boolean', 'boolean'], ], }, LT: { handler(args, context) { if (args[0] instanceof Date && args[1] instanceof Date) { return isBefore(args[0], args[1]); } if (typeof args[0] === 'string' || typeof args[1] === 'string') { const [first, second] = getStringValues(context, String(args[0]), String(args[1])); return first < second; } return args[0] < args[1]; }, isHiddenFromMenu: true, category: 'comparison', description: 'Returns true if the 1st input is less than 2nd input', signatures: [ 'number < number', 'date < date', 'LT(a: number, b: number)', 'LT(a: date, b: date)', ], examples: ['[col1] < 5', 'LT([col1], 5)'], returnType: 'boolean', inputs: [ ['number', 'number'], ['date', 'date'], ], }, LTE: { handler(args, context) { if (args[0] instanceof Date && args[1] instanceof Date) { return isBefore(args[0], args[1]) || isEqual(args[0], args[1]); } if (typeof args[0] === 'string' || typeof args[1] === 'string') { const [first, second] = getStringValues(context, String(args[0]), String(args[1])); return first <= second; } return args[0] <= args[1]; }, isHiddenFromMenu: true, category: 'comparison', description: 'Returns true if 1st input is less than or equals 2nd input', signatures: [ 'number <= number', 'date <= date', 'LTE(a: number, b: number)', 'LTE(a: date, b: date)', ], examples: ['[col1] <= 5', 'LTE([col1], 5)'], returnType: 'boolean', inputs: [ ['number', 'number'], ['date', 'date'], ], }, GT: { handler(args, context) { if (args[0] instanceof Date && args[1] instanceof Date) { return isAfter(args[0], args[1]); } if (typeof args[0] === 'string' || typeof args[1] === 'string') { const [first, second] = getStringValues(context, String(args[0]), String(args[1])); return first > second; } return args[0] > args[1]; }, isHiddenFromMenu: true, category: 'comparison', description: 'Returns true if the 1st input is greater than 2nd input', signatures: [ 'number > number', 'date > date', 'GT(a: number, b: number)', 'GT(a: date, b: date)', ], examples: ['[col1] > 5', 'GT([col1], 5)'], returnType: 'boolean', inputs: [ ['number', 'number'], ['date', 'date'], ], }, GTE: { handler(args, context) { if (args[0] instanceof Date && args[1] instanceof Date) { return isAfter(args[0], args[1]) || isEqual(args[0], args[1]); } if (typeof args[0] === 'string' || typeof args[1] === 'string') { const [first, second] = getStringValues(context, String(args[0]), String(args[1])); return first >= second; } return args[0] >= args[1]; }, isHiddenFromMenu: true, category: 'comparison', description: 'Returns true if 1st input is greater than or equals 2nd input', signatures: [ 'number >= number', 'date >= date', 'GTE(a: number, b: number)', 'GTE(a: date, b: date)', ], examples: ['[col1] >= 5', 'GTE([col1], 5)'], returnType: 'boolean', inputs: [ ['number', 'number'], ['date', 'date'], ], }, BETWEEN: { handler([input, lower, upper]) { if (typeof input !== 'number') throw new ExpressionEvaluationError('BETWEEN', 'arg 1 should be a number'); return input >= lower && input <= upper; }, category: 'comparison', description: 'Returns true if 1st input is between 2nd and 3rd inputs', signatures: ['BETWEEN(input: number, lower: number, upper: number)'], examples: ['BETWEEN([col1], 10, 30)'], returnType: 'boolean', inputs: ['number', 'number', 'number'], }, IN: { handler([needle, haystack]) { return haystack.includes(needle); }, category: 'comparison', description: 'Returns true if the left-hand side value is a constituent element of the right-hand side sequence', signatures: ['values IN (value, value, ...value)'], examples: ['[col1] IN (5, 10, AVG([col2],[col3]))'], returnType: 'boolean', inputs: [ ['number', 'number[]'], // Date is currently not supported in select // ['date', 'date[]'], ['text', 'text[]'], ], }, CONTAINS: { handler(args, context) { const [first, second] = getStringValues(context, String(args[0]), String(args[1])); return first.indexOf(second) !== -1; }, category: 'strings', description: 'Returns true if 1st input contains 2nd input', signatures: ['CONTAINS(a: string, b: string)'], examples: ['CONTAINS([col1], "S")'], returnType: 'boolean', inputs: ['text', 'text'], }, STARTS_WITH: { handler(args, context) { const [first, second] = getStringValues(context, String(args[0]), String(args[1])); return first.startsWith(second); }, category: 'strings', description: 'Returns true if 1st input starts with the 2nd input', signatures: ['STARTS_WITH(a: string, b: string)'], examples: ['STARTS_WITH([col1], "S")'], returnType: 'boolean', inputs: ['text', 'text'], }, ENDS_WITH: { handler(args, context) { const [first, second] = getStringValues(context, String(args[0]), String(args[1])); return first.endsWith(second); }, category: 'strings', description: 'Returns true if 1st input ends with the 2nd input', signatures: ['ENDS_WITH(a: string, b: string)'], examples: ['ENDS_WITH([col1], "S")'], returnType: 'boolean', inputs: ['text', 'text'], }, ANY_CONTAINS: { handler(args, context) { const searchTerm = getStringValue(context, String(args[0])); return context.adaptableApi?.columnApi.getColumns().some((column) => { const value = context.adaptableApi?.gridApi.getDisplayValueFromRowNode(context.node, column.columnId); const columnValue = getStringValue(context, String(value)); return columnValue.indexOf(searchTerm) !== -1; }); }, category: 'strings', description: 'Returns true if any Column contains input', signatures: ['ANY_CONTAINS(value)'], examples: ['ANY_CONTAINS("abc")'], returnType: 'boolean', }, IS_NUMERIC: { handler(args) { return !isNaN(Number(args[0])); }, isHiddenFromMenu: false, description: 'Returns true if input is numeric', signatures: ['IS_NUMERIC(a: number)'], examples: ['IS_NUMERIC([columnName])'], category: 'maths', returnType: 'boolean', inputs: ['number'], }, REGEX: { handler(args) { // dont need context as here we always want case insenstivity in the Regex const firstInput = String(args[0]); const regex = String(args[1]); return RegExp(regex).test(firstInput); }, isHiddenFromMenu: false, description: 'Returns true if Regular Expression matches', signatures: ['REGEX(a: string, b: pattern)'], examples: ['REGEX([col1], "[A-Z]+")'], inputs: ['text', 'text'], category: 'strings', returnType: 'boolean', }, IS_HOLIDAY: { handler(args, context) { const dateToCheck = normalizeDateParam(args[0]); return context.adaptableApi.calendarApi.isHoliday(dateToCheck); }, isHiddenFromMenu: false, description: 'Returns true if input date is a Holiday', signatures: ['IS_HOLIDAY(a: date)'], examples: ['IS_HOLIDAY([columnName])'], category: 'dates', returnType: 'boolean', inputs: ['date'], }, IS_WORKDAY: { handler(args, context) { const dateToCheck = normalizeDateParam(args[0]); return context.adaptableApi.calendarApi.isWorkingDay(dateToCheck); }, isHiddenFromMenu: false, description: 'Returns true if input date is a Working Day', signatures: ['IS_WORKDAY(a: date)'], examples: ['IS_WORKDAY([columnName])'], category: 'dates', returnType: 'boolean', inputs: ['date'], }, }; export const booleanExpressionFunctionsNames = getTypedKeys(booleanExpressionFunctions); export const isBooleanAdaptableQlFunction = (functionName) => { return booleanExpressionFunctionsNames.includes(functionName); };