antares/src/renderer/components/WorkspaceExploreBar.vue

626 lines
19 KiB
Vue
Raw Normal View History

2020-05-08 18:02:18 +02:00
<template>
2020-06-06 16:27:42 +02:00
<div class="column col-auto p-relative">
2020-06-02 19:13:57 +02:00
<div ref="resizer" class="workspace-explorebar-resizer" />
<div
ref="explorebar"
class="workspace-explorebar column"
:style="{width: localWidth ? localWidth+'px' : ''}"
tabindex="0"
@keypress="explorebarSearch"
@keydown="explorebarSearch"
2020-06-02 19:13:57 +02:00
>
<div class="workspace-explorebar-header">
<span class="workspace-explorebar-title">{{ connectionName }}</span>
<span v-if="workspace.connectionStatus === 'connected'" class="workspace-explorebar-tools">
<i
v-if="customizations.schemas"
class="mdi mdi-18px mdi-database-plus c-hand mr-2"
:title="$t('message.createNewSchema')"
@click="showNewDBModal"
/>
2020-09-25 12:39:58 +02:00
<i
class="mdi mdi-18px mdi-refresh c-hand mr-2"
2020-06-02 19:13:57 +02:00
:class="{'rotate':isRefreshing}"
:title="$t('word.refresh')"
@click="refresh"
/>
<i
class="mdi mdi-18px mdi-power c-hand"
2020-06-02 19:13:57 +02:00
:title="$t('word.disconnect')"
@click="disconnectWorkspace(connection.uid)"
/>
2020-06-02 19:13:57 +02:00
</span>
</div>
2021-02-20 11:55:34 +01:00
<div class="workspace-explorebar-search">
<div v-if="workspace.connectionStatus === 'connected'" class="has-icon-right">
2021-02-20 11:55:34 +01:00
<input
ref="searchInput"
2021-02-20 11:55:34 +01:00
v-model="searchTerm"
class="form-input input-sm"
type="text"
:placeholder="$t('message.searchForElements')"
>
<i v-if="!searchTerm" class="form-icon mdi mdi-magnify mdi-18px" />
<i
v-else
class="form-icon c-hand mdi mdi-backspace mdi-18px pr-1"
@click="searchTerm = ''"
/>
2021-02-20 11:55:34 +01:00
</div>
</div>
<div class="workspace-explorebar-body" @click="$refs.explorebar.focus()">
2021-03-17 11:15:14 +01:00
<WorkspaceExploreBarSchema
2020-06-02 19:13:57 +02:00
v-for="db of workspace.structure"
2020-06-05 21:00:15 +02:00
:key="db.name"
2020-06-03 20:56:44 +02:00
:database="db"
2020-06-05 21:00:15 +02:00
:connection="connection"
@show-schema-context="openSchemaContext"
2020-12-03 13:00:54 +01:00
@show-table-context="openTableContext"
2021-01-02 14:46:27 +01:00
@show-misc-context="openMiscContext"
@show-misc-folder-context="openMiscFolderContext"
2020-06-03 20:56:44 +02:00
/>
2020-05-31 17:56:33 +02:00
</div>
</div>
2021-03-17 11:15:14 +01:00
<ModalNewSchema
2020-09-25 12:39:58 +02:00
v-if="isNewDBModal"
@close="hideNewDBModal"
@reload="refresh"
/>
2020-10-01 15:08:35 +02:00
<DatabaseContext
v-if="isDatabaseContext"
:selected-schema="selectedSchema"
2020-10-01 15:08:35 +02:00
:context-event="databaseContextEvent"
@close-context="closeDatabaseContext"
2021-08-18 17:28:41 +02:00
@open-create-table-tab="openCreateElementTab('table')"
@open-create-view-tab="openCreateElementTab('view')"
2021-09-02 18:08:23 +02:00
@open-create-trigger-tab="openCreateElementTab('trigger')"
2021-09-06 17:29:34 +02:00
@open-create-routine-tab="openCreateElementTab('routine')"
2021-09-07 18:20:45 +02:00
@open-create-function-tab="openCreateElementTab('function')"
2021-09-11 10:24:21 +02:00
@open-create-trigger-function-tab="openCreateElementTab('trigger-function')"
2021-09-10 18:23:32 +02:00
@open-create-scheduler-tab="openCreateElementTab('scheduler')"
2020-10-01 15:08:35 +02:00
@reload="refresh"
/>
2020-12-03 16:15:10 +01:00
<TableContext
v-if="isTableContext"
:selected-schema="selectedSchema"
2020-12-03 16:15:10 +01:00
:selected-table="selectedTable"
:context-event="tableContextEvent"
@delete-table="deleteTable"
@duplicate-table="duplicateTable"
2020-12-03 16:15:10 +01:00
@close-context="closeTableContext"
@reload="refresh"
/>
2021-01-02 14:46:27 +01:00
<MiscContext
v-if="isMiscContext"
:selected-misc="selectedMisc"
2021-07-17 13:10:54 +02:00
:selected-schema="selectedSchema"
2021-01-02 14:46:27 +01:00
:context-event="miscContextEvent"
@close-context="closeMiscContext"
@reload="refresh"
/>
<MiscFolderContext
v-if="isMiscFolderContext"
:selected-misc="selectedMisc"
2021-07-17 13:10:54 +02:00
:selected-schema="selectedSchema"
:context-event="miscContextEvent"
2021-09-06 17:29:34 +02:00
@open-create-trigger-tab="openCreateElementTab('trigger')"
@open-create-routine-tab="openCreateElementTab('routine')"
2021-09-07 18:20:45 +02:00
@open-create-function-tab="openCreateElementTab('function')"
2021-09-11 10:24:21 +02:00
@open-create-trigger-function-tab="openCreateElementTab('trigger-function')"
2021-09-10 18:23:32 +02:00
@open-create-scheduler-tab="openCreateElementTab('scheduler')"
@close-context="closeMiscFolderContext"
@reload="refresh"
/>
2020-05-08 18:02:18 +02:00
</div>
</template>
<script>
2020-05-18 18:06:32 +02:00
import { mapGetters, mapActions } from 'vuex';
2021-01-06 11:57:49 +01:00
import Tables from '@/ipc-api/Tables';
import Views from '@/ipc-api/Views';
2021-01-11 09:55:13 +01:00
import Functions from '@/ipc-api/Functions';
2021-01-16 11:32:42 +01:00
import Schedulers from '@/ipc-api/Schedulers';
2021-01-06 11:57:49 +01:00
2021-03-17 11:15:14 +01:00
import WorkspaceExploreBarSchema from '@/components/WorkspaceExploreBarSchema';
import DatabaseContext from '@/components/WorkspaceExploreBarSchemaContext';
2020-12-03 16:15:10 +01:00
import TableContext from '@/components/WorkspaceExploreBarTableContext';
2021-01-02 14:46:27 +01:00
import MiscContext from '@/components/WorkspaceExploreBarMiscContext';
import MiscFolderContext from '@/components/WorkspaceExploreBarMiscFolderContext';
2021-03-17 11:15:14 +01:00
import ModalNewSchema from '@/components/ModalNewSchema';
2021-09-02 18:08:23 +02:00
2020-05-08 18:02:18 +02:00
export default {
2020-06-03 20:56:44 +02:00
name: 'WorkspaceExploreBar',
components: {
2021-03-17 11:15:14 +01:00
WorkspaceExploreBarSchema,
2020-10-01 15:08:35 +02:00
DatabaseContext,
2020-12-03 16:15:10 +01:00
TableContext,
2021-01-02 14:46:27 +01:00
MiscContext,
MiscFolderContext,
2021-09-11 10:24:21 +02:00
ModalNewSchema
},
2020-05-14 15:21:57 +02:00
props: {
2020-06-02 19:13:57 +02:00
connection: Object,
isSelected: Boolean
2020-05-18 18:06:32 +02:00
},
2020-05-20 18:00:14 +02:00
data () {
return {
2020-06-02 19:13:57 +02:00
isRefreshing: false,
2021-01-02 15:27:02 +01:00
2020-09-25 12:39:58 +02:00
isNewDBModal: false,
2020-12-27 16:16:48 +01:00
isNewViewModal: false,
2021-01-02 15:27:02 +01:00
isNewTriggerModal: false,
2021-01-06 11:57:49 +01:00
isNewRoutineModal: false,
2021-01-11 09:55:13 +01:00
isNewFunctionModal: false,
isNewTriggerFunctionModal: false,
2021-01-16 11:32:42 +01:00
isNewSchedulerModal: false,
2021-01-02 15:27:02 +01:00
2020-10-01 15:08:35 +02:00
localWidth: null,
2021-02-20 11:55:34 +01:00
explorebarWidthInterval: null,
searchTermInterval: null,
2020-10-01 15:08:35 +02:00
isDatabaseContext: false,
isTableContext: false,
2021-01-02 14:46:27 +01:00
isMiscContext: false,
isMiscFolderContext: false,
2021-01-02 15:27:02 +01:00
2020-10-01 15:08:35 +02:00
databaseContextEvent: null,
tableContextEvent: null,
2021-01-02 14:46:27 +01:00
miscContextEvent: null,
2021-01-02 15:27:02 +01:00
selectedSchema: '',
2021-01-02 14:46:27 +01:00
selectedTable: null,
2021-02-20 11:55:34 +01:00
selectedMisc: null,
searchTerm: ''
2020-05-20 18:00:14 +02:00
};
},
2020-05-18 18:06:32 +02:00
computed: {
...mapGetters({
2020-05-31 17:56:33 +02:00
getWorkspace: 'workspaces/getWorkspace',
2020-06-02 19:13:57 +02:00
explorebarSize: 'settings/getExplorebarSize',
2020-05-31 17:56:33 +02:00
getConnectionName: 'connections/getConnectionName'
2020-05-18 18:06:32 +02:00
}),
2020-05-20 18:00:14 +02:00
workspace () {
return this.getWorkspace(this.connection.uid);
2020-05-31 17:56:33 +02:00
},
connectionName () {
return this.getConnectionName(this.connection.uid);
2021-06-26 16:36:05 +02:00
},
customizations () {
return this.workspace.customizations;
2020-05-18 18:06:32 +02:00
}
},
2020-06-02 19:13:57 +02:00
watch: {
2021-02-19 17:41:33 +01:00
localWidth (val) {
2021-02-20 11:55:34 +01:00
clearTimeout(this.explorebarWidthInterval);
2021-02-19 17:41:33 +01:00
2021-02-20 11:55:34 +01:00
this.explorebarWidthInterval = setTimeout(() => {
2021-02-19 17:41:33 +01:00
this.changeExplorebarSize(val);
}, 500);
},
2020-06-02 19:13:57 +02:00
isSelected (val) {
if (val) this.localWidth = this.explorebarSize;
2021-02-20 11:55:34 +01:00
},
searchTerm () {
clearTimeout(this.searchTermInterval);
this.searchTermInterval = setTimeout(() => {
this.setSearchTerm(this.searchTerm);
}, 200);
2020-06-02 19:13:57 +02:00
}
},
created () {
this.localWidth = this.explorebarSize;
},
mounted () {
const resizer = this.$refs.resizer;
2021-01-31 13:03:25 +01:00
resizer.addEventListener('mousedown', e => {
2020-06-02 19:13:57 +02:00
e.preventDefault();
window.addEventListener('mousemove', this.resize);
window.addEventListener('mouseup', this.stopResize);
});
},
2020-05-18 18:06:32 +02:00
methods: {
...mapActions({
2020-05-20 18:00:14 +02:00
disconnectWorkspace: 'workspaces/removeConnected',
2020-06-02 19:13:57 +02:00
refreshStructure: 'workspaces/refreshStructure',
2020-12-03 13:00:54 +01:00
changeBreadcrumbs: 'workspaces/changeBreadcrumbs',
selectTab: 'workspaces/selectTab',
newTab: 'workspaces/newTab',
removeTabs: 'workspaces/removeTabs',
2021-02-20 11:55:34 +01:00
setSearchTerm: 'workspaces/setSearchTerm',
2020-12-03 13:00:54 +01:00
addNotification: 'notifications/addNotification',
changeExplorebarSize: 'settings/changeExplorebarSize',
addLoadingElement: 'workspaces/addLoadingElement',
removeLoadingElement: 'workspaces/removeLoadingElement'
2020-05-20 18:00:14 +02:00
}),
async refresh () {
2020-06-10 19:29:10 +02:00
if (!this.isRefreshing) {
this.isRefreshing = true;
await this.refreshStructure(this.connection.uid);
this.isRefreshing = false;
}
2020-06-02 19:13:57 +02:00
},
explorebarSearch (e) {
if (e.code === 'Backspace') {
e.preventDefault();
if (this.searchTerm.length)
this.searchTerm = this.searchTerm.slice(0, -1);
else
return;
}
else if (e.key.length > 1)// Prevent non-alphanumerics
return;
this.$refs.searchInput.focus();
},
2020-06-02 19:13:57 +02:00
resize (e) {
const el = this.$refs.explorebar;
let explorebarWidth = e.pageX - el.getBoundingClientRect().left;
if (explorebarWidth > 500) explorebarWidth = 500;
if (explorebarWidth < 150) explorebarWidth = 150;
this.localWidth = explorebarWidth;
},
stopResize () {
window.removeEventListener('mousemove', this.resize);
2020-09-25 12:39:58 +02:00
},
showNewDBModal () {
this.isNewDBModal = true;
},
hideNewDBModal () {
this.isNewDBModal = false;
2020-10-01 15:08:35 +02:00
},
2021-08-18 17:28:41 +02:00
openCreateElementTab (element) {
2020-12-03 13:00:54 +01:00
this.closeDatabaseContext();
2021-09-06 17:29:34 +02:00
this.closeMiscFolderContext();
2021-08-13 16:50:59 +02:00
this.newTab({
uid: this.workspace.uid,
schema: this.selectedSchema,
elementName: '',
2021-08-18 17:28:41 +02:00
elementType: element,
type: `new-${element}`
2021-08-13 16:50:59 +02:00
});
2020-12-03 13:00:54 +01:00
},
openSchemaContext (payload) {
this.selectedSchema = payload.schema;
2020-10-01 15:08:35 +02:00
this.databaseContextEvent = payload.event;
this.isDatabaseContext = true;
},
closeDatabaseContext () {
this.isDatabaseContext = false;
2020-12-03 13:00:54 +01:00
},
openTableContext (payload) {
this.selectedTable = payload.table;
this.selectedSchema = payload.schema;
2020-12-03 13:00:54 +01:00
this.tableContextEvent = payload.event;
this.isTableContext = true;
},
closeTableContext () {
2020-12-03 16:15:10 +01:00
this.isTableContext = false;
2020-12-27 16:16:48 +01:00
},
2021-01-02 14:46:27 +01:00
openMiscContext (payload) {
this.selectedMisc = payload.misc;
2021-07-17 13:10:54 +02:00
this.selectedSchema = payload.schema;
2021-01-02 14:46:27 +01:00
this.miscContextEvent = payload.event;
this.isMiscContext = true;
},
openMiscFolderContext (payload) {
this.selectedMisc = payload.type;
2021-07-17 13:10:54 +02:00
this.selectedSchema = payload.schema;
this.miscContextEvent = payload.event;
this.isMiscFolderContext = true;
},
2021-01-02 14:46:27 +01:00
closeMiscContext () {
this.isMiscContext = false;
},
closeMiscFolderContext () {
this.isMiscFolderContext = false;
},
2021-01-02 15:27:02 +01:00
showCreateTriggerModal () {
this.closeDatabaseContext();
this.closeMiscFolderContext();
2021-01-02 15:27:02 +01:00
this.isNewTriggerModal = true;
},
hideCreateTriggerModal () {
this.isNewTriggerModal = false;
},
2021-01-06 11:57:49 +01:00
showCreateRoutineModal () {
this.closeDatabaseContext();
this.closeMiscFolderContext();
2021-01-06 11:57:49 +01:00
this.isNewRoutineModal = true;
},
hideCreateRoutineModal () {
this.isNewRoutineModal = false;
},
2021-01-11 09:55:13 +01:00
showCreateFunctionModal () {
this.closeDatabaseContext();
this.closeMiscFolderContext();
2021-01-11 09:55:13 +01:00
this.isNewFunctionModal = true;
},
hideCreateFunctionModal () {
this.isNewFunctionModal = false;
},
showCreateTriggerFunctionModal () {
this.closeDatabaseContext();
this.closeMiscFolderContext();
this.isNewTriggerFunctionModal = true;
},
hideCreateTriggerFunctionModal () {
this.isNewTriggerFunctionModal = false;
},
2021-01-16 11:32:42 +01:00
showCreateSchedulerModal () {
this.closeDatabaseContext();
this.closeMiscFolderContext();
2021-01-16 11:32:42 +01:00
this.isNewSchedulerModal = true;
},
hideCreateSchedulerModal () {
this.isNewSchedulerModal = false;
},
async deleteTable (payload) {
this.closeTableContext();
this.addLoadingElement({
name: payload.table.name,
schema: payload.schema,
type: 'table'
});
try {
let res;
if (payload.table.type === 'table') {
res = await Tables.dropTable({
uid: this.connection.uid,
table: payload.table.name,
schema: payload.schema
});
}
else if (payload.table.type === 'view') {
res = await Views.dropView({
uid: this.connection.uid,
view: payload.table.name,
schema: payload.schema
});
}
const { status, response } = res;
if (status === 'success') {
this.refresh();
this.removeTabs({
uid: this.connection.uid,
elementName: payload.table.name,
elementType: payload.table.type,
schema: payload.schema
});
}
else
this.addNotification({ status: 'error', message: response });
}
catch (err) {
this.addNotification({ status: 'error', message: err.stack });
}
this.removeLoadingElement({
name: payload.table.name,
schema: payload.schema,
type: 'table'
});
},
async duplicateTable (payload) {
this.closeTableContext();
this.addLoadingElement({
name: payload.table.name,
schema: payload.schema,
type: 'table'
});
try {
const { status, response } = await Tables.duplicateTable({
uid: this.connection.uid,
table: payload.table.name,
schema: payload.schema
});
if (status === 'success')
this.refresh();
else
this.addNotification({ status: 'error', message: response });
}
catch (err) {
this.addNotification({ status: 'error', message: err.stack });
}
this.removeLoadingElement({
name: payload.table.name,
schema: payload.schema,
type: 'table'
});
},
2021-01-11 09:55:13 +01:00
async openCreateFunctionEditor (payload) {
const params = {
uid: this.connection.uid,
schema: this.selectedSchema,
2021-01-11 09:55:13 +01:00
...payload
};
const { status, response } = await Functions.createFunction(params);
if (status === 'success') {
await this.refresh();
this.changeBreadcrumbs({ schema: this.selectedSchema, function: payload.name });
this.newTab({
uid: this.workspace.uid,
schema: this.selectedSchema,
elementName: payload.name,
elementType: 'function',
type: 'function-props'
});
2021-01-11 09:55:13 +01:00
}
else
this.addNotification({ status: 'error', message: response });
2021-01-16 11:32:42 +01:00
},
async openCreateTriggerFunctionEditor (payload) {
const params = {
uid: this.connection.uid,
schema: this.selectedSchema,
...payload
};
const { status, response } = await Functions.createTriggerFunction(params);
if (status === 'success') {
await this.refresh();
this.changeBreadcrumbs({ schema: this.selectedSchema, triggerFunction: payload.name });
this.newTab({
uid: this.workspace.uid,
schema: this.selectedSchema,
elementName: payload.name,
elementType: 'triggerFunction',
type: 'trigger-function-props'
});
}
else
this.addNotification({ status: 'error', message: response });
},
2021-01-16 11:32:42 +01:00
async openCreateSchedulerEditor (payload) {
const params = {
uid: this.connection.uid,
schema: this.selectedSchema,
2021-01-16 11:32:42 +01:00
...payload
};
const { status, response } = await Schedulers.createScheduler(params);
if (status === 'success') {
await this.refresh();
this.changeBreadcrumbs({ schema: this.selectedSchema, scheduler: payload.name });
this.newTab({
uid: this.workspace.uid,
schema: this.selectedSchema,
elementName: payload.name,
elementType: 'scheduler',
type: 'scheduler-props'
});
2021-01-16 11:32:42 +01:00
}
else
this.addNotification({ status: 'error', message: response });
2020-05-20 18:00:14 +02:00
}
2020-05-14 15:21:57 +02:00
}
2020-05-08 18:02:18 +02:00
};
</script>
<style lang="scss">
2020-07-31 18:16:28 +02:00
.workspace-explorebar-resizer {
position: absolute;
width: 4px;
right: -2px;
top: 0;
height: calc(100vh - #{$excluding-size});
cursor: ew-resize;
z-index: 99;
transition: background 0.2s;
&:hover {
background: rgba($primary-color, 50%);
}
2020-07-31 18:16:28 +02:00
}
2020-06-02 19:13:57 +02:00
2020-07-31 18:16:28 +02:00
.workspace-explorebar {
width: $explorebar-width;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
text-align: left;
z-index: 8;
flex: initial;
position: relative;
padding: 0;
2020-05-15 17:52:59 +02:00
&:focus {
outline: none;
}
2020-07-31 18:16:28 +02:00
.workspace-explorebar-header {
width: 100%;
padding: 0.3rem;
display: flex;
justify-content: space-between;
font-size: 0.6rem;
font-weight: 700;
text-transform: uppercase;
2020-05-18 18:06:32 +02:00
2020-07-31 18:16:28 +02:00
.workspace-explorebar-title {
width: 80%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
display: block;
align-items: center;
}
2020-05-18 18:06:32 +02:00
2020-07-31 18:16:28 +02:00
.workspace-explorebar-tools {
display: flex;
align-items: center;
2020-05-20 18:00:14 +02:00
2020-07-31 18:16:28 +02:00
> i {
opacity: 0.6;
transition: opacity 0.2s;
display: flex;
align-items: center;
2020-05-18 18:06:32 +02:00
2020-07-31 18:16:28 +02:00
&:hover {
opacity: 1;
}
}
2020-05-15 17:52:59 +02:00
}
2020-07-31 18:16:28 +02:00
}
2020-05-31 17:56:33 +02:00
2021-02-20 11:55:34 +01:00
.workspace-explorebar-search {
width: 100%;
display: flex;
justify-content: space-between;
font-size: 0.6rem;
height: 28px;
.has-icon-right {
width: 100%;
padding: 0.1rem;
.form-icon {
opacity: 0.5;
transition: opacity 0.2s;
}
.form-input {
height: 1.2rem;
padding-left: 0.2rem;
&:focus + .form-icon {
opacity: 0.9;
}
&::placeholder {
opacity: 0.6;
}
}
}
}
2020-07-31 18:16:28 +02:00
.workspace-explorebar-body {
width: 100%;
2021-02-20 11:55:34 +01:00
height: calc((100vh - 58px) - #{$excluding-size});
2020-07-31 18:16:28 +02:00
overflow: overlay;
padding: 0 0.1rem;
}
}
2020-05-08 18:02:18 +02:00
</style>