mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-21 01:16:01 +00:00
213 lines
5.2 KiB
Svelte
213 lines
5.2 KiB
Svelte
<script context="module">
|
|
const electron = getElectron();
|
|
|
|
registerCommand({
|
|
id: 'commandPalette.show',
|
|
category: 'Command palette',
|
|
name: 'Show',
|
|
toolbarName: 'Menu',
|
|
toolbarOrder: 0,
|
|
keyText: 'F1',
|
|
toolbar: true,
|
|
showDisabled: true,
|
|
icon: 'icon menu',
|
|
onClick: () => visibleCommandPalette.set(true),
|
|
testEnabled: () => !getVisibleCommandPalette(),
|
|
});
|
|
|
|
registerCommand({
|
|
id: 'database.search',
|
|
category: 'Database',
|
|
name: 'Search',
|
|
keyText: electron ? 'Ctrl+P' : 'F3',
|
|
onClick: () => visibleCommandPalette.set(true),
|
|
testEnabled: () => !getVisibleCommandPalette(),
|
|
});
|
|
|
|
function extractDbItems(db) {
|
|
return db?.tables?.map(table => ({ text: table.pureName, onClick: () => handleDatabaseObjectClick(table) }));
|
|
}
|
|
</script>
|
|
|
|
<script>
|
|
import { filterName } from 'dbgate-tools';
|
|
|
|
import _ from 'lodash';
|
|
import { onMount } from 'svelte';
|
|
import FontIcon from '../icons/FontIcon.svelte';
|
|
import {
|
|
commands,
|
|
commandsCustomized,
|
|
currentDatabase,
|
|
getVisibleCommandPalette,
|
|
visibleCommandPalette,
|
|
} from '../stores';
|
|
import clickOutside from '../utility/clickOutside';
|
|
import getElectron from '../utility/getElectron';
|
|
import keycodes from '../utility/keycodes';
|
|
import { useDatabaseInfo } from '../utility/metadataLoaders';
|
|
import registerCommand from './registerCommand';
|
|
|
|
let domInput;
|
|
let filter = '';
|
|
let selectedPage = 'menu';
|
|
const domItems = {};
|
|
|
|
$: selectedIndex = true ? 0 : filter;
|
|
$: parentCommand = _.isPlainObject($visibleCommandPalette) ? $visibleCommandPalette : null;
|
|
|
|
onMount(() => {
|
|
const oldFocus = document.activeElement;
|
|
domInput.focus();
|
|
return () => {
|
|
if (oldFocus) oldFocus.focus();
|
|
};
|
|
});
|
|
|
|
$: sortedComands = _.sortBy(
|
|
Object.values($commandsCustomized).filter(x => x.enabled),
|
|
'text'
|
|
);
|
|
|
|
$: conid = _.get($currentDatabase, 'connection._id');
|
|
$: database = _.get($currentDatabase, 'name');
|
|
$: databaseInfo = useDatabaseInfo({ conid, database });
|
|
|
|
$: filteredItems = (selectedPage == 'database'
|
|
? extractDbItems($databaseInfo)
|
|
: parentCommand
|
|
? parentCommand.getSubCommands()
|
|
: sortedComands
|
|
).filter(x => !x.isGroupCommand && filterName(filter, x.text));
|
|
|
|
function handleCommand(command) {
|
|
if (command.getSubCommands) {
|
|
$visibleCommandPalette = command;
|
|
domInput.focus();
|
|
filter = '';
|
|
selectedIndex = 0;
|
|
} else {
|
|
$visibleCommandPalette = false;
|
|
command.onClick();
|
|
}
|
|
}
|
|
|
|
function handleKeyDown(e) {
|
|
if (e.keyCode == keycodes.upArrow && selectedIndex > 0) selectedIndex--;
|
|
if (e.keyCode == keycodes.downArrow && selectedIndex < filteredItems.length - 1) selectedIndex++;
|
|
if (e.keyCode == keycodes.enter) {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
handleCommand(filteredItems[selectedIndex]);
|
|
}
|
|
if (e.keyCode == keycodes.escape) $visibleCommandPalette = false;
|
|
|
|
if (e.keyCode == keycodes.pageDown) selectedIndex = Math.min(selectedIndex + 15, filteredItems.length - 1);
|
|
if (e.keyCode == keycodes.pageUp) selectedIndex = Math.max(selectedIndex - 15, 0);
|
|
}
|
|
|
|
$: if (domItems[selectedIndex]) domItems[selectedIndex].scrollIntoView({ block: 'nearest', inline: 'nearest' });
|
|
</script>
|
|
|
|
<div class="main" use:clickOutside on:clickOutside={() => ($visibleCommandPalette = false)}>
|
|
<div class="pages">
|
|
<div
|
|
class="page"
|
|
class:selected={selectedPage == 'menu'}
|
|
on:click={() => {
|
|
selectedPage = 'menu';
|
|
domInput.focus();
|
|
}}
|
|
>
|
|
<FontIcon icon="icon menu" /> Commands
|
|
</div>
|
|
<div
|
|
class="page"
|
|
class:selected={selectedPage == 'database'}
|
|
on:click={() => {
|
|
selectedPage = 'database';
|
|
domInput.focus();
|
|
}}
|
|
>
|
|
<FontIcon icon="icon database" /> Database
|
|
</div>
|
|
</div>
|
|
<div class="mainInner">
|
|
<div class="search">
|
|
<input
|
|
type="text"
|
|
bind:this={domInput}
|
|
bind:value={filter}
|
|
on:keydown={handleKeyDown}
|
|
placeholder={parentCommand?.text || ''}
|
|
/>
|
|
</div>
|
|
<div class="content">
|
|
{#each filteredItems as command, index}
|
|
<div
|
|
class="command"
|
|
class:selected={index == selectedIndex}
|
|
on:click={() => handleCommand(command)}
|
|
bind:this={domItems[index]}
|
|
>
|
|
<div>{command.text}</div>
|
|
{#if command.keyText}
|
|
<div class="shortcut">{command.keyText}</div>
|
|
{/if}
|
|
</div>
|
|
{/each}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<style>
|
|
.main {
|
|
width: 500px;
|
|
background: var(--theme-bg-2);
|
|
}
|
|
|
|
.mainInner {
|
|
padding: 5px;
|
|
}
|
|
|
|
.content {
|
|
max-height: 400px;
|
|
overflow-y: scroll;
|
|
}
|
|
.search {
|
|
display: flex;
|
|
}
|
|
input {
|
|
width: 100%;
|
|
}
|
|
.command {
|
|
padding: 5px;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
}
|
|
.command:hover {
|
|
background: var(--theme-bg-3);
|
|
}
|
|
.command.selected {
|
|
background: var(--theme-bg-selected);
|
|
}
|
|
.shortcut {
|
|
background: var(--theme-bg-3);
|
|
}
|
|
|
|
.pages {
|
|
display: flex;
|
|
}
|
|
.page {
|
|
padding: 5px;
|
|
border: 1px solid var(--theme-border);
|
|
cursor: pointer;
|
|
}
|
|
.page:hover {
|
|
color: var(--theme-font-hover);
|
|
}
|
|
.page.selected {
|
|
background: var(--theme-bg-1);
|
|
}
|
|
</style>
|