Browse Source

feat: add import excel option in project

Signed-off-by: Pranav C <pranavxc@gmail.com>
pull/805/head
Pranav C 3 years ago
parent
commit
a4fd84779b
  1. 22
      packages/nc-gui/components/ProjectTreeView.vue
  2. 9
      packages/nc-gui/components/import/excelImport.vue
  3. 5
      packages/nc-gui/components/import/templateParsers/ExcelTemplateAdapter.js
  4. 2
      packages/nc-gui/components/project/spreadsheet/components/exportImport.vue
  5. 2
      packages/nc-gui/components/project/spreadsheet/public/xcTable.vue
  6. 2
      packages/nc-gui/components/project/spreadsheet/rowsXcDataTable.vue
  7. 39
      packages/nc-gui/components/templates/createProjectFromTemplateBtn.vue
  8. 1
      packages/nc-gui/helpers/rightClickOptions.js
  9. 18
      packages/nc-gui/helpers/sqlUi/PgUi.js
  10. 6
      packages/nc-gui/package-lock.json
  11. 2
      packages/nc-gui/package.json
  12. 2
      packages/nc-lib-gui/package.json
  13. 2
      packages/nocodb/src/lib/noco/common/BaseApiBuilder.ts
  14. 6
      packages/nocodb/src/lib/sqlUi/PgUi.ts

22
packages/nc-gui/components/ProjectTreeView.vue

@ -642,6 +642,13 @@
:heading="selectedNodeForDelete.heading" :heading="selectedNodeForDelete.heading"
type="error" type="error"
/> />
<excel-import
ref="excelImport"
v-model="excelImportDialog"
hide-label
import-to-project
@success="onExcelImport"
/>
</div> </div>
</template> </template>
@ -661,11 +668,13 @@ import DlgTableCreate from '@/components/utils/dlgTableCreate';
import DlgViewCreate from '@/components/utils/dlgViewCreate'; import DlgViewCreate from '@/components/utils/dlgViewCreate';
import SponsorMini from '@/components/sponsorMini'; import SponsorMini from '@/components/sponsorMini';
import {validateTableName} from "~/helpers"; import {validateTableName} from "~/helpers";
import ExcelImport from "~/components/import/excelImport";
// const {clipboard} = require('electron'); // const {clipboard} = require('electron');
export default { export default {
components: { components: {
ExcelImport,
SponsorMini, SponsorMini,
DlgViewCreate, DlgViewCreate,
DlgTableCreate, DlgTableCreate,
@ -704,6 +713,7 @@ export default {
open: [], open: [],
search: null, search: null,
menuVisible: false, menuVisible: false,
excelImportDialog:false,
x: 0, x: 0,
y: 0, y: 0,
menuItem: null, menuItem: null,
@ -924,7 +934,12 @@ export default {
this.miniExpanded = false; this.miniExpanded = false;
} }
}, },
onExcelImport(){
if (!this.menuItem || this.menuItem.type !== 'tableDir') {
this.menuItem = this.listViewArr.find(n => n.type === 'tableDir');
}
this.loadTables(this.menuItem)
},
...mapMutations({ ...mapMutations({
setProject: 'project/list', setProject: 'project/list',
updateProject: 'project/update', updateProject: 'project/update',
@ -1146,12 +1161,11 @@ export default {
this.dialogGetFunctionName.dialogShow = true; this.dialogGetFunctionName.dialogShow = true;
} else if (action === 'ENV_DB_FUNCTIONS_CREATE') { } else if (action === 'ENV_DB_FUNCTIONS_CREATE') {
this.dialogGetFunctionName.dialogShow = true; this.dialogGetFunctionName.dialogShow = true;
} else if (action === 'ENV_DB_TABLES_REFRESH') {
await this.loadTables(this.menuItem);
this.$toast.success('Tables refreshed').goAway(1000);
} else if (action === 'ENV_DB_VIEWS_REFRESH') { } else if (action === 'ENV_DB_VIEWS_REFRESH') {
await this.loadViews(this.menuItem); await this.loadViews(this.menuItem);
this.$toast.success('Views refreshed').goAway(1000); this.$toast.success('Views refreshed').goAway(1000);
} else if (action === 'IMPORT_EXCEL') {
this.excelImportDialog=true
} else if (action === 'ENV_DB_FUNCTIONS_REFRESH') { } else if (action === 'ENV_DB_FUNCTIONS_REFRESH') {
await this.loadFunctions(this.menuItem); await this.loadFunctions(this.menuItem);
this.$toast.success('Functions refreshed').goAway(1000); this.$toast.success('Functions refreshed').goAway(1000);

9
packages/nc-gui/components/import/excelImport.vue

@ -1,5 +1,5 @@
<template> <template>
<div class="pt-10"> <div :class="{'pt-10':!hideLabel}">
<v-dialog v-model="dropOrUpload" max-width="600"> <v-dialog v-model="dropOrUpload" max-width="600">
<v-card max-width="600"> <v-card max-width="600">
<v-tabs height="30"> <v-tabs height="30">
@ -125,7 +125,7 @@
</v-tooltip> </v-tooltip>
<v-dialog v-if="templateData" v-model="templateEditorModal" max-width="1000"> <v-dialog v-if="templateData" v-model="templateEditorModal" max-width="1000">
<v-card class="pa-6"> <v-card class="pa-6" min-width="500">
<template-editor :project-template.sync="templateData" excel-import> <template-editor :project-template.sync="templateData" excel-import>
<template #toolbar="{valid}"> <template #toolbar="{valid}">
<h3 class="mt-2 grey--text"> <h3 class="mt-2 grey--text">
@ -138,10 +138,12 @@
<create-project-from-template-btn <create-project-from-template-btn
:template-data="templateData" :template-data="templateData"
:import-data="importData" :import-data="importData"
:import-to-project="importToProject"
excel-import excel-import
:valid="valid" :valid="valid"
create-gql-text="Import as GQL Project" create-gql-text="Import as GQL Project"
create-rest-text="Import as REST Project" create-rest-text="Import as REST Project"
@success="$emit('success'),templateEditorModal = false"
> >
Import Excel Import Excel
</create-project-from-template-btn> </create-project-from-template-btn>
@ -165,7 +167,8 @@ export default {
components: { CreateProjectFromTemplateBtn, TemplateEditor }, components: { CreateProjectFromTemplateBtn, TemplateEditor },
props: { props: {
hideLabel: Boolean, hideLabel: Boolean,
value: Boolean value: Boolean,
importToProject: Boolean
}, },
data() { data() {
return { return {

5
packages/nc-gui/components/import/templateParsers/ExcelTemplateAdapter.js

@ -63,7 +63,6 @@ export default class ExcelTemplateAdapter extends TemplateGenerator {
const column = { const column = {
cn cn
} }
// const cellId = `${col.toString(26).split('').map(s => (parseInt(s, 26) + 10).toString(36).toUpperCase())}2`; // const cellId = `${col.toString(26).split('').map(s => (parseInt(s, 26) + 10).toString(36).toUpperCase())}2`;
const cellId = XLSX.utils.encode_cell({ const cellId = XLSX.utils.encode_cell({
c: range.s.c + col, c: range.s.c + col,
@ -94,13 +93,13 @@ export default class ExcelTemplateAdapter extends TemplateGenerator {
if (vals.some(v => v && v.toString().includes(','))) { if (vals.some(v => v && v.toString().includes(','))) {
const flattenedVals = vals.flatMap(v => v ? v.toString().split(',') : []) const flattenedVals = vals.flatMap(v => v ? v.toString().split(',') : [])
const uniqueVals = new Set(flattenedVals) const uniqueVals = new Set(flattenedVals)
if (flattenedVals.length > uniqueVals.size && uniqueVals.size <= flattenedVals.length / 10) { if (flattenedVals.length > uniqueVals.size && uniqueVals.size <= Math.ceil(flattenedVals.length / 2)) {
column.uidt = UITypes.MultiSelect column.uidt = UITypes.MultiSelect
column.dtxp = [...uniqueVals].join(',') column.dtxp = [...uniqueVals].join(',')
} }
} else { } else {
const uniqueVals = new Set(vals) const uniqueVals = new Set(vals)
if (vals.length > uniqueVals.size && uniqueVals.size <= vals.length / 10) { if (vals.length > uniqueVals.size && uniqueVals.size <= Math.ceil(vals.length / 2)) {
column.uidt = UITypes.SingleSelect column.uidt = UITypes.SingleSelect
column.dtxp = [...uniqueVals].join(',') column.dtxp = [...uniqueVals].join(',')
} }

2
packages/nc-gui/components/project/spreadsheet/components/csvExportImport.vue → packages/nc-gui/components/project/spreadsheet/components/exportImport.vue

@ -78,7 +78,7 @@ import ColumnMappingModal from '~/components/project/spreadsheet/components/colu
import CSVTemplateAdapter from '~/components/import/templateParsers/CSVTemplateAdapter' import CSVTemplateAdapter from '~/components/import/templateParsers/CSVTemplateAdapter'
export default { export default {
name: 'CsvExportImport', name: 'ExportImport',
components: { ColumnMappingModal, DropOrSelectFileModal }, components: { ColumnMappingModal, DropOrSelectFileModal },
props: { props: {
meta: Object, meta: Object,

2
packages/nc-gui/components/project/spreadsheet/public/xcTable.vue

@ -197,7 +197,7 @@ import SortListMenu from '../components/sortListMenu'
import ColumnFilterMenu from '../components/columnFilterMenu' import ColumnFilterMenu from '../components/columnFilterMenu'
import XcGridView from '../views/xcGridView' import XcGridView from '../views/xcGridView'
import { SqlUI } from '@/helpers/sqlUi' import { SqlUI } from '@/helpers/sqlUi'
import CsvExportImport from '~/components/project/spreadsheet/components/csvExportImport' import CsvExportImport from '~/components/project/spreadsheet/components/exportImport'
// import ExpandedForm from "../expandedForm"; // import ExpandedForm from "../expandedForm";
export default { export default {

2
packages/nc-gui/components/project/spreadsheet/rowsXcDataTable.vue

@ -560,7 +560,7 @@ import ExpandedForm from '@/components/project/spreadsheet/components/expandedFo
import Pagination from '@/components/project/spreadsheet/components/pagination' import Pagination from '@/components/project/spreadsheet/components/pagination'
import { SqlUI } from '~/helpers/sqlUi' import { SqlUI } from '~/helpers/sqlUi'
import ColumnFilter from '~/components/project/spreadsheet/components/columnFilterMenu' import ColumnFilter from '~/components/project/spreadsheet/components/columnFilterMenu'
import CsvExportImport from '~/components/project/spreadsheet/components/csvExportImport' import CsvExportImport from '~/components/project/spreadsheet/components/exportImport'
export default { export default {
name: 'RowsXcDataTable', name: 'RowsXcDataTable',

39
packages/nc-gui/components/templates/createProjectFromTemplateBtn.vue

@ -44,6 +44,7 @@ export default {
props: { props: {
excelImport: Boolean, excelImport: Boolean,
loading: Boolean, loading: Boolean,
importToProject: Boolean,
templateData: [Array, Object], templateData: [Array, Object],
importData: [Array, Object], importData: [Array, Object],
valid: { valid: {
@ -107,30 +108,56 @@ export default {
this.$store.commit('loader/MutMessage', this.loaderMessages[this.loaderMessagesIndex]) this.$store.commit('loader/MutMessage', this.loaderMessages[this.loaderMessagesIndex])
}, 1000) }, 1000)
let projectId, prefix
if (this.importToProject) {
this.$store.commit('loader/MutMessage', 'Importing excel template')
const res = await this.$store.dispatch('sqlMgr/ActSqlOp', [{
// todo: extract based on active
dbAlias: 'db', // this.nodes.dbAlias,
env: '_noco'
}, 'xcModelsCreateFromTemplate', {
template: this.templateData
}])
if (res && res.tables && res.tables.length) {
this.$toast.success(`Imported ${res.tables.length} tables successfully`).goAway(3000)
} else {
this.$toast.success('Template imported successfully').goAway(3000)
}
projectId = this.$route.params.project_id
prefix = this.$store.getters['project/GtrProjectPrefix']
} else {
const result = await this.$store.dispatch('sqlMgr/ActSqlOp', [null, 'projectCreateByWebWithXCDB', { const result = await this.$store.dispatch('sqlMgr/ActSqlOp', [null, 'projectCreateByWebWithXCDB', {
title: this.templateData.title, title: this.templateData.title,
projectType, projectType,
template: this.templateData, template: this.templateData,
excelImport: this.excelImport excelImport: this.excelImport
}]) }])
projectId = result.id
prefix = result.prefix
await this.$store.dispatch('project/ActLoadProjectInfo') await this.$store.dispatch('project/ActLoadProjectInfo')
}
clearInterval(interv) clearInterval(interv)
if (this.importData) { if (this.importData) {
this.$store.commit('loader/MutMessage', 'Importing excel data to project') this.$store.commit('loader/MutMessage', 'Importing excel data to project')
await this.importDataToProject({ projectId: result.id, projectType, prefix: result.prefix }) await this.importDataToProject({ projectId, projectType, prefix })
} }
this.$store.commit('loader/MutMessage', null) this.$store.commit('loader/MutMessage', null)
this.projectReloading = false this.projectReloading = false
if (!this.importToProject) {
this.$router.push({ await this.$router.push({
path: `/nc/${result.id}`, path: `/nc/${projectId}`,
query: { query: {
new: 1 new: 1
} }
}) })
}
this.$emit('success')
} catch (e) { } catch (e) {
console.log(e) console.log(e)
this.$toast.error(e.message).goAway(3000) this.$toast.error(e.message).goAway(3000)

1
packages/nc-gui/helpers/rightClickOptions.js

@ -20,6 +20,7 @@ export default {
tableDir: { tableDir: {
'Table Create': 'ENV_DB_TABLES_CREATE', 'Table Create': 'ENV_DB_TABLES_CREATE',
'Tables Refresh': 'ENV_DB_TABLES_REFRESH', 'Tables Refresh': 'ENV_DB_TABLES_REFRESH',
'Import Excel': 'IMPORT_EXCEL',
// "Table Create": "ENV_DB_TABLES_CREATE", // "Table Create": "ENV_DB_TABLES_CREATE",
...(process.env.NODE_ENV === 'dev' ? { 'Show _Nodes Info': 'SHOW_NODES' } : {}) ...(process.env.NODE_ENV === 'dev' ? { 'Show _Nodes Info': 'SHOW_NODES' } : {})
}, },

18
packages/nc-gui/helpers/sqlUi/PgUi.js

@ -1630,13 +1630,13 @@ export class PgUi {
colProp.dt = 'character varying' colProp.dt = 'character varying'
break break
case 'DateTime': case 'DateTime':
colProp.dt = 'datetime' colProp.dt = 'timestamp'
break break
case 'CreateTime': case 'CreateTime':
colProp.dt = 'datetime' colProp.dt = 'timestamp'
break break
case 'LastModifiedTime': case 'LastModifiedTime':
colProp.dt = 'datetime' colProp.dt = 'timestamp'
break break
case 'AutoNumber': case 'AutoNumber':
colProp.dt = 'int' colProp.dt = 'int'
@ -1761,7 +1761,7 @@ export class PgUi {
'float8', 'float8',
'smallint', 'smallint',
'smallserial', 'smallserial',
'numeric', 'numeric'
] ]
case 'Decimal': case 'Decimal':
@ -1769,7 +1769,7 @@ export class PgUi {
'double precision', 'double precision',
'float4', 'float4',
'float8', 'float8',
'numeric', 'numeric'
] ]
case 'Currency': case 'Currency':
@ -1787,7 +1787,7 @@ export class PgUi {
'double precision', 'double precision',
'money', 'float4', 'money', 'float4',
'float8', 'float8',
'numeric', 'numeric'
] ]
case 'Percent': case 'Percent':
@ -1807,7 +1807,7 @@ export class PgUi {
'float8', 'float8',
'smallint', 'smallint',
'smallserial', 'smallserial',
'numeric', 'numeric'
] ]
case 'Duration': case 'Duration':
@ -1827,7 +1827,7 @@ export class PgUi {
'float8', 'float8',
'smallint', 'smallint',
'smallserial', 'smallserial',
'numeric', 'numeric'
] ]
case 'Rating': case 'Rating':
@ -1847,7 +1847,7 @@ export class PgUi {
'float8', 'float8',
'smallint', 'smallint',
'smallserial', 'smallserial',
'numeric', 'numeric'
] ]
case 'Formula': case 'Formula':

6
packages/nc-gui/package-lock.json generated

@ -8073,9 +8073,9 @@
} }
}, },
"monaco-editor": { "monaco-editor": {
"version": "0.18.1", "version": "0.19.3",
"resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.18.1.tgz", "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.19.3.tgz",
"integrity": "sha512-fmL+RFZ2Hrezy+X/5ZczQW51LUmvzfcqOurnkCIRFTyjdVjzR7JvENzI6+VKBJzJdPh6EYL4RoWl92b2Hrk9fw==" "integrity": "sha512-2n1vJBVQF2Hhi7+r1mMeYsmlf18hjVb6E0v5SoMZyb4aeOmYPKun+CE3gYpiNA1KEvtSdaDHFBqH9d7Wd9vREg=="
}, },
"monaco-editor-webpack-plugin": { "monaco-editor-webpack-plugin": {
"version": "1.9.1", "version": "1.9.1",

2
packages/nc-gui/package.json

@ -26,7 +26,7 @@
"inflection": "^1.12.0", "inflection": "^1.12.0",
"jsep": "^0.4.0", "jsep": "^0.4.0",
"material-design-icons-iconfont": "^5.0.1", "material-design-icons-iconfont": "^5.0.1",
"monaco-editor": "^0.18.1", "monaco-editor": "^0.19.3",
"monaco-themes": "^0.2.5", "monaco-themes": "^0.2.5",
"nano-assign": "^1.0.1", "nano-assign": "^1.0.1",
"nuxt": "^2.14.0", "nuxt": "^2.14.0",

2
packages/nc-lib-gui/package.json

@ -1,6 +1,6 @@
{ {
"name": "nc-lib-gui", "name": "nc-lib-gui",
"version": "0.82.0", "version": "0.82.1",
"description": "> TODO: description", "description": "> TODO: description",
"author": "“pranavxc” <pranavxc@gmail.com>", "author": "“pranavxc” <pranavxc@gmail.com>",
"homepage": "https://gitlab.com/xgenecloud-ts/xgenecloud-ts#readme", "homepage": "https://gitlab.com/xgenecloud-ts/xgenecloud-ts#readme",

2
packages/nocodb/src/lib/noco/common/BaseApiBuilder.ts

@ -236,6 +236,8 @@ export default abstract class BaseApiBuilder<T extends Noco>
model_name: tn model_name: tn
} }
); );
if (delete this.metas[tn]) delete this.metas[tn];
if (delete this.models[tn]) delete this.models[tn];
} }
public async onRelationCreate( public async onRelationCreate(

6
packages/nocodb/src/lib/sqlUi/PgUi.ts

@ -1665,13 +1665,13 @@ export class PgUi {
colProp.dt = 'character varying'; colProp.dt = 'character varying';
break; break;
case 'DateTime': case 'DateTime':
colProp.dt = 'datetime'; colProp.dt = 'timestamp';
break; break;
case 'CreateTime': case 'CreateTime':
colProp.dt = 'datetime'; colProp.dt = 'timestamp';
break; break;
case 'LastModifiedTime': case 'LastModifiedTime':
colProp.dt = 'datetime'; colProp.dt = 'timestamp';
break; break;
case 'AutoNumber': case 'AutoNumber':
colProp.dt = 'int'; colProp.dt = 'int';

Loading…
Cancel
Save