多维表格
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

302 lines
9.0 KiB

<template>
<div>
<v-btn
:loading="projectCreation"
:disabled="projectCreation"
class="primary nc-btn-use-template"
x-large
@click="useTemplate('rest')"
>
<slot>Use template</slot>
</v-btn>
</div>
</template>
<script>
import { SqlUiFactory } from 'nocodb-sdk';
import colors from '~/mixins/colors';
export default {
name: 'CreateProjectFromTemplateBtn',
mixins: [colors],
props: {
quickImport: Boolean,
loading: Boolean,
importToProject: Boolean,
templateData: [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 {
localTemplateData: null,
projectCreation: false,
tableCreation: false,
loaderMessagesIndex: 0,
loaderMessages: [
'Setting up new database configs',
'Inferring database schema',
'Generating APIs.',
'Generating APIs..',
'Generating APIs...',
'Generating APIs....',
'Please wait',
'Please wait.',
'Please wait..',
'Please wait...',
'Please wait..',
'Please wait.',
'Please wait',
'Please wait.',
'Please wait..',
'Please wait...',
'Please wait..',
'Please wait.',
'Please wait..',
'Please wait...',
],
};
},
watch: {
templateData: {
deep: true,
handler(data) {
this.localTemplateData = JSON.parse(JSON.stringify(data));
},
},
},
created() {
this.localTemplateData = JSON.parse(JSON.stringify(this.templateData));
},
methods: {
async useTemplate(projectType) {
if (!this.valid) {
return this.$toast.error(this.validationErrorMsg).goAway(3000);
}
// this.$emit('useTemplate', type)
// this.projectCreation = true
let interv;
try {
interv = setInterval(() => {
this.loaderMessagesIndex =
this.loaderMessagesIndex < this.loaderMessages.length - 1 ? this.loaderMessagesIndex + 1 : 6;
this.$store.commit('loader/MutMessage', this.loaderMessages[this.loaderMessagesIndex]);
}, 1000);
const projectId = this.$store.state.project.project.id;
let firstTable = null;
// Not available now
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 {
// Create tables
try {
for (const t of this.localTemplateData.tables) {
// enrich system fields if not provided
// e.g. id, created_at, updated_at
const systemColumns = SqlUiFactory.create({ client: this.$store.state.project.project.bases[0].type })
.getNewTableColumns()
.filter(c => c.column_name !== 'title');
for (const systemColumn of systemColumns) {
if (!t.columns.some(c => c.column_name.toLowerCase() === systemColumn.column_name.toLowerCase())) {
t.columns.push(systemColumn);
}
}
// set pk & rqd if ID is provided
for (const column of t.columns) {
if (column.column_name.toLowerCase() === 'id' && !('pk' in column)) {
column.pk = true;
column.rqd = true;
break;
}
}
// create table
const table = await this.$api.dbTable.create(projectId, {
table_name: t.table_name,
title: '',
columns: t.columns,
});
t.table_title = table.title;
// open the first table after import
if (firstTable === null) {
firstTable = table;
}
// set primary value
await this.$api.dbTableColumn.primaryColumnSet(table.columns[0].id);
}
this.tableCreation = true;
} catch (e) {
this.$toast.error(await this._extractSdkResponseErrorMsg(e)).goAway(3000);
this.tableCreation = false;
} finally {
clearInterval(interv);
}
}
if (!this.tableCreation) {
// failed to create table
return;
}
// Bulk import data
if (this.importData) {
this.$store.commit('loader/MutMessage', 'Importing excel data to project');
await this.importDataToProject();
}
// reload table list
this.$store
.dispatch('project/_loadTables', {
dbKey: '0.projectJson.envs._noco.db.0',
key: '0.projectJson.envs._noco.db.0.tables',
_nodes: {
dbAlias: 'db',
env: '_noco',
type: 'tableDir',
},
})
.then(() => {
// add tab - choose the first one if multiple tables are created
this.$store
.dispatch('tabs/loadFirstCreatedTableTab', {
title: firstTable.title,
})
.then(item => {
// set active tab - choose the first one if multiple tables are created
this.$nextTick(() => {
this.$router.push({
query: {
name: item.name || '',
dbalias: (item._nodes && item._nodes.dbAlias) || '',
type: (item._nodes && item._nodes.type) || 'table',
},
});
});
});
});
// confetti effect
this.simpleAnim();
} catch (e) {
console.log(e);
this.$toast.error(await this._extractSdkResponseErrorMsg(e)).goAway(3000);
} finally {
clearInterval(interv);
this.$store.commit('loader/MutMessage', null);
this.projectCreation = false;
this.tableCreation = false;
this.$emit('closeModal');
}
},
async importDataToProject() {
let total = 0;
let progress = 0;
const projectName = this.$store.state.project.project.title;
await Promise.all(
this.localTemplateData.tables.map(v =>
(async tableMeta => {
const tableName = tableMeta.table_title;
const data = this.importData[tableMeta.ref_table_name];
total += data.length;
for (let i = 0; i < data.length; i += 500) {
this.$store.commit('loader/MutMessage', `Importing data to ${projectName}: ${progress}/${total} records`);
this.$store.commit('loader/MutProgress', Math.round(progress && (100 * progress) / total));
const batchData = this.remapColNames(data.slice(i, i + 500), tableMeta.columns);
await this.$api.dbTableRow.bulkCreate('noco', projectName, tableName, batchData);
progress += batchData.length;
}
this.$store.commit('loader/MutClear');
})(v)
)
);
},
remapColNames(batchData, columns) {
return batchData.map(data =>
(columns || []).reduce(
(aggObj, col) => ({
...aggObj,
[col.column_name]: data[col.ref_column_name || col.column_name],
}),
{}
)
);
},
simpleAnim() {
const count = 200;
const defaults = {
origin: { y: 0.7 },
};
function fire(particleRatio, opts) {
window.confetti(
Object.assign({}, defaults, opts, {
particleCount: Math.floor(count * particleRatio),
})
);
}
fire(0.25, {
spread: 26,
startVelocity: 55,
});
fire(0.2, {
spread: 60,
});
fire(0.35, {
spread: 100,
decay: 0.91,
scalar: 0.8,
});
fire(0.1, {
spread: 120,
startVelocity: 25,
decay: 0.92,
scalar: 1.2,
});
fire(0.1, {
spread: 120,
startVelocity: 45,
});
},
},
};
</script>
<style scoped></style>