From 3240ce4228f11debf4a8316363f4f125c831b1c7 Mon Sep 17 00:00:00 2001 From: Pranav C Date: Fri, 13 Aug 2021 15:40:09 +0530 Subject: [PATCH] feat: Formula argument validation Signed-off-by: Pranav C --- .../components/editColumn/formulaOptions.vue | 32 +++++------- packages/nc-gui/helpers/formulaList.js | 49 +++++++++++++++++++ 2 files changed, 61 insertions(+), 20 deletions(-) create mode 100644 packages/nc-gui/helpers/formulaList.js diff --git a/packages/nc-gui/components/project/spreadsheet/components/editColumn/formulaOptions.vue b/packages/nc-gui/components/project/spreadsheet/components/editColumn/formulaOptions.vue index 30601d6513..0762a29b5e 100644 --- a/packages/nc-gui/components/project/spreadsheet/components/editColumn/formulaOptions.vue +++ b/packages/nc-gui/components/project/spreadsheet/components/editColumn/formulaOptions.vue @@ -64,6 +64,7 @@ import NcAutocompleteTree from '@/helpers/NcAutocompleteTree' import { getWordUntilCaret, insertAtCursor } from '@/helpers' import debounce from 'debounce' import jsep from 'jsep' +import formulaList, { validations } from '../../../../../helpers/formulaList' export default { name: 'FormulaOptions', @@ -71,26 +72,7 @@ export default { data: () => ({ formula: {}, // formulas: ['AVERAGE()', 'COUNT()', 'COUNTA()', 'COUNTALL()', 'SUM()', 'MIN()', 'MAX()', 'AND()', 'OR()', 'TRUE()', 'FALSE()', 'NOT()', 'XOR()', 'ISERROR()', 'IF()', 'LEN()', 'MID()', 'LEFT()', 'RIGHT()', 'FIND()', 'CONCATENATE()', 'T()', 'VALUE()', 'ARRAYJOIN()', 'ARRAYUNIQUE()', 'ARRAYCOMPACT()', 'ARRAYFLATTEN()', 'ROUND()', 'ROUNDUP()', 'ROUNDDOWN()', 'INT()', 'EVEN()', 'ODD()', 'MOD()', 'LOG()', 'EXP()', 'POWER()', 'SQRT()', 'CEILING()', 'FLOOR()', 'ABS()', 'RECORD_ID()', 'CREATED_TIME()', 'ERROR()', 'BLANK()', 'YEAR()', 'MONTH()', 'DAY()', 'HOUR()', 'MINUTE()', 'SECOND()', 'TODAY()', 'NOW()', 'WORKDAY()', 'DATETIME_PARSE()', 'DATETIME_FORMAT()', 'SET_LOCALE()', 'SET_TIMEZONE()', 'DATESTR()', 'TIMESTR()', 'TONOW()', 'FROMNOW()', 'DATEADD()', 'WEEKDAY()', 'WEEKNUM()', 'DATETIME_DIFF()', 'WORKDAY_DIFF()', 'IS_BEFORE()', 'IS_SAME()', 'IS_AFTER()', 'REPLACE()', 'REPT()', 'LOWER()', 'UPPER()', 'TRIM()', 'SUBSTITUTE()', 'SEARCH()', 'SWITCH()', 'LAST_MODIFIED_TIME()', 'ENCODE_URL_COMPONENT()', 'REGEX_EXTRACT()', 'REGEX_MATCH()', 'REGEX_REPLACE()'] - availableFunctions: [ - 'AVG', 'ADD', 'CONCAT', 'TRIM', - 'UPPER', - 'LOWER', - 'LEN', - 'MIN', - 'MAX', - 'CEILING', 'FLOOR', 'ROUND', - 'MOD', 'REPEAT', - 'LOG', 'EXP', 'POWER', 'SQRT', // todo: remove in sqlite - 'ABS', - 'NOW', - 'REPLACE', - 'SEARCH', - 'INT', - 'RIGHT', - 'LEFT', - 'SUBSTR', - 'MID' - ], + availableFunctions: formulaList, availableBinOps: ['+', '-', '*', '/'], autocomplete: false, suggestion: null, @@ -200,6 +182,16 @@ export default { if (!this.availableFunctions.includes(pt.callee.name)) { arr.push(`'${pt.callee.name}' function is not available`) } + const validation = validations[pt.callee.name] && validations[pt.callee.name].validation + if (validation && validation.args) { + if (validation.args.rqd !== undefined && validation.args.rqd !== pt.arguments.length) { + arr.push(`'${pt.callee.name}' required ${validation.args.rqd} arguments`) + } else if (validation.args.min !== undefined && validation.args.min > pt.arguments.length) { + arr.push(`'${pt.callee.name}' required minimum ${validation.args.min} arguments`) + } else if (validation.args.max !== undefined && validation.args.max < pt.arguments.length) { + arr.push(`'${pt.callee.name}' required maximum ${validation.args.max} arguments`) + } + } pt.arguments.map(arg => this.validateAgainstMeta(arg, arr)) } else if (pt.type === 'Identifier') { if (this.meta.columns.every(c => c._cn !== pt.name)) { diff --git a/packages/nc-gui/helpers/formulaList.js b/packages/nc-gui/helpers/formulaList.js new file mode 100644 index 0000000000..a5a46c9e79 --- /dev/null +++ b/packages/nc-gui/helpers/formulaList.js @@ -0,0 +1,49 @@ +const validations = { + AVG: { + validation: { + args: { min: 1 } + } + }, + ADD: { + validation: { + args: { min: 1 } + + } + }, + CONCAT: { + validation: { args: { min: 1 } } + }, + TRIM: { + validation: { args: { min: 1 } } + }, + UPPER: { + validation: { args: { rqd: 1 } } + }, + LOWER: { validation: { args: { rqd: 1 } } }, + LEN: { validation: { args: { rqd: 1 } } }, + MIN: { validation: { args: { min: 1 } } }, + MAX: { validation: { args: { min: 1 } } }, + CEILING: { validation: { args: { rqd: 1 } } }, + FLOOR: { validation: { args: { rqd: 1 } } }, + ROUND: { validation: { args: { rqd: 1 } } }, + MOD: { validation: { args: { rqd: 2 } } }, + REPEAT: { validation: { args: { rqd: 2 } } }, + LOG: { validation: {} }, + EXP: { validation: {} }, + POWER: { validation: { args: { rqd: 2 } } }, + SQRT: { validation: { args: { rqd: 1 } } }, + ABS: { validation: { args: { rqd: 1 } } }, + NOW: { validation: { args: { rqd: 0 } } }, + REPLACE: { validation: { args: { rqd: 2 } } }, + SEARCH: { validation: { args: { rqd: 2 } } }, + INT: { validation: { args: { rqd: 1 } } }, + RIGHT: { validation: { args: { rqd: 2 } } }, + LEFT: { + validation: { args: { rqd: 1 } } + }, + SUBSTR: { validation: { args: { min: 2, max: 3 } } }, + MID: { validation: { args: { rqd: 1 } } } +} + +export default Object.keys(validations) +export { validations }