mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-29 22:43:58 +00:00
context menu submenu support
This commit is contained in:
@@ -51,7 +51,8 @@
|
|||||||
label: 'Export',
|
label: 'Export',
|
||||||
isExport: true,
|
isExport: true,
|
||||||
},
|
},
|
||||||
electron && {
|
// electron &&
|
||||||
|
{
|
||||||
label: 'Quick export',
|
label: 'Quick export',
|
||||||
isQuickExport: true,
|
isQuickExport: true,
|
||||||
},
|
},
|
||||||
@@ -394,6 +395,23 @@
|
|||||||
.filter(x => x)
|
.filter(x => x)
|
||||||
.map(menu => {
|
.map(menu => {
|
||||||
if (menu.divider) return menu;
|
if (menu.divider) return menu;
|
||||||
|
|
||||||
|
if (menu.isQuickExport) {
|
||||||
|
return {
|
||||||
|
text: menu.label,
|
||||||
|
submenu: [
|
||||||
|
{
|
||||||
|
text: 'CSV file',
|
||||||
|
isQuickExport: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Excel',
|
||||||
|
isQuickExport: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
text: menu.label,
|
text: menu.label,
|
||||||
onClick: async () => {
|
onClick: async () => {
|
||||||
|
|||||||
@@ -67,6 +67,7 @@
|
|||||||
'icon chevron-left': 'mdi mdi-chevron-left',
|
'icon chevron-left': 'mdi mdi-chevron-left',
|
||||||
'icon chevron-right': 'mdi mdi-chevron-right',
|
'icon chevron-right': 'mdi mdi-chevron-right',
|
||||||
'icon chevron-up': 'mdi mdi-chevron-up',
|
'icon chevron-up': 'mdi mdi-chevron-up',
|
||||||
|
'icon menu-right': 'mdi mdi-menu-right',
|
||||||
'icon plugin': 'mdi mdi-toy-brick',
|
'icon plugin': 'mdi mdi-toy-brick',
|
||||||
'icon menu': 'mdi mdi-menu',
|
'icon menu': 'mdi mdi-menu',
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
<script context="module">
|
<script context="module">
|
||||||
function getElementOffset(element) {
|
function getElementOffset(element, side = null) {
|
||||||
var de = document.documentElement;
|
var de = document.documentElement;
|
||||||
var box = element.getBoundingClientRect();
|
var box = element.getBoundingClientRect();
|
||||||
var top = box.top + window.pageYOffset - de.clientTop;
|
var top = box.top + window.pageYOffset - de.clientTop;
|
||||||
var left = box.left + window.pageXOffset - de.clientLeft;
|
var left = box.left + window.pageXOffset - de.clientLeft;
|
||||||
|
if (side == 'right') return { top: top, left: left + box.width };
|
||||||
return { top: top, left: left };
|
return { top: top, left: left };
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,6 +53,7 @@
|
|||||||
}
|
}
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -61,6 +63,7 @@
|
|||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
import { commandsCustomized, visibleCommandPalette } from '../stores';
|
import { commandsCustomized, visibleCommandPalette } from '../stores';
|
||||||
import { extractMenuItems } from '../utility/contextMenu';
|
import { extractMenuItems } from '../utility/contextMenu';
|
||||||
|
import FontIcon from '../icons/FontIcon.svelte';
|
||||||
|
|
||||||
export let items;
|
export let items;
|
||||||
export let top;
|
export let top;
|
||||||
@@ -68,10 +71,24 @@
|
|||||||
|
|
||||||
let element;
|
let element;
|
||||||
|
|
||||||
|
let hoverItem;
|
||||||
|
let hoverOffset;
|
||||||
|
|
||||||
|
let submenuItem;
|
||||||
|
let submenuOffset;
|
||||||
|
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
function handleClick(item) {
|
function handleClick(e, item) {
|
||||||
if (item.disabled) return;
|
if (item.disabled) return;
|
||||||
|
if (item.submenu) {
|
||||||
|
hoverItem = item;
|
||||||
|
hoverOffset = getElementOffset(e.target, 'right');
|
||||||
|
|
||||||
|
submenuItem = item;
|
||||||
|
submenuOffset = hoverOffset;
|
||||||
|
return;
|
||||||
|
}
|
||||||
dispatch('close');
|
dispatch('close');
|
||||||
if (item.onClick) item.onClick();
|
if (item.onClick) item.onClick();
|
||||||
}
|
}
|
||||||
@@ -80,9 +97,15 @@
|
|||||||
fixPopupPlacement(element);
|
fixPopupPlacement(element);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const changeActiveSubmenu = _.throttle(() => {
|
||||||
|
submenuItem = hoverItem;
|
||||||
|
submenuOffset = hoverOffset;
|
||||||
|
}, 500);
|
||||||
|
|
||||||
$: extracted = extractMenuItems(items);
|
$: extracted = extractMenuItems(items);
|
||||||
$: compacted = _.compact(extracted.map(x => mapItem(x, $commandsCustomized)));
|
$: 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>
|
||||||
|
|
||||||
<ul
|
<ul
|
||||||
@@ -95,17 +118,31 @@
|
|||||||
{#if item.divider}
|
{#if item.divider}
|
||||||
<li class="divider" />
|
<li class="divider" />
|
||||||
{:else}
|
{:else}
|
||||||
<li>
|
<li
|
||||||
<a on:click={() => handleClick(item)} class:disabled={item.disabled}>
|
on:mouseenter={e => {
|
||||||
|
hoverOffset = getElementOffset(e.target, 'right');
|
||||||
|
hoverItem = item;
|
||||||
|
changeActiveSubmenu();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<a on:click={e => handleClick(e, item)} class:disabled={item.disabled}>
|
||||||
{item.text}
|
{item.text}
|
||||||
{#if item.keyText}
|
{#if item.keyText}
|
||||||
<span class="keyText">{item.keyText}</span>
|
<span class="keyText">{item.keyText}</span>
|
||||||
{/if}
|
{/if}
|
||||||
|
{#if item.submenu}
|
||||||
|
<div class="menu-right">
|
||||||
|
<FontIcon icon="icon menu-right" />
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{/if}
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
</ul>
|
</ul>
|
||||||
|
{#if submenuItem?.submenu}
|
||||||
|
<svelte:self items={submenuItem?.submenu} {...submenuOffset} />
|
||||||
|
{/if}
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
ul {
|
ul {
|
||||||
@@ -136,9 +173,10 @@
|
|||||||
a {
|
a {
|
||||||
padding: 3px 20px;
|
padding: 3px 20px;
|
||||||
line-height: 1.42;
|
line-height: 1.42;
|
||||||
display: block;
|
|
||||||
white-space: nop-wrap;
|
white-space: nop-wrap;
|
||||||
color: #262626;
|
color: #262626;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
a.disabled {
|
a.disabled {
|
||||||
@@ -156,4 +194,10 @@
|
|||||||
border-top: 1px solid #f2f2f2;
|
border-top: 1px solid #f2f2f2;
|
||||||
border-bottom: 1px solid #fff;
|
border-bottom: 1px solid #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.menu-right {
|
||||||
|
position: relative;
|
||||||
|
left: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user