Browse Source

refactor: show unsupported formula functions as disabled

pull/8516/head
Pranav C 6 months ago
parent
commit
36b2e203b5
  1. 66
      packages/nc-gui/components/smartsheet/column/FormulaOptions.vue
  2. 1
      packages/nc-gui/lang/en.json
  3. 11
      packages/nocodb-sdk/src/lib/formulaHelpers.ts

66
packages/nc-gui/components/smartsheet/column/FormulaOptions.vue

@ -102,36 +102,47 @@ const sortOrder: Record<string, number> = {
const suggestionsList = computed(() => { const suggestionsList = computed(() => {
const unsupportedFnList = sqlUi.value.getUnsupportedFnList() const unsupportedFnList = sqlUi.value.getUnsupportedFnList()
return [ return (
...availableFunctions [
.filter((fn: string) => !unsupportedFnList.includes(fn)) ...availableFunctions.map((fn: string) => ({
.map((fn: string) => ({
text: `${fn}()`, text: `${fn}()`,
type: 'function', type: 'function',
description: formulas[fn].description, description: formulas[fn].description,
syntax: formulas[fn].syntax, syntax: formulas[fn].syntax,
examples: formulas[fn].examples, examples: formulas[fn].examples,
docsUrl: formulas[fn].docsUrl, docsUrl: formulas[fn].docsUrl,
unsupported: unsupportedFnList.includes(fn),
})), })),
...supportedColumns.value ...supportedColumns.value
.filter((c) => { .filter((c) => {
// skip system LTAR columns // skip system LTAR columns
if (c.uidt === UITypes.LinkToAnotherRecord && c.system) return false if (c.uidt === UITypes.LinkToAnotherRecord && c.system) return false
// v1 logic? skip the current column // v1 logic? skip the current column
if (!column) return true if (!column) return true
return column.value?.id !== c.id return column.value?.id !== c.id
}) })
.map((c: any) => ({ .map((c: any) => ({
text: c.title, text: c.title,
type: 'column', type: 'column',
icon: getUIDTIcon(c.uidt), icon: getUIDTIcon(c.uidt),
uidt: c.uidt, uidt: c.uidt,
})),
...availableBinOps.map((op: string) => ({
text: op,
type: 'op',
})), })),
...availableBinOps.map((op: string) => ({ ]
text: op, // move unsupported functions to the end
type: 'op', .sort((a: Record<string, any>, b: Record<string, any>) => {
})), if (a.unsupported && !b.unsupported) {
] return 1
}
if (!a.unsupported && b.unsupported) {
return -1
}
return 0
})
)
}) })
// set default suggestion list // set default suggestion list
@ -214,6 +225,7 @@ function handleInput() {
function selectText() { function selectText() {
if (suggestion.value && selected.value > -1 && selected.value < suggestionsList.value.length) { if (suggestion.value && selected.value > -1 && selected.value < suggestionsList.value.length) {
if (selected.value < suggestedFormulas.value.length) { if (selected.value < suggestedFormulas.value.length) {
if (suggestedFormulas.value[selected.value].unsupported) return
appendText(suggestedFormulas.value[selected.value]) appendText(suggestedFormulas.value[selected.value])
} else { } else {
appendText(variableList.value[selected.value + suggestedFormulas.value.length]) appendText(variableList.value[selected.value + suggestedFormulas.value.length])
@ -276,7 +288,7 @@ onMounted(() => {
<template> <template>
<div class="formula-wrapper relative"> <div class="formula-wrapper relative">
<div <div
v-if="suggestionPreviewed && suggestionPreviewed.type === 'function'" v-if="suggestionPreviewed && !suggestionPreviewed.unsupported && suggestionPreviewed.type === 'function'"
class="absolute -left-91 w-84 top-0 bg-white z-10 pl-3 pt-3 border-1 shadow-md rounded-xl" class="absolute -left-91 w-84 top-0 bg-white z-10 pl-3 pt-3 border-1 shadow-md rounded-xl"
> >
<div class="pr-3"> <div class="pr-3">
@ -357,20 +369,22 @@ onMounted(() => {
class="cursor-pointer !overflow-hidden hover:bg-gray-50" class="cursor-pointer !overflow-hidden hover:bg-gray-50"
:class="{ :class="{
'!bg-gray-100': selected === index, '!bg-gray-100': selected === index,
'cursor-not-allowed': item.unsupported,
}" }"
@click.prevent.stop="appendText(item)" @click.prevent.stop="!item.unsupported && appendText(item)"
@mouseenter="suggestionPreviewed = item" @mouseenter="suggestionPreviewed = item"
> >
<a-list-item-meta> <a-list-item-meta>
<template #title> <template #title>
<div class="flex items-center gap-x-1"> <div class="flex items-center gap-x-1" :class="{ 'text-gray-400': item.unsupported }">
<component :is="iconMap.function" v-if="item.type === 'function'" class="text-lg" /> <component :is="iconMap.function" v-if="item.type === 'function'" class="text-lg" />
<component :is="iconMap.calculator" v-if="item.type === 'op'" class="text-lg" /> <component :is="iconMap.calculator" v-if="item.type === 'op'" class="text-lg" />
<component :is="item.icon" v-if="item.type === 'column'" class="text-lg" /> <component :is="item.icon" v-if="item.type === 'column'" class="text-lg" />
<span class="prose-sm text-gray-600">{{ item.text }}</span> <span class="prose-sm" :class="{ 'text-gray-600': !item.unsupported }">{{ item.text }}</span>
</div> </div>
<div v-if="item.unsupported" class="ml-5 text-gray-400 text-xs">{{ $t('msg.formulaNotSupported') }}</div>
</template> </template>
</a-list-item-meta> </a-list-item-meta>
</a-list-item> </a-list-item>

1
packages/nc-gui/lang/en.json

@ -1101,6 +1101,7 @@
"searchOptions": "Search options" "searchOptions": "Search options"
}, },
"msg": { "msg": {
"formulaNotSupported": "This function is unavailable for your database",
"controlOrgAppearance": "Control your organisations name and appearance.", "controlOrgAppearance": "Control your organisations name and appearance.",
"addCompanyDomains": "Add company domains to restrict access to unwanted users.", "addCompanyDomains": "Add company domains to restrict access to unwanted users.",
"restrictUsersFromSharing": "Restrict users from being able to share bases publicly.", "restrictUsersFromSharing": "Restrict users from being able to share bases publicly.",

11
packages/nocodb-sdk/src/lib/formulaHelpers.ts

@ -1631,15 +1631,18 @@ export async function validateFormulaAndExtractTreeWithType({
if (parsedTree.type === JSEPNode.CALL_EXP) { if (parsedTree.type === JSEPNode.CALL_EXP) {
const calleeName = parsedTree.callee.name.toUpperCase(); const calleeName = parsedTree.callee.name.toUpperCase();
// validate function name // validate function name
if ( if (!formulas[calleeName]) {
!formulas[calleeName] ||
sqlUI?.getUnsupportedFnList().includes(calleeName)
) {
throw new FormulaError( throw new FormulaError(
FormulaErrorType.INVALID_FUNCTION_NAME, FormulaErrorType.INVALID_FUNCTION_NAME,
{}, {},
`Function ${calleeName} is not available` `Function ${calleeName} is not available`
); );
} else if (sqlUI?.getUnsupportedFnList().includes(calleeName)) {
throw new FormulaError(
FormulaErrorType.INVALID_FUNCTION_NAME,
{},
`Function ${calleeName} is unavailable for your database`
);
} }
// validate arguments // validate arguments

Loading…
Cancel
Save