From 1e0f6ba908b0e136f3f08523cfdbd9d5795de6eb Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Mon, 18 Jul 2022 20:08:04 +0800 Subject: [PATCH 01/34] wip(gui-v2): template editor draft --- .../nc-gui-v2/components/template/Editor.vue | 420 ++++++++++++++++++ 1 file changed, 420 insertions(+) create mode 100644 packages/nc-gui-v2/components/template/Editor.vue diff --git a/packages/nc-gui-v2/components/template/Editor.vue b/packages/nc-gui-v2/components/template/Editor.vue new file mode 100644 index 0000000000..44a1408947 --- /dev/null +++ b/packages/nc-gui-v2/components/template/Editor.vue @@ -0,0 +1,420 @@ + + + From 562227dbd458a29049f0d8099fe5a8c20050f861 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Tue, 19 Jul 2022 12:28:42 +0800 Subject: [PATCH 02/34] wip(gui-v2): parse and load template --- .../nc-gui-v2/components/template/Editor.vue | 94 +++++++++++++++++-- 1 file changed, 85 insertions(+), 9 deletions(-) diff --git a/packages/nc-gui-v2/components/template/Editor.vue b/packages/nc-gui-v2/components/template/Editor.vue index 44a1408947..bec279f8b6 100644 --- a/packages/nc-gui-v2/components/template/Editor.vue +++ b/packages/nc-gui-v2/components/template/Editor.vue @@ -1,23 +1,98 @@ - - - - - - - - - - + + + + + Column + + + + + + + From bdf6cbbfda7e1b7bcda20a6b404ec703ebd27898 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Tue, 19 Jul 2022 16:33:40 +0800 Subject: [PATCH 04/34] wip(gui-v2): action column --- .../nc-gui-v2/components/template/Editor.vue | 40 +++++++++++++++++-- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/packages/nc-gui-v2/components/template/Editor.vue b/packages/nc-gui-v2/components/template/Editor.vue index be0b5ece0f..161a12872b 100644 --- a/packages/nc-gui-v2/components/template/Editor.vue +++ b/packages/nc-gui-v2/components/template/Editor.vue @@ -9,6 +9,8 @@ import MdiStringIcon from '~icons/mdi/alpha-a' import MdiLongTextIcon from '~icons/mdi/text' import MdiNumericIcon from '~icons/mdi/numeric' import MdiPlusIcon from '~icons/mdi/plus' +import MdiKeyStarIcon from '~icons/mdi/key-star' +import MdiDeleteOutlineIcon from '~icons/mdi/delete-outline' interface Props { quickImportType: string @@ -35,6 +37,10 @@ const tableColumns = [ dataIndex: 'column_type', key: 'column_type', }, + { + name: 'Action', + key: 'action', + }, ] const project = reactive({ @@ -60,7 +66,10 @@ const parseTemplate = ({ tables = [], ...rest }: Record) => { ({ manyToMany = [], hasMany = [], belongsTo = [], v = [], columns = [], ...rest }: Record) => ({ ...rest, columns: [ - ...columns, + ...columns.map((c: any, idx: number) => { + c.key = idx + return c + }), ...manyToMany.map((mm: any) => ({ column_name: mm.title || `${rest.table_name} <=> ${mm.ref_table_name}`, uidt: LinkToAnotherRecord, @@ -212,7 +221,12 @@ const getIcon = (type: string) => { - + -
+
- + - + + - -
+
- From 7d3ff6b2c3cf793597305ba975b8ef3329d8fe63 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Thu, 21 Jul 2022 13:56:31 +0800 Subject: [PATCH 27/34] chore(gui-v2): revise margin --- packages/nc-gui-v2/components/template/Editor.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nc-gui-v2/components/template/Editor.vue b/packages/nc-gui-v2/components/template/Editor.vue index b6d72cd014..98fd5bc49d 100644 --- a/packages/nc-gui-v2/components/template/Editor.vue +++ b/packages/nc-gui-v2/components/template/Editor.vue @@ -326,7 +326,7 @@ const importTemplate = async () => { From 96640b293330c19e6226047fe5ed512a6d50a8f3 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Thu, 21 Jul 2022 16:08:56 +0800 Subject: [PATCH 28/34] feat(gui-v2): add spinning to template editor & clean up --- .../nc-gui-v2/components/template/Editor.vue | 443 +++++++++--------- 1 file changed, 222 insertions(+), 221 deletions(-) diff --git a/packages/nc-gui-v2/components/template/Editor.vue b/packages/nc-gui-v2/components/template/Editor.vue index 98fd5bc49d..1ba9872290 100644 --- a/packages/nc-gui-v2/components/template/Editor.vue +++ b/packages/nc-gui-v2/components/template/Editor.vue @@ -27,38 +27,6 @@ interface Option { const useForm = Form.useForm const { quickImportType, projectTemplate, importData } = defineProps() const { $api } = useNuxtApp() -const hasSelectColumn = ref({}) -const expansionPanel = ref([]) -const editableTn = ref({}) -const inputRefs = ref([]) -const { addTab } = useTabs() -const { sqlUi, project, loadTables } = useProject() -const loading = ref(false) -const toast = useToast() -const buttonSize = ref('large') -const templateForm = reactive<{ tables: object[] }>({ - tables: [], -}) - -const uiTypeOptions = ref( - (Object.keys(UITypes) as Array) - .filter( - (uiType: any) => - !isVirtualCol(uiType) && - ![UITypes.ForeignKey, UITypes.ID, UITypes.CreateTime, UITypes.LastModifiedTime, UITypes.Barcode, UITypes.Button].includes( - uiType, - ), - ) - .map((uiType: string) => ({ - value: uiType, - label: uiType, - })), -) - -const filterOption = (input: string, option: Option) => { - return option.value.toUpperCase().indexOf(input.toUpperCase()) >= 0 -} - const tableColumns = [ { name: 'Column Name', @@ -82,19 +50,48 @@ const tableColumns = [ align: 'right', }, ] - +const templateForm = reactive<{ tables: object[] }>({ + tables: [], +}) +const buttonSize = ref('large') +const hasSelectColumn = ref({}) +const expansionPanel = ref([]) +const editableTn = ref({}) +const inputRefs = ref([]) +const isImporting = ref(false) +const importingTip = ref('Importing') +const uiTypeOptions = ref( + (Object.keys(UITypes) as Array) + .filter( + (uiType: any) => + !isVirtualCol(uiType) && + ![UITypes.ForeignKey, UITypes.ID, UITypes.CreateTime, UITypes.LastModifiedTime, UITypes.Barcode, UITypes.Button].includes( + uiType, + ), + ) + .map((uiType: string) => ({ + value: uiType, + label: uiType, + })), +) const data = reactive({ name: 'Project Name', tables: [], }) +const toast = useToast() +const { addTab } = useTabs() +const { sqlUi, project, loadTables } = useProject() + +onMounted(() => { + parseAndLoadTemplate() +}) + const validators = computed(() => { // TODO: centralise const tnValidator = [{ required: true, message: 'Please fill in table name', trigger: 'change' }] 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 tableIdx = 0; tableIdx < data.tables.length; tableIdx++) { res[`tables.${tableIdx}.table_name`] = tnValidator @@ -104,22 +101,21 @@ const validators = computed(() => { res[`tables.${tableIdx}.columns.${columnIdx}.uidt`] = uidtValidator if (isSelect(data.tables[tableIdx].columns[columnIdx])) { hasSelectColumn.value[tableIdx] = true - res[`tables.${tableIdx}.columns.${columnIdx}.dtxp`] = dtxpValidator } } } return res }) -const { resetFields, validate, validateInfos } = useForm(data, validators) - const editorTitle = computed(() => { return `${quickImportType.toUpperCase()} Import: ${data.title}` }) -onMounted(() => { - parseAndLoadTemplate() -}) +const { resetFields, validate, validateInfos } = useForm(data, validators) + +const filterOption = (input: string, option: Option) => { + return option.value.toUpperCase().indexOf(input.toUpperCase()) >= 0 +} const parseAndLoadTemplate = () => { if (projectTemplate) { @@ -198,12 +194,12 @@ const importTemplate = async () => { await validate() } catch (errorInfo) { toast.error('Please fill all the required values') - loading.value = false + isImporting.value = false return } try { - loading.value = true + isImporting.value = true // tab info to be used to show the tab after successful import const tab = { id: '', @@ -263,6 +259,7 @@ const importTemplate = async () => { if (data) { total += data.length for (let i = 0; i < data.length; i += offset) { + importingTip.value = `Importing data to ${projectName}: ${progress}/${total} records` const batchData = remapColNames(data.slice(i, i + offset), tableMeta.columns) await $api.dbTableRow.bulkCreate('noco', projectName, tableMeta.table_title, batchData) progress += batchData.length @@ -282,202 +279,206 @@ const importTemplate = async () => { toast.error(await extractSdkResponseErrorMsg(e)) } finally { // TODO: close dialog when the integration is ready - loading.value = false + isImporting.value = false } }