mirror of https://github.com/nocodb/nocodb
Wing-Kam Wong
2 years ago
1 changed files with 169 additions and 0 deletions
@ -0,0 +1,169 @@ |
|||||||
|
import { UITypes } from 'nocodb-sdk' |
||||||
|
import { |
||||||
|
extractMultiOrSingleSelectProps, |
||||||
|
getCheckboxValue, |
||||||
|
isCheckboxType, |
||||||
|
isDecimalType, |
||||||
|
isEmailType, |
||||||
|
isMultiLineTextType, |
||||||
|
isUrlType, |
||||||
|
} from './parserHelpers' |
||||||
|
import TemplateGenerator from './TemplateGenerator' |
||||||
|
|
||||||
|
const jsonTypeToUidt: Record<string, string> = { |
||||||
|
number: UITypes.Number, |
||||||
|
string: UITypes.SingleLineText, |
||||||
|
date: UITypes.DateTime, |
||||||
|
boolean: UITypes.Checkbox, |
||||||
|
object: UITypes.JSON, |
||||||
|
} |
||||||
|
|
||||||
|
const extractNestedData: any = (obj: any, path: any) => path.reduce((val: any, key: any) => val && val[key], obj) |
||||||
|
|
||||||
|
export default class JSONTemplateAdapter extends TemplateGenerator { |
||||||
|
config: Record<string, any> |
||||||
|
name: string |
||||||
|
_jsonData: string | object |
||||||
|
project: Record<string, any> |
||||||
|
data: Record<string, any> |
||||||
|
columns: object |
||||||
|
csv: Record<string, any> |
||||||
|
constructor(name = 'test', data: object, parserConfig = {}) { |
||||||
|
super() |
||||||
|
this.config = { |
||||||
|
maxRowsToParse: 500, |
||||||
|
...parserConfig, |
||||||
|
} |
||||||
|
this.name = name |
||||||
|
this._jsonData = typeof data === 'string' ? JSON.parse(data) : data |
||||||
|
this.project = { |
||||||
|
title: this.name, |
||||||
|
tables: [], |
||||||
|
} |
||||||
|
this.columns = {} |
||||||
|
this.data = {} |
||||||
|
this.csv = {} |
||||||
|
} |
||||||
|
|
||||||
|
async init() {} |
||||||
|
|
||||||
|
parseData(): any { |
||||||
|
this.columns = this.csv.meta.fields |
||||||
|
this.data = this.csv.data |
||||||
|
} |
||||||
|
|
||||||
|
getColumns(): any { |
||||||
|
return this.columns |
||||||
|
} |
||||||
|
|
||||||
|
getData(): any { |
||||||
|
return this.data |
||||||
|
} |
||||||
|
|
||||||
|
get jsonData(): any { |
||||||
|
return Array.isArray(this._jsonData) ? this._jsonData : [this._jsonData] |
||||||
|
} |
||||||
|
|
||||||
|
parse(): any { |
||||||
|
const jsonData = this.jsonData |
||||||
|
const tn = 'table' |
||||||
|
const table: any = { table_name: tn, ref_table_name: tn, columns: [] } |
||||||
|
|
||||||
|
this.data[tn] = [] |
||||||
|
|
||||||
|
for (const col of Object.keys(jsonData[0])) { |
||||||
|
const columns = this._parseColumn([col], jsonData) |
||||||
|
table.columns.push(...columns) |
||||||
|
} |
||||||
|
|
||||||
|
if (this.config.importData) { |
||||||
|
this._parseTableData(table) |
||||||
|
} |
||||||
|
|
||||||
|
this.project.tables.push(table) |
||||||
|
} |
||||||
|
|
||||||
|
getTemplate() { |
||||||
|
return this.project |
||||||
|
} |
||||||
|
|
||||||
|
_parseColumn( |
||||||
|
path: any = [], |
||||||
|
jsonData = this.jsonData, |
||||||
|
firstRowVal = path.reduce((val: any, k: any) => val && val[k], this.jsonData[0]), |
||||||
|
): any { |
||||||
|
const columns = [] |
||||||
|
// parse nested
|
||||||
|
if (firstRowVal && typeof firstRowVal === 'object' && !Array.isArray(firstRowVal) && this.config.normalizeNested) { |
||||||
|
for (const key of Object.keys(firstRowVal)) { |
||||||
|
const normalizedNestedColumns = this._parseColumn([...path, key], this.jsonData, firstRowVal[key]) |
||||||
|
columns.push(...normalizedNestedColumns) |
||||||
|
} |
||||||
|
} else { |
||||||
|
const cn = path.join('_').replace(/\W/g, '_').trim() |
||||||
|
|
||||||
|
const column: Record<string, any> = { |
||||||
|
column_name: cn, |
||||||
|
ref_column_name: cn, |
||||||
|
path, |
||||||
|
} |
||||||
|
|
||||||
|
column.uidt = jsonTypeToUidt[typeof firstRowVal] || UITypes.SingleLineText |
||||||
|
|
||||||
|
const colData = jsonData.map((r: any) => extractNestedData(r, path)) |
||||||
|
Object.assign(column, this._getColumnUIDTAndMetas(colData, column.uidt)) |
||||||
|
columns.push(column) |
||||||
|
} |
||||||
|
|
||||||
|
return columns |
||||||
|
} |
||||||
|
|
||||||
|
_getColumnUIDTAndMetas(colData: any, defaultType: any) { |
||||||
|
const colProps = { uidt: defaultType } |
||||||
|
// todo: optimize
|
||||||
|
if (colProps.uidt === UITypes.SingleLineText) { |
||||||
|
// check for long text
|
||||||
|
if (isMultiLineTextType(colData)) { |
||||||
|
colProps.uidt = UITypes.LongText |
||||||
|
} |
||||||
|
if (isEmailType(colData)) { |
||||||
|
colProps.uidt = UITypes.Email |
||||||
|
} |
||||||
|
if (isUrlType(colData)) { |
||||||
|
colProps.uidt = UITypes.URL |
||||||
|
} else { |
||||||
|
const checkboxType = isCheckboxType(colData) |
||||||
|
if (checkboxType.length === 1) { |
||||||
|
colProps.uidt = UITypes.Checkbox |
||||||
|
} else { |
||||||
|
Object.assign(colProps, extractMultiOrSingleSelectProps(colData)) |
||||||
|
} |
||||||
|
} |
||||||
|
} else if (colProps.uidt === UITypes.Number) { |
||||||
|
if (isDecimalType(colData)) { |
||||||
|
colProps.uidt = UITypes.Decimal |
||||||
|
} |
||||||
|
} |
||||||
|
return colProps |
||||||
|
} |
||||||
|
|
||||||
|
_parseTableData(tableMeta: any) { |
||||||
|
for (const row of this.jsonData) { |
||||||
|
const rowData: any = {} |
||||||
|
for (let i = 0; i < tableMeta.columns.length; i++) { |
||||||
|
const value = extractNestedData(row, tableMeta.columns[i].path || []) |
||||||
|
if (tableMeta.columns[i].uidt === UITypes.Checkbox) { |
||||||
|
rowData[tableMeta.columns[i].ref_column_name] = getCheckboxValue(value) |
||||||
|
} else if (tableMeta.columns[i].uidt === UITypes.SingleSelect || tableMeta.columns[i].uidt === UITypes.MultiSelect) { |
||||||
|
rowData[tableMeta.columns[i].ref_column_name] = (value || '').toString().trim() || null |
||||||
|
} else if (tableMeta.columns[i].uidt === UITypes.JSON) { |
||||||
|
rowData[tableMeta.columns[i].ref_column_name] = JSON.stringify(value) |
||||||
|
} else { |
||||||
|
// toto: do parsing if necessary based on type
|
||||||
|
rowData[tableMeta.columns[i].column_name] = value |
||||||
|
} |
||||||
|
} |
||||||
|
this.data[tableMeta.ref_table_name].push(rowData) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue