Browse Source

refactor: template editor ui, template editor modal toggling

Signed-off-by: Pranav C <pranavxc@gmail.com>
pull/789/head
Pranav C 3 years ago
parent
commit
9c4a212fbc
  1. 64
      packages/nc-gui/components/import/excelImport.vue
  2. 6
      packages/nc-gui/components/import/templateParsers/ExcelTemplateAdapter.js
  3. 31
      packages/nc-gui/components/templates/createProjectFromTemplateBtn.vue
  4. 120
      packages/nc-gui/components/templates/editor.vue

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

@ -1,3 +1,11 @@
<script>
import CreateProjectFromTemplateBtn from '~/components/templates/createProjectFromTemplateBtn'
import TemplateEditor from '~/components/templates/editor'
export default {
components: { TemplateEditor, CreateProjectFromTemplateBtn }
}
</script>
<template>
<div class="pt-10">
<v-dialog v-model="dropOrUpload" max-width="600">
@ -21,7 +29,7 @@
<div
class="nc-droppable d-flex align-center justify-center flex-column"
:style="{
background : dragOver ? '#7774' : ''
background : dragOver ? '#7772' : ''
}"
@click="$refs.file.click()"
@drop.prevent="dropHandler"
@ -76,7 +84,7 @@
<div class="d-flex">
<v-spacer />
<span class="caption pointer grey--text" @click="showMore = !showMore">{{ showMore ? 'Hide' : 'Show' }} more
<v-icon small>mdi-menu-{{ showMore ? 'up':'down' }}</v-icon>
<v-icon small>mdi-menu-{{ showMore ? 'up' : 'down' }}</v-icon>
</span>
</div>
<div class="mb-2 pt-2 nc-excel-import-options" :style="{ maxHeight: showMore ? '100px' : '0'}">
@ -124,15 +132,24 @@
<span class="caption">Create template from Excel</span>
</v-tooltip>
<v-dialog v-if="templateData" :value="true">
<v-dialog v-if="templateData" v-model="templateEditorModal" max-width="1000">
<v-card>
<template-editor :project-template.sync="templateData">
<template #toolbar>
<template-editor :project-template.sync="templateData" excel-import>
<template #toolbar="{valid}">
<h3 class="mt-2 grey--text">
Import Excel as Project : {{ filename }}
</h3>
<v-spacer />
<create-project-from-template-btn
:template-data="templateData"
:import-data="importData"
/>
:valid="valid"
create-gql-text="Import as GQL Project"
create-rest-text="Import as REST Project"
>
Import Excel
</create-project-from-template-btn>
</template>
</template-editor>
</v-card>
@ -150,13 +167,14 @@ import ExcelTemplateAdapter from '~/components/import/templateParsers/ExcelTempl
export default {
name: 'ExcelImport',
components: { CreateProjectFromTemplateBtn, TemplateEditor },
components: {CreateProjectFromTemplateBtn, TemplateEditor},
props: {
hideLabel: Boolean,
value: Boolean
},
data() {
return {
templateEditorModal:false,
valid: null,
templateData: null,
importData: null,
@ -165,7 +183,8 @@ export default {
showMore: false,
parserConfig: {
maxRowsToParse: 500
}
},
filename: ''
}
},
computed: {
@ -187,10 +206,11 @@ export default {
this.$refs.file.click()
},
_change(file) {
const files = file.target.files
_change(event) {
const files = event.target.files
if (files && files[0]) {
this._file(files[0])
event.target.value = ''
}
},
async _file(file) {
@ -199,11 +219,10 @@ export default {
const int = setInterval(() => {
this.$store.commit('loader/MutMessage', `Loading excel file${'.'.repeat(++i % 4)}`)
}, 1000)
this.dropOrUpload = false
const reader = new FileReader()
reader.onload = async(e) => {
this.filename = file.name
reader.onload = async (e) => {
const ab = e.target.result
await this.parseAndExtractData('file', ab, file.name)
this.$store.commit('loader/MutMessage', null)
@ -216,7 +235,8 @@ export default {
}
reader.addEventListener('progress', handleEvent)
reader.onerror = () => {
reader.onerror = (e) => {
console.log('error', e)
this.$store.commit('loader/MutClear')
}
reader.readAsArrayBuffer(file)
@ -236,9 +256,11 @@ export default {
templateGenerator.parse()
this.templateData = templateGenerator.getTemplate()
this.importData = templateGenerator.getData()
this.templateEditorModal = true;
},
dropHandler(ev) {
this.dragOver = false;
console.log('File(s) dropped')
let file
if (ev.dataTransfer.items) {
@ -250,12 +272,12 @@ export default {
file = ev.dataTransfer.files[0]
}
if (file.type !== 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' && file.type !== 'application/vnd.ms-excel') {
return this.$toast.error('Dropped file is not an accepted file type. The accepted file types are .xlsx,.xls!').goAway(3000)
}
if (file) {
this._file(file)
if (!file) return
if (!/\.xls[xm]?$/.test(file.name)) {
return this.$toast.error('Dropped file is not an accepted file type. The accepted file types are .xlsx,.xls,.xlsm!').goAway(3000)
}
this._file(file)
},
dragOverHandler(ev) {
console.log('File(s) in drop zone')
@ -303,8 +325,8 @@ export default {
width: 100%;
}
.nc-excel-import-options{
transition:.4s max-height;
.nc-excel-import-options {
transition: .4s max-height;
overflow: hidden;
}
</style>

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

@ -105,12 +105,12 @@ export default class ExcelTemplateAdapter extends TemplateGenerator {
}
}
} else if (column.uidt === UITypes.Number) {
if (rows.slice(1, 500).some((v) => {
if (rows.slice(1, this.config.maxRowsToParse).some((v) => {
return v && v[col] && parseInt(+v[col]) !== +v[col]
})) {
column.uidt = UITypes.Decimal
}
if (rows.slice(1, 500).every((v, i) => {
if (rows.slice(1, this.config.maxRowsToParse).every((v, i) => {
const cellId = XLSX.utils.encode_cell({
c: range.s.c + col,
r: i + 2
@ -123,7 +123,7 @@ export default class ExcelTemplateAdapter extends TemplateGenerator {
column.uidt = UITypes.Currency
}
} else if (column.uidt === UITypes.DateTime) {
if (rows.slice(1, 500).every((v, i) => {
if (rows.slice(1, this.config.maxRowsToParse).every((v, i) => {
const cellId = XLSX.utils.encode_cell({
c: range.s.c + col,
r: i + 2

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

@ -9,7 +9,7 @@
x-large
v-on="on"
>
Use template
<slot>Use template</slot>
<v-icon>mdi-menu-down</v-icon>
</v-btn>
</template>
@ -19,7 +19,7 @@
<v-icon class="mr-1" :color="textColors[7]">
mdi-code-json
</v-icon>
Create REST Project
{{ createRestText }}
</v-list-item-title>
</v-list-item>
<v-list-item dense class="py-2" @click="useTemplate('graphql')">
@ -27,7 +27,7 @@
<v-icon class="mr-1" :color="textColors[3]">
mdi-graphql
</v-icon>
Create GQL Project
{{ createGqlText }}
</v-list-item-title>
</v-list-item>
</v-list>
@ -44,7 +44,23 @@ export default {
props: {
loading: Boolean,
templateData: [Array, Object],
importData: [Array, Object]
importData: [Array, Object],
valid: {
default: true,
type: Boolean
},
validationErrorMsg: {
default: 'Please fill all the required values',
type: String
},
createGqlText: {
default: 'Create GQL Project',
type: String
},
createRestText: {
default: 'Create REST Project',
type: String
}
},
data() {
return {
@ -76,6 +92,10 @@ export default {
},
methods: {
async useTemplate(projectType) {
if (!this.valid) {
return this.$toast.error(this.validationErrorMsg).goAway(3000)
}
// this.$emit('useTemplate', type)
this.projectCreation = true
@ -118,7 +138,8 @@ export default {
// this.$store.commit('project/MutProjectId', projectId)
this.$ncApis.setProjectId(projectId)
let total = 0; let progress = 0
let total = 0
let progress = 0
await Promise.all(Object.entries(this.importData).map(v => (async([table, data]) => {
await this.$store.dispatch('meta/ActLoadMeta', {

120
packages/nc-gui/components/templates/editor.vue

@ -1,7 +1,7 @@
<template>
<div class="h-100">
<v-toolbar v-if="!viewMode" class="elevation-0">
<slot name="toolbar">
<slot name="toolbar" :valid="valid">
<!-- <v-text-field
v-model="url"
clearable
@ -87,7 +87,7 @@
</slot>
</v-toolbar>
<v-container class="text-center" style="height:calc(100% - 64px);overflow-y: auto">
<v-form ref="form">
<v-form ref="form" v-model="valid">
<v-row fluid class="justify-center">
<v-col cols="12">
<v-card>
@ -130,7 +130,7 @@
<v-spacer />
<v-icon v-if="!viewMode" class="flex-grow-0 mr-2" small color="grey" @click.stop="deleteTable(i)">
mdi-delete
mdi-delete-outline
</v-icon>
</v-expansion-panel-header>
<v-expansion-panel-content>
@ -144,10 +144,10 @@
<v-simple-table v-if="table.columns.length" dense class="my-4">
<thead>
<tr>
<th class="caption text-left pa-3">
<th class="caption text-left pa-1">
Column Name
</th>
<th class="caption text-left pa-3" colspan="4">
<th class="caption text-left pa-1" colspan="4">
Column Type
</th>
<th />
@ -157,7 +157,7 @@
</thead>
<tbody>
<tr v-for="(col,j) in table.columns" :key="j" :data-exp="i">
<td class="pa-3 text-left" :style="{width:viewMode ? '33%' : ''}">
<td class="pa-1 text-left" :style="{width:viewMode ? '33%' : '15%'}">
<span v-if="viewMode" class="body-1 ">
{{ col.cn }}
</span>
@ -225,12 +225,12 @@
<template v-else>
<td
class="pa-3 text-left"
:colspan="isLookupOrRollup(col) || isRelation(col) || isSelect(col) ? (isRollup(col)?
1 :2) : 4"
class="pa-1 text-left"
style="width:200px;max-width:200px"
>
<v-autocomplete
:ref="`uidt_${table.tn}_${j}`"
style="max-width: 200px"
:value="col.uidt"
placeholder="Column Datatype"
outlined
@ -253,8 +253,8 @@
</v-chip>
<span v-else class="caption">{{ name }}</span>
</template>
<template #selection="{item:{name}}">
<v-chip v-if="colors[name]" :color="colors[name]" small>
<template #selection="{item:{name}} ">
<v-chip v-if="colors[name]" :color="colors[name]" small style="max-width: 100px">
{{ name }}
</v-chip>
<span v-else class="caption">{{ name }}</span>
@ -265,7 +265,7 @@
<template
v-if="isRelation(col) || isLookupOrRollup(col)"
>
<td class="pa-3 text-left">
<td class="pa-1 text-left">
<v-autocomplete
:value="col.rtn"
placeholder="Related table"
@ -282,7 +282,7 @@
/>
</td>
<td v-if="isRelation(col)" class="pa-3">
<td v-if="isRelation(col)" class="pa-1">
<template v-if="col.uidt !== 'ForeignKey'">
<span
v-if="viewMode"
@ -304,7 +304,7 @@
/>
</template>
</td>
<td v-if="isLookupOrRollup(col)" class="pa-3">
<td v-if="isLookupOrRollup(col)" class="pa-1">
<span
v-if="viewMode"
class="caption"
@ -326,7 +326,7 @@
item-value="cn"
/>
</td>
<td v-if="isRollup(col)" class="pa-3">
<td v-if="isRollup(col)" class="pa-1">
<span
v-if="viewMode"
class="caption"
@ -350,7 +350,7 @@
<template
v-if="isSelect(col)"
>
<td class="pa-3 text-left" colspan="2">
<td class="pa-1 text-left" colspan="2">
<span
v-if="viewMode"
class="caption"
@ -367,7 +367,12 @@
/>
</td>
</template>
<td>
<td
v-if="!isRollup(col) "
:colspan="isLookupOrRollup(col) || isRelation(col) || isSelect(col) ? (isRollup(col)?
0 :1) : 3"
/>
<td style="max-width: 50px;width: 50px">
<v-icon
v-if="!viewMode"
class="flex-grow-0"
@ -375,7 +380,7 @@
color="grey"
@click.stop="deleteTableColumn(i,j, col, table)"
>
mdi-delete
mdi-delete-outline
</v-icon>
</td>
</template>
@ -439,40 +444,41 @@
>
Click to change gradient
</div>-->
<gradient-generator v-model="project.image_url" class=" d-100" />
<v-row>
<v-col>
<v-text-field
v-model="project.category"
:rules="[v => !!v || 'Category name required']"
class="caption"
outlined
dense
label="Project Category"
/>
</v-col>
<v-col>
<v-text-field
v-model="project.tags"
<template v-if="!excelImport">
<gradient-generator v-model="project.image_url" class=" d-100" />
<v-row>
<v-col>
<v-text-field
v-model="project.category"
:rules="[v => !!v || 'Category name required']"
class="caption"
outlined
dense
label="Project Category"
/>
</v-col>
<v-col>
<v-text-field
v-model="project.tags"
class="caption"
outlined
dense
label="Project Tags"
/>
</v-col>
</v-row>
<div>
<v-textarea
v-model="project.description"
class="caption"
outlined
dense
label="Project Tags"
label="Project Description"
@click="counter++"
/>
</v-col>
</v-row>
<div>
<v-textarea
v-model="project.description"
class="caption"
outlined
dense
label="Project Description"
@click="counter++"
/>
</div>
</div>
</template>
</div>
</v-card-text>
</v-card>
@ -571,7 +577,8 @@ export default {
props: {
id: [Number, String],
viewMode: Boolean,
projectTemplate: Object
projectTemplate: Object,
excelImport: Boolean
},
data: () => ({
loading: false,
@ -1277,14 +1284,16 @@ export default {
if (oldVal === UITypes.LinkToAnotherRecord) {
rTable = this.project.tables.find(t => t.tn === col.rtn)
if (col.type === 'hm') {
index = rTable.columns.findIndex(c => c.uidt === UITypes.ForeignKey && c.rtn === table.tn)
} else if (col.type === 'mm') {
index = rTable.columns.findIndex(c => c.uidt === UITypes.LinkToAnotherRecord && c.rtn === table.tn && c.type === 'mm')
if (rTable) {
if (col.type === 'hm') {
index = rTable.columns.findIndex(c => c.uidt === UITypes.ForeignKey && c.rtn === table.tn)
} else if (col.type === 'mm') {
index = rTable.columns.findIndex(c => c.uidt === UITypes.LinkToAnotherRecord && c.rtn === table.tn && c.type === 'mm')
}
}
} else if (oldVal === UITypes.ForeignKey) {
rTable = this.project.tables.find(t => t.tn === col.rtn)
index = rTable.columns.findIndex(c => c.uidt === UITypes.LinkToAnotherRecord && c.rtn === table.tn && c.type === 'hm')
if (rTable) { index = rTable.columns.findIndex(c => c.uidt === UITypes.LinkToAnotherRecord && c.rtn === table.tn && c.type === 'hm') }
}
if (rTable && index > -1) {
rTable.columns.splice(index, 1)
@ -1303,4 +1312,7 @@ export default {
</script>
<style scoped>
/deep/ .v-select__selections{
flex-wrap: nowrap;
}
</style>

Loading…
Cancel
Save