mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-26 06:26:00 +00:00
custom error shortcuts
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
<script lang="ts" context="module">
|
<script lang="ts" context="module">
|
||||||
import { commands, visibleCommandPalette } from '../stores';
|
import { commandsCustomized, visibleCommandPalette } from '../stores';
|
||||||
import { get } from 'svelte/store';
|
import { get } from 'svelte/store';
|
||||||
import { runGroupCommand } from './runCommand';
|
import { runGroupCommand } from './runCommand';
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
// console.log('keyText', keyText);
|
// console.log('keyText', keyText);
|
||||||
|
|
||||||
const commandsValue = get(commands);
|
const commandsValue = get(commandsCustomized);
|
||||||
const commandsFiltered: any = Object.values(commandsValue).filter(
|
const commandsFiltered: any = Object.values(commandsValue).filter(
|
||||||
(x: any) =>
|
(x: any) =>
|
||||||
x.keyText &&
|
x.keyText &&
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
import { commands, getVisibleCommandPalette, visibleCommandPalette } from '../stores';
|
import { commands, commandsCustomized, getVisibleCommandPalette, visibleCommandPalette } from '../stores';
|
||||||
import clickOutside from '../utility/clickOutside';
|
import clickOutside from '../utility/clickOutside';
|
||||||
import keycodes from '../utility/keycodes';
|
import keycodes from '../utility/keycodes';
|
||||||
import registerCommand from './registerCommand';
|
import registerCommand from './registerCommand';
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
$: sortedComands = _.sortBy(
|
$: sortedComands = _.sortBy(
|
||||||
Object.values($commands).filter(x => x.enabled),
|
Object.values($commandsCustomized).filter(x => x.enabled),
|
||||||
'text'
|
'text'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -203,6 +203,20 @@ registerCommand({
|
|||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
registerCommand({
|
||||||
|
id: 'settings.commands',
|
||||||
|
category: 'Settings',
|
||||||
|
name: 'Keyboard shortcuts',
|
||||||
|
onClick: () => {
|
||||||
|
openNewTab({
|
||||||
|
title: 'Keyboard Shortcuts',
|
||||||
|
icon: 'icon keyboard',
|
||||||
|
tabComponent: 'CommandListTab',
|
||||||
|
props: {},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export function registerFileCommands({
|
export function registerFileCommands({
|
||||||
idPrefix,
|
idPrefix,
|
||||||
category,
|
category,
|
||||||
|
|||||||
@@ -6,24 +6,28 @@
|
|||||||
getProps?: any;
|
getProps?: any;
|
||||||
formatter?: any;
|
formatter?: any;
|
||||||
slot?: number;
|
slot?: number;
|
||||||
|
isHighlighted?: Function;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
|
||||||
import { compact } from 'lodash';
|
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
import keycodes from '../utility/keycodes';
|
import keycodes from '../utility/keycodes';
|
||||||
|
import { createEventDispatcher } from 'svelte';
|
||||||
|
|
||||||
export let columns: TableControlColumn[];
|
export let columns: TableControlColumn[];
|
||||||
export let rows;
|
export let rows;
|
||||||
export let focusOnCreate = false;
|
export let focusOnCreate = false;
|
||||||
export let selectable = false;
|
export let selectable = false;
|
||||||
export let selectedIndex = 0;
|
export let selectedIndex = 0;
|
||||||
|
export let clickable = false;
|
||||||
|
|
||||||
export let domTable;
|
export let domTable;
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
$: columnList = _.compact(_.flatten(columns));
|
$: columnList = _.compact(_.flatten(columns));
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
@@ -58,15 +62,19 @@
|
|||||||
{#each rows as row, index}
|
{#each rows as row, index}
|
||||||
<tr
|
<tr
|
||||||
class:selected={selectable && selectedIndex == index}
|
class:selected={selectable && selectedIndex == index}
|
||||||
|
class:clickable
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
if (selectable) {
|
if (selectable) {
|
||||||
selectedIndex = index;
|
selectedIndex = index;
|
||||||
domTable.focus();
|
domTable.focus();
|
||||||
}
|
}
|
||||||
|
if (clickable) {
|
||||||
|
dispatch('clickrow', row);
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{#each columnList as col}
|
{#each columnList as col}
|
||||||
<td>
|
<td class:isHighlighted={col.isHighlighted && col.isHighlighted(row)}>
|
||||||
{#if col.component}
|
{#if col.component}
|
||||||
<svelte:component this={col.component} {...col.getProps(row)} />
|
<svelte:component this={col.component} {...col.getProps(row)} />
|
||||||
{:else if col.formatter}
|
{:else if col.formatter}
|
||||||
@@ -106,6 +114,9 @@
|
|||||||
tbody tr.selected {
|
tbody tr.selected {
|
||||||
background: var(--theme-bg-selected);
|
background: var(--theme-bg-selected);
|
||||||
}
|
}
|
||||||
|
tbody tr.clickable:hover {
|
||||||
|
background: var(--theme-bg-hover);
|
||||||
|
}
|
||||||
thead td {
|
thead td {
|
||||||
border: 1px solid var(--theme-border);
|
border: 1px solid var(--theme-border);
|
||||||
background-color: var(--theme-bg-1);
|
background-color: var(--theme-bg-1);
|
||||||
@@ -115,4 +126,8 @@
|
|||||||
border: 1px solid var(--theme-border);
|
border: 1px solid var(--theme-border);
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
td.isHighlighted {
|
||||||
|
background-color: var(--theme-bg-1);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
'icon connection': 'mdi mdi-connection',
|
'icon connection': 'mdi mdi-connection',
|
||||||
'icon cell-data': 'mdi mdi-details',
|
'icon cell-data': 'mdi mdi-details',
|
||||||
'icon sql-generator': 'mdi mdi-cog-transfer',
|
'icon sql-generator': 'mdi mdi-cog-transfer',
|
||||||
|
'icon keyboard': 'mdi mdi-keyboard-settings',
|
||||||
|
|
||||||
'icon database': 'mdi mdi-database',
|
'icon database': 'mdi mdi-database',
|
||||||
'icon server': 'mdi mdi-server',
|
'icon server': 'mdi mdi-server',
|
||||||
|
|||||||
49
packages/web/src/modals/CommandModal.svelte
Normal file
49
packages/web/src/modals/CommandModal.svelte
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
|
import FormStyledButton from '../elements/FormStyledButton.svelte';
|
||||||
|
|
||||||
|
import FormProvider from '../forms/FormProvider.svelte';
|
||||||
|
import FormSubmit from '../forms/FormSubmit.svelte';
|
||||||
|
import FormTextField from '../forms/FormTextField.svelte';
|
||||||
|
import { customKeyboardShortcuts } from '../stores';
|
||||||
|
import ModalBase from './ModalBase.svelte';
|
||||||
|
import { closeCurrentModal } from './modalTools';
|
||||||
|
|
||||||
|
export let command;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<FormProvider initialValues={command}>
|
||||||
|
<ModalBase {...$$restProps}>
|
||||||
|
<svelte:fragment slot="header">Configure commmand</svelte:fragment>
|
||||||
|
|
||||||
|
<FormTextField label="Category" name="category" disabled />
|
||||||
|
<FormTextField label="Name" name="name" disabled />
|
||||||
|
<FormTextField label="Keyboard shortcut" name="keyText" />
|
||||||
|
|
||||||
|
<svelte:fragment slot="footer">
|
||||||
|
<FormSubmit
|
||||||
|
value="OK"
|
||||||
|
on:click={e => {
|
||||||
|
closeCurrentModal();
|
||||||
|
customKeyboardShortcuts.update(list => ({
|
||||||
|
...list,
|
||||||
|
[command.id]: {
|
||||||
|
keyText: e.detail.keyText,
|
||||||
|
customKeyboardShortcut: true,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<FormStyledButton
|
||||||
|
type="button"
|
||||||
|
value="Reset"
|
||||||
|
on:click={() => {
|
||||||
|
closeCurrentModal();
|
||||||
|
customKeyboardShortcuts.update(list => _.omit(list, [command.id]));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<FormStyledButton type="button" value="Close" on:click={closeCurrentModal} />
|
||||||
|
</svelte:fragment>
|
||||||
|
</ModalBase>
|
||||||
|
</FormProvider>
|
||||||
@@ -48,7 +48,7 @@
|
|||||||
import clickOutside from '../utility/clickOutside';
|
import clickOutside from '../utility/clickOutside';
|
||||||
import { createEventDispatcher } from 'svelte';
|
import { createEventDispatcher } from 'svelte';
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
import { commands } from '../stores';
|
import { commands, commandsCustomized } from '../stores';
|
||||||
import { extractMenuItems } from '../utility/contextMenu';
|
import { extractMenuItems } from '../utility/contextMenu';
|
||||||
|
|
||||||
export let items;
|
export let items;
|
||||||
@@ -70,7 +70,7 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
$: extracted = extractMenuItems(items);
|
$: extracted = extractMenuItems(items);
|
||||||
$: compacted = _.compact(extracted.map(x => mapItem(x, $commands)));
|
$: compacted = _.compact(extracted.map(x => mapItem(x, $commandsCustomized)));
|
||||||
$: filtered = compacted.filter(x => !x.disabled || !x.hideDisabled);
|
$: filtered = compacted.filter(x => !x.disabled || !x.hideDisabled);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,16 @@ export const currentTheme = writableWithStorage('theme-light', 'currentTheme');
|
|||||||
export const activeTabId = derived([openedTabs], ([$openedTabs]) => $openedTabs.find(x => x.selected)?.tabid);
|
export const activeTabId = derived([openedTabs], ([$openedTabs]) => $openedTabs.find(x => x.selected)?.tabid);
|
||||||
export const activeTab = derived([openedTabs], ([$openedTabs]) => $openedTabs.find(x => x.selected));
|
export const activeTab = derived([openedTabs], ([$openedTabs]) => $openedTabs.find(x => x.selected));
|
||||||
export const recentDatabases = writableWithStorage([], 'recentDatabases');
|
export const recentDatabases = writableWithStorage([], 'recentDatabases');
|
||||||
|
export const customKeyboardShortcuts = writableWithStorage({}, 'customKeyboardShortcuts');
|
||||||
|
export const commandsCustomized = derived(
|
||||||
|
[commands, customKeyboardShortcuts],
|
||||||
|
([$commands, $customKeyboardShortcuts]) =>
|
||||||
|
_.mapValues($commands, (v, k) => ({
|
||||||
|
// @ts-ignore
|
||||||
|
...v,
|
||||||
|
...$customKeyboardShortcuts[k],
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
|
||||||
export const visibleToolbar = writableWithStorage(1, 'visibleToolbar');
|
export const visibleToolbar = writableWithStorage(1, 'visibleToolbar');
|
||||||
export const leftPanelWidth = writable(300);
|
export const leftPanelWidth = writable(300);
|
||||||
|
|||||||
35
packages/web/src/tabs/CommandListTab.svelte
Normal file
35
packages/web/src/tabs/CommandListTab.svelte
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<script lang="ts" context="module">
|
||||||
|
export const matchingProps = [];
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
|
import TableControl from '../elements/TableControl.svelte';
|
||||||
|
import CommandModal from '../modals/CommandModal.svelte';
|
||||||
|
import { showModal } from '../modals/modalTools';
|
||||||
|
import { commandsCustomized } from '../stores';
|
||||||
|
|
||||||
|
$: commandList = _.sortBy(_.values($commandsCustomized), ['category', 'name']);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="wrapper">
|
||||||
|
<TableControl
|
||||||
|
clickable
|
||||||
|
rows={commandList}
|
||||||
|
columns={[
|
||||||
|
{ header: 'Category', fieldName: 'category' },
|
||||||
|
{ header: 'Name', fieldName: 'name' },
|
||||||
|
{ header: 'Keyboard shortcut', fieldName: 'keyText', isHighlighted: row => row.customKeyboardShortcut },
|
||||||
|
{ header: 'commandId', fieldName: 'id' },
|
||||||
|
]}
|
||||||
|
on:clickrow={e => showModal(CommandModal, { command: e.detail })}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.wrapper {
|
||||||
|
overflow: auto;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -13,6 +13,7 @@ import * as MarkdownViewTab from './MarkdownViewTab.svelte';
|
|||||||
import * as MarkdownPreviewTab from './MarkdownPreviewTab.svelte';
|
import * as MarkdownPreviewTab from './MarkdownPreviewTab.svelte';
|
||||||
import * as FavoriteEditorTab from './FavoriteEditorTab.svelte';
|
import * as FavoriteEditorTab from './FavoriteEditorTab.svelte';
|
||||||
import * as QueryDesignTab from './QueryDesignTab.svelte';
|
import * as QueryDesignTab from './QueryDesignTab.svelte';
|
||||||
|
import * as CommandListTab from './CommandListTab.svelte';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
TableDataTab,
|
TableDataTab,
|
||||||
@@ -30,4 +31,5 @@ export default {
|
|||||||
MarkdownPreviewTab,
|
MarkdownPreviewTab,
|
||||||
FavoriteEditorTab,
|
FavoriteEditorTab,
|
||||||
QueryDesignTab,
|
QueryDesignTab,
|
||||||
|
CommandListTab,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ export default async function openNewTab(newTab, initialData = undefined, option
|
|||||||
|
|
||||||
let existing = null;
|
let existing = null;
|
||||||
|
|
||||||
|
|
||||||
const { savedFile, savedFolder, savedFilePath } = newTab.props || {};
|
const { savedFile, savedFolder, savedFilePath } = newTab.props || {};
|
||||||
if (savedFile || savedFilePath) {
|
if (savedFile || savedFilePath) {
|
||||||
existing = oldTabs.find(
|
existing = oldTabs.find(
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
import AppObjectList from '../appobj/AppObjectList.svelte';
|
import AppObjectList from '../appobj/AppObjectList.svelte';
|
||||||
import * as connectionAppObject from '../appobj/ConnectionAppObject.svelte';
|
import * as connectionAppObject from '../appobj/ConnectionAppObject.svelte';
|
||||||
import SubDatabaseList from '../appobj/SubDatabaseList.svelte';
|
import SubDatabaseList from '../appobj/SubDatabaseList.svelte';
|
||||||
import { commands, openedConnections } from '../stores';
|
import { commands, commandsCustomized, openedConnections } from '../stores';
|
||||||
import axiosInstance from '../utility/axiosInstance';
|
import axiosInstance from '../utility/axiosInstance';
|
||||||
import ToolbarButton from './ToolbarButton.svelte';
|
import ToolbarButton from './ToolbarButton.svelte';
|
||||||
import runCommand from '../commands/runCommand';
|
import runCommand from '../commands/runCommand';
|
||||||
@@ -43,7 +43,7 @@
|
|||||||
isExpandable={data => $openedConnections.includes(data._id)}
|
isExpandable={data => $openedConnections.includes(data._id)}
|
||||||
{filter}
|
{filter}
|
||||||
/>
|
/>
|
||||||
{#if $connections && $connections.length == 0 && $commands['new.connection']?.enabled}
|
{#if $connections && $connections.length == 0 && $commandsCustomized['new.connection']?.enabled}
|
||||||
<ToolbarButton icon="icon new-connection" on:click={() => runCommand('new.connection')}>
|
<ToolbarButton icon="icon new-connection" on:click={() => runCommand('new.connection')}>
|
||||||
Add new connection
|
Add new connection
|
||||||
</ToolbarButton>
|
</ToolbarButton>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import { openFavorite } from '../appobj/FavoriteFileAppObject.svelte';
|
import { openFavorite } from '../appobj/FavoriteFileAppObject.svelte';
|
||||||
import runCommand from '../commands/runCommand';
|
import runCommand from '../commands/runCommand';
|
||||||
import { commands } from '../stores';
|
import { commands, commandsCustomized } from '../stores';
|
||||||
import getElectron from '../utility/getElectron';
|
import getElectron from '../utility/getElectron';
|
||||||
import { useFavorites } from '../utility/metadataLoaders';
|
import { useFavorites } from '../utility/metadataLoaders';
|
||||||
import ToolbarButton from './ToolbarButton.svelte';
|
import ToolbarButton from './ToolbarButton.svelte';
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
$: favorites = useFavorites();
|
$: favorites = useFavorites();
|
||||||
|
|
||||||
$: list = _.sortBy(
|
$: list = _.sortBy(
|
||||||
Object.values($commands).filter(x => (x.enabled || x.showDisabled) && x.toolbar && x.onClick),
|
Object.values($commandsCustomized).filter(x => (x.enabled || x.showDisabled) && x.toolbar && x.onClick),
|
||||||
x => (x.toolbarOrder == null ? 100 : x.toolbarOrder)
|
x => (x.toolbarOrder == null ? 100 : x.toolbarOrder)
|
||||||
);
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user