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"
|
||||
}
|
||||
},
|
||||
"scrollparent": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/scrollparent/-/scrollparent-2.0.1.tgz",
|
||||
"integrity": "sha1-cV1bnMV3YPsivczDvvtb/gaxoxc="
|
||||
},
|
||||
"scss-tokenizer": {
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz",
|
||||
|
@ -12848,16 +12843,6 @@
|
|||
"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": {
|
||||
"version": "4.1.2",
|
||||
"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==",
|
||||
"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": {
|
||||
"version": "2.23.2",
|
||||
"resolved": "https://registry.npmjs.org/vuedraggable/-/vuedraggable-2.23.2.tgz",
|
||||
|
|
|
@ -41,8 +41,6 @@
|
|||
"spectre.css": "^0.5.8",
|
||||
"vue-click-outside": "^1.1.0",
|
||||
"vue-i18n": "^8.18.2",
|
||||
"vue-virtual-scroll-list": "^2.2.9",
|
||||
"vue-virtual-scroller": "^1.0.10",
|
||||
"vuedraggable": "^2.23.2",
|
||||
"vuex": "^3.4.0",
|
||||
"vuex-persist": "^2.2.0"
|
||||
|
|
|
@ -7,6 +7,17 @@ export class AntaresConnector {
|
|||
this.params = args.params;
|
||||
this.poolSize = args.poolSize || false;
|
||||
this.connection = null;
|
||||
|
||||
this.query = {
|
||||
select: [],
|
||||
from: '',
|
||||
where: [],
|
||||
groupBy: [],
|
||||
orderBy: [],
|
||||
join: [],
|
||||
update: [],
|
||||
insert: []
|
||||
};
|
||||
}
|
||||
|
||||
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) {
|
||||
switch (this.client) {
|
||||
case 'maria':
|
||||
|
|
|
@ -47,7 +47,7 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
checkScrollPosition (e = {}) {
|
||||
var el = this.$el;
|
||||
const el = this.$el;
|
||||
|
||||
// prevent parent scroll
|
||||
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">
|
||||
<ul class="tab tab-block column col-12">
|
||||
<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"
|
||||
class="tab-item"
|
||||
: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>
|
||||
</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>
|
||||
</template>
|
||||
|
@ -22,12 +44,14 @@ import { mapGetters, mapActions } from 'vuex';
|
|||
import Connection from '@/ipc-api/Connection';
|
||||
import WorkspaceExploreBar from '@/components/WorkspaceExploreBar';
|
||||
import WorkspaceQueryTab from '@/components/WorkspaceQueryTab';
|
||||
import WorkspaceTableTab from '@/components/WorkspaceTableTab';
|
||||
|
||||
export default {
|
||||
name: 'Workspace',
|
||||
components: {
|
||||
WorkspaceExploreBar,
|
||||
WorkspaceQueryTab
|
||||
WorkspaceQueryTab,
|
||||
WorkspaceTableTab
|
||||
},
|
||||
props: {
|
||||
connection: Object
|
||||
|
@ -44,7 +68,10 @@ export default {
|
|||
return this.selectedWorkspace === this.connection.uid;
|
||||
},
|
||||
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 () {
|
||||
|
@ -58,7 +85,8 @@ export default {
|
|||
addNotification: 'notifications/addNotification',
|
||||
addWorkspace: 'workspaces/addWorkspace',
|
||||
connectWorkspace: 'workspaces/connectWorkspace',
|
||||
removeConnected: 'workspaces/removeConnected'
|
||||
removeConnected: 'workspaces/removeConnected',
|
||||
selectTab: 'workspaces/selectTab'
|
||||
})
|
||||
}
|
||||
};
|
||||
|
@ -78,7 +106,71 @@ export default {
|
|||
margin-top: 0;
|
||||
|
||||
.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;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: flex;
|
||||
display: block;
|
||||
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,11 +17,16 @@
|
|||
<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>
|
||||
|
@ -112,40 +117,12 @@ export default {
|
|||
margin-right: .4rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.workspace-query-results{
|
||||
overflow: auto;
|
||||
white-space: nowrap;
|
||||
.workspace-query-info{
|
||||
display: flex;
|
||||
|
||||
.table{
|
||||
width: auto;
|
||||
|
||||
.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;
|
||||
> div + div{
|
||||
padding-left: .6rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<BaseVirtualScroll
|
||||
v-if="results.rows"
|
||||
ref="resultTable"
|
||||
:items="results.rows"
|
||||
:items="rows"
|
||||
:item-height="25"
|
||||
class="vscroll"
|
||||
:style="{'height': resultsSize+'px'}"
|
||||
|
@ -22,8 +22,8 @@
|
|||
</div>
|
||||
<div class="tbody">
|
||||
<div
|
||||
v-for="(row, rKey) in items"
|
||||
:key="rKey"
|
||||
v-for="row in items"
|
||||
:key="row._id"
|
||||
class="tr"
|
||||
tabindex="0"
|
||||
>
|
||||
|
@ -32,6 +32,7 @@
|
|||
:key="cKey"
|
||||
class="td"
|
||||
:class="fieldType(col)"
|
||||
:style="{'display': cKey === '_id'? 'none' : ''}"
|
||||
>
|
||||
{{ col }}
|
||||
</div>
|
||||
|
@ -43,6 +44,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { uidGen } from 'common/libs/utilities';
|
||||
import BaseVirtualScroll from '@/components/BaseVirtualScroll';
|
||||
|
||||
export default {
|
||||
|
@ -59,15 +61,15 @@ export default {
|
|||
};
|
||||
},
|
||||
computed: {
|
||||
rows () {
|
||||
return this.results.rows ? this.results.rows.map(item => Object.assign({}, item)) : [];
|
||||
rows () { // Adds uid to rows
|
||||
return this.results.rows ? this.results.rows.map(item => {
|
||||
return { ...item, _id: uidGen() };
|
||||
}) : [];
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
results: function () {
|
||||
updated () {
|
||||
if (this.$refs.resultTable)
|
||||
this.resizeResults();
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
window.addEventListener('resize', this.resizeResults);
|
||||
|
@ -86,6 +88,7 @@ export default {
|
|||
return `type-${type}`;
|
||||
},
|
||||
resizeResults (e) {
|
||||
if (this.$refs.resultTable) {
|
||||
const el = this.$refs.resultTable.$el;
|
||||
const footer = document.getElementById('footer');
|
||||
|
||||
|
@ -95,6 +98,7 @@ export default {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
@ -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',
|
||||
donate: 'Donate',
|
||||
run: 'Run',
|
||||
schema: 'Schema'
|
||||
schema: 'Schema',
|
||||
results: 'Results'
|
||||
},
|
||||
message: {
|
||||
appWelcome: 'Welcome to Antares SQL Client!',
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
import Vue from 'vue';
|
||||
|
||||
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css';
|
||||
import 'material-design-icons/iconfont/material-icons.css';
|
||||
import '@/scss/main.scss';
|
||||
|
||||
|
|
|
@ -59,7 +59,8 @@ export default {
|
|||
NEW_TAB (state, uid) {
|
||||
const newTab = {
|
||||
uid: uidGen(),
|
||||
selected: false
|
||||
selected: false,
|
||||
type: 'query'
|
||||
};
|
||||
state.workspaces = state.workspaces.map(workspace => {
|
||||
if (workspace.uid === uid) {
|
||||
|
@ -71,6 +72,9 @@ export default {
|
|||
else
|
||||
return workspace;
|
||||
});
|
||||
},
|
||||
SELECT_TAB (state, { uid, tab }) {
|
||||
state.workspaces = state.workspaces.map(workspace => workspace.uid === uid ? { ...workspace, selected_tab: tab } : workspace);
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
|
@ -109,14 +113,15 @@ export default {
|
|||
const workspace = {
|
||||
uid,
|
||||
connected: false,
|
||||
tabs: [],
|
||||
selectedTab: 0,
|
||||
tabs: [{ uid: 1, type: 'table' }],
|
||||
structure: {},
|
||||
breadcrumbs: {}
|
||||
};
|
||||
|
||||
commit('ADD_WORKSPACE', workspace);
|
||||
|
||||
if (!getters.getWorkspace(uid).tabs.length)
|
||||
if (getters.getWorkspace(uid).tabs.length < 2)
|
||||
dispatch('newTab', uid);
|
||||
},
|
||||
changeBreadcrumbs ({ commit, getters }, payload) {
|
||||
|
@ -124,6 +129,9 @@ export default {
|
|||
},
|
||||
newTab ({ commit }, uid) {
|
||||
commit('NEW_TAB', uid);
|
||||
},
|
||||
selectTab ({ commit }, payload) {
|
||||
commit('SELECT_TAB', payload);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue