mirror of https://github.com/nocodb/nocodb
Pranav C
3 years ago
13 changed files with 484 additions and 65 deletions
@ -0,0 +1,28 @@ |
|||||||
|
import Papaparse from 'papaparse' |
||||||
|
import TemplateGenerator from '~/components/import/TemplateGenerator' |
||||||
|
|
||||||
|
export default class CSVTemplateAdapter extends TemplateGenerator { |
||||||
|
constructor(name, data) { |
||||||
|
super() |
||||||
|
this.name = name |
||||||
|
this.csv = Papaparse.parse(data, { header: true }) |
||||||
|
this.project = { |
||||||
|
title: this.name, |
||||||
|
tables: [] |
||||||
|
} |
||||||
|
this.data = {} |
||||||
|
} |
||||||
|
|
||||||
|
parseData() { |
||||||
|
this.columns = this.csv.meta.fields |
||||||
|
this.data = this.csv.data |
||||||
|
} |
||||||
|
|
||||||
|
getColumns() { |
||||||
|
return this.columns |
||||||
|
} |
||||||
|
|
||||||
|
getData() { |
||||||
|
return this.data |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,109 @@ |
|||||||
|
<template> |
||||||
|
<v-dialog v-model="dropOrUpload" max-width="600"> |
||||||
|
<v-card max-width="600"> |
||||||
|
<div class="pa-4"> |
||||||
|
<div |
||||||
|
class="nc-droppable d-flex align-center justify-center flex-column" |
||||||
|
:style="{ |
||||||
|
background : dragOver ? '#7774' : '' |
||||||
|
}" |
||||||
|
@click="$refs.file.click()" |
||||||
|
@drop.prevent="dropHandler" |
||||||
|
@dragover.prevent="dragOver = true" |
||||||
|
@dragenter.prevent="dragOver = true" |
||||||
|
@dragexit="dragOver = false" |
||||||
|
@dragleave="dragOver = false" |
||||||
|
@dragend="dragOver = false" |
||||||
|
> |
||||||
|
<v-icon size="50" color="grey"> |
||||||
|
mdi-file-plus-outline |
||||||
|
</v-icon> |
||||||
|
<p class="title grey--text mb-1 mt-2"> |
||||||
|
Select {{ text }} file to Upload |
||||||
|
</p> |
||||||
|
<p class="grey--text "> |
||||||
|
or drag and drop {{ text }} file |
||||||
|
</p> |
||||||
|
</div> |
||||||
|
<input |
||||||
|
ref="file" |
||||||
|
class="nc-excel-import-input" |
||||||
|
type="file" |
||||||
|
style="display: none" |
||||||
|
:accept="accept" |
||||||
|
@change="_change($event)" |
||||||
|
> |
||||||
|
</div> |
||||||
|
</v-card> |
||||||
|
</v-dialog> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
|
||||||
|
export default { |
||||||
|
name: 'DropOrSelectFileModal', |
||||||
|
props: { |
||||||
|
value: Boolean, |
||||||
|
accept: String, |
||||||
|
text: String |
||||||
|
}, |
||||||
|
data() { |
||||||
|
return { |
||||||
|
dragOver: false |
||||||
|
} |
||||||
|
}, |
||||||
|
computed: { |
||||||
|
dropOrUpload: { |
||||||
|
set(v) { |
||||||
|
this.$emit('input', v) |
||||||
|
}, |
||||||
|
get() { |
||||||
|
return this.value |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
_change(file) { |
||||||
|
const files = file.target.files |
||||||
|
if (files && files[0]) { |
||||||
|
this.$emit('file', files[0]) |
||||||
|
} |
||||||
|
}, |
||||||
|
dropHandler(ev) { |
||||||
|
this.dragOver = false |
||||||
|
let file |
||||||
|
if (ev.dataTransfer.items) { |
||||||
|
// Use DataTransferItemList interface to access the file(s) |
||||||
|
if (ev.dataTransfer.items.length && ev.dataTransfer.items[0].kind === 'file') { |
||||||
|
file = ev.dataTransfer.items[0].getAsFile() |
||||||
|
} |
||||||
|
} else if (ev.dataTransfer.files.length) { |
||||||
|
file = ev.dataTransfer.files[0] |
||||||
|
} |
||||||
|
|
||||||
|
if (this.accept && !this.accept.split(',').some(ext => file.name.endsWith(ext.trim()))) { |
||||||
|
return this.$toast.error(`Dopped file is not an accepted file type. The accepted file types are ${this.accept}!`).goAway(3000) |
||||||
|
} |
||||||
|
if (file) { |
||||||
|
this.$emit('file', file) |
||||||
|
} |
||||||
|
}, |
||||||
|
dragOverHandler(ev) { |
||||||
|
console.log('File(s) in drop zone') |
||||||
|
|
||||||
|
// Prevent default behavior (Prevent file from being opened) |
||||||
|
ev.preventDefault() |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
</script> |
||||||
|
|
||||||
|
<style scoped> |
||||||
|
|
||||||
|
.nc-droppable { |
||||||
|
width: 100%; |
||||||
|
min-height: 200px; |
||||||
|
border-radius: 4px; |
||||||
|
border: 2px dashed var(--v-textColor-lighten5); |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,40 @@ |
|||||||
|
<template> |
||||||
|
<v-overlay :value="message" z-index="99999" opacity=".9"> |
||||||
|
<div class="d-flex flex-column align-center"> |
||||||
|
<v-progress-circular |
||||||
|
v-if="progress !== null " |
||||||
|
:rotate="360" |
||||||
|
:size="100" |
||||||
|
:width="15" |
||||||
|
:value="progress" |
||||||
|
> |
||||||
|
{{ progress }}% |
||||||
|
</v-progress-circular> |
||||||
|
|
||||||
|
<v-progress-circular v-else indeterminate size="100" width="15" class="mb-10" /> |
||||||
|
<span class="title">{{ message }}</span> |
||||||
|
</div> |
||||||
|
</v-overlay> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
export default { |
||||||
|
name: 'Loader', |
||||||
|
props: { |
||||||
|
// message: String, |
||||||
|
// progress: Number |
||||||
|
}, |
||||||
|
computed: { |
||||||
|
message() { |
||||||
|
return this.$store.state.loader.message |
||||||
|
}, |
||||||
|
progress() { |
||||||
|
return this.$store.state.loader.progress |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
</script> |
||||||
|
|
||||||
|
<style scoped> |
||||||
|
|
||||||
|
</style> |
@ -0,0 +1,118 @@ |
|||||||
|
<template> |
||||||
|
<v-dialog v-model="visible" max-width="800px"> |
||||||
|
<v-card> |
||||||
|
<v-card-actions> |
||||||
|
<v-card-title> |
||||||
|
Table : {{ meta._tn }} |
||||||
|
</v-card-title> |
||||||
|
<v-spacer /> |
||||||
|
<v-btn color="primary" large @click="$emit('import',mappings)"> |
||||||
|
<v-icon small class="mr-1"> |
||||||
|
mdi-database-import-outline |
||||||
|
</v-icon> Import |
||||||
|
</v-btn> |
||||||
|
</v-card-actions> |
||||||
|
<v-divider /> |
||||||
|
<v-container fluid> |
||||||
|
<v-simple-table dense style="position:relative;"> |
||||||
|
<thead> |
||||||
|
<tr> |
||||||
|
<th /> |
||||||
|
<th style="width:45%" class="grey--text"> |
||||||
|
Source column |
||||||
|
</th> |
||||||
|
<th style="width:45%" class="grey--text"> |
||||||
|
Destination column |
||||||
|
</th> |
||||||
|
</tr> |
||||||
|
</thead> |
||||||
|
<tbody> |
||||||
|
<tr v-for="(r,i) in mappings" :key="i"> |
||||||
|
<td> |
||||||
|
<v-checkbox v-model="r.enabled" class="mt-0" dense hide-details /> |
||||||
|
</td><td class="caption" style="width:45%"> |
||||||
|
<div :title="r.sourceCn" style=""> |
||||||
|
{{ r.sourceCn }} |
||||||
|
</div> |
||||||
|
</td><td style="width:45%"> |
||||||
|
<v-select |
||||||
|
v-model="r.destCn" |
||||||
|
class="caption" |
||||||
|
dense |
||||||
|
hide-details |
||||||
|
:items="meta.columns" |
||||||
|
item-text="_cn" |
||||||
|
item-value="_cn" |
||||||
|
> |
||||||
|
<template #selection="{item}"> |
||||||
|
<v-icon small class="mr-1"> |
||||||
|
{{ getIcon(item.uidt) }} |
||||||
|
</v-icon> |
||||||
|
{{ item._cn }} |
||||||
|
</template> |
||||||
|
<template #item="{item}"> |
||||||
|
<v-icon small class="mr-1"> |
||||||
|
{{ getIcon(item.uidt) }} |
||||||
|
</v-icon> |
||||||
|
<span class="caption"> {{ item._cn }}</span> |
||||||
|
</template> |
||||||
|
</v-select> |
||||||
|
</td> |
||||||
|
</tr> |
||||||
|
</tbody> |
||||||
|
</v-simple-table> |
||||||
|
</v-container> |
||||||
|
</v-card> |
||||||
|
</v-dialog> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import { getUIDTIcon } from '~/components/project/spreadsheet/helpers/uiTypes' |
||||||
|
|
||||||
|
export default { |
||||||
|
name: 'ColumnMappingModal', |
||||||
|
props: { |
||||||
|
meta: Object, |
||||||
|
importDataColumns: Array, |
||||||
|
value: Boolean |
||||||
|
}, |
||||||
|
data() { |
||||||
|
return { |
||||||
|
mappings: [] |
||||||
|
} |
||||||
|
}, |
||||||
|
computed: { |
||||||
|
visible: { |
||||||
|
get() { |
||||||
|
return this.value |
||||||
|
}, |
||||||
|
set(v) { |
||||||
|
this.$emit('input', v) |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
mounted() { |
||||||
|
this.mapDefaultColumns() |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
mapDefaultColumns() { |
||||||
|
this.mappings = [] |
||||||
|
for (const col of this.importDataColumns) { |
||||||
|
const o = { sourceCn: col, enabled: true } |
||||||
|
const tableColumn = this.meta.columns.find(c => c._cn === col) |
||||||
|
if (tableColumn) { |
||||||
|
o.destCn = tableColumn._cn |
||||||
|
} |
||||||
|
this.mappings.push(o) |
||||||
|
} |
||||||
|
}, |
||||||
|
getIcon(uidt) { |
||||||
|
return getUIDTIcon(uidt) || 'mdi-alpha-v-circle-outline' |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
</script> |
||||||
|
|
||||||
|
<style scoped> |
||||||
|
|
||||||
|
</style> |
@ -0,0 +1,22 @@ |
|||||||
|
const state = () => ({ |
||||||
|
message: null, |
||||||
|
progress: null |
||||||
|
}) |
||||||
|
|
||||||
|
const mutations = { |
||||||
|
MutMessage(state, message) { |
||||||
|
state.message = message |
||||||
|
}, |
||||||
|
MutProgress(state, progress) { |
||||||
|
state.progress = progress |
||||||
|
}, |
||||||
|
MutClear(state) { |
||||||
|
state.progress = null |
||||||
|
state.message = null |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
export { |
||||||
|
state, |
||||||
|
mutations |
||||||
|
} |
Loading…
Reference in new issue