feat: create new tables

This commit is contained in:
Fabio Di Stasio 2020-12-03 13:00:54 +01:00
parent f8cf90a89e
commit e6602d1bfa
11 changed files with 348 additions and 18 deletions

View File

@ -165,6 +165,16 @@ export default (connections) => {
}
});
ipcMain.handle('create-table', async (event, params) => {
try {
await connections[params.uid].createTable(params);
return { status: 'success' };
}
catch (err) {
return { status: 'error', response: err.toString() };
}
});
ipcMain.handle('alter-table', async (event, params) => {
try {
await connections[params.uid].alterTable(params);

View File

@ -306,13 +306,33 @@ export class MySQLClient extends AntaresCore {
name: row.Engine,
support: row.Support,
comment: row.Comment,
transactions: row.Trasactions,
transactions: row.Transactions,
xa: row.XA,
savepoints: row.Savepoints
savepoints: row.Savepoints,
isDefault: row.Support.includes('DEFAULT')
};
});
}
/**
* CREATE TABLE
*
* @returns {Array.<Object>} parameters
* @memberof MySQLClient
*/
async createTable (params) {
const {
name,
collation,
comment,
engine
} = params;
const sql = `CREATE TABLE \`${name}\` (\`${name}_ID\` INT NULL) COMMENT='${comment}', COLLATE='${collation}', ENGINE=${engine}`;
return await this.raw(sql);
}
/**
* ALTER TABLE
*

View File

@ -0,0 +1,122 @@
<template>
<ConfirmModal
:confirm-text="$t('word.confirm')"
size="400"
@confirm="confirmOptionsChange"
@hide="$emit('close')"
>
<template :slot="'header'">
<div class="d-flex">
<i class="mdi mdi-24px mdi-table-plus mr-1" /> {{ $t('message.createNewTable') }}
</div>
</template>
<div :slot="'body'">
<form class="form-horizontal">
<div class="form-group">
<label class="form-label col-4">
{{ $t('word.name') }}
</label>
<div class="column">
<input
v-model="localOptions.name"
class="form-input"
type="text"
>
</div>
</div>
<div class="form-group">
<label class="form-label col-4">
{{ $t('word.comment') }}
</label>
<div class="column">
<input
v-model="localOptions.comment"
class="form-input"
type="text"
>
</div>
</div>
<div class="form-group">
<label class="form-label col-4">
{{ $t('word.collation') }}
</label>
<div class="column">
<select v-model="localOptions.collation" class="form-select">
<option
v-for="collation in workspace.collations"
:key="collation.id"
:value="collation.collation"
>
{{ collation.collation }}
</option>
</select>
</div>
</div>
<div class="form-group">
<label class="form-label col-4">
{{ $t('word.engine') }}
</label>
<div class="column">
<select v-model="localOptions.engine" class="form-select">
<option
v-for="engine in workspace.engines"
:key="engine.name"
:value="engine.name"
>
{{ engine.name }}
</option>
</select>
</div>
</div>
</form>
</div>
</ConfirmModal>
</template>
<script>
import { mapGetters } from 'vuex';
import ConfirmModal from '@/components/BaseConfirmModal';
export default {
name: 'ModalNewTable',
components: {
ConfirmModal
},
props: {
table: String,
workspace: Object
},
data () {
return {
localOptions: {
name: '',
comment: '',
collation: '',
engine: ''
},
isOptionsChanging: false
};
},
computed: {
...mapGetters({
selectedWorkspace: 'workspaces/getSelected',
getDatabaseVariable: 'workspaces/getDatabaseVariable'
}),
defaultCollation () {
return this.getDatabaseVariable(this.selectedWorkspace, 'collation_server').value || '';
},
defaultEngine () {
return this.workspace.engines.find(engine => engine.isDefault).name;
}
},
mounted () {
this.localOptions.collation = this.defaultCollation;
this.localOptions.engine = this.defaultEngine;
},
methods: {
confirmOptionsChange () {
this.$emit('open-create-table-editor', this.localOptions);
}
}
};
</script>

View File

@ -39,6 +39,7 @@
:database="db"
:connection="connection"
@show-database-context="openDatabaseContext"
@show-table-context="openTableContext"
/>
</div>
</div>
@ -47,11 +48,18 @@
@close="hideNewDBModal"
@reload="refresh"
/>
<ModalNewTable
v-if="isNewTableModal"
:workspace="workspace"
@close="hideCreateTableModal"
@open-create-table-editor="openCreateTableEditor"
/>
<DatabaseContext
v-if="isDatabaseContext"
:selected-database="selectedDatabase"
:context-event="databaseContextEvent"
@close-context="closeDatabaseContext"
@show-create-table-modal="showCreateTableModal"
@reload="refresh"
/>
</div>
@ -60,10 +68,12 @@
<script>
import { mapGetters, mapActions } from 'vuex';
import _ from 'lodash';
import Tables from '@/ipc-api/Tables';
import WorkspaceConnectPanel from '@/components/WorkspaceConnectPanel';
import WorkspaceExploreBarDatabase from '@/components/WorkspaceExploreBarDatabase';
import DatabaseContext from '@/components/WorkspaceExploreBarDatabaseContext';
import ModalNewDatabase from '@/components/ModalNewDatabase';
import ModalNewTable from '@/components/ModalNewTable';
export default {
name: 'WorkspaceExploreBar',
@ -71,7 +81,8 @@ export default {
WorkspaceConnectPanel,
WorkspaceExploreBarDatabase,
DatabaseContext,
ModalNewDatabase
ModalNewDatabase,
ModalNewTable
},
props: {
connection: Object,
@ -81,6 +92,7 @@ export default {
return {
isRefreshing: false,
isNewDBModal: false,
isNewTableModal: false,
localWidth: null,
isDatabaseContext: false,
isTableContext: false,
@ -128,6 +140,9 @@ export default {
...mapActions({
disconnectWorkspace: 'workspaces/removeConnected',
refreshStructure: 'workspaces/refreshStructure',
changeBreadcrumbs: 'workspaces/changeBreadcrumbs',
selectTab: 'workspaces/selectTab',
addNotification: 'notifications/addNotification',
changeExplorebarSize: 'settings/changeExplorebarSize'
}),
async refresh () {
@ -153,15 +168,44 @@ export default {
hideNewDBModal () {
this.isNewDBModal = false;
},
showCreateTableModal () {
this.closeDatabaseContext();
this.isNewTableModal = true;
},
hideCreateTableModal () {
this.isNewTableModal = false;
},
async openCreateTableEditor (payload) {
const params = {
uid: this.connection.uid,
...payload
};
const { status, response } = await Tables.createTable(params);
if (status === 'success') {
await this.refresh();
this.changeBreadcrumbs({ schema: this.selectedDatabase, table: payload.name });
this.selectTab({ uid: this.workspace.uid, tab: 'prop' });
}
else
this.addNotification({ status: 'error', message: response });
},
openDatabaseContext (payload) {
this.isTableContext = false;
this.selectedDatabase = payload.database;
this.databaseContextEvent = payload.event;
this.isDatabaseContext = true;
},
closeDatabaseContext () {
this.isDatabaseContext = false;
this.selectedDatabase = '';
},
openTableContext (payload) {
this.selectedTable = payload.table;
this.tableContextEvent = payload.event;
this.isTableContext = true;
},
closeTableContext () {
this.isDatabaseContext = false;
}
}
};

View File

@ -70,8 +70,8 @@ export default {
showDatabaseContext (event, database) {
this.$emit('show-database-context', { event, database });
},
showTableContext (table) {
this.$emit('show-table-context', table);
showTableContext (event, table) {
this.$emit('show-table-context', { event, table });
},
piePercentage (val) {
const perc = val / this.maxSize * 100;

View File

@ -7,7 +7,7 @@
<span class="d-flex"><i class="mdi mdi-18px mdi-plus text-light pr-1" /> {{ $t('word.add') }}</span>
<i class="mdi mdi-18px mdi-chevron-right text-light pl-1" />
<div class="context-submenu">
<div class="context-element">
<div class="context-element" @click="showCreateTableModal">
<span class="d-flex"><i class="mdi mdi-18px mdi-table text-light pr-1" /> {{ $t('word.table') }}</span>
</div>
</div>
@ -74,10 +74,11 @@ export default {
},
methods: {
...mapActions({
deleteConnection: 'connections/deleteConnection',
showEditModal: 'application/showEditConnModal',
addNotification: 'notifications/addNotification'
}),
showCreateTableModal () {
this.$emit('show-create-table-modal');
},
showDeleteModal () {
this.isDeleteModal = true;
},

View File

@ -0,0 +1,115 @@
<template>
<BaseContextMenu
:context-event="contextEvent"
@close-context="closeContext"
>
<div class="context-element">
<span class="d-flex"><i class="mdi mdi-18px mdi-plus text-light pr-1" /> {{ $t('word.add') }}</span>
<i class="mdi mdi-18px mdi-chevron-right text-light pl-1" />
<div class="context-submenu">
<div class="context-element" @click="showCreateTableModal">
<span class="d-flex"><i class="mdi mdi-18px mdi-table text-light pr-1" /> {{ $t('word.table') }}</span>
</div>
</div>
</div>
<div class="context-element" @click="showEditModal">
<span class="d-flex"><i class="mdi mdi-18px mdi-pencil text-light pr-1" /> {{ $t('word.edit') }}</span>
</div>
<div class="context-element" @click="showDeleteModal">
<span class="d-flex"><i class="mdi mdi-18px mdi-delete text-light pr-1" /> {{ $t('word.delete') }}</span>
</div>
<ConfirmModal
v-if="isDeleteModal"
@confirm="deleteDatabase"
@hide="hideDeleteModal"
>
<template slot="header">
<div class="d-flex">
<i class="mdi mdi-24px mdi-database-remove mr-1" /> {{ $t('message.deleteDatabase') }}
</div>
</template>
<div slot="body">
<div class="mb-2">
{{ $t('message.deleteCorfirm') }} "<b>{{ selectedDatabase }}</b>"?
</div>
</div>
</ConfirmModal>
<ModalEditDatabase
v-if="isEditModal"
:selected-database="selectedDatabase"
@close="hideEditModal"
/>
</BaseContextMenu>
</template>
<script>
import { mapGetters, mapActions } from 'vuex';
import BaseContextMenu from '@/components/BaseContextMenu';
import ConfirmModal from '@/components/BaseConfirmModal';
import Tables from '@/ipc-api/Tables';
export default {
name: 'WorkspaceExploreBarTableContext',
components: {
BaseContextMenu,
ConfirmModal
},
props: {
contextEvent: MouseEvent,
selectedTable: String
},
data () {
return {
isDeleteModal: false
};
},
computed: {
...mapGetters({
selectedWorkspace: 'workspaces/getSelected'
})
},
methods: {
...mapActions({
addNotification: 'notifications/addNotification'
}),
showCreateTableModal () {
this.$emit('show-create-table-modal');
},
showDeleteModal () {
this.isDeleteModal = true;
},
hideDeleteModal () {
this.isDeleteModal = false;
},
showEditModal () {
this.isEditModal = true;
},
hideEditModal () {
this.isEditModal = false;
this.closeContext();
},
closeContext () {
this.$emit('close-context');
},
async deleteDatabase () {
try {
const { status, response } = await Database.deleteDatabase({
uid: this.selectedWorkspace,
database: this.selectedDatabase
});
if (status === 'success') {
this.closeContext();
this.$emit('reload');
}
else
this.addNotification({ status: 'error', message: response });
}
catch (err) {
this.addNotification({ status: 'error', message: err.stack });
}
}
}
};
</script>

View File

@ -107,7 +107,9 @@ module.exports = {
onUpdate: 'On update',
deleteField: 'Delete field',
createNewIndex: 'Create new index',
addToIndex: 'Add to index'
addToIndex: 'Add to index',
createNewTable: 'Create new table',
emptyTable: 'Empty table'
},
// Date and Time
short: {

View File

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 34 32"><path fill="#444" d="M21.576 3.59c-1.115-.994-2.465-.595-3.798.588a9.407 9.407 0 00-.591.579c-2.279 2.418-4.395 6.897-5.053 10.318.256.519.456 1.182.588 1.688.034.13.064.252.089.355.058.245.089.405.089.405s-.02-.077-.104-.321l-.055-.158a1.44 1.44 0 00-.035-.087c-.149-.346-.56-1.075-.741-1.393-.155.457-.292.884-.406 1.271.523.956.841 2.595.841 2.595s-.028-.106-.159-.477c-.117-.328-.697-1.345-.835-1.583-.235.869-.329 1.455-.244 1.598.164.277.32.754.457 1.282.309 1.189.524 2.637.524 2.637l.019.244c-.043.999-.017 2.034.06 2.97.103 1.239.295 2.303.541 2.873l.167-.091c-.361-1.122-.508-2.593-.444-4.289.097-2.593.694-5.719 1.796-8.978 1.863-4.919 4.447-8.866 6.811-10.751-2.155 1.947-5.073 8.248-5.946 10.581-.978 2.613-1.671 5.065-2.088 7.414.721-2.202 3.05-3.149 3.05-3.149s1.143-1.409 2.478-3.422c-.8.182-2.113.495-2.553.68-.649.272-.824.365-.824.365s2.102-1.28 3.905-1.86c2.48-3.906 5.182-9.456 2.461-11.884z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 34 32"><path fill="#fff" d="M21.576 3.59c-1.115-.994-2.465-.595-3.798.588a9.407 9.407 0 00-.591.579c-2.279 2.418-4.395 6.897-5.053 10.318.256.519.456 1.182.588 1.688.034.13.064.252.089.355.058.245.089.405.089.405s-.02-.077-.104-.321l-.055-.158a1.44 1.44 0 00-.035-.087c-.149-.346-.56-1.075-.741-1.393-.155.457-.292.884-.406 1.271.523.956.841 2.595.841 2.595s-.028-.106-.159-.477c-.117-.328-.697-1.345-.835-1.583-.235.869-.329 1.455-.244 1.598.164.277.32.754.457 1.282.309 1.189.524 2.637.524 2.637l.019.244c-.043.999-.017 2.034.06 2.97.103 1.239.295 2.303.541 2.873l.167-.091c-.361-1.122-.508-2.593-.444-4.289.097-2.593.694-5.719 1.796-8.978 1.863-4.919 4.447-8.866 6.811-10.751-2.155 1.947-5.073 8.248-5.946 10.581-.978 2.613-1.671 5.065-2.088 7.414.721-2.202 3.05-3.149 3.05-3.149s1.143-1.409 2.478-3.422c-.8.182-2.113.495-2.553.68-.649.272-.824.365-.824.365s2.102-1.28 3.905-1.86c2.48-3.906 5.182-9.456 2.461-11.884z"/></svg>

Before

Width:  |  Height:  |  Size: 1004 B

After

Width:  |  Height:  |  Size: 1004 B

View File

@ -34,6 +34,10 @@ export default class {
return ipcRenderer.invoke('get-foreign-list', params);
}
static createTable (params) {
return ipcRenderer.invoke('create-table', params);
}
static alterTable (params) {
return ipcRenderer.invoke('alter-table', params);
}

View File

@ -3,14 +3,15 @@ import Connection from '@/ipc-api/Connection';
import Database from '@/ipc-api/Database';
import { uidGen } from 'common/libs/uidGen';
const tabIndex = [];
let lastBreadcrumb = '';
let lastBreadcrumbs = {};
export default {
namespaced: true,
strict: true,
state: {
workspaces: [],
selected_workspace: null
selected_workspace: null,
has_unsaved_changes: false
},
getters: {
getSelected: state => {
@ -295,13 +296,24 @@ export default {
dispatch('newTab', uid);
},
changeBreadcrumbs ({ commit, getters }, payload) {
if (lastBreadcrumb.schema === payload.schema && lastBreadcrumb.table !== null && payload.table === null) return;
const breadcrumbsObj = {
schema: null,
table: null,
trigger: null,
procedure: null,
scheduler: null
};
if (lastBreadcrumb.schema !== payload.schema)
const hasLastChildren = Object.keys(lastBreadcrumbs).filter(b => b !== 'schema').some(b => lastBreadcrumbs[b]);
const hasChildren = Object.keys(payload).filter(b => b !== 'schema').some(b => payload[b]);
if (lastBreadcrumbs.schema === payload.schema && hasLastChildren && !hasChildren) return;
if (lastBreadcrumbs.schema !== payload.schema)
Database.useSchema({ uid: getters.getSelected, schema: payload.schema });
commit('CHANGE_BREADCRUMBS', { uid: getters.getSelected, breadcrumbs: payload });
lastBreadcrumb = { ...payload };
commit('CHANGE_BREADCRUMBS', { uid: getters.getSelected, breadcrumbs: { ...breadcrumbsObj, ...payload } });
lastBreadcrumbs = { ...breadcrumbsObj, ...payload };
},
newTab ({ commit }, uid) {
commit('NEW_TAB', uid);