Browse Source

feat(nc-gui): optionally import data

pull/4135/head
Wing-Kam Wong 2 years ago
parent
commit
4ad73666f8
  1. 8
      packages/nc-gui/components/dlg/QuickImport.vue
  2. 69
      packages/nc-gui/utils/parsers/CSVTemplateAdapter.ts
  3. 73
      packages/nc-gui/utils/parsers/ExcelTemplateAdapter.ts
  4. 5
      packages/nc-gui/utils/parsers/JSONTemplateAdapter.ts

8
packages/nc-gui/components/dlg/QuickImport.vue

@ -467,16 +467,16 @@ const beforeUpload = (file: UploadFile) => {
</a-form-item>
<!-- Flatten nested -->
<div v-if="isImportTypeJson" class="mt-3">
<a-form-item v-if="isImportTypeJson" class="!my-2">
<a-checkbox v-model:checked="importState.parserConfig.normalizeNested">
<span class="caption">{{ $t('labels.flattenNested') }}</span>
</a-checkbox>
</div>
</a-form-item>
<!-- Import Data -->
<div v-if="isImportTypeJson" class="mt-4">
<a-form-item class="!my-2">
<a-checkbox v-model:checked="importState.parserConfig.importData">{{ $t('labels.importData') }}</a-checkbox>
</div>
</a-form-item>
</div>
</div>
</div>

69
packages/nc-gui/utils/parsers/CSVTemplateAdapter.ts

@ -27,12 +27,7 @@ export default class CSVTemplateAdapter {
columnValues: Record<number, []>
constructor(files: UploadFile[], parserConfig = {}) {
this.config = {
maxRowsToParse: 500,
autoSelectFieldTypes: true,
firstRowAsHeaders: true,
...parserConfig,
}
this.config = parserConfig
this.files = files
this.project = {
tables: [],
@ -258,38 +253,40 @@ export default class CSVTemplateAdapter {
let steppers = 0
const tn = file.name.replace(/[` ~!@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/g, '_').trim()
this.data[tn] = []
parse(file.originFileObj as File, {
worker: true,
step(row) {
steppers += 1
if (row && steppers >= +that.config.firstRowAsHeaders + 1) {
const rowData: Record<string, any> = {}
for (let columnIdx = 0; columnIdx < that.headers[tableIdx].length; columnIdx++) {
const column = that.project.tables[tableIdx].columns[columnIdx]
const data = (row.data as [])[columnIdx] === '' ? null : (row.data as [])[columnIdx]
if (column.uidt === UITypes.Checkbox) {
rowData[column.column_name] = getCheckboxValue(data)
rowData[column.column_name] = data
} else if (column.uidt === UITypes.Currency) {
rowData[column.column_name] = data
} else if (column.uidt === UITypes.SingleSelect || column.uidt === UITypes.MultiSelect) {
rowData[column.column_name] = (data || '').toString().trim() || null
} else if (column.uidt === UITypes.Date) {
// TODO(import): check format
rowData[column.column_name] = data
} else {
// TODO(import): do parsing if necessary based on type
rowData[column.column_name] = data
if (this.config.importData) {
parse(file.originFileObj as File, {
worker: true,
step(row) {
steppers += 1
if (row && steppers >= +that.config.firstRowAsHeaders + 1) {
const rowData: Record<string, any> = {}
for (let columnIdx = 0; columnIdx < that.headers[tableIdx].length; columnIdx++) {
const column = that.project.tables[tableIdx].columns[columnIdx]
const data = (row.data as [])[columnIdx] === '' ? null : (row.data as [])[columnIdx]
if (column.uidt === UITypes.Checkbox) {
rowData[column.column_name] = getCheckboxValue(data)
rowData[column.column_name] = data
} else if (column.uidt === UITypes.Currency) {
rowData[column.column_name] = data
} else if (column.uidt === UITypes.SingleSelect || column.uidt === UITypes.MultiSelect) {
rowData[column.column_name] = (data || '').toString().trim() || null
} else if (column.uidt === UITypes.Date) {
// TODO(import): check format
rowData[column.column_name] = data
} else {
// TODO(import): do parsing if necessary based on type
rowData[column.column_name] = data
}
}
that.data[tn].push(rowData)
}
that.data[tn].push(rowData)
}
},
complete() {
console.log('getData(): complete')
console.log(`getData(): steppers: ${steppers}`)
},
})
},
complete() {
console.log('getData(): complete')
console.log(`getData(): steppers: ${steppers}`)
},
})
}
}
return this.data
}

73
packages/nc-gui/utils/parsers/ExcelTemplateAdapter.ts

@ -18,9 +18,7 @@ const excelTypeToUidt: Record<string, UITypes> = {
}
export default class ExcelTemplateAdapter extends TemplateGenerator {
config: {
maxRowsToParse: number
} & Record<string, any>
config: Record<string, any>
excelData: any
@ -36,17 +34,11 @@ export default class ExcelTemplateAdapter extends TemplateGenerator {
constructor(data = {}, parserConfig = {}) {
super()
this.config = {
maxRowsToParse: 500,
...parserConfig,
}
this.config = parserConfig
this.excelData = data
this.project = {
tables: [],
}
this.xlsx = {} as any
}
@ -79,7 +71,6 @@ export default class ExcelTemplateAdapter extends TemplateGenerator {
tableNamePrefixRef[tn] = 0
const table = { table_name: tn, ref_table_name: tn, columns: [] as any[] }
this.data[tn] = []
const ws: any = this.wb.Sheets[sheet]
const range = this.xlsx.utils.decode_range(ws['!ref'])
let rows: any = this.xlsx.utils.sheet_to_json(ws, { header: 1, blankrows: false, defval: null })
@ -207,39 +198,43 @@ export default class ExcelTemplateAdapter extends TemplateGenerator {
}
table.columns.push(column)
}
this.project.tables.push(table)
let rowIndex = 0
for (const row of rows.slice(1)) {
const rowData: Record<string, any> = {}
for (let i = 0; i < table.columns.length; i++) {
if (table.columns[i].uidt === UITypes.Checkbox) {
rowData[table.columns[i].column_name] = getCheckboxValue(row[i])
} else if (table.columns[i].uidt === UITypes.Currency) {
const cellId = this.xlsx.utils.encode_cell({
c: range.s.c + i,
r: rowIndex + columnNameRowExist,
})
this.data[tn] = []
if (this.config.importData) {
let rowIndex = 0
for (const row of rows.slice(1)) {
const rowData: Record<string, any> = {}
for (let i = 0; i < table.columns.length; i++) {
if (table.columns[i].uidt === UITypes.Checkbox) {
rowData[table.columns[i].column_name] = getCheckboxValue(row[i])
} else if (table.columns[i].uidt === UITypes.Currency) {
const cellId = this.xlsx.utils.encode_cell({
c: range.s.c + i,
r: rowIndex + columnNameRowExist,
})
const cellObj = ws[cellId]
rowData[table.columns[i].column_name] = (cellObj && cellObj.w && cellObj.w.replace(/[^\d.]+/g, '')) || row[i]
} else if (table.columns[i].uidt === UITypes.SingleSelect || table.columns[i].uidt === UITypes.MultiSelect) {
rowData[table.columns[i].column_name] = (row[i] || '').toString().trim() || null
} else if (table.columns[i].uidt === UITypes.Date) {
const cellId = this.xlsx.utils.encode_cell({
c: range.s.c + i,
r: rowIndex + columnNameRowExist,
})
const cellObj = ws[cellId]
rowData[table.columns[i].column_name] = (cellObj && cellObj.w) || row[i]
} else {
// toto: do parsing if necessary based on type
rowData[table.columns[i].column_name] = row[i]
const cellObj = ws[cellId]
rowData[table.columns[i].column_name] = (cellObj && cellObj.w && cellObj.w.replace(/[^\d.]+/g, '')) || row[i]
} else if (table.columns[i].uidt === UITypes.SingleSelect || table.columns[i].uidt === UITypes.MultiSelect) {
rowData[table.columns[i].column_name] = (row[i] || '').toString().trim() || null
} else if (table.columns[i].uidt === UITypes.Date) {
const cellId = this.xlsx.utils.encode_cell({
c: range.s.c + i,
r: rowIndex + columnNameRowExist,
})
const cellObj = ws[cellId]
rowData[table.columns[i].column_name] = (cellObj && cellObj.w) || row[i]
} else {
// toto: do parsing if necessary based on type
rowData[table.columns[i].column_name] = row[i]
}
}
this.data[tn].push(rowData)
rowIndex++
}
this.data[tn].push(rowData)
rowIndex++
}
this.project.tables.push(table)
resolve(true)
}),
)

5
packages/nc-gui/utils/parsers/JSONTemplateAdapter.ts

@ -24,10 +24,7 @@ export default class JSONTemplateAdapter extends TemplateGenerator {
columns: object
constructor(data: object, parserConfig = {}) {
super()
this.config = {
maxRowsToParse: 500,
...parserConfig,
}
this.config = parserConfig
this._jsonData = data
this.project = {
tables: [],

Loading…
Cancel
Save