mirror of
https://github.com/Fabio286/antares.git
synced 2025-06-05 21:59:22 +02:00
Improvements
This commit is contained in:
@ -2,6 +2,7 @@
|
|||||||
import { ipcMain } from 'electron';
|
import { ipcMain } from 'electron';
|
||||||
import knex from 'knex';
|
import knex from 'knex';
|
||||||
import InformationSchema from '../models/InformationSchema';
|
import InformationSchema from '../models/InformationSchema';
|
||||||
|
import { RawQuery } from '../models/RawQuery';
|
||||||
|
|
||||||
const connections = {};
|
const connections = {};
|
||||||
|
|
||||||
@ -74,4 +75,19 @@ export default () => {
|
|||||||
return { status: 'error', response: err.toString() };
|
return { status: 'error', response: err.toString() };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ipcMain.on('runQuery', async (event, { connection, query, database }) => {
|
||||||
|
const knexIstance = connections[connection.uid];
|
||||||
|
const Query = new RawQuery({ knexIstance, database });
|
||||||
|
try {
|
||||||
|
Query.runQuery(query);
|
||||||
|
|
||||||
|
Query.on('row', row => {
|
||||||
|
event.sender.send('row', row);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
return { status: 'error', response: err.toString() };
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
22
src/main/models/RawQuery.js
Normal file
22
src/main/models/RawQuery.js
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
'use strict';
|
||||||
|
import { EventEmitter } from 'events';
|
||||||
|
|
||||||
|
export class RawQuery extends EventEmitter {
|
||||||
|
constructor ({ knexIstance, database }) {
|
||||||
|
super();
|
||||||
|
this.conn = knexIstance;
|
||||||
|
this.database = database;
|
||||||
|
}
|
||||||
|
|
||||||
|
async runQuery (query) {
|
||||||
|
if (this.database) await this.conn.raw(`USE \`${this.database}\``);
|
||||||
|
const stream = this.conn.raw(query).stream();
|
||||||
|
stream.on('data', row => {
|
||||||
|
this.emit('row', row);
|
||||||
|
});
|
||||||
|
|
||||||
|
stream.on('error', err => {
|
||||||
|
this.emit('error', err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -89,6 +89,7 @@ export default {
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
height: calc(100vh - #{$excluding-size});
|
height: calc(100vh - #{$excluding-size});
|
||||||
|
width: calc(100% - #{$settingbar-width});
|
||||||
|
|
||||||
> .columns{
|
> .columns{
|
||||||
height: calc(100vh - #{$footer-height});
|
height: calc(100vh - #{$footer-height});
|
||||||
|
@ -85,7 +85,7 @@ export default {
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
max-width: 25rem;
|
max-width: 30rem;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-show="isSelected" class="workspace column columns">
|
<div v-show="isSelected" class="workspace column columns col-gapless">
|
||||||
<WorkspaceExploreBar :connection="connection" :is-selected="isSelected" />
|
<WorkspaceExploreBar :connection="connection" :is-selected="isSelected" />
|
||||||
<div class="workspace-tabs column p-0">
|
<div v-if="workspace.connected" class="workspace-tabs column columns col-gapless">
|
||||||
<ul class="tab tab-block">
|
<ul class="tab tab-block column col-12">
|
||||||
<li
|
<li
|
||||||
v-for="(tab, key) of workspace.tabs"
|
v-for="(tab, key) of workspace.tabs"
|
||||||
:key="tab.uid"
|
:key="tab.uid"
|
||||||
class="tab-item"
|
class="tab-item"
|
||||||
:class="{'active': selectedTab === tab.uid}"
|
:class="{'active': selectedTab === tab.uid}"
|
||||||
>
|
>
|
||||||
<a href="#">Query #{{ key }} <span class="btn btn-clear" /></a>
|
<a href="#">Query #{{ key }} <span v-if="workspace.tabs.length > 1" class="btn btn-clear" /></a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<QueryEditor v-model="query" />
|
<WorkspaceQueryTab :connection="connection" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -21,22 +21,17 @@
|
|||||||
import { mapGetters, mapActions } from 'vuex';
|
import { mapGetters, mapActions } from 'vuex';
|
||||||
import Connection from '@/ipc-api/Connection';
|
import Connection from '@/ipc-api/Connection';
|
||||||
import WorkspaceExploreBar from '@/components/WorkspaceExploreBar';
|
import WorkspaceExploreBar from '@/components/WorkspaceExploreBar';
|
||||||
import QueryEditor from '@/components/QueryEditor';
|
import WorkspaceQueryTab from '@/components/WorkspaceQueryTab';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Workspace',
|
name: 'Workspace',
|
||||||
components: {
|
components: {
|
||||||
WorkspaceExploreBar,
|
WorkspaceExploreBar,
|
||||||
QueryEditor
|
WorkspaceQueryTab
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
connection: Object
|
connection: Object
|
||||||
},
|
},
|
||||||
data () {
|
|
||||||
return {
|
|
||||||
query: ''
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters({
|
...mapGetters({
|
||||||
selectedWorkspace: 'workspaces/getSelected',
|
selectedWorkspace: 'workspaces/getSelected',
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="p-relative">
|
<div class="column col-auto p-relative">
|
||||||
<div ref="resizer" class="workspace-explorebar-resizer" />
|
<div ref="resizer" class="workspace-explorebar-resizer" />
|
||||||
<div
|
<div
|
||||||
ref="explorebar"
|
ref="explorebar"
|
||||||
|
145
src/renderer/components/WorkspaceQueryTab.vue
Normal file
145
src/renderer/components/WorkspaceQueryTab.vue
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
<template>
|
||||||
|
<div class="workspace-query-tab column col-12 columns col-gapless">
|
||||||
|
<div class="workspace-query-runner column col-12">
|
||||||
|
<QueryEditor v-model="query" />
|
||||||
|
<div class="workspace-query-runner-footer">
|
||||||
|
<div class="workspace-query-buttons">
|
||||||
|
<i class="material-icons text-success" @click="runQuery">play_arrow</i>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Schema: <b>{{ workspace.breadcrumbs.database }}</b>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div ref="resultTable" class="workspace-query-results column col-12">
|
||||||
|
<table v-if="results.length" class="table table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th v-for="field in fields" :key="field">
|
||||||
|
{{ field }}
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr v-for="(row, rKey) in results" :key="rKey">
|
||||||
|
<td v-for="(col, cKey) in row" :key="cKey">
|
||||||
|
{{ col }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { ipcRenderer } from 'electron';
|
||||||
|
import QueryEditor from '@/components/QueryEditor';
|
||||||
|
import { mapGetters, mapActions } from 'vuex';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'WorkspaceQueryTab',
|
||||||
|
components: {
|
||||||
|
QueryEditor
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
connection: Object
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
query: '',
|
||||||
|
results: []
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapGetters({
|
||||||
|
getWorkspace: 'workspaces/getWorkspace'
|
||||||
|
}),
|
||||||
|
workspace () {
|
||||||
|
return this.getWorkspace(this.connection.uid);
|
||||||
|
},
|
||||||
|
fields () {
|
||||||
|
return Object.keys(this.results[0]);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
window.addEventListener('resize', this.resizeResults);
|
||||||
|
},
|
||||||
|
destroyed () {
|
||||||
|
window.removeEventListener('resize', this.resizeResults);
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapActions({
|
||||||
|
addNotification: 'notifications/addNotification'
|
||||||
|
}),
|
||||||
|
async runQuery () {
|
||||||
|
this.results = [];
|
||||||
|
this.resizeResults();
|
||||||
|
|
||||||
|
const params = {
|
||||||
|
connection: this.connection,
|
||||||
|
query: this.query,
|
||||||
|
database: this.workspace.breadcrumbs.database
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
ipcRenderer.send('runQuery', params);
|
||||||
|
|
||||||
|
ipcRenderer.on('row', (event, row) => {
|
||||||
|
this.results.push(row);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
this.addNotification({ status: 'error', message: err.stack });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
resizeResults (e) {
|
||||||
|
const el = this.$refs.resultTable;
|
||||||
|
const footer = document.getElementById('footer');
|
||||||
|
|
||||||
|
if (el) {
|
||||||
|
const size = window.innerHeight - el.getBoundingClientRect().top - footer.offsetHeight;
|
||||||
|
el.style.height = size + 'px';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.workspace-tabs{
|
||||||
|
align-content: baseline;
|
||||||
|
|
||||||
|
.workspace-query-runner{
|
||||||
|
|
||||||
|
.workspace-query-runner-footer{
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: .2rem .6rem;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.workspace-query-buttons{
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.workspace-query-results{
|
||||||
|
overflow: auto;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
th{
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
background: $bg-color;
|
||||||
|
border-color: $bg-color-light;
|
||||||
|
}
|
||||||
|
|
||||||
|
td{
|
||||||
|
border-color: $bg-color-light;
|
||||||
|
padding: 0 .4rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
Reference in New Issue
Block a user