2021-12-28 15:30:07 +01:00
|
|
|
<template>
|
|
|
|
<div class="modal active">
|
|
|
|
<a class="modal-overlay" @click.stop="closeModal" />
|
|
|
|
<div class="modal-container p-0">
|
|
|
|
<div class="modal-header pl-2">
|
|
|
|
<div class="modal-title h6">
|
|
|
|
<div class="d-flex">
|
|
|
|
<i class="mdi mdi-24px mdi-database-arrow-up mr-1" />
|
|
|
|
<span class="cut-text">{{ $t('message.importSchema') }}</span>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<a class="btn btn-clear c-hand" @click.stop="closeModal" />
|
|
|
|
</div>
|
|
|
|
<div class="modal-body pb-0">
|
|
|
|
{{ sqlFile }}
|
2022-03-05 18:55:11 +01:00
|
|
|
<div v-if="queryErrors.length > 0" class="mt-2">
|
|
|
|
<label>{{ $tc('message.importQueryErrors', queryErrors.length) }}</label>
|
|
|
|
<textarea
|
|
|
|
v-model="formattedQueryErrors"
|
|
|
|
class="form-input"
|
|
|
|
rows="5"
|
|
|
|
readonly
|
|
|
|
/>
|
|
|
|
</div>
|
2021-12-28 15:30:07 +01:00
|
|
|
</div>
|
|
|
|
<div class="modal-footer columns">
|
|
|
|
<div class="column col modal-progress-wrapper text-left">
|
|
|
|
<div class="import-progress">
|
|
|
|
<span class="progress-status">
|
2022-03-05 18:55:11 +01:00
|
|
|
{{ progressPercentage }}% - {{ progressStatus }} - {{ $tc('message.executedQueries', queryCount) }}
|
2021-12-28 15:30:07 +01:00
|
|
|
</span>
|
|
|
|
<progress
|
|
|
|
class="progress d-block"
|
|
|
|
:value="progressPercentage"
|
|
|
|
max="100"
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="column col-auto px-0">
|
|
|
|
<button class="btn btn-link" @click.stop="closeModal">
|
2022-03-05 18:55:11 +01:00
|
|
|
{{ completed ? $t('word.close') : $t('word.cancel') }}
|
2021-12-28 15:30:07 +01:00
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script>
|
|
|
|
import { ipcRenderer } from 'electron';
|
|
|
|
import { mapActions, mapGetters } from 'vuex';
|
2022-03-05 18:55:11 +01:00
|
|
|
import moment from 'moment';
|
2021-12-28 15:30:07 +01:00
|
|
|
import Schema from '@/ipc-api/Schema';
|
|
|
|
|
|
|
|
export default {
|
|
|
|
name: 'ModalImportSchema',
|
|
|
|
|
|
|
|
props: {
|
|
|
|
selectedSchema: String
|
|
|
|
},
|
|
|
|
data () {
|
|
|
|
return {
|
|
|
|
sqlFile: '',
|
|
|
|
isImporting: false,
|
|
|
|
progressPercentage: 0,
|
2022-03-05 18:55:11 +01:00
|
|
|
queryCount: 0,
|
|
|
|
completed: false,
|
|
|
|
progressStatus: 'Reading',
|
|
|
|
queryErrors: []
|
2021-12-28 15:30:07 +01:00
|
|
|
};
|
|
|
|
},
|
|
|
|
computed: {
|
|
|
|
...mapGetters({
|
|
|
|
selectedWorkspace: 'workspaces/getSelected',
|
|
|
|
getWorkspace: 'workspaces/getWorkspace'
|
|
|
|
}),
|
|
|
|
currentWorkspace () {
|
|
|
|
return this.getWorkspace(this.selectedWorkspace);
|
2022-03-05 18:55:11 +01:00
|
|
|
},
|
|
|
|
formattedQueryErrors () {
|
|
|
|
return this.queryErrors.map(err =>
|
|
|
|
`Time: ${moment(err.time).format('HH:mm:ss.S')} (${err.time})\nError: ${err.message}`
|
|
|
|
).join('\n\n');
|
2021-12-28 15:30:07 +01:00
|
|
|
}
|
|
|
|
},
|
|
|
|
async created () {
|
|
|
|
window.addEventListener('keydown', this.onKey);
|
|
|
|
|
|
|
|
ipcRenderer.on('import-progress', this.updateProgress);
|
2022-03-05 18:55:11 +01:00
|
|
|
ipcRenderer.on('query-error', this.handleQueryError);
|
2021-12-28 15:30:07 +01:00
|
|
|
},
|
|
|
|
beforeDestroy () {
|
|
|
|
window.removeEventListener('keydown', this.onKey);
|
|
|
|
ipcRenderer.off('import-progress', this.updateProgress);
|
2022-03-05 18:55:11 +01:00
|
|
|
ipcRenderer.off('query-error', this.handleQueryError);
|
2021-12-28 15:30:07 +01:00
|
|
|
},
|
|
|
|
methods: {
|
|
|
|
...mapActions({
|
2022-03-01 19:05:53 +01:00
|
|
|
addNotification: 'notifications/addNotification',
|
2021-12-28 15:30:07 +01:00
|
|
|
refreshSchema: 'workspaces/refreshSchema'
|
|
|
|
}),
|
|
|
|
async startImport (sqlFile) {
|
|
|
|
this.isImporting = true;
|
|
|
|
this.sqlFile = sqlFile;
|
|
|
|
|
|
|
|
const { uid, client } = this.currentWorkspace;
|
|
|
|
const params = {
|
|
|
|
uid,
|
|
|
|
type: client,
|
2022-02-24 13:14:57 +01:00
|
|
|
schema: this.selectedSchema,
|
2021-12-28 15:30:07 +01:00
|
|
|
file: sqlFile
|
|
|
|
};
|
|
|
|
|
2022-02-24 13:14:57 +01:00
|
|
|
try {
|
2022-03-05 18:55:11 +01:00
|
|
|
this.completed = false;
|
2022-02-24 13:14:57 +01:00
|
|
|
const { status, response } = await Schema.import(params);
|
|
|
|
if (status === 'success')
|
|
|
|
this.progressStatus = response.cancelled ? this.$t('word.aborted') : this.$t('word.completed');
|
|
|
|
else {
|
|
|
|
this.progressStatus = response;
|
|
|
|
this.addNotification({ status: 'error', message: response });
|
|
|
|
}
|
2022-03-06 19:54:32 +01:00
|
|
|
this.refreshSchema({ uid, schema: this.selectedSchema });
|
2022-03-05 18:55:11 +01:00
|
|
|
this.completed = true;
|
2022-02-24 13:14:57 +01:00
|
|
|
}
|
|
|
|
catch (err) {
|
|
|
|
this.addNotification({ status: 'error', message: err.stack });
|
|
|
|
}
|
2021-12-28 15:30:07 +01:00
|
|
|
|
|
|
|
this.isImporting = false;
|
|
|
|
},
|
|
|
|
updateProgress (event, state) {
|
|
|
|
this.progressPercentage = Number(state.percentage).toFixed(1);
|
2022-03-05 18:55:11 +01:00
|
|
|
this.queryCount = Number(state.queryCount);
|
|
|
|
},
|
|
|
|
handleQueryError (event, err) {
|
|
|
|
this.queryErrors.push(err);
|
2021-12-28 15:30:07 +01:00
|
|
|
},
|
|
|
|
async closeModal () {
|
|
|
|
let willClose = true;
|
|
|
|
if (this.isImporting) {
|
|
|
|
willClose = false;
|
|
|
|
const { response } = await Schema.abortImport();
|
|
|
|
willClose = response.willAbort;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (willClose)
|
|
|
|
this.$emit('close');
|
|
|
|
},
|
|
|
|
onKey (e) {
|
|
|
|
e.stopPropagation();
|
|
|
|
if (e.key === 'Escape')
|
|
|
|
this.closeModal();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
.modal {
|
|
|
|
|
|
|
|
.modal-container {
|
|
|
|
max-width: 800px;
|
|
|
|
}
|
|
|
|
|
|
|
|
.modal-body {
|
|
|
|
max-height: 60vh;
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
}
|
|
|
|
|
|
|
|
.modal-footer {
|
|
|
|
display: flex;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.progress-status {
|
|
|
|
font-style: italic;
|
|
|
|
font-size: 80%;
|
|
|
|
}
|
|
|
|
</style>
|