1
1
mirror of https://github.com/Fabio286/antares.git synced 2025-02-17 04:00:48 +01:00

feat: database creation

This commit is contained in:
Fabio 2020-09-25 12:39:58 +02:00
parent c1cdd03938
commit 3d0a83f2cf
12 changed files with 311 additions and 73 deletions

View File

@ -66,36 +66,4 @@ export default connections => {
connections[uid].destroy();
delete connections[uid];
});
ipcMain.handle('get-structure', async (event, uid) => {
try {
const { rows: structure } = await connections[uid]
.select('*')
.schema('information_schema')
.from('TABLES')
.orderBy({ TABLE_SCHEMA: 'ASC', TABLE_NAME: 'ASC' })
.run();
return { status: 'success', response: structure };
}
catch (err) {
return { status: 'error', response: err.toString() };
}
});
ipcMain.handle('raw-query', async (event, { uid, query, schema }) => {
if (!query) return;
try {
if (schema)
await connections[uid].use(schema);
const result = await connections[uid].raw(query, true);
return { status: 'success', response: result };
}
catch (err) {
return { status: 'error', response: err.toString() };
}
});
};

View File

@ -0,0 +1,70 @@
import { ipcMain } from 'electron';
export default connections => {
ipcMain.handle('create-database', async (event, params) => {
try {
const query = `CREATE DATABASE \`${params.name}\` COLLATE ${params.collation}`;
const result = await connections[params.uid].raw(query, true);
return { status: 'success', response: result };
}
catch (err) {
return { status: 'error', response: err.toString() };
}
});
ipcMain.handle('get-structure', async (event, uid) => {
try {
const { rows: structure } = await connections[uid]
.select('*')
.schema('information_schema')
.from('TABLES')
.orderBy({ TABLE_SCHEMA: 'ASC', TABLE_NAME: 'ASC' })
.run();
return { status: 'success', response: structure };
}
catch (err) {
return { status: 'error', response: err.toString() };
}
});
ipcMain.handle('get-collations', async (event, uid) => {
try {
const result = await connections[uid].getCollations();
return { status: 'success', response: result };
}
catch (err) {
return { status: 'error', response: err.toString() };
}
});
ipcMain.handle('get-variables', async (event, uid) => {
try {
const result = await connections[uid].getVariables();
return { status: 'success', response: result };
}
catch (err) {
return { status: 'error', response: err.toString() };
}
});
ipcMain.handle('raw-query', async (event, { uid, query, schema }) => {
if (!query) return;
try {
if (schema)
await connections[uid].use(schema);
const result = await connections[uid].raw(query, true);
return { status: 'success', response: result };
}
catch (err) {
return { status: 'error', response: err.toString() };
}
});
};

View File

@ -2,14 +2,14 @@ import connection from './connection';
import tables from './tables';
import updates from './updates';
import application from './application';
import properties from './properties';
import database from './database';
const connections = {};
export default () => {
connection(connections);
tables(connections);
properties(connections);
database(connections);
updates();
application();
};

View File

@ -1,14 +0,0 @@
import { ipcMain } from 'electron';
export default (connections) => {
ipcMain.handle('get-collations', async (event, uid) => {
try {
const result = await connections[uid].getCollations();
return { status: 'success', response: result };
}
catch (err) {
return { status: 'error', response: err.toString() };
}
});
};

View File

@ -31,9 +31,44 @@ export class MySQLClient extends AntaresCore {
return this.raw(sql);
}
getCollations () {
/**
* SHOW COLLATION
*
* @returns
* @memberof MySQLClient
*/
async getCollations () {
const sql = 'SHOW COLLATION';
return this.raw(sql);
const results = await this.raw(sql);
return results.rows.map(row => {
return {
charset: row.Charset,
collation: row.Collation,
compiled: row.Compiled.includes('Yes'),
default: row.Default.includes('Yes'),
id: row.Id,
sortLen: row.Sortlen
};
});
}
/**
* SHOW VARIABLES
*
* @returns
* @memberof MySQLClient
*/
async getVariables () {
const sql = 'SHOW VARIABLES';
const results = await this.raw(sql);
return results.rows.map(row => {
return {
name: row.Variable_name,
value: row.Value
};
});
}
/**

View File

@ -0,0 +1,125 @@
<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-plus mr-1" /> {{ $t('message.createNewDatabase') }}
</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')"
>
</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="createDatabase">
{{ $t('word.add') }}
</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: 'ModalNewDB',
data () {
return {
database: {
name: '',
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 || '';
}
},
created () {
this.database = { ...this.database, collation: this.defaultCollation };
},
methods: {
...mapActions({
addNotification: 'notifications/addNotification'
}),
async createDatabase () {
try {
const { status, response } = await Database.createDatabase({
uid: this.selectedWorkspace,
...this.database
});
if (status === 'success') {
this.closeModal();
this.$emit('reload');
}
else
this.addNotification({ status: 'error', message: response });
}
catch (err) {
this.addNotification({ status: 'error', message: err.stack });
}
},
closeModal () {
this.$emit('close');
}
}
};
</script>
<style scoped>
.modal-container {
max-width: 360px;
}
</style>

View File

@ -10,13 +10,18 @@
<span class="workspace-explorebar-title">{{ connectionName }}</span>
<span v-if="workspace.connected" class="workspace-explorebar-tools">
<i
class="mdi mdi-18px mdi-refresh c-hand"
class="mdi mdi-18px mdi-database-plus c-hand mr-2"
:title="$t('message.createNewDatabase')"
@click="showNewDBModal"
/>
<i
class="mdi mdi-18px mdi-refresh c-hand mr-2"
:class="{'rotate':isRefreshing}"
:title="$t('word.refresh')"
@click="refresh"
/>
<i
class="mdi mdi-18px mdi-power-plug-off c-hand mr-1 ml-2"
class="mdi mdi-18px mdi-power-plug-off c-hand"
:title="$t('word.disconnect')"
@click="disconnectWorkspace(connection.uid)"
/>
@ -36,6 +41,11 @@
/>
</div>
</div>
<ModalNewDB
v-if="isNewDBModal"
@close="hideNewDBModal"
@reload="refresh"
/>
</div>
</template>
@ -44,12 +54,14 @@ import { mapGetters, mapActions } from 'vuex';
import _ from 'lodash';
import WorkspaceConnectPanel from '@/components/WorkspaceConnectPanel';
import WorkspaceExploreBarDatabase from '@/components/WorkspaceExploreBarDatabase';
import ModalNewDB from '@/components/ModalNewDB';
export default {
name: 'WorkspaceExploreBar',
components: {
WorkspaceConnectPanel,
WorkspaceExploreBarDatabase
WorkspaceExploreBarDatabase,
ModalNewDB
},
props: {
connection: Object,
@ -58,6 +70,7 @@ export default {
data () {
return {
isRefreshing: false,
isNewDBModal: false,
localWidth: null
};
},
@ -117,6 +130,12 @@ export default {
},
stopResize () {
window.removeEventListener('mousemove', this.resize);
},
showNewDBModal () {
this.isNewDBModal = true;
},
hideNewDBModal () {
this.isNewDBModal = false;
}
}
};

View File

@ -44,7 +44,7 @@
</template>
<script>
import Connection from '@/ipc-api/Connection';
import Database from '@/ipc-api/Database';
import Tables from '@/ipc-api/Tables';
import QueryEditor from '@/components/QueryEditor';
import WorkspaceQueryTable from '@/components/WorkspaceQueryTable';
@ -114,7 +114,7 @@ export default {
query
};
const { status, response } = await Connection.rawQuery(params);
const { status, response } = await Database.rawQuery(params);
if (status === 'success') {
this.results = Array.isArray(response) ? response : [response];

View File

@ -75,7 +75,8 @@ module.exports = {
openNewTab: 'Open a new tab',
affectedRows: 'Affected rows',
createNewDatabase: 'Create new Database',
databaseName: 'Database name'
databaseName: 'Database name',
serverDefault: 'Server default'
},
// Date and Time
short: {

View File

@ -17,16 +17,4 @@ export default class {
static disconnect (uid) {
return ipcRenderer.invoke('disconnect', uid);
}
static getStructure (uid) {
return ipcRenderer.invoke('get-structure', uid);
}
static getCollations (uid) {
return ipcRenderer.invoke('get-collations', uid);
}
static rawQuery (params) {
return ipcRenderer.invoke('raw-query', params);
}
}

View File

@ -0,0 +1,24 @@
'use strict';
import { ipcRenderer } from 'electron';
export default class {
static createDatabase (params) {
return ipcRenderer.invoke('create-database', params);
}
static getStructure (uid) {
return ipcRenderer.invoke('get-structure', uid);
}
static getCollations (uid) {
return ipcRenderer.invoke('get-collations', uid);
}
static getVariables (uid) {
return ipcRenderer.invoke('get-variables', uid);
}
static rawQuery (params) {
return ipcRenderer.invoke('raw-query', params);
}
}

View File

@ -1,9 +1,10 @@
'use strict';
import Connection from '@/ipc-api/Connection';
import Database from '@/ipc-api/Database';
import { uidGen } from 'common/libs/uidGen';
const tabIndex = [];
function remapStructure (structure) { // TODO: move to main process and add fields (for autocomplete purpose)
function remapStructure (structure) { // TODO: move to main process and add fields (for autocomplete purpose), also add empty database
const databases = structure.map(table => table.TABLE_SCHEMA)
.filter((value, index, self) => self.indexOf(value) === index);
@ -31,6 +32,9 @@ export default {
getWorkspace: state => uid => {
return state.workspaces.find(workspace => workspace.uid === uid);
},
getDatabaseVariable: state => (uid, name) => {
return state.workspaces.find(workspace => workspace.uid === uid).variables.find(variable => variable.name === name);
},
getWorkspaceTab: (state, getters) => tUid => {
if (!getters.getSelected) return;
const workspace = state.workspaces.find(workspace => workspace.uid === getters.getSelected);
@ -57,8 +61,11 @@ export default {
REFRESH_STRUCTURE (state, { uid, structure }) {
state.workspaces = state.workspaces.map(workspace => workspace.uid === uid ? { ...workspace, structure } : workspace);
},
REFRESH_COLLATIONS (state, { uid, collations }) { // TODO: Save collations
// state.workspaces = state.workspaces.map(workspace => workspace.uid === uid ? { ...workspace, structure } : workspace);
REFRESH_COLLATIONS (state, { uid, collations }) {
state.workspaces = state.workspaces.map(workspace => workspace.uid === uid ? { ...workspace, collations } : workspace);
},
REFRESH_VARIABLES (state, { uid, variables }) {
state.workspaces = state.workspaces.map(workspace => workspace.uid === uid ? { ...workspace, variables } : workspace);
},
ADD_WORKSPACE (state, workspace) {
state.workspaces.push(workspace);
@ -150,6 +157,7 @@ export default {
else {
commit('ADD_CONNECTED', { uid: connection.uid, structure: remapStructure(response) });
dispatch('refreshCollations', connection.uid);
dispatch('refreshVariables', connection.uid);
}
}
catch (err) {
@ -158,7 +166,7 @@ export default {
},
async refreshStructure ({ dispatch, commit }, uid) {
try {
const { status, response } = await Connection.getStructure(uid);
const { status, response } = await Database.getStructure(uid);
if (status === 'error')
dispatch('notifications/addNotification', { status, message: response }, { root: true });
else
@ -170,7 +178,7 @@ export default {
},
async refreshCollations ({ dispatch, commit }, uid) {
try {
const { status, response } = await Connection.getCollations(uid);
const { status, response } = await Database.getCollations(uid);
if (status === 'error')
dispatch('notifications/addNotification', { status, message: response }, { root: true });
else
@ -180,6 +188,18 @@ export default {
dispatch('notifications/addNotification', { status: 'error', message: err.stack }, { root: true });
}
},
async refreshVariables ({ dispatch, commit }, uid) {
try {
const { status, response } = await Database.getVariables(uid);
if (status === 'error')
dispatch('notifications/addNotification', { status, message: response }, { root: true });
else
commit('REFRESH_VARIABLES', { uid, variables: response });
}
catch (err) {
dispatch('notifications/addNotification', { status: 'error', message: err.stack }, { root: true });
}
},
removeConnected ({ commit }, uid) {
Connection.disconnect(uid);
commit('REMOVE_CONNECTED', uid);
@ -203,6 +223,8 @@ export default {
keyUsage: []
}],
structure: {},
variables: [],
collations: [],
breadcrumbs: {}
};