mirror of
https://github.com/dbgate/dbgate
synced 2024-11-07 20:26:23 +00:00
toolbar
This commit is contained in:
parent
a101f21483
commit
d9387bef1f
@ -4,5 +4,16 @@
|
||||
--dim-left-panel-width: 300px;
|
||||
--dim-tabs-panel-height: 53px;
|
||||
--dim-splitter-thickness: 3px;
|
||||
--dim-content-left: calc(var(--dim-widget-icon-size) + var(--dim-left-panel-width) + var(--dim-splitter-thickness));
|
||||
|
||||
--dim-visible-left-panel: 1; /* set from JS */
|
||||
--dim-content-left: calc(
|
||||
var(--dim-widget-icon-size) + var(--dim-visible-left-panel) *
|
||||
(var(--dim-left-panel-width) + var(--dim-splitter-thickness))
|
||||
);
|
||||
|
||||
--dim-visible-toolbar: 1; /* set from JS */
|
||||
|
||||
--dim-toolbar-height: 30px;
|
||||
--dim-header-top: calc(var(--dim-toolbar-height) * var(--dim-visible-toolbar));
|
||||
--dim-content-top: calc(var(--dim-header-top) + var(--dim-tabs-panel-height));
|
||||
}
|
||||
|
@ -1,10 +1,11 @@
|
||||
<script lang="ts">
|
||||
import WidgetContainer from './widgets/WidgetContainer.svelte';
|
||||
import WidgetIconPanel from './widgets/WidgetIconPanel.svelte';
|
||||
import { currentTheme, selectedWidget, visibleCommandPalette } from './stores';
|
||||
import { currentTheme, selectedWidget, visibleCommandPalette, visibleToolbar } from './stores';
|
||||
import TabsPanel from './widgets/TabsPanel.svelte';
|
||||
import TabContent from './TabContent.svelte';
|
||||
import CommandPalette from './commands/CommandPalette.svelte';
|
||||
import Toolbar from './widgets/Toolbar.svelte';
|
||||
</script>
|
||||
|
||||
<div class={`${$currentTheme} root`}>
|
||||
@ -28,6 +29,11 @@
|
||||
<CommandPalette />
|
||||
</div>
|
||||
{/if}
|
||||
{#if $visibleToolbar}
|
||||
<div class="toolbar">
|
||||
<Toolbar />
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
@ -37,7 +43,7 @@
|
||||
.iconbar {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
top: var(--dim-header-top);
|
||||
bottom: var(--dim-statusbar-height);
|
||||
width: var(--dim-widget-icon-size);
|
||||
background: var(--theme-bg-inv-1);
|
||||
@ -52,7 +58,7 @@
|
||||
}
|
||||
.leftpanel {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
top: var(--dim-header-top);
|
||||
left: var(--dim-widget-icon-size);
|
||||
bottom: var(--dim-statusbar-height);
|
||||
width: var(--dim-left-panel-width);
|
||||
@ -62,7 +68,7 @@
|
||||
.tabs {
|
||||
display: flex;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
top: var(--dim-header-top);
|
||||
left: var(--dim-content-left);
|
||||
height: var(--dim-tabs-panel-height);
|
||||
right: 0;
|
||||
@ -76,7 +82,7 @@
|
||||
}
|
||||
.content {
|
||||
position: fixed;
|
||||
top: var(--dim-tabs-panel-height);
|
||||
top: var(--dim-content-top);
|
||||
left: var(--dim-content-left);
|
||||
bottom: var(--dim-statusbar-height);
|
||||
right: 0;
|
||||
@ -84,7 +90,14 @@
|
||||
}
|
||||
.commads {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
top: var(--dim-header-top);
|
||||
left: var(--dim-widget-icon-size);
|
||||
}
|
||||
.toolbar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
height: var(--dim-toolbar-height);
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,8 +1,12 @@
|
||||
<script context="module">
|
||||
registerCommand({
|
||||
id: 'commandPalette.show',
|
||||
text: 'Command palette: Show',
|
||||
category: 'Command palette',
|
||||
name: 'Show',
|
||||
keyText: 'F1',
|
||||
toolbar: true,
|
||||
showDisabled: true,
|
||||
icon: 'icon menu',
|
||||
onClick: () => visibleCommandPalette.set(true),
|
||||
enabledStore: derived(visibleCommandPalette, $visibleCommandPalette => !$visibleCommandPalette),
|
||||
});
|
||||
@ -61,7 +65,7 @@
|
||||
</div>
|
||||
{#each filteredItems as command, index}
|
||||
<div class="command" class:selected={index == selectedIndex} on:click={() => handleCommand(command)}>
|
||||
<div>{command.text}</div>
|
||||
<div>{command.category}: {command.name}</div>
|
||||
{#if command.keyText}
|
||||
<div class="shortcut">{command.keyText}</div>
|
||||
{/if}
|
||||
|
@ -7,7 +7,8 @@ export interface SubCommand {
|
||||
|
||||
export interface GlobalCommand {
|
||||
id: string;
|
||||
text: string;
|
||||
category: string;
|
||||
name: string;
|
||||
keyText?: string;
|
||||
getSubCommands?: () => SubCommand[];
|
||||
onClick?: Function;
|
||||
@ -15,6 +16,7 @@ export interface GlobalCommand {
|
||||
icon?: string;
|
||||
toolbar?: boolean;
|
||||
enabled?: boolean;
|
||||
showDisabled?: boolean;
|
||||
}
|
||||
|
||||
export default function registerCommand(command: GlobalCommand) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { currentTheme, extensions } from '../stores';
|
||||
import { currentTheme, extensions, visibleToolbar } from '../stores';
|
||||
import registerCommand from './registerCommand';
|
||||
import { get } from 'svelte/store';
|
||||
import { derived, get } from 'svelte/store';
|
||||
import { ThemeDefinition } from 'dbgate-types';
|
||||
|
||||
function themeCommand(theme: ThemeDefinition) {
|
||||
@ -19,6 +19,23 @@ function themeCommand(theme: ThemeDefinition) {
|
||||
|
||||
registerCommand({
|
||||
id: 'theme.changeTheme',
|
||||
text: 'Theme: Change',
|
||||
category: 'Theme',
|
||||
name: 'Change',
|
||||
getSubCommands: () => get(extensions).themes.map(themeCommand),
|
||||
});
|
||||
|
||||
registerCommand({
|
||||
id: 'toolbar.show',
|
||||
category: 'Toolbar',
|
||||
name: 'Show',
|
||||
onClick: () => visibleToolbar.set(1),
|
||||
enabledStore: derived(visibleToolbar, $visibleToolbar => !$visibleToolbar),
|
||||
});
|
||||
|
||||
registerCommand({
|
||||
id: 'toolbar.hide',
|
||||
category: 'Toolbar',
|
||||
name: 'Hide',
|
||||
onClick: () => visibleToolbar.set(0),
|
||||
enabledStore: derived(visibleToolbar, $visibleToolbar => $visibleToolbar),
|
||||
});
|
||||
|
@ -3,8 +3,11 @@
|
||||
|
||||
registerCommand({
|
||||
id: 'dataGrid.refresh',
|
||||
text: 'Data grid: Refresh',
|
||||
category: 'Data grid',
|
||||
name: 'Refresh',
|
||||
keyText: 'F5',
|
||||
toolbar: true,
|
||||
icon: 'icon reload',
|
||||
enabledStore: derived([currentDataGrid], ([grid]) => grid != null),
|
||||
onClick: () => get(currentDataGrid).refresh(),
|
||||
});
|
||||
|
@ -20,6 +20,10 @@ export function writableWithStorage<T>(defaultValue: T, storageName) {
|
||||
return res;
|
||||
}
|
||||
|
||||
function subscribeCssVariable(store, transform, cssVariable) {
|
||||
store.subscribe(value => document.documentElement.style.setProperty(cssVariable, transform(value)));
|
||||
}
|
||||
|
||||
export const selectedWidget = writable('database');
|
||||
export const openedConnections = writable([]);
|
||||
export const currentDatabase = writable(null);
|
||||
@ -29,5 +33,9 @@ export const visibleCommandPalette = writable(false);
|
||||
export const commands = writable({});
|
||||
export const currentTheme = writableWithStorage('theme-light', 'currentTheme');
|
||||
export const activeTabId = derived([openedTabs], ([$openedTabs]) => $openedTabs.find(x => x.selected)?.tabid);
|
||||
export const visibleToolbar = writableWithStorage(1, 'visibleToolbar');
|
||||
|
||||
subscribeCssVariable(selectedWidget, x => (x ? 1 : 0), '--dim-visible-left-panel');
|
||||
subscribeCssVariable(visibleToolbar, x => (x ? 1 : 0), '--dim-visible-toolbar');
|
||||
|
||||
// export const leftPanelWidth = writable(300);
|
||||
|
23
packages/web/src/widgets/Toolbar.svelte
Normal file
23
packages/web/src/widgets/Toolbar.svelte
Normal file
@ -0,0 +1,23 @@
|
||||
<script>
|
||||
import { filter } from 'lodash';
|
||||
import App from '../App.svelte';
|
||||
import { commands } from '../stores';
|
||||
import ToolbarButton from './ToolbarButton.svelte';
|
||||
</script>
|
||||
|
||||
<div class="container">
|
||||
{#each Object.values($commands).filter(x => (x.enabled || x.showDisabled) && x.toolbar && x.onClick) as command}
|
||||
<ToolbarButton icon={command.icon} on:click={command.onClick} disabled={!command.enabled}
|
||||
>{command.name}</ToolbarButton
|
||||
>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.container {
|
||||
display: flex;
|
||||
user-select: none;
|
||||
align-items: stretch;
|
||||
height: var(--dim-toolbar-height);
|
||||
}
|
||||
</style>
|
57
packages/web/src/widgets/ToolbarButton.svelte
Normal file
57
packages/web/src/widgets/ToolbarButton.svelte
Normal file
@ -0,0 +1,57 @@
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import FontIcon from '../icons/FontIcon.svelte';
|
||||
|
||||
export let disabled;
|
||||
export let icon;
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
function handleClick(e) {
|
||||
if (disabled) return;
|
||||
dispatch('click');
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="button" on:click={handleClick} class:disabled>
|
||||
<div class="inner">
|
||||
<span class="icon" class:disabled><FontIcon {icon} /></span>
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.button {
|
||||
/* padding: 5px 15px; */
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
color: var(--theme-font-1);
|
||||
border: 0;
|
||||
border-right: 1px solid var(--theme-border);
|
||||
align-self: stretch;
|
||||
display: flex;
|
||||
}
|
||||
.button.disabled {
|
||||
background: var(--theme-bg-2);
|
||||
color: var(--theme-font-3);
|
||||
}
|
||||
.button:hover {
|
||||
background: var(--theme-bg-2);
|
||||
}
|
||||
.button:active:hover {
|
||||
background: var(--theme-bg-3);
|
||||
}
|
||||
.icon {
|
||||
margin-right: 5px;
|
||||
color: var(--theme-font-link);
|
||||
}
|
||||
.icon.disabled {
|
||||
color: var(--theme-font-3);
|
||||
}
|
||||
.inner {
|
||||
/* position: relative;
|
||||
top: 2px; */
|
||||
white-space: nowrap;
|
||||
align-self: center;
|
||||
}
|
||||
</style>
|
Loading…
Reference in New Issue
Block a user