1
1
mirror of https://github.com/Fabio286/antares.git synced 2025-04-13 17:52:04 +02:00

feat(UI): new context menu and some minor improvements to query tabs, closes #867

This commit is contained in:
Fabio Di Stasio 2024-09-30 18:10:38 +02:00
parent 7969294a93
commit 14aeebed9c
7 changed files with 105 additions and 19 deletions

View File

@ -141,8 +141,11 @@ onMounted(() => {
while (node) { while (node) {
if (node.nodeName.match(/^(input|textarea)$/i) || node.isContentEditable) { if (node.nodeName.match(/^(input|textarea)$/i) || node.isContentEditable) {
InputMenu.popup({ window: getCurrentWindow() }); if (!node.parentNode.className.split(' ').includes('editor-query')) {
break; InputMenu.popup({ window: getCurrentWindow() });
console.log(node.parentNode.className);
break;
}
} }
node = node.parentNode; node = node.parentNode;
} }

View File

@ -612,7 +612,7 @@ const otherContributors = computed(() => {
return contributors return contributors
.split(',') .split(',')
.filter(c => !c.includes(appAuthor)) .filter(c => !c.includes(appAuthor))
.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase())); .sort((a, b) => a.toLowerCase().trim().localeCompare(b.toLowerCase()));
}); });
const selectTab = (tab: string) => { const selectTab = (tab: string) => {

View File

@ -3,6 +3,7 @@
<div <div
:id="`editor-${id}`" :id="`editor-${id}`"
class="editor" class="editor"
:class="editorClasses"
:style="{height: `${height}px`}" :style="{height: `${height}px`}"
/> />
</div> </div>
@ -54,7 +55,8 @@ const props = defineProps({
schema: { type: String, default: '' }, schema: { type: String, default: '' },
autoFocus: { type: Boolean, default: false }, autoFocus: { type: Boolean, default: false },
readOnly: { type: Boolean, default: false }, readOnly: { type: Boolean, default: false },
height: { type: Number, default: 200 } height: { type: Number, default: 200 },
editorClasses: { type: String, default: '' }
}); });
const emit = defineEmits(['update:modelValue']); const emit = defineEmits(['update:modelValue']);
@ -405,18 +407,17 @@ defineExpose({ editor });
.ace_gutter-cell.ace_breakpoint { .ace_gutter-cell.ace_breakpoint {
&::before { &::before {
content: '\F0403'; content: '';
position: absolute; position: absolute;
left: 3px; left: 0px;
top: 2px; top: 8px;
color: var(--primary-color);
display: inline-block; display: inline-block;
font: normal normal normal 24px/1 "Material Design Icons", sans-serif; width: 0;
font-size: inherit; height: 0;
text-rendering: auto; border-left: 8px solid transparent;
line-height: inherit; border-top: 8px solid transparent;
-webkit-font-smoothing: antialiased; border-right: 8px solid var(--primary-color);
-moz-osx-font-smoothing: grayscale; transform: rotate(-45deg);
} }
} }
</style> </style>

View File

@ -15,6 +15,7 @@
:schema="breadcrumbsSchema" :schema="breadcrumbsSchema"
:is-selected="isSelected" :is-selected="isSelected"
:height="editorHeight" :height="editorHeight"
editor-classes="editor-query"
/> />
<div ref="resizer" class="query-area-resizer" /> <div ref="resizer" class="query-area-resizer" />
<div ref="queryAreaFooter" class="workspace-query-runner-footer"> <div ref="queryAreaFooter" class="workspace-query-runner-footer">
@ -273,6 +274,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { getCurrentWindow, Menu } from '@electron/remote';
import { Ace } from 'ace-builds'; import { Ace } from 'ace-builds';
import { ConnectionParams } from 'common/interfaces/antares'; import { ConnectionParams } from 'common/interfaces/antares';
import { uidGen } from 'common/libs/uidGen'; import { uidGen } from 'common/libs/uidGen';
@ -475,6 +477,8 @@ const runQuery = async (query: string) => {
saveHistory(params); saveHistory(params);
if (!autocommit.value) if (!autocommit.value)
setUnsavedChanges({ uid: props.connection.uid, tUid: props.tabUid, isChanged: true }); setUnsavedChanges({ uid: props.connection.uid, tUid: props.tabUid, isChanged: true });
queryEditor.value.editor.focus();
} }
else else
addNotification({ status: 'error', message: response }); addNotification({ status: 'error', message: response });
@ -739,7 +743,11 @@ const openFile = async () => {
const saveFileAs = async () => { const saveFileAs = async () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
const result: any = await Application.showSaveDialog({ filters: [{ name: 'SQL', extensions: ['sql'] }], defaultPath: `${queryName.value || 'query'}.sql` }); const result: any = await Application.showSaveDialog({
filters: [{ name: 'SQL', extensions: ['sql'] }],
defaultPath: (!queryName.value.includes('.sql') ? `${queryName.value}.sql` :queryName.value) || 'query.sql'
});
if (result && !result.canceled) { if (result && !result.canceled) {
await Application.writeFile(result.filePath, query.value); await Application.writeFile(result.filePath, query.value);
addNotification({ status: 'success', message: t('general.actionSuccessful', { action: t('application.saveFile') }) }); addNotification({ status: 'success', message: t('general.actionSuccessful', { action: t('application.saveFile') }) });
@ -750,9 +758,13 @@ const saveFileAs = async () => {
}; };
const saveFile = async () => { const saveFile = async () => {
await Application.writeFile(filePath.value, query.value); if (filePath.value) {
addNotification({ status: 'success', message: t('general.actionSuccessful', { action: t('application.saveFile') }) }); await Application.writeFile(filePath.value, query.value);
lastSavedQuery.value = toRaw(query.value); addNotification({ status: 'success', message: t('general.actionSuccessful', { action: t('application.saveFile') }) });
lastSavedQuery.value = toRaw(query.value);
}
else
saveFileAs();
}; };
const loadFileContent = async (file: string) => { const loadFileContent = async (file: string) => {
@ -785,6 +797,67 @@ onMounted(() => {
if (props.tab.filePath) if (props.tab.filePath)
loadFileContent(props.tab.filePath); loadFileContent(props.tab.filePath);
queryEditor.value.editor.container.addEventListener('contextmenu', (e) => {
const InputMenu = Menu.buildFromTemplate([
{
label: t('general.run'),
click: () => runQuery(query.value)
},
{
label: t('general.clear'),
click: () => clear()
},
{
type: 'separator'
},
{
label: t('application.saveFile'),
click: () => saveFile()
},
{
label: t('application.saveFileAs'),
click: () => saveFileAs()
},
{
label: t('application.openFile'),
click: () => openFile()
},
{
type: 'separator'
},
{
label: t('general.cut'),
role: 'cut'
},
{
label: t('general.copy'),
role: 'copy'
},
{
label: t('general.paste'),
role: 'paste'
},
{
type: 'separator'
},
{
label: t('general.selectAll'),
role: 'selectAll'
}
]);
e.preventDefault();
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let node: any = e.target;
while (node) {
if (node.nodeName.match(/^(input|textarea)$/i) || node.isContentEditable) {
InputMenu.popup({ window: getCurrentWindow() });
break;
}
node = node.parentNode;
}
});
}); });
onBeforeUnmount(() => { onBeforeUnmount(() => {

View File

@ -9,7 +9,7 @@ export const localesNames: Record<string, string> = {
'vi-VN': 'Tiếng Việt', 'vi-VN': 'Tiếng Việt',
'ja-JP': '日本語', 'ja-JP': '日本語',
'zh-CN': '简体中文', 'zh-CN': '简体中文',
'zh-TW': '體中文', 'zh-TW': '體中文',
'ru-RU': 'Русский', 'ru-RU': 'Русский',
'id-ID': 'Bahasa Indonesia', 'id-ID': 'Bahasa Indonesia',
'ko-KR': '한국어', 'ko-KR': '한국어',

View File

@ -256,6 +256,10 @@ option:checked {
} }
&.active { &.active {
a {
border-bottom-color: transparent;
}
.tab-link { .tab-link {
border-color: transparent; border-color: transparent;
} }

View File

@ -255,6 +255,11 @@
} }
} }
&.result-tabs .tab-item {
background: transparent;
}
.workspace-query-runner .workspace-query-runner-footer .workspace-query-buttons .btn { .workspace-query-runner .workspace-query-runner-footer .workspace-query-buttons .btn {
color: $body-font-color-dark; color: $body-font-color-dark;
} }