From b9a15f2c517a6115daceebad3e66d002d28f9ae4 Mon Sep 17 00:00:00 2001 From: Anbarasu Date: Wed, 24 Jul 2024 21:26:06 +0530 Subject: [PATCH] feat: formula formatting support (#9048) * feat: numeric formula formatting support * feat: support url, email and phone feat: add datetime supports feat: add checkbox support * fix: clean up * fix: handle invalid source, fix: handle plain cell chore: translations * fix: update the datatype when formula changes * fix: formula fixes * fix: tab ui * fix: pr review changes --- .../smartsheet/FormulaWrapperCell.vue | 82 ++++ .../components/smartsheet/PlainCell.vue | 7 + .../smartsheet/column/FormulaOptions.vue | 377 +++++++++++++----- .../components/virtual-cell/Formula.vue | 11 +- packages/nc-gui/lang/en.json | 3 + packages/nocodb-sdk/src/lib/UITypes.ts | 23 ++ packages/nocodb-sdk/src/lib/index.ts | 3 +- 7 files changed, 405 insertions(+), 101 deletions(-) create mode 100644 packages/nc-gui/components/smartsheet/FormulaWrapperCell.vue diff --git a/packages/nc-gui/components/smartsheet/FormulaWrapperCell.vue b/packages/nc-gui/components/smartsheet/FormulaWrapperCell.vue new file mode 100644 index 0000000000..002d801ed9 --- /dev/null +++ b/packages/nc-gui/components/smartsheet/FormulaWrapperCell.vue @@ -0,0 +1,82 @@ + + + + + diff --git a/packages/nc-gui/components/smartsheet/PlainCell.vue b/packages/nc-gui/components/smartsheet/PlainCell.vue index c0355832fb..df60ad95ae 100644 --- a/packages/nc-gui/components/smartsheet/PlainCell.vue +++ b/packages/nc-gui/components/smartsheet/PlainCell.vue @@ -339,6 +339,13 @@ const parseValue = (value: any, col: ColumnType): string => { return getLinksValue(value, col) } + if (isFormula(col) && col?.meta?.display_type) { + return parseValue(value, { + uidt: col?.meta?.display_type, + ...col?.meta?.display_column_meta, + }) + } + return value as unknown as string } diff --git a/packages/nc-gui/components/smartsheet/column/FormulaOptions.vue b/packages/nc-gui/components/smartsheet/column/FormulaOptions.vue index d7971b5a23..6449a76d91 100644 --- a/packages/nc-gui/components/smartsheet/column/FormulaOptions.vue +++ b/packages/nc-gui/components/smartsheet/column/FormulaOptions.vue @@ -3,9 +3,12 @@ import type { Ref } from 'vue' import type { ListItem as AntListItem } from 'ant-design-vue' import jsep from 'jsep' import { + FormulaDataTypes, FormulaError, UITypes, + getUITypesForFormulaDataType, isHiddenCol, + isVirtualCol, jsepCurlyHook, substituteColumnIdWithAliasInFormula, validateFormulaAndExtractTreeWithType, @@ -30,6 +33,8 @@ const { predictFunction: _predictFunction } = useNocoEe() const meta = inject(MetaInj, ref()) +const { base: activeBase } = storeToRefs(useBase()) + const supportedColumns = computed( () => meta?.value?.columns?.filter((col) => { @@ -279,6 +284,25 @@ if ((column.value?.colOptions as any)?.formula_raw) { ) || '' } +const source = computed(() => activeBase.value?.sources?.find((s) => s.id === meta.value?.source_id)) + +const parsedTree = computedAsync(async () => { + try { + const parsed = await validateFormulaAndExtractTreeWithType({ + formula: vModel.value.formula || vModel.value.formula_raw, + columns: meta.value?.columns || [], + column: column.value ?? undefined, + clientOrSqlUi: source.value?.type as any, + getMeta: async (modelId) => await getMeta(modelId), + }) + return parsed + } catch (e) { + return { + dataType: FormulaDataTypes.UNKNOWN, + } + } +}) + // set additional validations setAdditionalValidations({ ...validators, @@ -332,12 +356,65 @@ const handleKeydown = (e: KeyboardEvent) => { } } } + +const activeKey = ref('formula') + +const supportedFormulaAlias = computed(() => { + if (!parsedTree.value?.dataType) return [] + try { + return getUITypesForFormulaDataType(parsedTree.value?.dataType as FormulaDataTypes).map((uidt) => { + return { + value: uidt, + label: t(`datatype.${uidt}`), + icon: h( + isVirtualCol(uidt) ? resolveComponent('SmartsheetHeaderVirtualCellIcon') : resolveComponent('SmartsheetHeaderCellIcon'), + { + columnMeta: { + uidt, + }, + }, + ), + } + }) + } catch (e) { + return [] + } +}) + +watch( + () => vModel.value.meta?.display_type, + (value, oldValue) => { + if (oldValue === undefined && !value) { + vModel.value.meta.display_column_meta = { + meta: {}, + custom: {}, + } + } + }, + { + immediate: true, + }, +) + +watch(parsedTree, (value, oldValue) => { + if (oldValue === undefined && value) { + return + } + if (value?.dataType !== oldValue?.dataType) { + vModel.value.meta.display_type = null + } +})