mirror of https://github.com/Fabio286/antares.git
Added table tab
This commit is contained in:
parent
29812f7ee3
commit
68b128c550
|
@ -10931,11 +10931,6 @@
|
||||||
"ajv-keywords": "^3.4.1"
|
"ajv-keywords": "^3.4.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"scrollparent": {
|
|
||||||
"version": "2.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/scrollparent/-/scrollparent-2.0.1.tgz",
|
|
||||||
"integrity": "sha1-cV1bnMV3YPsivczDvvtb/gaxoxc="
|
|
||||||
},
|
|
||||||
"scss-tokenizer": {
|
"scss-tokenizer": {
|
||||||
"version": "0.2.3",
|
"version": "0.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz",
|
||||||
|
@ -12848,16 +12843,6 @@
|
||||||
"vue-style-loader": "^4.1.0"
|
"vue-style-loader": "^4.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"vue-observe-visibility": {
|
|
||||||
"version": "0.4.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/vue-observe-visibility/-/vue-observe-visibility-0.4.6.tgz",
|
|
||||||
"integrity": "sha512-xo0CEVdkjSjhJoDdLSvoZoQrw/H2BlzB5jrCBKGZNXN2zdZgMuZ9BKrxXDjNP2AxlcCoKc8OahI3F3r3JGLv2Q=="
|
|
||||||
},
|
|
||||||
"vue-resize": {
|
|
||||||
"version": "0.4.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/vue-resize/-/vue-resize-0.4.5.tgz",
|
|
||||||
"integrity": "sha512-bhP7MlgJQ8TIkZJXAfDf78uJO+mEI3CaLABLjv0WNzr4CcGRGPIAItyWYnP6LsPA4Oq0WE+suidNs6dgpO4RHg=="
|
|
||||||
},
|
|
||||||
"vue-style-loader": {
|
"vue-style-loader": {
|
||||||
"version": "4.1.2",
|
"version": "4.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.2.tgz",
|
||||||
|
@ -12884,21 +12869,6 @@
|
||||||
"integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==",
|
"integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"vue-virtual-scroll-list": {
|
|
||||||
"version": "2.2.9",
|
|
||||||
"resolved": "https://registry.npmjs.org/vue-virtual-scroll-list/-/vue-virtual-scroll-list-2.2.9.tgz",
|
|
||||||
"integrity": "sha512-dPlvzIUUtxkaVBVea2/73sWsiTrsIpjWXd+7FWJPUEL+ME1i6LuwWNiMMqu2WVad82ONWeoXSiM5NMSDpMxYGA=="
|
|
||||||
},
|
|
||||||
"vue-virtual-scroller": {
|
|
||||||
"version": "1.0.10",
|
|
||||||
"resolved": "https://registry.npmjs.org/vue-virtual-scroller/-/vue-virtual-scroller-1.0.10.tgz",
|
|
||||||
"integrity": "sha512-Hn4qSBDhRY4XdngPioYy/ykDjrLX/NMm1fQXm/4UQQ/Xv1x8JbHGFZNftQowTcfICgN7yc31AKnUk1UGLJ2ndA==",
|
|
||||||
"requires": {
|
|
||||||
"scrollparent": "^2.0.1",
|
|
||||||
"vue-observe-visibility": "^0.4.4",
|
|
||||||
"vue-resize": "^0.4.5"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"vuedraggable": {
|
"vuedraggable": {
|
||||||
"version": "2.23.2",
|
"version": "2.23.2",
|
||||||
"resolved": "https://registry.npmjs.org/vuedraggable/-/vuedraggable-2.23.2.tgz",
|
"resolved": "https://registry.npmjs.org/vuedraggable/-/vuedraggable-2.23.2.tgz",
|
||||||
|
|
|
@ -41,8 +41,6 @@
|
||||||
"spectre.css": "^0.5.8",
|
"spectre.css": "^0.5.8",
|
||||||
"vue-click-outside": "^1.1.0",
|
"vue-click-outside": "^1.1.0",
|
||||||
"vue-i18n": "^8.18.2",
|
"vue-i18n": "^8.18.2",
|
||||||
"vue-virtual-scroll-list": "^2.2.9",
|
|
||||||
"vue-virtual-scroller": "^1.0.10",
|
|
||||||
"vuedraggable": "^2.23.2",
|
"vuedraggable": "^2.23.2",
|
||||||
"vuex": "^3.4.0",
|
"vuex": "^3.4.0",
|
||||||
"vuex-persist": "^2.2.0"
|
"vuex-persist": "^2.2.0"
|
||||||
|
|
|
@ -7,6 +7,17 @@ export class AntaresConnector {
|
||||||
this.params = args.params;
|
this.params = args.params;
|
||||||
this.poolSize = args.poolSize || false;
|
this.poolSize = args.poolSize || false;
|
||||||
this.connection = null;
|
this.connection = null;
|
||||||
|
|
||||||
|
this.query = {
|
||||||
|
select: [],
|
||||||
|
from: '',
|
||||||
|
where: [],
|
||||||
|
groupBy: [],
|
||||||
|
orderBy: [],
|
||||||
|
join: [],
|
||||||
|
update: [],
|
||||||
|
insert: []
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
connect () {
|
connect () {
|
||||||
|
@ -28,6 +39,20 @@ export class AntaresConnector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// select (args) {
|
||||||
|
// const type = typeof args;
|
||||||
|
|
||||||
|
// switch (type) {
|
||||||
|
// case string:
|
||||||
|
// case number:
|
||||||
|
// this.query.select;
|
||||||
|
// break;
|
||||||
|
|
||||||
|
// default:
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
async raw (sql) {
|
async raw (sql) {
|
||||||
switch (this.client) {
|
switch (this.client) {
|
||||||
case 'maria':
|
case 'maria':
|
||||||
|
|
|
@ -47,7 +47,7 @@ export default {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
checkScrollPosition (e = {}) {
|
checkScrollPosition (e = {}) {
|
||||||
var el = this.$el;
|
const el = this.$el;
|
||||||
|
|
||||||
// prevent parent scroll
|
// prevent parent scroll
|
||||||
if ((el.scrollTop === 0 && e.deltaY < 0) || (Math.abs(el.scrollTop - (el.scrollHeight - el.clientHeight)) <= 1 && e.deltaY > 0))
|
if ((el.scrollTop === 0 && e.deltaY < 0) || (Math.abs(el.scrollTop - (el.scrollHeight - el.clientHeight)) <= 1 && e.deltaY > 0))
|
||||||
|
|
|
@ -4,15 +4,37 @@
|
||||||
<div v-if="workspace.connected" class="workspace-tabs column columns col-gapless">
|
<div v-if="workspace.connected" class="workspace-tabs column columns col-gapless">
|
||||||
<ul class="tab tab-block column col-12">
|
<ul class="tab tab-block column col-12">
|
||||||
<li
|
<li
|
||||||
v-for="(tab, key) of workspace.tabs"
|
v-if="workspace.breadcrumbs.table"
|
||||||
|
class="tab-item"
|
||||||
|
:class="{'active': selectedTab === 1}"
|
||||||
|
@click="selectTab({uid: workspace.uid, tab: 1})"
|
||||||
|
>
|
||||||
|
<a class="tab-link">
|
||||||
|
<i class="material-icons md-18 mr-1">grid_on</i>
|
||||||
|
<span :title="workspace.breadcrumbs.table">{{ workspace.breadcrumbs.table }}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li
|
||||||
|
v-for="(tab, key) of queryTabs"
|
||||||
:key="tab.uid"
|
:key="tab.uid"
|
||||||
class="tab-item"
|
class="tab-item"
|
||||||
:class="{'active': selectedTab === tab.uid}"
|
:class="{'active': selectedTab === tab.uid}"
|
||||||
|
@click="selectTab({uid: workspace.uid, tab: tab.uid})"
|
||||||
>
|
>
|
||||||
<a href="#">Query #{{ key }} <span v-if="workspace.tabs.length > 1" class="btn btn-clear" /></a>
|
<a><span>Query #{{ key+1 }} <span v-if="queryTabs.length > 1" class="btn btn-clear" /></span></a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<WorkspaceQueryTab :connection="connection" />
|
<WorkspaceTableTab
|
||||||
|
v-show="selectedTab === 1"
|
||||||
|
:connection="connection"
|
||||||
|
:table="workspace.breadcrumbs.table"
|
||||||
|
/>
|
||||||
|
<WorkspaceQueryTab
|
||||||
|
v-for="tab of queryTabs"
|
||||||
|
v-show="selectedTab === tab.uid"
|
||||||
|
:key="tab.uid"
|
||||||
|
:connection="connection"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -22,12 +44,14 @@ 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 WorkspaceQueryTab from '@/components/WorkspaceQueryTab';
|
import WorkspaceQueryTab from '@/components/WorkspaceQueryTab';
|
||||||
|
import WorkspaceTableTab from '@/components/WorkspaceTableTab';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Workspace',
|
name: 'Workspace',
|
||||||
components: {
|
components: {
|
||||||
WorkspaceExploreBar,
|
WorkspaceExploreBar,
|
||||||
WorkspaceQueryTab
|
WorkspaceQueryTab,
|
||||||
|
WorkspaceTableTab
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
connection: Object
|
connection: Object
|
||||||
|
@ -44,7 +68,10 @@ export default {
|
||||||
return this.selectedWorkspace === this.connection.uid;
|
return this.selectedWorkspace === this.connection.uid;
|
||||||
},
|
},
|
||||||
selectedTab () {
|
selectedTab () {
|
||||||
return this.workspace.tabs.filter(tab => tab.selected).uid || this.workspace.tabs[0].uid;
|
return this.workspace.selected_tab || this.queryTabs[0].uid;
|
||||||
|
},
|
||||||
|
queryTabs () {
|
||||||
|
return this.workspace.tabs.filter(tab => tab.type === 'query');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async created () {
|
async created () {
|
||||||
|
@ -58,7 +85,8 @@ export default {
|
||||||
addNotification: 'notifications/addNotification',
|
addNotification: 'notifications/addNotification',
|
||||||
addWorkspace: 'workspaces/addWorkspace',
|
addWorkspace: 'workspaces/addWorkspace',
|
||||||
connectWorkspace: 'workspaces/connectWorkspace',
|
connectWorkspace: 'workspaces/connectWorkspace',
|
||||||
removeConnected: 'workspaces/removeConnected'
|
removeConnected: 'workspaces/removeConnected',
|
||||||
|
selectTab: 'workspaces/selectTab'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -78,7 +106,71 @@ export default {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
|
|
||||||
.tab-item{
|
.tab-item{
|
||||||
max-width: 6rem;
|
max-width: 12rem;
|
||||||
|
width: fit-content;
|
||||||
|
flex: initial;
|
||||||
|
|
||||||
|
&.active a{
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
> a{
|
||||||
|
padding: .2rem .8rem;
|
||||||
|
color: $body-font-color;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
opacity: .7;
|
||||||
|
transition: opacity .2s;
|
||||||
|
|
||||||
|
&:hover{
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
> span {
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.workspace-query-results{
|
||||||
|
overflow: auto;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
.table{
|
||||||
|
width: auto;
|
||||||
|
border-collapse: separate;
|
||||||
|
|
||||||
|
.tr:focus{
|
||||||
|
background: rgba($color: #000000, $alpha: .3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.th{
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
background: $bg-color;
|
||||||
|
border: 1px solid;
|
||||||
|
border-left: none;
|
||||||
|
border-color: $bg-color-light;
|
||||||
|
padding: .1rem .4rem;
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: .7rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.td{
|
||||||
|
border-right: 1px solid;
|
||||||
|
border-bottom: 1px solid;
|
||||||
|
border-color: $bg-color-light;
|
||||||
|
padding: 0 .4rem;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
max-width: 200px;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
font-size: .7rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -161,7 +161,7 @@ export default {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
display: flex;
|
display: block;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<div
|
|
||||||
v-for="(col, cKey) in source"
|
|
||||||
:key="cKey"
|
|
||||||
class="td"
|
|
||||||
:class="fieldType(col)"
|
|
||||||
>
|
|
||||||
{{ col }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: 'WorkspaceQueryRow',
|
|
||||||
props: {
|
|
||||||
index: { // index of current item
|
|
||||||
type: Number
|
|
||||||
},
|
|
||||||
source: { // here is: {uid: 'unique_1', text: 'abc'}
|
|
||||||
type: Object,
|
|
||||||
default () {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
fieldType (col) {
|
|
||||||
let type = typeof col;
|
|
||||||
if (type === 'object')
|
|
||||||
if (col instanceof Date) type = 'date';
|
|
||||||
if (col instanceof Uint8Array) type = 'blob';
|
|
||||||
if (col === null) type = 'null';
|
|
||||||
|
|
||||||
return `type-${type}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
</style>
|
|
|
@ -17,8 +17,13 @@
|
||||||
<i class="material-icons ml-1">save</i>
|
<i class="material-icons ml-1">save</i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="workspace.breadcrumbs.database">
|
<div class="workspace-query-info">
|
||||||
{{ $t('word.schema') }}: <b>{{ workspace.breadcrumbs.database }}</b>
|
<div v-if="results.rows">
|
||||||
|
{{ $t('word.results') }}: <b>{{ results.rows.length }}</b>
|
||||||
|
</div>
|
||||||
|
<div v-if="workspace.breadcrumbs.database">
|
||||||
|
{{ $t('word.schema') }}: <b>{{ workspace.breadcrumbs.database }}</b>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -112,40 +117,12 @@ export default {
|
||||||
margin-right: .4rem;
|
margin-right: .4rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.workspace-query-results{
|
.workspace-query-info{
|
||||||
overflow: auto;
|
display: flex;
|
||||||
white-space: nowrap;
|
|
||||||
|
|
||||||
.table{
|
> div + div{
|
||||||
width: auto;
|
padding-left: .6rem;
|
||||||
|
|
||||||
.tr:focus{
|
|
||||||
background: rgba($color: #000000, $alpha: .3);
|
|
||||||
}
|
|
||||||
|
|
||||||
.th{
|
|
||||||
position: sticky;
|
|
||||||
top: 0;
|
|
||||||
background: $bg-color;
|
|
||||||
border-color: $bg-color-light;
|
|
||||||
padding: .1rem .4rem;
|
|
||||||
font-weight: 400;
|
|
||||||
}
|
|
||||||
|
|
||||||
.td{
|
|
||||||
border-left: 1px solid;
|
|
||||||
border-color: $bg-color-light;
|
|
||||||
padding: 0 .4rem;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
max-width: 200px;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
&:first-child{
|
|
||||||
border-left: none;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<BaseVirtualScroll
|
<BaseVirtualScroll
|
||||||
v-if="results.rows"
|
v-if="results.rows"
|
||||||
ref="resultTable"
|
ref="resultTable"
|
||||||
:items="results.rows"
|
:items="rows"
|
||||||
:item-height="25"
|
:item-height="25"
|
||||||
class="vscroll"
|
class="vscroll"
|
||||||
:style="{'height': resultsSize+'px'}"
|
:style="{'height': resultsSize+'px'}"
|
||||||
|
@ -22,8 +22,8 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="tbody">
|
<div class="tbody">
|
||||||
<div
|
<div
|
||||||
v-for="(row, rKey) in items"
|
v-for="row in items"
|
||||||
:key="rKey"
|
:key="row._id"
|
||||||
class="tr"
|
class="tr"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
>
|
>
|
||||||
|
@ -32,6 +32,7 @@
|
||||||
:key="cKey"
|
:key="cKey"
|
||||||
class="td"
|
class="td"
|
||||||
:class="fieldType(col)"
|
:class="fieldType(col)"
|
||||||
|
:style="{'display': cKey === '_id'? 'none' : ''}"
|
||||||
>
|
>
|
||||||
{{ col }}
|
{{ col }}
|
||||||
</div>
|
</div>
|
||||||
|
@ -43,6 +44,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { uidGen } from 'common/libs/utilities';
|
||||||
import BaseVirtualScroll from '@/components/BaseVirtualScroll';
|
import BaseVirtualScroll from '@/components/BaseVirtualScroll';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -59,15 +61,15 @@ export default {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
rows () {
|
rows () { // Adds uid to rows
|
||||||
return this.results.rows ? this.results.rows.map(item => Object.assign({}, item)) : [];
|
return this.results.rows ? this.results.rows.map(item => {
|
||||||
|
return { ...item, _id: uidGen() };
|
||||||
|
}) : [];
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
updated () {
|
||||||
results: function () {
|
if (this.$refs.resultTable)
|
||||||
if (this.$refs.resultTable)
|
this.resizeResults();
|
||||||
this.resizeResults();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
window.addEventListener('resize', this.resizeResults);
|
window.addEventListener('resize', this.resizeResults);
|
||||||
|
@ -86,12 +88,14 @@ export default {
|
||||||
return `type-${type}`;
|
return `type-${type}`;
|
||||||
},
|
},
|
||||||
resizeResults (e) {
|
resizeResults (e) {
|
||||||
const el = this.$refs.resultTable.$el;
|
if (this.$refs.resultTable) {
|
||||||
const footer = document.getElementById('footer');
|
const el = this.$refs.resultTable.$el;
|
||||||
|
const footer = document.getElementById('footer');
|
||||||
|
|
||||||
if (el) {
|
if (el) {
|
||||||
const size = window.innerHeight - el.getBoundingClientRect().top - footer.offsetHeight;
|
const size = window.innerHeight - el.getBoundingClientRect().top - footer.offsetHeight;
|
||||||
this.resultsSize = size;
|
this.resultsSize = size;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,140 @@
|
||||||
|
<template>
|
||||||
|
<div class="workspace-query-tab column col-12 columns col-gapless">
|
||||||
|
<div class="workspace-query-runner column col-12">
|
||||||
|
<div class="workspace-query-runner-footer">
|
||||||
|
<div class="workspace-query-buttons">
|
||||||
|
<button
|
||||||
|
class="btn btn-link btn-sm"
|
||||||
|
:class="{'loading':isQuering}"
|
||||||
|
@click="runQuery"
|
||||||
|
>
|
||||||
|
<span>{{ $t('word.refresh') }}</span>
|
||||||
|
<i class="material-icons ml-1">refresh</i>
|
||||||
|
</button>
|
||||||
|
<button class="btn btn-link btn-sm">
|
||||||
|
<span>{{ $t('word.save') }}</span>
|
||||||
|
<i class="material-icons ml-1">save</i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="workspace-query-info">
|
||||||
|
<div v-if="results.rows">
|
||||||
|
{{ $t('word.results') }}: <b>{{ results.rows.length }}</b>
|
||||||
|
</div>
|
||||||
|
<div v-if="workspace.breadcrumbs.database">
|
||||||
|
{{ $t('word.schema') }}: <b>{{ workspace.breadcrumbs.database }}</b>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="workspace-query-results column col-12">
|
||||||
|
<WorkspaceQueryTable v-if="results" :results="results" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Connection from '@/ipc-api/Connection';
|
||||||
|
import WorkspaceQueryTable from '@/components/WorkspaceQueryTable';
|
||||||
|
import { mapGetters, mapActions } from 'vuex';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'WorkspaceQueryTab',
|
||||||
|
components: {
|
||||||
|
WorkspaceQueryTable
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
connection: Object,
|
||||||
|
table: String
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
isQuering: false,
|
||||||
|
results: {}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapGetters({
|
||||||
|
getWorkspace: 'workspaces/getWorkspace'
|
||||||
|
}),
|
||||||
|
workspace () {
|
||||||
|
return this.getWorkspace(this.connection.uid);
|
||||||
|
},
|
||||||
|
query () {
|
||||||
|
return `SELECT * FROM \`${this.table}\` LIMIT 1000`;// TODO: use query builder
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
table: function () {
|
||||||
|
this.runQuery();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created () {
|
||||||
|
this.runQuery();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapActions({
|
||||||
|
addNotification: 'notifications/addNotification'
|
||||||
|
}),
|
||||||
|
async runQuery () {
|
||||||
|
if (!this.table) return;
|
||||||
|
this.isQuering = true;
|
||||||
|
this.results = {};
|
||||||
|
|
||||||
|
const params = {
|
||||||
|
uid: this.connection.uid,
|
||||||
|
query: this.query,
|
||||||
|
database: this.workspace.breadcrumbs.database
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { status, response } = await Connection.rawQuery(params);
|
||||||
|
if (status === 'success')
|
||||||
|
this.results = response;
|
||||||
|
else
|
||||||
|
this.addNotification({ status: 'error', message: response });
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
this.addNotification({ status: 'error', message: err.stack });
|
||||||
|
}
|
||||||
|
|
||||||
|
this.isQuering = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.workspace-tabs{
|
||||||
|
align-content: baseline;
|
||||||
|
|
||||||
|
.workspace-query-runner{
|
||||||
|
|
||||||
|
.workspace-query-runner-footer{
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: .3rem .6rem .4rem;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.workspace-query-buttons{
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
.btn{
|
||||||
|
display: flex;
|
||||||
|
align-self: center;
|
||||||
|
color: $body-font-color;
|
||||||
|
margin-right: .4rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.workspace-query-info{
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
> div + div{
|
||||||
|
padding-left: .6rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
|
@ -28,7 +28,8 @@ module.exports = {
|
||||||
version: 'Version',
|
version: 'Version',
|
||||||
donate: 'Donate',
|
donate: 'Donate',
|
||||||
run: 'Run',
|
run: 'Run',
|
||||||
schema: 'Schema'
|
schema: 'Schema',
|
||||||
|
results: 'Results'
|
||||||
},
|
},
|
||||||
message: {
|
message: {
|
||||||
appWelcome: 'Welcome to Antares SQL Client!',
|
appWelcome: 'Welcome to Antares SQL Client!',
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
|
|
||||||
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css';
|
|
||||||
import 'material-design-icons/iconfont/material-icons.css';
|
import 'material-design-icons/iconfont/material-icons.css';
|
||||||
import '@/scss/main.scss';
|
import '@/scss/main.scss';
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,8 @@ export default {
|
||||||
NEW_TAB (state, uid) {
|
NEW_TAB (state, uid) {
|
||||||
const newTab = {
|
const newTab = {
|
||||||
uid: uidGen(),
|
uid: uidGen(),
|
||||||
selected: false
|
selected: false,
|
||||||
|
type: 'query'
|
||||||
};
|
};
|
||||||
state.workspaces = state.workspaces.map(workspace => {
|
state.workspaces = state.workspaces.map(workspace => {
|
||||||
if (workspace.uid === uid) {
|
if (workspace.uid === uid) {
|
||||||
|
@ -71,6 +72,9 @@ export default {
|
||||||
else
|
else
|
||||||
return workspace;
|
return workspace;
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
SELECT_TAB (state, { uid, tab }) {
|
||||||
|
state.workspaces = state.workspaces.map(workspace => workspace.uid === uid ? { ...workspace, selected_tab: tab } : workspace);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
|
@ -109,14 +113,15 @@ export default {
|
||||||
const workspace = {
|
const workspace = {
|
||||||
uid,
|
uid,
|
||||||
connected: false,
|
connected: false,
|
||||||
tabs: [],
|
selectedTab: 0,
|
||||||
|
tabs: [{ uid: 1, type: 'table' }],
|
||||||
structure: {},
|
structure: {},
|
||||||
breadcrumbs: {}
|
breadcrumbs: {}
|
||||||
};
|
};
|
||||||
|
|
||||||
commit('ADD_WORKSPACE', workspace);
|
commit('ADD_WORKSPACE', workspace);
|
||||||
|
|
||||||
if (!getters.getWorkspace(uid).tabs.length)
|
if (getters.getWorkspace(uid).tabs.length < 2)
|
||||||
dispatch('newTab', uid);
|
dispatch('newTab', uid);
|
||||||
},
|
},
|
||||||
changeBreadcrumbs ({ commit, getters }, payload) {
|
changeBreadcrumbs ({ commit, getters }, payload) {
|
||||||
|
@ -124,6 +129,9 @@ export default {
|
||||||
},
|
},
|
||||||
newTab ({ commit }, uid) {
|
newTab ({ commit }, uid) {
|
||||||
commit('NEW_TAB', uid);
|
commit('NEW_TAB', uid);
|
||||||
|
},
|
||||||
|
selectTab ({ commit }, payload) {
|
||||||
|
commit('SELECT_TAB', payload);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue