grid commands + ctx menu

This commit is contained in:
Jan Prochazka
2021-03-06 20:32:02 +01:00
parent 49f22e1a3b
commit e49c0169da
5 changed files with 168 additions and 19 deletions

View File

@@ -48,6 +48,7 @@ registerCommand({
icon: 'icon connection',
toolbarName: 'Add connection',
category: 'New',
toolbarOrder: 1,
name: 'Connection',
onClick: () => showModal(ConnectionModal),
});

View File

@@ -42,6 +42,61 @@
onClick: () => get(currentDataGrid).revertAllChanges(),
});
registerCommand({
id: 'dataGrid.deleteSelectedRows',
category: 'Data grid',
name: 'Delete selected rows',
keyText: 'Ctrl+Delete',
enabledStore: derived(currentDataGrid, grid => grid?.getGrider()?.editable),
onClick: () => get(currentDataGrid).deleteSelectedRows(),
});
registerCommand({
id: 'dataGrid.insertNewRow',
category: 'Data grid',
name: 'Insert new row',
keyText: 'Insert',
enabledStore: derived(currentDataGrid, grid => grid?.getGrider()?.editable),
onClick: () => get(currentDataGrid).insertNewRow(),
});
registerCommand({
id: 'dataGrid.setNull',
category: 'Data grid',
name: 'Set NULL',
keyText: 'Ctrl+0',
enabledStore: derived(currentDataGrid, grid => grid?.getGrider()?.editable),
onClick: () => get(currentDataGrid).setNull(),
});
registerCommand({
id: 'dataGrid.undo',
category: 'Data grid',
name: 'Undo',
keyText: 'Ctrl+Z',
icon: 'icon undo',
toolbar: true,
enabledStore: derived(currentDataGridChangeSet, (changeSet: any) => changeSet?.canUndo),
onClick: () => get(currentDataGrid).undo(),
});
registerCommand({
id: 'dataGrid.redo',
category: 'Data grid',
name: 'Redo',
keyText: 'Ctrl+Y',
enabledStore: derived(currentDataGridChangeSet, (changeSet: any) => changeSet?.canRedo),
onClick: () => get(currentDataGrid).redo(),
});
registerCommand({
id: 'dataGrid.reconnect',
category: 'Data grid',
name: 'Reconnect',
enabledStore: derived(currentDataGrid, grid => grid != null),
onClick: () => get(currentDataGrid).reconnect(),
});
function getRowCountInfo(selectedCells, grider, realColumnUniqueNames, selectedRowData, allRowCount) {
if (selectedCells.length > 1 && selectedCells.every(x => _.isNumber(x[0]) && _.isNumber(x[1]))) {
let sum = _.sumBy(selectedCells, cell => {
@@ -77,6 +132,7 @@
import DataGridRow from './DataGridRow.svelte';
import { getFilterType, getFilterValueExpression } from 'dbgate-filterparser';
import stableStringify from 'json-stable-stringify';
import contextMenu from '../utility/contextMenu';
import { tick } from 'svelte';
import {
cellIsSelected,
@@ -96,6 +152,7 @@
import keycodes from '../utility/keycodes';
import { nullStore } from '../stores';
import memberStore from '../utility/memberStore';
import axios from '../utility/axios';
export let loadNextData = undefined;
export let grider = undefined;
@@ -161,6 +218,47 @@
grider.revertAllChanges();
}
export function deleteSelectedRows() {
grider.beginUpdate();
for (const index of getSelectedRowIndexes()) {
if (_.isNumber(index)) grider.deleteRow(index);
}
grider.endUpdate();
}
export function insertNewRow() {
if (grider.canInsert) {
const rowIndex = grider.insertRow();
const cell = [rowIndex, (currentCell && currentCell[1]) || 0];
// @ts-ignore
currentCell = cell;
// @ts-ignore
selectedCells = [cell];
scrollIntoView(cell);
}
}
export function setNull() {
grider.beginUpdate();
selectedCells.filter(isRegularCell).forEach(cell => {
setCellValue(cell, null);
});
grider.endUpdate();
}
export function undo() {
grider.undo();
}
export function redo() {
grider.redo();
}
export async function reconnect() {
await axios.post('database-connections/refresh', { conid, database });
display.reload();
}
$: autofillMarkerCell =
selectedCells && selectedCells.length > 0 && _.uniq(selectedCells.map(x => x[0])).length == 1
? [_.max(selectedCells.map(x => x[0])), _.max(selectedCells.map(x => x[1]))]
@@ -416,10 +514,10 @@
// // this.saveAndFocus();
// }
if (event.keyCode == keycodes.n0 && event.ctrlKey) {
event.preventDefault();
setNull();
}
// if (event.keyCode == keycodes.n0 && event.ctrlKey) {
// event.preventDefault();
// setNull();
// }
// if (event.keyCode == keycodes.r && event.ctrlKey) {
// event.preventDefault();
@@ -542,14 +640,6 @@
return null;
}
function setNull() {
grider.beginUpdate();
selectedCells.filter(isRegularCell).forEach(cell => {
setCellValue(cell, null);
});
grider.endUpdate();
}
function setCellValue(cell, value) {
grider.setCellValue(cell[0], realColumnUniqueNames[cell[1]], value);
}
@@ -598,9 +688,30 @@
}
return {};
}, {});
function createMenu() {
return [
{ command: 'dataGrid.refresh' },
{ divider: true },
{ command: 'dataGrid.save' },
{ command: 'dataGrid.revertRowChanges' },
{ command: 'dataGrid.revertAllChanges' },
{ command: 'dataGrid.deleteSelectedRows' },
{ command: 'dataGrid.insertNewRow' },
{ command: 'dataGrid.setNull' },
{ divider: true },
{ command: 'dataGrid.undo' },
{ command: 'dataGrid.redo' },
];
}
</script>
<div class="container" bind:clientWidth={containerWidth} bind:clientHeight={containerHeight}>
<div
class="container"
bind:clientWidth={containerWidth}
bind:clientHeight={containerHeight}
use:contextMenu={createMenu}
>
<input
type="text"
class="focus-field"

View File

@@ -24,12 +24,30 @@
if (newLeft != null) element.style.left = `${newLeft}px`;
if (newTop != null) element.style.top = `${newTop}px`;
}
function mapItem(item, commands) {
if (item.command) {
const command = commands[item.command];
if (command) {
return {
text: command.name,
keyText: command.keyText,
onClick: command.onClick,
disabled: !command.enabled,
};
}
return null;
}
return item;
}
</script>
<script>
import _ from 'lodash';
import clickOutside from '../utility/clickOutside';
import { createEventDispatcher } from 'svelte';
import { onMount } from 'svelte';
import { commands } from '../stores';
export let items;
export let top;
@@ -55,12 +73,12 @@
on:clickOutside={() => dispatch('close')}
bind:this={element}
>
{#each items as item}
{#each _.compact(items.map(x => mapItem(x, $commands))) as item}
{#if item.divider}
<li class="divider" />
{:else}
<li>
<a on:click={() => handleClick(item)}>
<a on:click={() => handleClick(item)} class:disabled={item.disabled}>
{item.text}
{#if item.keyText}
<span class="keyText">{item.keyText}</span>
@@ -86,6 +104,7 @@
min-width: 160px;
z-index: 1050;
cursor: default;
white-space: nowrap;
}
.keyText {
@@ -103,7 +122,11 @@
color: #262626;
}
a:hover {
a.disabled {
color: gray;
}
a:hover:not(.disabled) {
background-color: #f5f5f5;
text-decoration: none;
color: #262626;

View File

@@ -1,3 +1,11 @@
<script context="module">
function getCommandTitle(command) {
let res = command.text;
if (command.keyText) res += ` (${command.keyText})`;
return res;
}
</script>
<script>
import _ from 'lodash';
import App from '../App.svelte';
@@ -12,9 +20,14 @@
<div class="container">
{#each list as command}
<ToolbarButton icon={command.icon} on:click={command.onClick} disabled={!command.enabled}
>{command.toolbarName || command.name}</ToolbarButton
<ToolbarButton
icon={command.icon}
on:click={command.onClick}
disabled={!command.enabled}
title={getCommandTitle(command)}
>
{command.toolbarName || command.name}
</ToolbarButton>
{/each}
</div>

View File

@@ -4,6 +4,7 @@
export let disabled;
export let icon;
export let title;
const dispatch = createEventDispatcher();
@@ -13,7 +14,7 @@
}
</script>
<div class="button" on:click={handleClick} class:disabled>
<div class="button" on:click={handleClick} class:disabled {title}>
<div class="inner">
<span class="icon" class:disabled><FontIcon {icon} /></span>
<slot />