mirror of
https://github.com/Fabio286/antares.git
synced 2025-06-05 21:59:22 +02:00
feat: in-app debug console, closes #824
This commit is contained in:
@ -10,10 +10,8 @@
|
|||||||
:key="connection.uid"
|
:key="connection.uid"
|
||||||
:connection="connection"
|
:connection="connection"
|
||||||
/>
|
/>
|
||||||
<div class="connection-panel-wrapper p-relative">
|
|
||||||
<WorkspaceAddConnectionPanel v-if="selectedWorkspace === 'NEW'" />
|
<WorkspaceAddConnectionPanel v-if="selectedWorkspace === 'NEW'" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<TheFooter />
|
<TheFooter />
|
||||||
<TheNotificationsBoard />
|
<TheNotificationsBoard />
|
||||||
<TheScratchpad v-if="isScratchpad" />
|
<TheScratchpad v-if="isScratchpad" />
|
||||||
@ -48,6 +46,8 @@ import { useSchemaExportStore } from '@/stores/schemaExport';
|
|||||||
import { useSettingsStore } from '@/stores/settings';
|
import { useSettingsStore } from '@/stores/settings';
|
||||||
import { useWorkspacesStore } from '@/stores/workspaces';
|
import { useWorkspacesStore } from '@/stores/workspaces';
|
||||||
|
|
||||||
|
import { useConsoleStore } from './stores/console';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const TheTitleBar = defineAsyncComponent(() => import(/* webpackChunkName: "TheTitleBar" */'@/components/TheTitleBar.vue'));
|
const TheTitleBar = defineAsyncComponent(() => import(/* webpackChunkName: "TheTitleBar" */'@/components/TheTitleBar.vue'));
|
||||||
@ -80,6 +80,8 @@ const schemaExportStore = useSchemaExportStore();
|
|||||||
const { hideExportModal } = schemaExportStore;
|
const { hideExportModal } = schemaExportStore;
|
||||||
const { isExportModal: isExportSchemaModal } = storeToRefs(schemaExportStore);
|
const { isExportModal: isExportSchemaModal } = storeToRefs(schemaExportStore);
|
||||||
|
|
||||||
|
const consoleStore = useConsoleStore();
|
||||||
|
|
||||||
const isAllConnectionsModal: Ref<boolean> = ref(false);
|
const isAllConnectionsModal: Ref<boolean> = ref(false);
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
@ -152,6 +154,60 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Console messages
|
||||||
|
const oldLog = console.log;
|
||||||
|
const oldWarn = console.warn;
|
||||||
|
const oldInfo = console.info;
|
||||||
|
const oldError = console.error;
|
||||||
|
|
||||||
|
console.log = function (...args) {
|
||||||
|
consoleStore.putLog('debug', {
|
||||||
|
level: 'log',
|
||||||
|
process: 'renderer',
|
||||||
|
message: args.join(' '),
|
||||||
|
date: new Date()
|
||||||
|
});
|
||||||
|
oldLog.apply(this, args);
|
||||||
|
};
|
||||||
|
|
||||||
|
console.info = function (...args) {
|
||||||
|
consoleStore.putLog('debug', {
|
||||||
|
level: 'info',
|
||||||
|
process: 'renderer',
|
||||||
|
message: args.join(' '),
|
||||||
|
date: new Date()
|
||||||
|
});
|
||||||
|
oldInfo.apply(this, args);
|
||||||
|
};
|
||||||
|
|
||||||
|
console.warn = function (...args) {
|
||||||
|
consoleStore.putLog('debug', {
|
||||||
|
level: 'warn',
|
||||||
|
process: 'renderer',
|
||||||
|
message: args.join(' '),
|
||||||
|
date: new Date()
|
||||||
|
});
|
||||||
|
oldWarn.apply(this, args);
|
||||||
|
};
|
||||||
|
|
||||||
|
console.error = function (...args) {
|
||||||
|
consoleStore.putLog('debug', {
|
||||||
|
level: 'error',
|
||||||
|
process: 'renderer',
|
||||||
|
message: args.join(' '),
|
||||||
|
date: new Date()
|
||||||
|
});
|
||||||
|
oldError.apply(this, args);
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener('unhandledrejection', (event) => {
|
||||||
|
console.error(event.reason);
|
||||||
|
});
|
||||||
|
|
||||||
|
window.addEventListener('error', (event) => {
|
||||||
|
console.error(event.error, '| File name:', event.filename.split('/').pop().split('?')[0]);
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
@ -365,7 +365,11 @@ export default defineComponent({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleWheelEvent = (e) => {
|
const handleWheelEvent = (e) => {
|
||||||
|
try {
|
||||||
if (!e.target.className.includes('select__')) deactivate();
|
if (!e.target.className.includes('select__')) deactivate();
|
||||||
|
}
|
||||||
|
catch (_) {
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
285
src/renderer/components/DebugConsole.vue
Normal file
285
src/renderer/components/DebugConsole.vue
Normal file
@ -0,0 +1,285 @@
|
|||||||
|
<template>
|
||||||
|
<div
|
||||||
|
ref="wrapper"
|
||||||
|
class="console-wrapper"
|
||||||
|
@mouseenter="isHover = true"
|
||||||
|
@mouseleave="isHover = false"
|
||||||
|
>
|
||||||
|
<div ref="resizer" class="console-resizer" />
|
||||||
|
<div
|
||||||
|
id="console"
|
||||||
|
ref="queryConsole"
|
||||||
|
class="console column col-12"
|
||||||
|
:style="{height: localHeight ? localHeight+'px' : ''}"
|
||||||
|
>
|
||||||
|
<div class="console-header">
|
||||||
|
<ul class="tab tab-block">
|
||||||
|
<li class="tab-item" :class="{'active': selectedTab === 'query'}">
|
||||||
|
<a class="tab-link" @click="selectedTab = 'query'">{{ t('application.executedQueries') }}</a>
|
||||||
|
</li>
|
||||||
|
<li class="tab-item" :class="{'active': selectedTab === 'debug'}">
|
||||||
|
<a class="tab-link" @click="selectedTab = 'debug'">{{ t('application.debugConsole') }}</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<button class="btn btn-clear mr-1" @click="resizeConsole(0)" />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-show="selectedTab === 'query'"
|
||||||
|
ref="queryConsoleBody"
|
||||||
|
class="console-body"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-for="(wLog, i) in workspaceQueryLogs"
|
||||||
|
:key="i"
|
||||||
|
class="console-log"
|
||||||
|
tabindex="0"
|
||||||
|
@contextmenu.prevent="contextMenu($event, wLog)"
|
||||||
|
>
|
||||||
|
<span class="console-log-datetime">{{ moment(wLog.date).format('HH:mm:ss') }}</span>: <code class="console-log-sql" v-html="highlight(wLog.sql, {html: true})" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-show="selectedTab === 'debug'"
|
||||||
|
ref="logConsoleBody"
|
||||||
|
class="console-body"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-for="(log, i) in debugLogs"
|
||||||
|
:key="i"
|
||||||
|
class="console-log"
|
||||||
|
tabindex="0"
|
||||||
|
@contextmenu.prevent="contextMenu($event, log)"
|
||||||
|
>
|
||||||
|
<span class="console-log-datetime">{{ moment(log.date).format('HH:mm:ss') }}</span> <small>[{{ log.process.substring(0, 1).toUpperCase() }}]</small>: <span class="console-log-message" :class="`console-log-level-${log.level}`">{{ log.message }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<BaseContextMenu
|
||||||
|
v-if="isContext"
|
||||||
|
:context-event="contextEvent"
|
||||||
|
@close-context="isContext = false"
|
||||||
|
>
|
||||||
|
<div class="context-element" @click="copyLog">
|
||||||
|
<span class="d-flex">
|
||||||
|
<BaseIcon
|
||||||
|
class="text-light mt-1 mr-1"
|
||||||
|
icon-name="mdiContentCopy"
|
||||||
|
:size="18"
|
||||||
|
/> {{ t('general.copy') }}</span>
|
||||||
|
</div>
|
||||||
|
</BaseContextMenu>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import * as moment from 'moment';
|
||||||
|
import { storeToRefs } from 'pinia';
|
||||||
|
import { highlight } from 'sql-highlight';
|
||||||
|
import { computed, nextTick, onMounted, Ref, ref, watch } from 'vue';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
|
import BaseContextMenu from '@/components/BaseContextMenu.vue';
|
||||||
|
import BaseIcon from '@/components/BaseIcon.vue';
|
||||||
|
import { copyText } from '@/libs/copyText';
|
||||||
|
import { useConsoleStore } from '@/stores/console';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const consoleStore = useConsoleStore();
|
||||||
|
|
||||||
|
const { resizeConsole, getLogsByWorkspace } = consoleStore;
|
||||||
|
const {
|
||||||
|
isConsoleOpen,
|
||||||
|
consoleHeight,
|
||||||
|
selectedTab,
|
||||||
|
debugLogs
|
||||||
|
} = storeToRefs(consoleStore);
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
uid: {
|
||||||
|
type: String,
|
||||||
|
default: null,
|
||||||
|
required: false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const wrapper: Ref<HTMLInputElement> = ref(null);
|
||||||
|
const queryConsole: Ref<HTMLInputElement> = ref(null);
|
||||||
|
const queryConsoleBody: Ref<HTMLInputElement> = ref(null);
|
||||||
|
const logConsoleBody: Ref<HTMLInputElement> = ref(null);
|
||||||
|
const resizer: Ref<HTMLInputElement> = ref(null);
|
||||||
|
const localHeight = ref(consoleHeight.value);
|
||||||
|
const isHover = ref(false);
|
||||||
|
const isContext = ref(false);
|
||||||
|
const contextContent: Ref<string> = ref(null);
|
||||||
|
const contextEvent: Ref<MouseEvent> = ref(null);
|
||||||
|
|
||||||
|
const resize = (e: MouseEvent) => {
|
||||||
|
const el = queryConsole.value;
|
||||||
|
let elementHeight = el.getBoundingClientRect().bottom - e.pageY;
|
||||||
|
if (elementHeight > 400) elementHeight = 400;
|
||||||
|
localHeight.value = elementHeight;
|
||||||
|
};
|
||||||
|
|
||||||
|
const workspaceQueryLogs = computed(() => {
|
||||||
|
return getLogsByWorkspace(props.uid);
|
||||||
|
});
|
||||||
|
|
||||||
|
const stopResize = () => {
|
||||||
|
if (localHeight.value < 0) localHeight.value = 0;
|
||||||
|
resizeConsole(localHeight.value);
|
||||||
|
window.removeEventListener('mousemove', resize);
|
||||||
|
window.removeEventListener('mouseup', stopResize);
|
||||||
|
};
|
||||||
|
|
||||||
|
const contextMenu = (event: MouseEvent, wLog: {date: Date; sql?: string; message?: string}) => {
|
||||||
|
contextEvent.value = event;
|
||||||
|
contextContent.value = wLog.sql || wLog.message;
|
||||||
|
isContext.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const copyLog = () => {
|
||||||
|
copyText(contextContent.value);
|
||||||
|
isContext.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(workspaceQueryLogs, async () => {
|
||||||
|
if (!isHover.value) {
|
||||||
|
await nextTick();
|
||||||
|
queryConsoleBody.value.scrollTop = queryConsoleBody.value.scrollHeight;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(() => debugLogs.value.length, async () => {
|
||||||
|
if (!isHover.value) {
|
||||||
|
await nextTick();
|
||||||
|
logConsoleBody.value.scrollTop = logConsoleBody.value.scrollHeight;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(isConsoleOpen, async () => {
|
||||||
|
queryConsoleBody.value.scrollTop = queryConsoleBody.value.scrollHeight;
|
||||||
|
logConsoleBody.value.scrollTop = logConsoleBody.value.scrollHeight;
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(selectedTab, async () => {
|
||||||
|
queryConsoleBody.value.scrollTop = queryConsoleBody.value.scrollHeight;
|
||||||
|
logConsoleBody.value.scrollTop = logConsoleBody.value.scrollHeight;
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(consoleHeight, async (val) => {
|
||||||
|
await nextTick();
|
||||||
|
localHeight.value = val;
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
queryConsoleBody.value.scrollTop = queryConsoleBody.value.scrollHeight;
|
||||||
|
logConsoleBody.value.scrollTop = logConsoleBody.value.scrollHeight;
|
||||||
|
|
||||||
|
resizer.value.addEventListener('mousedown', (e: MouseEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
window.addEventListener('mousemove', resize);
|
||||||
|
window.addEventListener('mouseup', stopResize);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.console-wrapper {
|
||||||
|
width: -webkit-fill-available;
|
||||||
|
z-index: 9;
|
||||||
|
margin-top: auto;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
|
||||||
|
.console-resizer {
|
||||||
|
height: 4px;
|
||||||
|
top: -1px;
|
||||||
|
width: 100%;
|
||||||
|
cursor: ns-resize;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 99;
|
||||||
|
transition: background 0.2s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: var(--primary-color-dark);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.console {
|
||||||
|
padding: 0;
|
||||||
|
padding-bottom: $footer-height;
|
||||||
|
|
||||||
|
.console-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0 4px;
|
||||||
|
|
||||||
|
.tab-block {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-block,
|
||||||
|
.tab-item {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-link {
|
||||||
|
padding: 0.2rem 0.6rem;
|
||||||
|
cursor: pointer;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.console-body {
|
||||||
|
overflow: auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
max-height: 100%;
|
||||||
|
padding: 0 6px 3px;
|
||||||
|
|
||||||
|
.console-log {
|
||||||
|
padding: 1px 3px;
|
||||||
|
margin: 1px 0;
|
||||||
|
border-radius: $border-radius;
|
||||||
|
user-select: text;
|
||||||
|
|
||||||
|
&-datetime {
|
||||||
|
opacity: .6;
|
||||||
|
font-size: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-sql {
|
||||||
|
font-size: 95%;
|
||||||
|
opacity: 0.8;
|
||||||
|
font-weight: 700;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
user-select: text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-message {
|
||||||
|
font-size: 95%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-level {
|
||||||
|
// &-log,
|
||||||
|
// &-info {}
|
||||||
|
&-warn {
|
||||||
|
color: orange;
|
||||||
|
}
|
||||||
|
&-error {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
small {
|
||||||
|
opacity: .6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -282,7 +282,7 @@
|
|||||||
import { ClientCode, SchemaInfos } from 'common/interfaces/antares';
|
import { ClientCode, SchemaInfos } from 'common/interfaces/antares';
|
||||||
import { Customizations } from 'common/interfaces/customizations';
|
import { Customizations } from 'common/interfaces/customizations';
|
||||||
import { ExportOptions, ExportState } from 'common/interfaces/exporter';
|
import { ExportOptions, ExportState } from 'common/interfaces/exporter';
|
||||||
import { ipcRenderer } from 'electron';
|
import { ipcRenderer, IpcRendererEvent } from 'electron';
|
||||||
import * as moment from 'moment';
|
import * as moment from 'moment';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import { computed, onBeforeUnmount, Ref, ref } from 'vue';
|
import { computed, onBeforeUnmount, Ref, ref } from 'vue';
|
||||||
@ -293,6 +293,7 @@ import BaseSelect from '@/components/BaseSelect.vue';
|
|||||||
import { useFocusTrap } from '@/composables/useFocusTrap';
|
import { useFocusTrap } from '@/composables/useFocusTrap';
|
||||||
import Application from '@/ipc-api/Application';
|
import Application from '@/ipc-api/Application';
|
||||||
import Schema from '@/ipc-api/Schema';
|
import Schema from '@/ipc-api/Schema';
|
||||||
|
import { useConsoleStore } from '@/stores/console';
|
||||||
import { useNotificationsStore } from '@/stores/notifications';
|
import { useNotificationsStore } from '@/stores/notifications';
|
||||||
import { useSchemaExportStore } from '@/stores/schemaExport';
|
import { useSchemaExportStore } from '@/stores/schemaExport';
|
||||||
import { useWorkspacesStore } from '@/stores/workspaces';
|
import { useWorkspacesStore } from '@/stores/workspaces';
|
||||||
@ -384,16 +385,28 @@ const startExport = async () => {
|
|||||||
else {
|
else {
|
||||||
progressStatus.value = response;
|
progressStatus.value = response;
|
||||||
addNotification({ status: 'error', message: response });
|
addNotification({ status: 'error', message: response });
|
||||||
|
useConsoleStore().putLog('debug', {
|
||||||
|
level: 'error',
|
||||||
|
process: 'worker',
|
||||||
|
message: response,
|
||||||
|
date: new Date()
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
addNotification({ status: 'error', message: err.stack });
|
addNotification({ status: 'error', message: err.stack });
|
||||||
|
useConsoleStore().putLog('debug', {
|
||||||
|
level: 'error',
|
||||||
|
process: 'worker',
|
||||||
|
message: err.stack,
|
||||||
|
date: new Date()
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
isExporting.value = false;
|
isExporting.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateProgress = (event: Event, state: ExportState) => {
|
const updateProgress = (event: IpcRendererEvent, state: ExportState) => {
|
||||||
progressPercentage.value = Number((state.currentItemIndex / state.totalItems * 100).toFixed(1));
|
progressPercentage.value = Number((state.currentItemIndex / state.totalItems * 100).toFixed(1));
|
||||||
switch (state.op) {
|
switch (state.op) {
|
||||||
case 'PROCESSING':
|
case 'PROCESSING':
|
||||||
|
@ -55,7 +55,7 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ImportState } from 'common/interfaces/importer';
|
import { ImportState } from 'common/interfaces/importer';
|
||||||
import { ipcRenderer } from 'electron';
|
import { ipcRenderer, IpcRendererEvent } from 'electron';
|
||||||
import * as moment from 'moment';
|
import * as moment from 'moment';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import { computed, onBeforeUnmount, Ref, ref } from 'vue';
|
import { computed, onBeforeUnmount, Ref, ref } from 'vue';
|
||||||
@ -63,6 +63,7 @@ import { useI18n } from 'vue-i18n';
|
|||||||
|
|
||||||
import BaseIcon from '@/components/BaseIcon.vue';
|
import BaseIcon from '@/components/BaseIcon.vue';
|
||||||
import Schema from '@/ipc-api/Schema';
|
import Schema from '@/ipc-api/Schema';
|
||||||
|
import { useConsoleStore } from '@/stores/console';
|
||||||
import { useNotificationsStore } from '@/stores/notifications';
|
import { useNotificationsStore } from '@/stores/notifications';
|
||||||
import { useWorkspacesStore } from '@/stores/workspaces';
|
import { useWorkspacesStore } from '@/stores/workspaces';
|
||||||
|
|
||||||
@ -118,23 +119,35 @@ const startImport = async (file: string) => {
|
|||||||
else {
|
else {
|
||||||
progressStatus.value = response;
|
progressStatus.value = response;
|
||||||
addNotification({ status: 'error', message: response });
|
addNotification({ status: 'error', message: response });
|
||||||
|
useConsoleStore().putLog('debug', {
|
||||||
|
level: 'error',
|
||||||
|
process: 'worker',
|
||||||
|
message: response,
|
||||||
|
date: new Date()
|
||||||
|
});
|
||||||
}
|
}
|
||||||
refreshSchema({ uid, schema: props.selectedSchema });
|
refreshSchema({ uid, schema: props.selectedSchema });
|
||||||
completed.value = true;
|
completed.value = true;
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
addNotification({ status: 'error', message: err.stack });
|
addNotification({ status: 'error', message: err.stack });
|
||||||
|
useConsoleStore().putLog('debug', {
|
||||||
|
level: 'error',
|
||||||
|
process: 'worker',
|
||||||
|
message: err.stack,
|
||||||
|
date: new Date()
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
isImporting.value = false;
|
isImporting.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateProgress = (event: Event, state: ImportState) => {
|
const updateProgress = (event: IpcRendererEvent, state: ImportState) => {
|
||||||
progressPercentage.value = parseFloat(Number(state.percentage).toFixed(1));
|
progressPercentage.value = parseFloat(Number(state.percentage).toFixed(1));
|
||||||
queryCount.value = Number(state.queryCount);
|
queryCount.value = Number(state.queryCount);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleQueryError = (event: Event, err: { time: string; message: string }) => {
|
const handleQueryError = (event: IpcRendererEvent, err: { time: string; message: string }) => {
|
||||||
queryErrors.value.push(err);
|
queryErrors.value.push(err);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -43,11 +43,7 @@
|
|||||||
|
|
||||||
<div class="footer-right-elements">
|
<div class="footer-right-elements">
|
||||||
<ul class="footer-elements">
|
<ul class="footer-elements">
|
||||||
<li
|
<li class="footer-element footer-link" @click="toggleConsole()">
|
||||||
v-if="workspace?.connectionStatus === 'connected'"
|
|
||||||
class="footer-element footer-link"
|
|
||||||
@click="toggleConsole()"
|
|
||||||
>
|
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
icon-name="mdiConsoleLine"
|
icon-name="mdiConsoleLine"
|
||||||
class="mr-1"
|
class="mr-1"
|
||||||
|
@ -15,7 +15,8 @@
|
|||||||
:connection="connection"
|
:connection="connection"
|
||||||
:is-selected="isSelected"
|
:is-selected="isSelected"
|
||||||
/>
|
/>
|
||||||
<div v-if="workspace?.connectionStatus === 'connected'" class="workspace-tabs column columns col-gapless">
|
<div class="workspace-tabs column">
|
||||||
|
<div v-if="workspace?.connectionStatus === 'connected'" class="columns col-gapless">
|
||||||
<Draggable
|
<Draggable
|
||||||
ref="tabWrap"
|
ref="tabWrap"
|
||||||
v-model="draggableTabs"
|
v-model="draggableTabs"
|
||||||
@ -598,11 +599,12 @@
|
|||||||
:schema="tab.schema"
|
:schema="tab.schema"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<WorkspaceQueryConsole v-if="isConsoleOpen(workspace.uid)" :uid="workspace.uid" />
|
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="connection-panel-wrapper p-relative">
|
<div v-else class="connection-panel-wrapper p-relative">
|
||||||
<WorkspaceEditConnectionPanel :connection="connection" />
|
<WorkspaceEditConnectionPanel :connection="connection" />
|
||||||
</div>
|
</div>
|
||||||
|
<DebugConsole v-if="isConsoleOpen" :uid="workspace.uid" />
|
||||||
|
</div>
|
||||||
<ModalProcessesList
|
<ModalProcessesList
|
||||||
v-if="isProcessesModal"
|
v-if="isProcessesModal"
|
||||||
:connection="connection"
|
:connection="connection"
|
||||||
@ -626,12 +628,12 @@ import { useI18n } from 'vue-i18n';
|
|||||||
import * as Draggable from 'vuedraggable';
|
import * as Draggable from 'vuedraggable';
|
||||||
|
|
||||||
import BaseIcon from '@/components/BaseIcon.vue';
|
import BaseIcon from '@/components/BaseIcon.vue';
|
||||||
|
import DebugConsole from '@/components/DebugConsole.vue';
|
||||||
import ModalDiscardChanges from '@/components/ModalDiscardChanges.vue';
|
import ModalDiscardChanges from '@/components/ModalDiscardChanges.vue';
|
||||||
import ModalProcessesList from '@/components/ModalProcessesList.vue';
|
import ModalProcessesList from '@/components/ModalProcessesList.vue';
|
||||||
import WorkspaceEditConnectionPanel from '@/components/WorkspaceEditConnectionPanel.vue';
|
import WorkspaceEditConnectionPanel from '@/components/WorkspaceEditConnectionPanel.vue';
|
||||||
import WorkspaceEmptyState from '@/components/WorkspaceEmptyState.vue';
|
import WorkspaceEmptyState from '@/components/WorkspaceEmptyState.vue';
|
||||||
import WorkspaceExploreBar from '@/components/WorkspaceExploreBar.vue';
|
import WorkspaceExploreBar from '@/components/WorkspaceExploreBar.vue';
|
||||||
import WorkspaceQueryConsole from '@/components/WorkspaceQueryConsole.vue';
|
|
||||||
import WorkspaceTabNewFunction from '@/components/WorkspaceTabNewFunction.vue';
|
import WorkspaceTabNewFunction from '@/components/WorkspaceTabNewFunction.vue';
|
||||||
import WorkspaceTabNewRoutine from '@/components/WorkspaceTabNewRoutine.vue';
|
import WorkspaceTabNewRoutine from '@/components/WorkspaceTabNewRoutine.vue';
|
||||||
import WorkspaceTabNewScheduler from '@/components/WorkspaceTabNewScheduler.vue';
|
import WorkspaceTabNewScheduler from '@/components/WorkspaceTabNewScheduler.vue';
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<div class="connection-panel-wrapper p-relative">
|
||||||
<div class="connection-panel">
|
<div class="connection-panel">
|
||||||
<div class="panel">
|
<div class="panel">
|
||||||
<div class="panel-nav">
|
<div class="panel-nav">
|
||||||
@ -420,21 +421,26 @@
|
|||||||
@credentials="continueTest"
|
@credentials="continueTest"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<DebugConsole v-if="isConsoleOpen" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import customizations from 'common/customizations';
|
import customizations from 'common/customizations';
|
||||||
import { ConnectionParams } from 'common/interfaces/antares';
|
import { ConnectionParams } from 'common/interfaces/antares';
|
||||||
import { uidGen } from 'common/libs/uidGen';
|
import { uidGen } from 'common/libs/uidGen';
|
||||||
|
import { storeToRefs } from 'pinia';
|
||||||
import { computed, Ref, ref, watch } from 'vue';
|
import { computed, Ref, ref, watch } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
import BaseIcon from '@/components/BaseIcon.vue';
|
import BaseIcon from '@/components/BaseIcon.vue';
|
||||||
import BaseSelect from '@/components/BaseSelect.vue';
|
import BaseSelect from '@/components/BaseSelect.vue';
|
||||||
import BaseUploadInput from '@/components/BaseUploadInput.vue';
|
import BaseUploadInput from '@/components/BaseUploadInput.vue';
|
||||||
|
import DebugConsole from '@/components/DebugConsole.vue';
|
||||||
import ModalAskCredentials from '@/components/ModalAskCredentials.vue';
|
import ModalAskCredentials from '@/components/ModalAskCredentials.vue';
|
||||||
import Connection from '@/ipc-api/Connection';
|
import Connection from '@/ipc-api/Connection';
|
||||||
import { useConnectionsStore } from '@/stores/connections';
|
import { useConnectionsStore } from '@/stores/connections';
|
||||||
|
import { useConsoleStore } from '@/stores/console';
|
||||||
import { useNotificationsStore } from '@/stores/notifications';
|
import { useNotificationsStore } from '@/stores/notifications';
|
||||||
import { useWorkspacesStore } from '@/stores/workspaces';
|
import { useWorkspacesStore } from '@/stores/workspaces';
|
||||||
|
|
||||||
@ -443,6 +449,7 @@ const { t } = useI18n();
|
|||||||
const { addConnection } = useConnectionsStore();
|
const { addConnection } = useConnectionsStore();
|
||||||
const { addNotification } = useNotificationsStore();
|
const { addNotification } = useNotificationsStore();
|
||||||
const workspacesStore = useWorkspacesStore();
|
const workspacesStore = useWorkspacesStore();
|
||||||
|
const { isConsoleOpen } = storeToRefs(useConsoleStore());
|
||||||
|
|
||||||
const { connectWorkspace, selectWorkspace } = workspacesStore;
|
const { connectWorkspace, selectWorkspace } = workspacesStore;
|
||||||
|
|
||||||
|
@ -598,6 +598,22 @@ localConnection.value = JSON.parse(JSON.stringify(props.connection));
|
|||||||
min-width: 450px;
|
min-width: 450px;
|
||||||
border-radius: $border-radius;
|
border-radius: $border-radius;
|
||||||
|
|
||||||
|
.panel-nav {
|
||||||
|
.tab-block {
|
||||||
|
background: transparent;
|
||||||
|
margin: 0.2rem 0 0.15rem 0;
|
||||||
|
|
||||||
|
.tab-item {
|
||||||
|
background: transparent;
|
||||||
|
flex: 1 0 0;
|
||||||
|
|
||||||
|
> a {
|
||||||
|
padding: 8px 4px 6px 4px
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.panel-body {
|
.panel-body {
|
||||||
flex: initial;
|
flex: initial;
|
||||||
}
|
}
|
||||||
|
@ -1,189 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div
|
|
||||||
ref="wrapper"
|
|
||||||
class="query-console-wrapper"
|
|
||||||
@mouseenter="isHover = true"
|
|
||||||
@mouseleave="isHover = false"
|
|
||||||
>
|
|
||||||
<div ref="resizer" class="query-console-resizer" />
|
|
||||||
<div
|
|
||||||
id="query-console"
|
|
||||||
ref="queryConsole"
|
|
||||||
class="query-console column col-12"
|
|
||||||
:style="{height: localHeight ? localHeight+'px' : ''}"
|
|
||||||
>
|
|
||||||
<div class="query-console-header">
|
|
||||||
<div>{{ t('application.console') }}</div>
|
|
||||||
<button class="btn btn-clear mr-1" @click="resizeConsole(0)" />
|
|
||||||
</div>
|
|
||||||
<div ref="queryConsoleBody" class="query-console-body">
|
|
||||||
<div
|
|
||||||
v-for="(wLog, i) in workspaceLogs"
|
|
||||||
:key="i"
|
|
||||||
class="query-console-log"
|
|
||||||
tabindex="0"
|
|
||||||
@contextmenu.prevent="contextMenu($event, wLog)"
|
|
||||||
>
|
|
||||||
<span class="type-datetime">{{ moment(wLog.date).format('HH:mm:ss') }}</span>: <code class="query-console-log-sql" v-html="highlight(wLog.sql, {html: true})" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<BaseContextMenu
|
|
||||||
v-if="isContext"
|
|
||||||
:context-event="contextEvent"
|
|
||||||
@close-context="isContext = false"
|
|
||||||
>
|
|
||||||
<div class="context-element" @click="copyQuery">
|
|
||||||
<span class="d-flex">
|
|
||||||
<BaseIcon
|
|
||||||
class="text-light mt-1 mr-1"
|
|
||||||
icon-name="mdiContentCopy"
|
|
||||||
:size="18"
|
|
||||||
/> {{ t('general.copy') }}</span>
|
|
||||||
</div>
|
|
||||||
</BaseContextMenu>
|
|
||||||
</template>
|
|
||||||
<script setup lang="ts">
|
|
||||||
import * as moment from 'moment';
|
|
||||||
import { storeToRefs } from 'pinia';
|
|
||||||
import { highlight } from 'sql-highlight';
|
|
||||||
import { computed, nextTick, onMounted, Ref, ref, watch } from 'vue';
|
|
||||||
import { useI18n } from 'vue-i18n';
|
|
||||||
|
|
||||||
import BaseContextMenu from '@/components/BaseContextMenu.vue';
|
|
||||||
import BaseIcon from '@/components/BaseIcon.vue';
|
|
||||||
import { copyText } from '@/libs/copyText';
|
|
||||||
import { useConsoleStore } from '@/stores/console';
|
|
||||||
|
|
||||||
const { t } = useI18n();
|
|
||||||
|
|
||||||
const consoleStore = useConsoleStore();
|
|
||||||
|
|
||||||
const { resizeConsole, getLogsByWorkspace } = consoleStore;
|
|
||||||
const { consoleHeight } = storeToRefs(consoleStore);
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
uid: String
|
|
||||||
});
|
|
||||||
|
|
||||||
const wrapper: Ref<HTMLInputElement> = ref(null);
|
|
||||||
const queryConsole: Ref<HTMLInputElement> = ref(null);
|
|
||||||
const queryConsoleBody: Ref<HTMLInputElement> = ref(null);
|
|
||||||
const resizer: Ref<HTMLInputElement> = ref(null);
|
|
||||||
const localHeight = ref(250);
|
|
||||||
const isHover = ref(false);
|
|
||||||
const isContext = ref(false);
|
|
||||||
const contextQuery: Ref<string> = ref(null);
|
|
||||||
const contextEvent: Ref<MouseEvent> = ref(null);
|
|
||||||
|
|
||||||
const resize = (e: MouseEvent) => {
|
|
||||||
const el = queryConsole.value;
|
|
||||||
let consoleHeight = el.getBoundingClientRect().bottom - e.pageY;
|
|
||||||
if (consoleHeight > 400) consoleHeight = 400;
|
|
||||||
localHeight.value = consoleHeight;
|
|
||||||
};
|
|
||||||
|
|
||||||
const workspaceLogs = computed(() => {
|
|
||||||
return getLogsByWorkspace(props.uid);
|
|
||||||
});
|
|
||||||
|
|
||||||
const stopResize = () => {
|
|
||||||
if (localHeight.value < 0) localHeight.value = 0;
|
|
||||||
resizeConsole(localHeight.value);
|
|
||||||
window.removeEventListener('mousemove', resize);
|
|
||||||
window.removeEventListener('mouseup', stopResize);
|
|
||||||
};
|
|
||||||
|
|
||||||
const contextMenu = (event: MouseEvent, wLog: {date: Date; sql: string}) => {
|
|
||||||
contextEvent.value = event;
|
|
||||||
contextQuery.value = wLog.sql;
|
|
||||||
isContext.value = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
const copyQuery = () => {
|
|
||||||
copyText(contextQuery.value);
|
|
||||||
isContext.value = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
watch(workspaceLogs, async () => {
|
|
||||||
if (!isHover.value) {
|
|
||||||
await nextTick();
|
|
||||||
queryConsoleBody.value.scrollTop = queryConsoleBody.value.scrollHeight;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
localHeight.value = consoleHeight.value;
|
|
||||||
queryConsoleBody.value.scrollTop = queryConsoleBody.value.scrollHeight;
|
|
||||||
});
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
resizer.value.addEventListener('mousedown', (e: MouseEvent) => {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
window.addEventListener('mousemove', resize);
|
|
||||||
window.addEventListener('mouseup', stopResize);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.query-console-wrapper {
|
|
||||||
width: 100%;
|
|
||||||
z-index: 9;
|
|
||||||
margin-top: auto;
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
|
|
||||||
.query-console-resizer {
|
|
||||||
height: 4px;
|
|
||||||
top: -1px;
|
|
||||||
width: 100%;
|
|
||||||
cursor: ns-resize;
|
|
||||||
position: absolute;
|
|
||||||
z-index: 99;
|
|
||||||
transition: background 0.2s;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: var(--primary-color-dark);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.query-console {
|
|
||||||
padding: 0;
|
|
||||||
padding-bottom: $footer-height;
|
|
||||||
|
|
||||||
.query-console-header {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
padding: 4px;
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
|
|
||||||
.query-console-body {
|
|
||||||
overflow: auto;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
max-height: 100%;
|
|
||||||
padding: 0 6px 3px;
|
|
||||||
|
|
||||||
.query-console-log {
|
|
||||||
padding: 1px 3px;
|
|
||||||
margin: 1px 0;
|
|
||||||
border-radius: $border-radius;
|
|
||||||
|
|
||||||
.query-console-log-sql {
|
|
||||||
font-size: 95%;
|
|
||||||
opacity: 0.8;
|
|
||||||
font-weight: 700;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
user-select: text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -407,8 +407,9 @@ export const enUS = {
|
|||||||
saveFile: 'Save file',
|
saveFile: 'Save file',
|
||||||
saveFileAs: 'Save file as',
|
saveFileAs: 'Save file as',
|
||||||
openFile: 'Open file',
|
openFile: 'Open file',
|
||||||
openNotes: 'Open notes'
|
openNotes: 'Open notes',
|
||||||
|
debugConsole: 'Debug console', // <- console tab name
|
||||||
|
executedQueries: 'Executed queries' // <- console tab name
|
||||||
},
|
},
|
||||||
faker: { // Faker.js methods, used in random generated content
|
faker: { // Faker.js methods, used in random generated content
|
||||||
address: 'Address',
|
address: 'Address',
|
||||||
|
@ -12,7 +12,7 @@ import { createApp } from 'vue';
|
|||||||
import App from '@/App.vue';
|
import App from '@/App.vue';
|
||||||
import { i18n } from '@/i18n';
|
import { i18n } from '@/i18n';
|
||||||
import { useApplicationStore } from '@/stores/application';
|
import { useApplicationStore } from '@/stores/application';
|
||||||
import { useConsoleStore } from '@/stores/console';
|
import { QueryLog, useConsoleStore } from '@/stores/console';
|
||||||
import { useNotificationsStore } from '@/stores/notifications';
|
import { useNotificationsStore } from '@/stores/notifications';
|
||||||
import { useSettingsStore } from '@/stores/settings';
|
import { useSettingsStore } from '@/stores/settings';
|
||||||
|
|
||||||
@ -37,11 +37,17 @@ i18n.global.locale = locale;
|
|||||||
// IPC exceptions
|
// IPC exceptions
|
||||||
ipcRenderer.on('unhandled-exception', (event, error) => {
|
ipcRenderer.on('unhandled-exception', (event, error) => {
|
||||||
useNotificationsStore().addNotification({ status: 'error', message: error.message });
|
useNotificationsStore().addNotification({ status: 'error', message: error.message });
|
||||||
|
useConsoleStore().putLog('debug', {
|
||||||
|
level: 'error',
|
||||||
|
process: 'main',
|
||||||
|
message: error.message,
|
||||||
|
date: new Date()
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// IPC query logs
|
// IPC query logs
|
||||||
ipcRenderer.on('query-log', (event, logRecord) => {
|
ipcRenderer.on('query-log', (event, logRecord: QueryLog) => {
|
||||||
useConsoleStore().putLog(logRecord);
|
useConsoleStore().putLog('query', logRecord);
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcRenderer.on('toggle-console', () => {
|
ipcRenderer.on('toggle-console', () => {
|
||||||
|
@ -349,11 +349,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.query-console {
|
.console {
|
||||||
border-top: 1px solid #444;
|
border-top: 1px solid #444;
|
||||||
background-color: $bg-color-dark;
|
background-color: $bg-color-dark;
|
||||||
|
|
||||||
.query-console-log {
|
.console-log {
|
||||||
&:hover,
|
&:hover,
|
||||||
&:focus {
|
&:focus {
|
||||||
background: $bg-color-gray;
|
background: $bg-color-gray;
|
||||||
|
@ -173,11 +173,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.query-console {
|
.console {
|
||||||
border-top: 1px solid darken($bg-color-light-gray, 15%);
|
border-top: 1px solid darken($bg-color-light-gray, 15%);
|
||||||
background-color: $bg-color-light;
|
background-color: $bg-color-light;
|
||||||
|
|
||||||
.query-console-log {
|
.console-log {
|
||||||
&:hover,
|
&:hover,
|
||||||
&:focus {
|
&:focus {
|
||||||
background: $bg-color-light-gray;
|
background: $bg-color-light-gray;
|
||||||
|
@ -1,56 +1,63 @@
|
|||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
|
|
||||||
import { useWorkspacesStore } from './workspaces';
|
|
||||||
const logsSize = 1000;
|
const logsSize = 1000;
|
||||||
|
|
||||||
export interface ConsoleRecord {
|
export type LogType = 'query' | 'debug'
|
||||||
|
export interface QueryLog {
|
||||||
cUid: string;
|
cUid: string;
|
||||||
sql: string;
|
sql: string;
|
||||||
date: Date;
|
date: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface DebugLog {
|
||||||
|
level: 'log' | 'info' | 'warn' | 'error';
|
||||||
|
process: 'renderer' | 'main' | 'worker';
|
||||||
|
message: string;
|
||||||
|
date: Date;
|
||||||
|
}
|
||||||
|
|
||||||
export const useConsoleStore = defineStore('console', {
|
export const useConsoleStore = defineStore('console', {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
records: [] as ConsoleRecord[],
|
isConsoleOpen: false,
|
||||||
consolesHeight: new Map<string, number>(),
|
queryLogs: [] as QueryLog[],
|
||||||
consolesOpened: new Set([])
|
debugLogs: [] as DebugLog[],
|
||||||
|
selectedTab: 'query' as LogType,
|
||||||
|
consoleHeight: 0
|
||||||
}),
|
}),
|
||||||
getters: {
|
getters: {
|
||||||
getLogsByWorkspace: state => (uid: string) => state.records.filter(r => r.cUid === uid),
|
getLogsByWorkspace: state => (uid: string) => state.queryLogs.filter(r => r.cUid === uid)
|
||||||
isConsoleOpen: state => (uid: string) => state.consolesOpened.has(uid),
|
|
||||||
consoleHeight: state => {
|
|
||||||
const uid = useWorkspacesStore().getSelected;
|
|
||||||
return state.consolesHeight.get(uid) || 0;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
putLog (record: ConsoleRecord) {
|
putLog (type: LogType, record: QueryLog | DebugLog) {
|
||||||
this.records.push(record);
|
if (type === 'query') {
|
||||||
|
this.queryLogs.push(record);
|
||||||
|
|
||||||
if (this.records.length > logsSize)
|
if (this.queryLogs.length > logsSize)
|
||||||
this.records = this.records.slice(0, logsSize);
|
this.queryLogs = this.queryLogs.slice(0, logsSize);
|
||||||
|
}
|
||||||
|
else if (type === 'debug') {
|
||||||
|
this.debugLogs.push(record);
|
||||||
|
|
||||||
|
if (this.debugLogs.length > logsSize)
|
||||||
|
this.debugLogs = this.debugLogs.slice(0, logsSize);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
openConsole () {
|
openConsole () {
|
||||||
const uid = useWorkspacesStore().getSelected;
|
this.isConsoleOpen = true;
|
||||||
this.consolesOpened.add(uid);
|
this.consoleHeight = 250;
|
||||||
this.consolesHeight.set(uid, 250);
|
|
||||||
},
|
},
|
||||||
closeConsole () {
|
closeConsole () {
|
||||||
const uid = useWorkspacesStore().getSelected;
|
this.isConsoleOpen = false;
|
||||||
this.consolesOpened.delete(uid);
|
this.consoleHeight = 0;
|
||||||
this.consolesHeight.set(uid, 0);
|
|
||||||
},
|
},
|
||||||
resizeConsole (height: number) {
|
resizeConsole (height: number) {
|
||||||
const uid = useWorkspacesStore().getSelected;
|
|
||||||
if (height < 30)
|
if (height < 30)
|
||||||
this.closeConsole();
|
this.closeConsole();
|
||||||
else
|
else
|
||||||
this.consolesHeight.set(uid, height);
|
this.consoleHeight = height;
|
||||||
},
|
},
|
||||||
toggleConsole () {
|
toggleConsole () {
|
||||||
const uid = useWorkspacesStore().getSelected;
|
if (this.isConsoleOpen)
|
||||||
|
|
||||||
if (this.consolesOpened.has(uid))
|
|
||||||
this.closeConsole();
|
this.closeConsole();
|
||||||
else
|
else
|
||||||
this.openConsole();
|
this.openConsole();
|
||||||
|
Reference in New Issue
Block a user