mirror of https://github.com/Fabio286/antares.git
feat: edit database collation
This commit is contained in:
parent
4288a1fd33
commit
54717e1f6a
|
@ -14,6 +14,18 @@ export default connections => {
|
|||
}
|
||||
});
|
||||
|
||||
ipcMain.handle('update-database', async (event, params) => {
|
||||
try {
|
||||
const query = `ALTER DATABASE \`${params.name}\` COLLATE ${params.collation}`;
|
||||
await connections[params.uid].raw(query);
|
||||
|
||||
return { status: 'success' };
|
||||
}
|
||||
catch (err) {
|
||||
return { status: 'error', response: err.toString() };
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle('delete-database', async (event, params) => {
|
||||
try {
|
||||
const query = `DROP DATABASE \`${params.database}\``;
|
||||
|
@ -26,6 +38,18 @@ export default connections => {
|
|||
}
|
||||
});
|
||||
|
||||
ipcMain.handle('get-database-collation', async (event, params) => {
|
||||
try {
|
||||
const query = `SELECT \`DEFAULT_COLLATION_NAME\` FROM \`information_schema\`.\`SCHEMATA\` WHERE \`SCHEMA_NAME\`='${params.database}'`;
|
||||
const collation = await connections[params.uid].raw(query);
|
||||
|
||||
return { status: 'success', response: collation.rows.length ? collation.rows[0].DEFAULT_COLLATION_NAME : '' };
|
||||
}
|
||||
catch (err) {
|
||||
return { status: 'error', response: err.toString() };
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle('get-structure', async (event, uid) => {
|
||||
try {
|
||||
const structure = await connections[uid].getStructure();
|
||||
|
|
|
@ -36,6 +36,7 @@ export class MySQLClient extends AntaresCore {
|
|||
*/
|
||||
async getStructure () {
|
||||
const { rows: databases } = await this.raw('SHOW DATABASES');
|
||||
// TODO: SHOW TABLE STATUS FROM `{DATABASE_NAME}`;
|
||||
|
||||
const { rows: tables } = await this
|
||||
.select('*')
|
||||
|
@ -44,10 +45,30 @@ export class MySQLClient extends AntaresCore {
|
|||
.orderBy({ TABLE_SCHEMA: 'ASC', TABLE_NAME: 'ASC' })
|
||||
.run();
|
||||
|
||||
return databases.map(db => {
|
||||
const { rows: functions } = await this.raw('SHOW FUNCTION STATUS');
|
||||
const { rows: procedures } = await this.raw('SHOW PROCEDURE STATUS');
|
||||
const { rows: schedulers } = await this.raw('SELECT *, EVENT_SCHEMA AS `Db`, EVENT_NAME AS `Name` FROM information_schema.`EVENTS`');
|
||||
|
||||
const triggersArr = [];
|
||||
for (const db of databases) {
|
||||
let { rows: triggers } = await this.raw(`SHOW TRIGGERS FROM \`${db.Database}\``);
|
||||
if (triggers.length) {
|
||||
triggers = triggers.map(trigger => {
|
||||
trigger.Db = db.Database;
|
||||
return trigger;
|
||||
});
|
||||
triggersArr.push(...triggers);
|
||||
}
|
||||
}
|
||||
|
||||
return databases.map(db => { // TODO: remap all objects,
|
||||
return {
|
||||
name: db.Database,
|
||||
tables: tables.filter(table => table.TABLE_SCHEMA === db.Database)// TODO: remap tables objects
|
||||
tables: tables.filter(table => table.TABLE_SCHEMA === db.Database),
|
||||
functions: functions.filter(func => func.Db === db.Database),
|
||||
procedures: procedures.filter(procedure => procedure.Db === db.Database),
|
||||
triggers: triggersArr.filter(trigger => trigger.Db === db.Database),
|
||||
schedulers: schedulers.filter(scheduler => scheduler.Db === db.Database)
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
|
@ -0,0 +1,151 @@
|
|||
<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-edit mr-1" /> {{ $t('message.editDatabase') }}
|
||||
</div>
|
||||
</div>
|
||||
<a class="btn btn-clear c-hand" @click.stop="closeModal" />
|
||||
</div>
|
||||
<div class="modal-body pb-0">
|
||||
<div class="content">
|
||||
<form class="form-horizontal">
|
||||
<div class="form-group">
|
||||
<div class="col-3">
|
||||
<label class="form-label">{{ $t('word.name') }}:</label>
|
||||
</div>
|
||||
<div class="col-9">
|
||||
<input
|
||||
v-model="database.name"
|
||||
class="form-input"
|
||||
type="text"
|
||||
required
|
||||
:placeholder="$t('message.databaseName')"
|
||||
readonly
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-3">
|
||||
<label class="form-label">{{ $t('word.collation') }}:</label>
|
||||
</div>
|
||||
<div class="col-9">
|
||||
<select v-model="database.collation" class="form-select">
|
||||
<option
|
||||
v-for="collation in collations"
|
||||
:key="collation.id"
|
||||
:value="collation.collation"
|
||||
>
|
||||
{{ collation.collation }}
|
||||
</option>
|
||||
</select>
|
||||
<small>{{ $t('message.serverDefault') }}: {{ defaultCollation }}</small>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer text-light">
|
||||
<button class="btn btn-primary mr-2" @click.stop="updateDatabase">
|
||||
{{ $t('word.update') }}
|
||||
</button>
|
||||
<button class="btn btn-link" @click.stop="closeModal">
|
||||
{{ $t('word.close') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters, mapActions } from 'vuex';
|
||||
import Database from '@/ipc-api/Database';
|
||||
|
||||
export default {
|
||||
name: 'ModalEditDatabase',
|
||||
props: {
|
||||
selectedDatabase: String
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
database: {
|
||||
name: '',
|
||||
prevName: '',
|
||||
collation: ''
|
||||
}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
selectedWorkspace: 'workspaces/getSelected',
|
||||
getWorkspace: 'workspaces/getWorkspace',
|
||||
getDatabaseVariable: 'workspaces/getDatabaseVariable'
|
||||
}),
|
||||
collations () {
|
||||
return this.getWorkspace(this.selectedWorkspace).collations;
|
||||
},
|
||||
defaultCollation () {
|
||||
return this.getDatabaseVariable(this.selectedWorkspace, 'collation_server').value || '';
|
||||
}
|
||||
},
|
||||
async created () {
|
||||
let actualCollation;
|
||||
try {
|
||||
const { status, response } = await Database.getDatabaseCollation({ uid: this.selectedWorkspace, database: this.selectedDatabase });
|
||||
|
||||
if (status === 'success')
|
||||
actualCollation = response;
|
||||
|
||||
else
|
||||
this.addNotification({ status: 'error', message: response });
|
||||
}
|
||||
catch (err) {
|
||||
this.addNotification({ status: 'error', message: err.stack });
|
||||
}
|
||||
|
||||
this.database = {
|
||||
name: this.selectedDatabase,
|
||||
prevName: this.selectedDatabase,
|
||||
collation: actualCollation || this.defaultCollation,
|
||||
prevCollation: actualCollation || this.defaultCollation
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
...mapActions({
|
||||
addNotification: 'notifications/addNotification'
|
||||
}),
|
||||
async updateDatabase () {
|
||||
if (this.database.collation !== this.database.prevCollation) {
|
||||
try {
|
||||
const { status, response } = await Database.updateDatabase({
|
||||
uid: this.selectedWorkspace,
|
||||
...this.database
|
||||
});
|
||||
|
||||
if (status === 'success')
|
||||
this.closeModal();
|
||||
else
|
||||
this.addNotification({ status: 'error', message: response });
|
||||
}
|
||||
catch (err) {
|
||||
this.addNotification({ status: 'error', message: err.stack });
|
||||
}
|
||||
}
|
||||
else
|
||||
this.closeModal();
|
||||
},
|
||||
closeModal () {
|
||||
this.$emit('close');
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.modal-container {
|
||||
max-width: 360px;
|
||||
}
|
||||
</style>
|
|
@ -64,7 +64,7 @@ import { mapGetters, mapActions } from 'vuex';
|
|||
import Database from '@/ipc-api/Database';
|
||||
|
||||
export default {
|
||||
name: 'ModalNewDB',
|
||||
name: 'ModalNewDatabase',
|
||||
data () {
|
||||
return {
|
||||
database: {
|
|
@ -42,7 +42,7 @@
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
<ModalNewDB
|
||||
<ModalNewDatabase
|
||||
v-if="isNewDBModal"
|
||||
@close="hideNewDBModal"
|
||||
@reload="refresh"
|
||||
|
@ -63,7 +63,7 @@ import _ from 'lodash';
|
|||
import WorkspaceConnectPanel from '@/components/WorkspaceConnectPanel';
|
||||
import WorkspaceExploreBarDatabase from '@/components/WorkspaceExploreBarDatabase';
|
||||
import DatabaseContext from '@/components/WorkspaceExploreBarDatabaseContext';
|
||||
import ModalNewDB from '@/components/ModalNewDB';
|
||||
import ModalNewDatabase from '@/components/ModalNewDatabase';
|
||||
|
||||
export default {
|
||||
name: 'WorkspaceExploreBar',
|
||||
|
@ -71,7 +71,7 @@ export default {
|
|||
WorkspaceConnectPanel,
|
||||
WorkspaceExploreBarDatabase,
|
||||
DatabaseContext,
|
||||
ModalNewDB
|
||||
ModalNewDatabase
|
||||
},
|
||||
props: {
|
||||
connection: Object,
|
||||
|
@ -131,7 +131,6 @@ export default {
|
|||
changeExplorebarSize: 'settings/changeExplorebarSize'
|
||||
}),
|
||||
async refresh () {
|
||||
console.log('refresh');
|
||||
if (!this.isRefreshing) {
|
||||
this.isRefreshing = true;
|
||||
await this.refreshStructure(this.connection.uid);
|
||||
|
|
|
@ -7,17 +7,17 @@
|
|||
<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> -->
|
||||
<div class="context-element">
|
||||
<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="showConfirmModal">
|
||||
<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="isConfirmModal"
|
||||
v-if="isDeleteModal"
|
||||
@confirm="deleteDatabase"
|
||||
@hide="hideConfirmModal"
|
||||
@hide="hideDeleteModal"
|
||||
>
|
||||
<template slot="header">
|
||||
<div class="d-flex">
|
||||
|
@ -30,6 +30,11 @@
|
|||
</div>
|
||||
</div>
|
||||
</ConfirmModal>
|
||||
<ModalEditDatabase
|
||||
v-if="isEditModal"
|
||||
:selected-database="selectedDatabase"
|
||||
@close="hideEditModal"
|
||||
/>
|
||||
</BaseContextMenu>
|
||||
</template>
|
||||
|
||||
|
@ -37,13 +42,15 @@
|
|||
import { mapGetters, mapActions } from 'vuex';
|
||||
import BaseContextMenu from '@/components/BaseContextMenu';
|
||||
import ConfirmModal from '@/components/BaseConfirmModal';
|
||||
import ModalEditDatabase from '@/components/ModalEditDatabase';
|
||||
import Database from '@/ipc-api/Database';
|
||||
|
||||
export default {
|
||||
name: 'WorkspaceExploreBarDatabaseContext',
|
||||
components: {
|
||||
BaseContextMenu,
|
||||
ConfirmModal
|
||||
ConfirmModal,
|
||||
ModalEditDatabase
|
||||
},
|
||||
props: {
|
||||
contextEvent: MouseEvent,
|
||||
|
@ -51,7 +58,8 @@ export default {
|
|||
},
|
||||
data () {
|
||||
return {
|
||||
isConfirmModal: false
|
||||
isDeleteModal: false,
|
||||
isEditModal: false
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
@ -65,11 +73,18 @@ export default {
|
|||
showEditModal: 'application/showEditConnModal',
|
||||
addNotification: 'notifications/addNotification'
|
||||
}),
|
||||
showConfirmModal () {
|
||||
this.isConfirmModal = true;
|
||||
showDeleteModal () {
|
||||
this.isDeleteModal = true;
|
||||
},
|
||||
hideConfirmModal () {
|
||||
this.isConfirmModal = false;
|
||||
hideDeleteModal () {
|
||||
this.isDeleteModal = false;
|
||||
},
|
||||
showEditModal () {
|
||||
this.isEditModal = true;
|
||||
},
|
||||
hideEditModal () {
|
||||
this.isEditModal = false;
|
||||
this.closeContext();
|
||||
},
|
||||
closeContext () {
|
||||
this.$emit('close-context');
|
||||
|
|
|
@ -6,6 +6,14 @@ export default class {
|
|||
return ipcRenderer.invoke('create-database', params);
|
||||
}
|
||||
|
||||
static updateDatabase (params) {
|
||||
return ipcRenderer.invoke('update-database', params);
|
||||
}
|
||||
|
||||
static getDatabaseCollation (params) {
|
||||
return ipcRenderer.invoke('get-database-collation', params);
|
||||
}
|
||||
|
||||
static deleteDatabase (params) {
|
||||
return ipcRenderer.invoke('delete-database', params);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue