From 15024005d075ffcf078a689d788cb2464d70e35e Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Mon, 17 Oct 2022 16:03:27 +0800 Subject: [PATCH] refactor(nc-gui): use parserhelpers functions for import --- .../utils/parsers/ExcelTemplateAdapter.ts | 73 +++++-------------- .../utils/parsers/JSONTemplateAdapter.ts | 41 +---------- .../nc-gui/utils/parsers/parserHelpers.ts | 70 ++++++++++++++++-- 3 files changed, 83 insertions(+), 101 deletions(-) diff --git a/packages/nc-gui/utils/parsers/ExcelTemplateAdapter.ts b/packages/nc-gui/utils/parsers/ExcelTemplateAdapter.ts index 32e361b6b5..93d252867a 100644 --- a/packages/nc-gui/utils/parsers/ExcelTemplateAdapter.ts +++ b/packages/nc-gui/utils/parsers/ExcelTemplateAdapter.ts @@ -1,6 +1,13 @@ import { UITypes } from 'nocodb-sdk' import TemplateGenerator from './TemplateGenerator' -import { getCheckboxValue, isCheckboxType } from './parserHelpers' +import { + extractMultiOrSingleSelectProps, + getCheckboxValue, + isCheckboxType, + isEmailType, + isMultiLineTextType, + isUrlType, +} from './parserHelpers' import { getDateFormat } from '~/utils' const excelTypeToUidt: Record = { @@ -73,9 +80,6 @@ export default class ExcelTemplateAdapter extends TemplateGenerator { parse() { const tableNamePrefixRef: Record = {} - // TODO: find the upper bound / make it configurable - const maxSelectOptionsAllowed = 64 - for (let i = 0; i < this.wb.SheetNames.length; i++) { const columnNamePrefixRef: Record = { id: 0 } const sheet: any = this.wb.SheetNames[i] @@ -133,7 +137,6 @@ export default class ExcelTemplateAdapter extends TemplateGenerator { meta: {}, } - // const cellId = `${col.toString(26).split('').map(s => (parseInt(s, 26) + 10).toString(36).toUpperCase())}2`; const cellId = this.xlsx.utils.encode_cell({ c: range.s.c + col, r: columnNameRowExist, @@ -141,11 +144,18 @@ export default class ExcelTemplateAdapter extends TemplateGenerator { const cellProps = ws[cellId] || {} column.uidt = excelTypeToUidt[cellProps.t] || UITypes.SingleLineText - // todo: optimize if (column.uidt === UITypes.SingleLineText) { // check for long text - if (rows.some((r: any) => (r[col] || '').toString().match(/[\r\n]/) || (r[col] || '').toString().length > 255)) { + if (isMultiLineTextType(rows)) { column.uidt = UITypes.LongText + } + + if (isEmailType(rows)) { + column.uidt = UITypes.Email + } + + if (isUrlType(rows)) { + column.uidt = UITypes.URL } else { const vals = rows .slice(columnNameRowExist ? 1 : 0) @@ -156,53 +166,8 @@ export default class ExcelTemplateAdapter extends TemplateGenerator { if (checkboxType.length === 1) { column.uidt = UITypes.Checkbox } else { - if (vals.some((v: any) => v && v.toString().includes(','))) { - const flattenedVals = vals.flatMap((v: any) => - v - ? v - .toString() - .trim() - .split(/\s*,\s*/) - : [], - ) - - // TODO: handle case sensitive case - const uniqueVals = [...new Set(flattenedVals.map((v: any) => v.toString().trim().toLowerCase()))] - - if (uniqueVals.length > maxSelectOptionsAllowed) { - // too many options are detected, convert the column to SingleLineText instead - column.uidt = UITypes.SingleLineText - // _disableSelect is used to disable the in TemplateEditor - column._disableSelect = true - } else { - // assume the column type is multiple select if there are repeated values - if (flattenedVals.length > uniqueVals.length && uniqueVals.length <= Math.ceil(flattenedVals.length / 2)) { - column.uidt = UITypes.MultiSelect - } - // set dtxp here so that users can have the options even they switch the type from other types to MultiSelect - // once it's set, dtxp needs to be reset if the final column type is not MultiSelect - column.dtxp = `'${uniqueVals.join("','")}'` - } - } else { - // TODO: handle case sensitive case - const uniqueVals = [...new Set(vals.map((v: any) => v.toString().trim().toLowerCase()))] - - if (uniqueVals.length > maxSelectOptionsAllowed) { - // too many options are detected, convert the column to SingleLineText instead - column.uidt = UITypes.SingleLineText - // _disableSelect is used to disable the in TemplateEditor - column._disableSelect = true - } else { - // assume the column type is single select if there are repeated values - // once it's set, dtxp needs to be reset if the final column type is not Single Select - if (vals.length > uniqueVals.length && uniqueVals.length <= Math.ceil(vals.length / 2)) { - column.uidt = UITypes.SingleSelect - } - // set dtxp here so that users can have the options even they switch the type from other types to SingleSelect - // once it's set, dtxp needs to be reset if the final column type is not SingleSelect - column.dtxp = `'${uniqueVals.join("','")}'` - } - } + // Single Select / Multi Select + Object.assign(column, extractMultiOrSingleSelectProps(vals)) } } } else if (column.uidt === UITypes.Number) { diff --git a/packages/nc-gui/utils/parsers/JSONTemplateAdapter.ts b/packages/nc-gui/utils/parsers/JSONTemplateAdapter.ts index 91a8a62791..56812c6533 100644 --- a/packages/nc-gui/utils/parsers/JSONTemplateAdapter.ts +++ b/packages/nc-gui/utils/parsers/JSONTemplateAdapter.ts @@ -1,13 +1,5 @@ import { UITypes } from 'nocodb-sdk' -import { - extractMultiOrSingleSelectProps, - getCheckboxValue, - isCheckboxType, - isDecimalType, - isEmailType, - isMultiLineTextType, - isUrlType, -} from './parserHelpers' +import { getCheckboxValue, getColumnUIDTAndMetas } from './parserHelpers' import TemplateGenerator from './TemplateGenerator' const jsonTypeToUidt: Record = { @@ -110,42 +102,13 @@ export default class JSONTemplateAdapter extends TemplateGenerator { column.uidt = jsonTypeToUidt[typeof firstRowVal] || UITypes.SingleLineText const colData = jsonData.map((r: any) => extractNestedData(r, path)) - Object.assign(column, this._getColumnUIDTAndMetas(colData, column.uidt)) + Object.assign(column, 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 as any) { const rowData: any = {} diff --git a/packages/nc-gui/utils/parsers/parserHelpers.ts b/packages/nc-gui/utils/parsers/parserHelpers.ts index 639e641d54..ce07e8494d 100644 --- a/packages/nc-gui/utils/parsers/parserHelpers.ts +++ b/packages/nc-gui/utils/parsers/parserHelpers.ts @@ -40,6 +40,7 @@ export const isCheckboxType: any = (values: [], col = null) => { } return options } + export const getCheckboxValue = (value: number) => { return value && aggBooleanOptions[value] } @@ -51,6 +52,7 @@ export const isMultiLineTextType = (values: [], col = null) => { } export const extractMultiOrSingleSelectProps = (colData: []) => { + const maxSelectOptionsAllowed = 64 const colProps: any = {} if (colData.some((v: any) => v && (v || '').toString().includes(','))) { let flattenedVals = colData.flatMap((v: any) => @@ -64,20 +66,40 @@ export const extractMultiOrSingleSelectProps = (colData: []) => { const uniqueVals = (flattenedVals = flattenedVals.filter( (v, i, arr) => i === arr.findIndex((v1) => v.toLowerCase() === v1.toLowerCase()), )) - if (flattenedVals.length > uniqueVals.length && uniqueVals.length <= Math.ceil(flattenedVals.length / 2)) { - colProps.uidt = UITypes.MultiSelect + if (uniqueVals.length > maxSelectOptionsAllowed) { + // too many options are detected, convert the column to SingleLineText instead + colProps.uidt = UITypes.SingleLineText + // _disableSelect is used to disable the in TemplateEditor + colProps._disableSelect = true + } else { + // assume the column type is multiple select if there are repeated values + if (flattenedVals.length > uniqueVals.length && uniqueVals.length <= Math.ceil(flattenedVals.length / 2)) { + colProps.uidt = UITypes.MultiSelect + } + // set dtxp here so that users can have the options even they switch the type from other types to MultiSelect + // once it's set, dtxp needs to be reset if the final column type is not MultiSelect colProps.dtxp = `'${uniqueVals.join("','")}'` } } else { - const uniqueVals = colData - .map((v: any) => (v || '').toString().trim()) - .filter((v, i, arr) => i === arr.findIndex((v1) => v.toLowerCase() === v1.toLowerCase())) - if (colData.length > uniqueVals.length && uniqueVals.length <= Math.ceil(colData.length / 2)) { - colProps.uidt = UITypes.SingleSelect + const uniqueVals = [...new Set(colData.map((v: any) => v.toString().trim().toLowerCase()))] + + if (uniqueVals.length > maxSelectOptionsAllowed) { + // too many options are detected, convert the column to SingleLineText instead + colProps.uidt = UITypes.SingleLineText + // _disableSelect is used to disable the in TemplateEditor + colProps._disableSelect = true + } else { + // assume the column type is single select if there are repeated values + // once it's set, dtxp needs to be reset if the final column type is not Single Select + if (colData.length > uniqueVals.length && uniqueVals.length <= Math.ceil(colData.length / 2)) { + colProps.uidt = UITypes.SingleSelect + } + // set dtxp here so that users can have the options even they switch the type from other types to SingleSelect + // once it's set, dtxp needs to be reset if the final column type is not SingleSelect colProps.dtxp = `'${uniqueVals.join("','")}'` } + return colProps } - return colProps } export const isDecimalType = (colData: []) => @@ -89,7 +111,39 @@ export const isEmailType = (colData: []) => !colData.some((v: any) => { return v && !isEmail(v) }) + export const isUrlType = (colData: []) => !colData.some((v: any) => { return v && !isValidURL(v) }) + +export const getColumnUIDTAndMetas = (colData: [], defaultType: string) => { + const colProps = { uidt: defaultType } + + 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 + } + } + // TODO: currency + // TODO: date / datetime + return colProps +}