From b295dd0cb502b96649bf720cce44a622e8f874d8 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Wed, 20 Jul 2022 16:21:06 +0800 Subject: [PATCH] feat(gui-v2): template validation --- .../nc-gui-v2/components/template/Editor.vue | 93 ++++++++++++------- 1 file changed, 58 insertions(+), 35 deletions(-) diff --git a/packages/nc-gui-v2/components/template/Editor.vue b/packages/nc-gui-v2/components/template/Editor.vue index 19787a2e4f..394ef72563 100644 --- a/packages/nc-gui-v2/components/template/Editor.vue +++ b/packages/nc-gui-v2/components/template/Editor.vue @@ -4,6 +4,7 @@ import type { ColumnType } from 'nocodb-sdk' import { isVirtualCol, UITypes } from 'nocodb-sdk' import type { SizeType } from 'ant-design-vue/es/config-provider' import type { FormInstance } from 'ant-design-vue' +import { Form } from 'ant-design-vue' import { computed, onMounted } from '#imports' import MdiTableIcon from '~icons/mdi/table' import MdiStringIcon from '~icons/mdi/alpha-a' @@ -22,11 +23,9 @@ interface Props { interface Option { value: string } - +const useForm = Form.useForm const { quickImportType, projectTemplate, importData } = defineProps() -const formRef = ref() const { $api } = useNuxtApp() -const valid = ref(false) const expansionPanel = ref([]) const editableTn = ref({}) const inputRefs = ref([]) @@ -39,11 +38,6 @@ const templateForm = reactive<{ tables: object[] }>({ tables: [], }) -const formRules = { - columnName: [{ required: true, message: 'Please fill in column name', trigger: 'change' }], - columnType: [{ required: true, message: 'Please fill in column type', trigger: 'change' }], -} - const uiTypeOptions = ref( (Object.keys(UITypes) as Array) .filter( @@ -72,12 +66,12 @@ const tableColumns = [ { name: 'Column Type', dataIndex: 'column_type', - key: 'column_type', + key: 'uidt', width: 250, }, { name: 'Select Option', - key: 'select_option', + key: 'dtxp', }, { name: 'Action', @@ -90,6 +84,27 @@ const data = reactive({ tables: [], }) +const validators = computed(() => { + // TODO: centralise + const cnValidator = [{ required: true, message: 'Please fill in column name', trigger: 'change' }] + const uidtValidator = [{ required: true, message: 'Please fill in column type', trigger: 'change' }] + // TODO: check existing validation logic + const dtxpValidator = [{}] + let res: any = {} + for (let i = 0; i < data.tables.length; i++) { + for (let j = 0; j < data.tables[i].columns.length; j++) { + res[`tables.${i}.columns.${j}.column_name`] = cnValidator + res[`tables.${i}.columns.${j}.uidt`] = uidtValidator + if (isSelect(data.tables[i].columns)) { + res[`tables.${i}.columns.${j}.dtxp`] = dtxpValidator + } + } + } + return res +}) + +const { resetFields, validate, validateInfos } = useForm(data, validators) + const editorTitle = computed(() => { return `${quickImportType.toUpperCase()} Import` }) @@ -101,7 +116,7 @@ onMounted(() => { const parseAndLoadTemplate = () => { if (projectTemplate) { parseTemplate(projectTemplate) - expansionPanel.value = Array.from({ length: data.value?.tables.length || 0 }, (_, i) => i) + expansionPanel.value = Array.from({ length: data.tables.length || 0 }, (_, i) => i) } } @@ -127,18 +142,18 @@ const parseTemplate = ({ tables = [], ...rest }: Record) => { ], })), } - data.value = parsedTemplate + Object.assign(data, parsedTemplate) } const deleteTable = (tableIdx: number) => { - const deleteTable = data.value.tables[tableIdx] - for (const table of data.value.tables) { + const deleteTable = data.tables[tableIdx] + for (const table of data.tables) { if (table === deleteTable) { continue } table.columns = table.columns.filter((c: Record) => c.ref_table_name !== deleteTable.table_name) } - data.value.tables.splice(tableIdx, 1) + data.tables.splice(tableIdx, 1) } const isSelect = (col: ColumnType) => { @@ -146,9 +161,9 @@ const isSelect = (col: ColumnType) => { } const deleteTableColumn = (i: number, j: number, col: Record, table: Record) => { - const deleteTable = data.value.tables[i] + const deleteTable = data.tables[i] const deleteColumn = deleteTable.columns[j] - for (const table of data.value.tables) { + for (const table of data.tables) { if (table === deleteTable) { continue } @@ -191,16 +206,18 @@ const remapColNames = (batchData: any[], columns: ColumnType[]) => { const importTemplate = async () => { // check if form is valid try { - const values = await formRef.value.validateFields() + const values = await validate() console.log('Success:', values) } catch (errorInfo) { + // TODO: handle error message console.log('Failed:', errorInfo) + return } let firstTable = null try { loading.value = true - for (const t of data.value.tables) { + for (const t of data.tables) { // enrich system fields if not provided // e.g. id, created_at, updated_at const systemColumns = sqlUi?.value.getNewTableColumns().filter((c: ColumnType) => c.column_name !== 'title') @@ -220,11 +237,17 @@ const importTemplate = async () => { } // create table - const table = await $api.dbTable.create(project?.value?.id as string, { + const table: TableType = await $api.dbTable.create(project?.value?.id as string, { table_name: t.table_name, title: '', columns: t.columns, }) + // TODO: should catch error msg throw from sdk + if (!table) { + throw { + message: 'Failed to create table', + } + } t.table_title = table.title // open the first table after import @@ -233,10 +256,11 @@ const importTemplate = async () => { } // set primary value - // TODO: handle it later - // await $api.dbTableColumn.primaryColumnSet(table?.columns[0]?.id as string) + await $api.dbTableColumn.primaryColumnSet(table.columns[0].id as string) } } catch (e: any) { + // TODO: retrieve error msg from sdk + console.log(e) toast.error(e.message) return } @@ -261,6 +285,7 @@ const importTemplate = async () => { ), ) } catch (e: any) { + // TODO: retrieve error msg from sdk toast.error(e.message) return } @@ -284,14 +309,13 @@ const importTemplate = async () => { {{ $t('activity.import') }} - +

{{ data.tables.length }} sheet{{ data.tables.length > 1 ? 's' : '' }} available for import

- - {{ data.value }} - + + - + - {{ table }}