From 58e70afaacc5896724efdc3dcbabe147d7641efb Mon Sep 17 00:00:00 2001 From: Raju Udava <86527202+dstala@users.noreply.github.com> Date: Wed, 12 Jun 2024 15:17:29 +0530 Subject: [PATCH] Nc feat/type conversions rebased (#8680) * feat: created inferTypes.ts * chore: switch to sdk types * feat: convert string to given type * feat: convert string to rating * fix: handle the case with multiple . * feat: numeric decimal type conversion in postgres * feat: add cast for non text fields * refactor: move type casts to separate file * feat: add casts for date, date-time and time * doc: added function docs * feat: added cast for year and rating * feat: added cast for duration * fix: cast for multi-select * fix: cast for multi-select * fix: cast for year * feat: date conversion on best effort basis * fix: single line text to select * fix: any field to select * lint: simplified expressions * fix: user conversion * fix: user conversion * fix: date time conversion * test: added test cases for type casts * fix: SLT to User field * fix: SLT to Long text, single select and multiselect * chore: handle True/False & TRUE/FALSE in checkbox * lint: fixed eslint issues * chore: remove system fields as destination type when converting a field * feat: show warning when changing column type * fix: toned down edit modal * test: click on update button during warning popup * test: update selector * test: fix type change flag * fix: handle date format * chore: auto focus update button * fix: parameterize columnName and other values * chore: removed number of digits limit for hour * test: fix add-edit modal label * fix: fixed missing column reference * fix: handle missing date format * fix: handle missing date format * test: fix save routine mux * test: fix barCode & QRCode save * refactor: combined uiType filters * fix: sanitise column name * refactor: switch to some instead of find * feat: created inferTypes.ts * chore: switch to sdk types * feat: convert string to given type * feat: numeric decimal type conversion in postgres * feat: add cast for non text fields * refactor: move type casts to separate file * feat: add casts for date, date-time and time * doc: added function docs * feat: added cast for year and rating * feat: added cast for duration * fix: cast for multi-select * fix: cast for multi-select * fix: cast for year * feat: date conversion on best effort basis * fix: single line text to select * fix: user conversion * fix: date time conversion * fix: SLT to User field * fix: SLT to Long text, single select and multiselect * chore: handle True/False & TRUE/FALSE in checkbox * lint: fixed eslint issues * feat: show warning when changing column type * fix: toned down edit modal * test: click on update button during warning popup * fix: handle date format * chore: auto focus update button * fix: parameterize columnName and other values * chore: removed number of digits limit for hour * fix: handle missing date format * fix: handle missing date format * test: fix save routine mux * fix: revert removing verify * fix: sanitise column name * fix: pass context * tests: remove duplicate statement * fix: add context bypass for list method * fix: disable type conversion for Formula, BarCode, QrCode * fix: render confirm modal sing useDialog to avoid accidental closing * refactor: construct context using column while getting colOptions data --------- Co-authored-by: rohittp Co-authored-by: Pranav C --- .../components/dlg/ColumnUpdateConfirm.vue | 46 ++++ .../smartsheet/column/EditOrAdd.vue | 54 ++++- packages/nc-gui/helpers/typeConvertion.ts | 72 ++++++ .../controllers/columns.controller.spec.ts | 2 +- .../src/db/sql-client/lib/pg/PgClient.ts | 43 +++- .../src/db/sql-client/lib/pg/constants.ts | 79 ++++++ .../src/db/sql-client/lib/pg/pg.queries.ts | 12 + .../src/db/sql-client/lib/pg/typeCast.ts | 227 ++++++++++++++++++ packages/nocodb/src/models/Column.ts | 8 +- .../nocodb/src/services/columns.service.ts | 166 ++++--------- .../src/utils/cloud/populateCloudPlugins.ts | 18 +- packages/nocodb/tests/unit/rest/index.test.ts | 2 + .../tests/unit/rest/tests/typeCasts.test.ts | 133 ++++++++++ .../pages/Dashboard/Grid/Column/index.ts | 34 ++- .../tests/db/columns/columnUserSelect.spec.ts | 4 +- .../db/general/tableColumnOperation.spec.ts | 2 +- .../tests/db/views/viewCalendar.spec.ts | 2 +- .../tests/db/views/viewKanban.spec.ts | 2 +- 18 files changed, 753 insertions(+), 153 deletions(-) create mode 100644 packages/nc-gui/components/dlg/ColumnUpdateConfirm.vue create mode 100644 packages/nc-gui/helpers/typeConvertion.ts create mode 100644 packages/nocodb/src/db/sql-client/lib/pg/constants.ts create mode 100644 packages/nocodb/src/db/sql-client/lib/pg/typeCast.ts create mode 100644 packages/nocodb/tests/unit/rest/tests/typeCasts.test.ts diff --git a/packages/nc-gui/components/dlg/ColumnUpdateConfirm.vue b/packages/nc-gui/components/dlg/ColumnUpdateConfirm.vue new file mode 100644 index 0000000000..5ed4bdd73b --- /dev/null +++ b/packages/nc-gui/components/dlg/ColumnUpdateConfirm.vue @@ -0,0 +1,46 @@ + + + diff --git a/packages/nc-gui/components/smartsheet/column/EditOrAdd.vue b/packages/nc-gui/components/smartsheet/column/EditOrAdd.vue index d0d3410a07..62a70cf686 100644 --- a/packages/nc-gui/components/smartsheet/column/EditOrAdd.vue +++ b/packages/nc-gui/components/smartsheet/column/EditOrAdd.vue @@ -2,6 +2,7 @@ import type { ColumnReqType, ColumnType } from 'nocodb-sdk' import { UITypes, UITypesName, isLinksOrLTAR, isSelfReferencingTableColumn, isSystemColumn, isVirtualCol } from 'nocodb-sdk' +import Icon from '../header/Icon.vue' import MdiPlusIcon from '~icons/mdi/plus-circle-outline' import MdiMinusIcon from '~icons/mdi/minus-circle-outline' import MdiIdentifierIcon from '~icons/mdi/identifier' @@ -25,7 +26,6 @@ const emit = defineEmits(['submit', 'cancel', 'mounted', 'add', 'update']) const { formState, - column, generateNewColumnMeta, addOrUpdate, onAlter, @@ -33,6 +33,7 @@ const { validateInfos, isEdit, disableSubmitBtn, + column, } = useColumnCreateStoreOrThrow() const { getMeta } = useMetas() @@ -95,6 +96,9 @@ const onlyNameUpdateOnEditColumns = [ UITypes.LastModifiedTime, UITypes.CreatedBy, UITypes.LastModifiedBy, + UITypes.Formula, + UITypes.QrCode, + UITypes.Barcode, ] // To close column type dropdown on escape and @@ -109,16 +113,20 @@ const geoDataToggleCondition = (t: { name: UITypes }) => { const showDeprecated = ref(false) +const isSystemField = (t: { name: UITypes }) => + [UITypes.CreatedBy, UITypes.CreatedTime, UITypes.LastModifiedBy, UITypes.LastModifiedTime].includes(t.name) + +const uiFilters = (t: { name: UITypes; virtual?: number }) => { + const systemFiledNotEdited = !isSystemField(t) || formState.value.uidt === t.name || !isEdit.value + const geoDataToggle = geoDataToggleCondition(t) && (!isEdit.value || !t.virtual || t.name === formState.value.uidt) + const specificDBType = t.name === UITypes.SpecificDBType && isXcdbBase(meta.value?.source_id) + + return systemFiledNotEdited && geoDataToggle && !specificDBType +} + const uiTypesOptions = computed(() => { return [ - ...uiTypes - .filter( - (t) => - geoDataToggleCondition(t) && - (!isEdit.value || !t.virtual || t.name === formState.value.uidt) && - (!t.deprecated || showDeprecated.value), - ) - .filter((t) => !(t.name === UITypes.SpecificDBType && isXcdbBase(meta.value?.source_id))), + ...uiTypes.filter(uiFilters), ...(!isEdit.value && meta?.value?.columns?.every((c) => !c.pk) ? [ { @@ -146,7 +154,9 @@ const reloadMetaAndData = async () => { const saving = ref(false) -async function onSubmit() { +const warningVisible = ref(false) + +const saveSubmitted = async () => { if (readOnly.value) return saving.value = true @@ -166,6 +176,25 @@ async function onSubmit() { } } +async function onSubmit() { + if (readOnly.value) return + + // Show warning message if user tries to change type of column + if (isEdit.value && formState.value.uidt !== column.value?.uidt) { + warningVisible.value = true + + const { close } = useDialog(resolveComponent('DlgColumnUpdateConfirm'), { + 'visible': warningVisible, + 'onUpdate:visible': (value) => (warningVisible.value = value), + 'saving': saving, + 'onSubmit': async () => { + close() + await saveSubmitted() + }, + }) + } else await saveSubmitted() +} + // focus and select the column name field const antInput = ref() watchEffect(() => { @@ -294,6 +323,7 @@ const filterOption = (input: string, option: { value: UITypes }) => {