Browse Source

feat(gui-v2): include getWordUntilCaret & insertAtCursor in formula utils

pull/2998/head
Wing-Kam Wong 2 years ago
parent
commit
2bcfd7c7e5
  1. 939
      packages/nc-gui-v2/utils/formulaUtils.ts

939
packages/nc-gui-v2/utils/formulaUtils.ts

@ -1,494 +1,461 @@
import type { Input as AntInput } from 'ant-design-vue'
const formulaTypes = { const formulaTypes = {
NUMERIC: "numeric", NUMERIC: 'numeric',
STRING: "string", STRING: 'string',
DATE: "date", DATE: 'date',
LOGICAL: "logical", LOGICAL: 'logical',
COND_EXP: "conditional_expression" COND_EXP: 'conditional_expression',
} }
const formulas = { const formulas = {
AVG: { AVG: {
type: formulaTypes.NUMERIC, type: formulaTypes.NUMERIC,
validation: { validation: {
args: { args: {
min: 1 min: 1,
} },
}, },
description: 'Average of input parameters', description: 'Average of input parameters',
syntax: 'AVG(value1, [value2, ...])', syntax: 'AVG(value1, [value2, ...])',
examples: [ examples: ['AVG(10, 5) => 7.5', 'AVG({column1}, {column2})', 'AVG({column1}, {column2}, {column3})'],
'AVG(10, 5) => 7.5', },
'AVG({column1}, {column2})', ADD: {
'AVG({column1}, {column2}, {column3})' type: formulaTypes.NUMERIC,
] validation: {
}, args: {
ADD: { min: 1,
type: formulaTypes.NUMERIC, },
validation: { },
args: { description: 'Sum of input parameters',
min: 1 syntax: 'ADD(value1, [value2, ...])',
} examples: ['ADD(5, 5) => 10', 'ADD({column1}, {column2})', 'ADD({column1}, {column2}, {column3})'],
}, },
description: 'Sum of input parameters', DATEADD: {
syntax: 'ADD(value1, [value2, ...])', type: formulaTypes.DATE,
examples: [ validation: {
'ADD(5, 5) => 10', args: {
'ADD({column1}, {column2})', rqd: 3,
'ADD({column1}, {column2}, {column3})' },
] },
}, description: 'Adds a "count" units to Datetime.',
DATEADD: { syntax: 'DATEADD(date | datetime, value, ["day" | "week" | "month" | "year"])',
type: formulaTypes.DATE, examples: [
validation: { 'DATEADD({column1}, 2, "day")',
args: { 'DATEADD({column1}, -2, "day")',
rqd: 3 'DATEADD({column1}, 2, "week")',
} 'DATEADD({column1}, -2, "week")',
}, 'DATEADD({column1}, 2, "month")',
description: 'Adds a "count" units to Datetime.', 'DATEADD({column1}, -2, "month")',
syntax: 'DATEADD(date | datetime, value, ["day" | "week" | "month" | "year"])', 'DATEADD({column1}, 2, "year")',
examples: [ 'DATEADD({column1}, -2, "year")',
'DATEADD({column1}, 2, "day")', ],
'DATEADD({column1}, -2, "day")', },
'DATEADD({column1}, 2, "week")', AND: {
'DATEADD({column1}, -2, "week")', type: formulaTypes.COND_EXP,
'DATEADD({column1}, 2, "month")', validation: {
'DATEADD({column1}, -2, "month")', args: {
'DATEADD({column1}, 2, "year")', min: 1,
'DATEADD({column1}, -2, "year")' },
] },
}, description: 'TRUE if all expr evaluate to TRUE',
AND: { syntax: 'AND(expr1, [expr2, ...])',
type: formulaTypes.COND_EXP, examples: ['AND(5 > 2, 5 < 10) => 1', 'AND({column1} > 2, {column2} < 10)'],
validation: { },
args: { OR: {
min: 1 type: formulaTypes.COND_EXP,
} validation: {
}, args: {
description: 'TRUE if all expr evaluate to TRUE', min: 1,
syntax: 'AND(expr1, [expr2, ...])', },
examples: [ },
'AND(5 > 2, 5 < 10) => 1', description: 'TRUE if at least one expr evaluates to TRUE',
'AND({column1} > 2, {column2} < 10)' syntax: 'OR(expr1, [expr2, ...])',
] examples: ['OR(5 > 2, 5 < 10) => 1', 'OR({column1} > 2, {column2} < 10)'],
}, },
OR: { CONCAT: {
type: formulaTypes.COND_EXP, type: formulaTypes.STRING,
validation: { validation: {
args: { args: {
min: 1 min: 1,
} },
}, },
description: 'TRUE if at least one expr evaluates to TRUE', description: 'Concatenated string of input parameters',
syntax: 'OR(expr1, [expr2, ...])', syntax: 'CONCAT(str1, [str2, ...])',
examples: [ examples: ['CONCAT("AA", "BB", "CC") => "AABBCC"', 'CONCAT({column1}, {column2}, {column3})'],
'OR(5 > 2, 5 < 10) => 1', },
'OR({column1} > 2, {column2} < 10)' TRIM: {
] type: formulaTypes.STRING,
}, validation: {
CONCAT: { args: {
type: formulaTypes.STRING, rqd: 1,
validation: { },
args: { },
min: 1 description: 'Remove trailing and leading whitespaces from input parameter',
} syntax: 'TRIM(str)',
}, examples: ['TRIM(" HELLO WORLD ") => "HELLO WORLD"', 'TRIM({column1})'],
description: 'Concatenated string of input parameters', },
syntax: 'CONCAT(str1, [str2, ...])', UPPER: {
examples: [ type: formulaTypes.STRING,
'CONCAT("AA", "BB", "CC") => "AABBCC"', validation: {
'CONCAT({column1}, {column2}, {column3})' args: {
] rqd: 1,
}, },
TRIM: { },
type: formulaTypes.STRING, description: 'Upper case converted string of input parameter',
validation: { syntax: 'UPPER(str)',
args: { examples: ['UPPER("nocodb") => "NOCODB"', 'UPPER({column1})'],
rqd: 1 },
} LOWER: {
}, type: formulaTypes.STRING,
description: 'Remove trailing and leading whitespaces from input parameter', validation: {
syntax: 'TRIM(str)', args: {
examples: [ rqd: 1,
'TRIM(" HELLO WORLD ") => "HELLO WORLD"', },
'TRIM({column1})' },
] description: 'Lower case converted string of input parameter',
}, syntax: 'LOWER(str)',
UPPER: { examples: ['LOWER("NOCODB") => "nocodb"', 'LOWER({column1})'],
type: formulaTypes.STRING, },
validation: { LEN: {
args: { type: formulaTypes.STRING,
rqd: 1 validation: {
} args: {
}, rqd: 1,
description: 'Upper case converted string of input parameter', },
syntax: 'UPPER(str)', },
examples: [ description: 'Input parameter character length',
'UPPER("nocodb") => "NOCODB"', syntax: 'LEN(value)',
'UPPER({column1})' examples: ['LEN("NocoDB") => 6', 'LEN({column1})'],
] },
}, MIN: {
LOWER: { type: formulaTypes.NUMERIC,
type: formulaTypes.STRING, validation: {
validation: { args: {
args: { min: 1,
rqd: 1 },
} },
}, description: 'Minimum value amongst input parameters',
description: 'Lower case converted string of input parameter', syntax: 'MIN(value1, [value2, ...])',
syntax: 'LOWER(str)', examples: ['MIN(1000, 2000) => 1000', 'MIN({column1}, {column2})'],
examples: [ },
'LOWER("NOCODB") => "nocodb"', MAX: {
'LOWER({column1})' type: formulaTypes.NUMERIC,
] validation: {
}, args: {
LEN: { min: 1,
type: formulaTypes.STRING, },
validation: { },
args: { description: 'Maximum value amongst input parameters',
rqd: 1 syntax: 'MAX(value1, [value2, ...])',
} examples: ['MAX(1000, 2000) => 2000', 'MAX({column1}, {column2})'],
}, },
description: 'Input parameter character length', CEILING: {
syntax: 'LEN(value)', type: formulaTypes.NUMERIC,
examples: [ validation: {
'LEN("NocoDB") => 6', args: {
'LEN({column1})' rqd: 1,
] },
}, },
MIN: { description: 'Rounded next largest integer value of input parameter',
type: formulaTypes.NUMERIC, syntax: 'CEILING(value)',
validation: { examples: ['CEILING(1.01) => 2', 'CEILING({column1})'],
args: { },
min: 1 FLOOR: {
} type: formulaTypes.NUMERIC,
}, validation: {
description: 'Minimum value amongst input parameters', args: {
syntax: 'MIN(value1, [value2, ...])', rqd: 1,
examples: [ },
'MIN(1000, 2000) => 1000', },
'MIN({column1}, {column2})' description: 'Rounded largest integer less than or equal to input parameter',
] syntax: 'FLOOR(value)',
}, examples: ['FLOOR(3.1415) => 3', 'FLOOR({column1})'],
MAX: { },
type: formulaTypes.NUMERIC, ROUND: {
validation: { type: formulaTypes.NUMERIC,
args: { validation: {
min: 1 args: {
} rqd: 1,
}, },
description: 'Maximum value amongst input parameters', },
syntax: 'MAX(value1, [value2, ...])', description: 'Nearest integer to the input parameter',
examples: [ syntax: 'ROUND(value)',
'MAX(1000, 2000) => 2000', examples: ['ROUND(3.1415) => 3', 'ROUND({column1})'],
'MAX({column1}, {column2})' },
] MOD: {
}, type: formulaTypes.NUMERIC,
CEILING: { validation: {
type: formulaTypes.NUMERIC, args: {
validation: { rqd: 2,
args: { },
rqd: 1 },
} description: 'Remainder after integer division of input parameters',
}, syntax: 'MOD(value1, value2)',
description: 'Rounded next largest integer value of input parameter', examples: ['MOD(1024, 1000) => 24', 'MOD({column}, 2)'],
syntax: 'CEILING(value)', },
examples: [ REPEAT: {
'CEILING(1.01) => 2', type: formulaTypes.STRING,
'CEILING({column1})' validation: {
] args: {
}, rqd: 2,
FLOOR: { },
type: formulaTypes.NUMERIC, },
validation: { description: 'Specified copies of the input parameter string concatenated together',
args: { syntax: 'REPEAT(str, count)',
rqd: 1 examples: ['REPEAT("A", 5) => "AAAAA"', 'REPEAT({column}, 5)'],
} },
}, LOG: {
description: 'Rounded largest integer less than or equal to input parameter', type: formulaTypes.NUMERIC,
syntax: 'FLOOR(value)', validation: {},
examples: [ description: 'Logarithm of input parameter to the base (default = e) specified',
'FLOOR(3.1415) => 3', syntax: 'LOG([base], value)',
'FLOOR({column1})' examples: ['LOG(2, 1024) => 10', 'LOG(2, {column1})'],
] },
}, EXP: {
ROUND: { type: formulaTypes.NUMERIC,
type: formulaTypes.NUMERIC, validation: {},
validation: { description: 'Exponential value of input parameter (e ^ power)',
args: { syntax: 'EXP(power)',
rqd: 1 examples: ['EXP(1) => 2.718281828459045', 'EXP({column1})'],
} },
}, POWER: {
description: 'Nearest integer to the input parameter', type: formulaTypes.NUMERIC,
syntax: 'ROUND(value)', validation: {
examples: [ args: {
'ROUND(3.1415) => 3', rqd: 2,
'ROUND({column1})' },
] },
}, description: 'base to the exponent power, as in base ^ exponent',
MOD: { syntax: 'POWER(base, exponent)',
type: formulaTypes.NUMERIC, examples: ['POWER(2, 10) => 1024', 'POWER({column1}, 10)'],
validation: { },
args: { SQRT: {
rqd: 2 type: formulaTypes.NUMERIC,
} validation: {
}, args: {
description: 'Remainder after integer division of input parameters', rqd: 1,
syntax: 'MOD(value1, value2)', },
examples: [ },
'MOD(1024, 1000) => 24', description: 'Square root of the input parameter',
'MOD({column}, 2)' syntax: 'SQRT(value)',
] examples: ['SQRT(100) => 10', 'SQRT({column1})'],
}, },
REPEAT: { ABS: {
type: formulaTypes.STRING, type: formulaTypes.NUMERIC,
validation: { validation: {
args: { args: {
rqd: 2 rqd: 1,
} },
}, },
description: 'Specified copies of the input parameter string concatenated together', description: 'Absolute value of the input parameter',
syntax: 'REPEAT(str, count)', syntax: 'ABS(value)',
examples: [ examples: ['ABS({column1})'],
'REPEAT("A", 5) => "AAAAA"', },
'REPEAT({column}, 5)' NOW: {
] type: formulaTypes.DATE,
}, validation: {
LOG: { args: {
type: formulaTypes.NUMERIC, rqd: 0,
validation: {}, },
description: 'Logarithm of input parameter to the base (default = e) specified', },
syntax: 'LOG([base], value)', description: 'Returns the current time and day',
examples: [ syntax: 'NOW()',
'LOG(2, 1024) => 10', examples: ['NOW() => 2022-05-19 17:20:43'],
'LOG(2, {column1})' },
] REPLACE: {
}, type: formulaTypes.STRING,
EXP: { validation: {
type: formulaTypes.NUMERIC, args: {
validation: {}, rqd: 3,
description: 'Exponential value of input parameter (e ^ power)', },
syntax: 'EXP(power)', },
examples: [ description: 'String, after replacing all occurrences of srchStr with rplcStr',
'EXP(1) => 2.718281828459045', syntax: 'REPLACE(str, srchStr, rplcStr)',
'EXP({column1})' examples: ['REPLACE("AABBCC", "AA", "BB") => "BBBBCC"', 'REPLACE({column1}, {column2}, {column3})'],
] },
}, SEARCH: {
POWER: { type: formulaTypes.STRING,
type: formulaTypes.NUMERIC, validation: {
validation: { args: {
args: { rqd: 2,
rqd: 2 },
} },
}, description: 'Index of srchStr specified if found, 0 otherwise',
description: 'base to the exponent power, as in base ^ exponent', syntax: 'SEARCH(str, srchStr)',
syntax: 'POWER(base, exponent)', examples: ['SEARCH("HELLO WORLD", "WORLD") => 7', 'SEARCH({column1}, "abc")'],
examples: [ },
'POWER(2, 10) => 1024', INT: {
'POWER({column1}, 10)' type: formulaTypes.NUMERIC,
] validation: {
}, args: {
SQRT: { rqd: 1,
type: formulaTypes.NUMERIC, },
validation: { },
args: { description: 'Integer value of input parameter',
rqd: 1 syntax: 'INT(value)',
} examples: ['INT(3.1415) => 3', 'INT({column1})'],
}, },
description: 'Square root of the input parameter', RIGHT: {
syntax: 'SQRT(value)', type: formulaTypes.STRING,
examples: [ validation: {
'SQRT(100) => 10', args: {
'SQRT({column1})' rqd: 2,
] },
}, },
ABS: { description: 'n characters from the end of input parameter',
type: formulaTypes.NUMERIC, syntax: 'RIGHT(str, n)',
validation: { examples: ['RIGHT("HELLO WORLD", 5) => WORLD', 'RIGHT({column1}, 3)'],
args: { },
rqd: 1 LEFT: {
} type: formulaTypes.STRING,
}, validation: {
description: 'Absolute value of the input parameter', args: {
syntax: 'ABS(value)', rqd: 2,
examples: [ },
'ABS({column1})' },
] description: 'n characters from the beginning of input parameter',
}, syntax: 'LEFT(str, n)',
NOW: { examples: ['LEFT({column1}, 2)', 'LEFT("ABCD", 2) => "AB"'],
type: formulaTypes.DATE, },
validation: { SUBSTR: {
args: { type: formulaTypes.STRING,
rqd: 0 validation: {
} args: {
}, min: 2,
description: 'Returns the current time and day', max: 3,
syntax: 'NOW()', },
examples: [ },
'NOW() => 2022-05-19 17:20:43' description: 'Substring of length n of input string from the postition specified',
] syntax: ' SUBTR(str, position, [n])',
}, examples: ['SUBSTR("HELLO WORLD", 7) => WORLD', 'SUBSTR("HELLO WORLD", 7, 3) => WOR', 'SUBSTR({column1}, 7, 5)'],
REPLACE: { },
type: formulaTypes.STRING, MID: {
validation: { type: formulaTypes.STRING,
args: { validation: {
rqd: 3 args: {
} rqd: 3,
}, },
description: 'String, after replacing all occurrences of srchStr with rplcStr', },
syntax: 'REPLACE(str, srchStr, rplcStr)', description: 'Alias for SUBSTR',
examples: [ syntax: 'MID(str, position, [count])',
'REPLACE("AABBCC", "AA", "BB") => "BBBBCC"', examples: ['MID("NocoDB", 3, 2) => "co"', 'MID({column1}, 3, 2)'],
'REPLACE({column1}, {column2}, {column3})' },
] IF: {
}, type: formulaTypes.COND_EXP,
SEARCH: { validation: {
type: formulaTypes.STRING, args: {
validation: { min: 2,
args: { max: 3,
rqd: 2 },
} },
}, description: 'SuccessCase if expr evaluates to TRUE, elseCase otherwise',
description: 'Index of srchStr specified if found, 0 otherwise', syntax: 'IF(expr, successCase, elseCase)',
syntax: 'SEARCH(str, srchStr)', examples: ['IF(5 > 1, "YES", "NO") => "YES"', 'IF({column} > 1, "YES", "NO")'],
examples: [ },
'SEARCH("HELLO WORLD", "WORLD") => 7', SWITCH: {
'SEARCH({column1}, "abc")' type: formulaTypes.COND_EXP,
] validation: {
}, args: {
INT: { min: 3,
type: formulaTypes.NUMERIC, },
validation: { },
args: { description: 'Switch case value based on expr output',
rqd: 1 syntax: 'SWITCH(expr, [pattern, value, ..., default])',
} examples: [
}, 'SWITCH(1, 1, "One", 2, "Two", "N/A") => "One""',
description: 'Integer value of input parameter', 'SWITCH(2, 1, "One", 2, "Two", "N/A") => "Two"',
syntax: 'INT(value)', 'SWITCH(3, 1, "One", 2, "Two", "N/A") => "N/A"',
examples: [ 'SWITCH({column1}, 1, "One", 2, "Two", "N/A")',
'INT(3.1415) => 3', ],
'INT({column1})' },
] URL: {
}, type: formulaTypes.STRING,
RIGHT: { validation: {
type: formulaTypes.STRING, args: {
validation: { rqd: 1,
args: { },
rqd: 2 },
} description: 'Convert to a hyperlink if it is a valid URL',
}, syntax: 'URL(str)',
description: 'n characters from the end of input parameter', examples: ['URL("https://github.com/nocodb/nocodb")', 'URL({column1})'],
syntax: 'RIGHT(str, n)', },
examples: [ WEEKDAY: {
'RIGHT("HELLO WORLD", 5) => WORLD', type: formulaTypes.NUMERIC,
'RIGHT({column1}, 3)' validation: {
] args: {
}, min: 1,
LEFT: { max: 2,
type: formulaTypes.STRING, },
validation: { },
args: { description: 'Returns the day of the week as an integer between 0 and 6 inclusive starting from Monday by default',
rqd: 2 syntax: 'WEEKDAY(date, [startDayOfWeek])',
} examples: ['WEEKDAY("2021-06-09")', 'WEEKDAY(NOW(), "sunday")'],
}, },
description: 'n characters from the beginning of input parameter',
syntax: 'LEFT(str, n)',
examples: [
'LEFT({column1}, 2)',
'LEFT("ABCD", 2) => "AB"'
]
},
SUBSTR: {
type: formulaTypes.STRING,
validation: {
args: {
min: 2,
max: 3
}
},
description: 'Substring of length n of input string from the postition specified',
syntax: ' SUBTR(str, position, [n])',
examples: [
'SUBSTR("HELLO WORLD", 7) => WORLD',
'SUBSTR("HELLO WORLD", 7, 3) => WOR',
'SUBSTR({column1}, 7, 5)'
]
},
MID: {
type: formulaTypes.STRING,
validation: {
args: {
rqd: 3
}
},
description: 'Alias for SUBSTR',
syntax: 'MID(str, position, [count])',
examples: [
'MID("NocoDB", 3, 2) => "co"',
'MID({column1}, 3, 2)'
]
},
IF: {
type: formulaTypes.COND_EXP,
validation: {
args: {
min: 2,
max: 3
}
},
description: 'SuccessCase if expr evaluates to TRUE, elseCase otherwise',
syntax: 'IF(expr, successCase, elseCase)',
examples: [
'IF(5 > 1, "YES", "NO") => "YES"',
'IF({column} > 1, "YES", "NO")'
]
},
SWITCH: {
type: formulaTypes.COND_EXP,
validation: {
args: {
min: 3
}
},
description: 'Switch case value based on expr output',
syntax: 'SWITCH(expr, [pattern, value, ..., default])',
examples: [
'SWITCH(1, 1, "One", 2, "Two", "N/A") => "One""',
'SWITCH(2, 1, "One", 2, "Two", "N/A") => "Two"',
'SWITCH(3, 1, "One", 2, "Two", "N/A") => "N/A"',
'SWITCH({column1}, 1, "One", 2, "Two", "N/A")'
]
},
URL: {
type: formulaTypes.STRING,
validation: {
args: {
rqd: 1
}
},
description: 'Convert to a hyperlink if it is a valid URL',
syntax: 'URL(str)',
examples: [
'URL("https://github.com/nocodb/nocodb")',
'URL({column1})'
]
},
WEEKDAY: {
type: formulaTypes.NUMERIC,
validation: {
args: {
min: 1,
max: 2,
}
},
description: 'Returns the day of the week as an integer between 0 and 6 inclusive starting from Monday by default',
syntax: 'WEEKDAY(date, [startDayOfWeek])',
examples: [
'WEEKDAY("2021-06-09")',
'WEEKDAY(NOW(), "sunday")'
]
}
} }
const formulaList = Object.keys(formulas) const formulaList = Object.keys(formulas)
export { formulaList, formulas, formulaTypes } // ref : https://stackoverflow.com/a/11077016
function insertAtCursor(myField: typeof AntInput, myValue: string, len = 0, b = 0) {
// IE support
if (document) {
myField.focus()
const sel = document.createRange() as any
sel.text = myValue
} // MOZILLA and others
else if (myField.selectionStart || myField.selectionStart == '0') {
const startPos = myField.selectionStart
const endPos = myField.selectionEnd
myField.value = myField.value.substring(0, startPos - len) + myValue + myField.value.substring(endPos, myField.value.length)
const pos = +startPos - len + myValue.length - b
// https://stackoverflow.com/a/4302688
if (myField.setSelectionRange) {
myField.focus()
myField.setSelectionRange(pos, pos)
} else if (myField.createTextRange) {
const range = myField.createTextRange()
range.collapse(true)
range.moveEnd('character', pos)
range.moveStart('character', pos)
range.select()
}
} else {
myField.value += myValue
}
return myField.value
}
function ReturnWord(text: string, caretPos: number) {
const preText = text.substring(0, caretPos)
if (preText.indexOf(' ') > 0) {
const words = preText.split(' ')
return words[words.length - 1] // return last word
} else {
return preText
}
}
function getWordUntilCaret(ctrl: typeof AntInput) {
const caretPos = GetCaretPosition(ctrl)
const word = ReturnWord(ctrl.value, caretPos)
return word || ''
}
function GetCaretPosition(ctrl: typeof AntInput) {
let CaretPos = 0 // IE Support
if (document) {
ctrl.focus()
const Sel = document.createRange() as any
Sel.moveStart('character', -ctrl.value.length)
CaretPos = Sel.text.length
}
// Firefox support
else if (ctrl.selectionStart || ctrl.selectionStart == '0') {
CaretPos = ctrl.selectionStart
}
return CaretPos
}
export { formulaList, formulas, formulaTypes, getWordUntilCaret, insertAtCursor }

Loading…
Cancel
Save