feat(desktop): add DDL shortcut and grid row delete action
This commit is contained in:
19 files changed
+157
-4
No files matched your search
@@ -215,7 +215,16 @@ import { useQueryStore } from "@/stores/queryStore";
|
||||
import { useSettingsStore } from "@/stores/settingsStore";
|
||||
import { simpleDataGridOrderByMatchesSort, simpleDataGridOrderByReferencesMissingColumn, type DataGridSortDirection, type DataGridSortMode } from "@/lib/dataGrid/dataGridSort";
|
||||
import { buildOrderedGridRows, type GridInsertRowPosition, type GridNewRowPlacement } from "@/lib/dataGrid/gridNewRowPlacement";
|
||||
import { DATA_GRID_CONDITION_TOOLBAR_MIN_WIDTH, isDataGridToolbarCompact, type DataGridReloadIntent, type DataGridToolbarActionCapability, type DataGridToolbarAddRowCapability, type DataGridToolbarAutoRefreshCapability, type DataGridToolbarSaveCapability } from "@/lib/dataGrid/dataGridToolbar";
|
||||
import {
|
||||
DATA_GRID_CONDITION_TOOLBAR_MIN_WIDTH,
|
||||
dataGridDeleteRowToolbarState,
|
||||
isDataGridToolbarCompact,
|
||||
type DataGridReloadIntent,
|
||||
type DataGridToolbarActionCapability,
|
||||
type DataGridToolbarAddRowCapability,
|
||||
type DataGridToolbarAutoRefreshCapability,
|
||||
type DataGridToolbarSaveCapability,
|
||||
} from "@/lib/dataGrid/dataGridToolbar";
|
||||
import { getTableMetadataCapabilities } from "@/lib/table/tableMetadataCapabilities";
|
||||
import { getTableStructureCapabilities } from "@/lib/table/tableStructureCapabilities";
|
||||
import { filterObjectBrowserTableColumns } from "@/lib/table/objectBrowserTableInfo";
|
||||
@@ -3416,6 +3425,25 @@ const addRowToolbarCapability = computed<DataGridToolbarAddRowCapability>(() =>
|
||||
onTrigger: addRow,
|
||||
onSelect: handleAddRowMenuSelect,
|
||||
}));
|
||||
const deleteRowToolbarTargetCount = computed(() => deletableRowIds(selectedOrCurrentRowIds()).length);
|
||||
const deleteRowToolbarState = computed(() =>
|
||||
dataGridDeleteRowToolbarState({
|
||||
editable: !!props.editable,
|
||||
canDeleteRows: canDeleteRows.value,
|
||||
canDeleteExistingRows: canDeleteExistingRows.value,
|
||||
deletableTargetCount: deleteRowToolbarTargetCount.value,
|
||||
isSaving: isSaving.value,
|
||||
}),
|
||||
);
|
||||
const deleteRowToolbarCapability = computed<DataGridToolbarActionCapability>(() => ({
|
||||
label: deleteRowToolbarTargetCount.value > 1 ? t("grid.deleteRows", { count: deleteRowToolbarTargetCount.value }) : t("grid.deleteRow"),
|
||||
tooltip: `${t("grid.deleteRow")} (${formatShortcut(settingsStore.editorSettings.shortcuts.deleteCurrentRow)})`,
|
||||
visible: deleteRowToolbarState.value.visible,
|
||||
disabled: deleteRowToolbarState.value.disabled,
|
||||
onTrigger: () => {
|
||||
deleteCurrentRow();
|
||||
},
|
||||
}));
|
||||
const previewToolbarCapability = computed<DataGridToolbarActionCapability>(() => ({
|
||||
label: t(previewLabelKey.value),
|
||||
visible: saveToolbarState.value.showActions && pendingChangeCount.value > 0,
|
||||
@@ -8479,6 +8507,7 @@ const gridContextMenuItems = computed<ContextMenuItem[]>(() => {
|
||||
:refresh="refreshToolbarCapability"
|
||||
:auto-refresh="autoRefreshToolbarCapability"
|
||||
:add-row="addRowToolbarCapability"
|
||||
:delete-row="deleteRowToolbarCapability"
|
||||
:preview="previewToolbarCapability"
|
||||
:save="saveToolbarCapability"
|
||||
:rollback="rollbackToolbarCapability"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from "vue";
|
||||
import { Check, ChevronDown, Copy, Eye, Loader2, Plus, RefreshCcw, RotateCcw, Rows3, Save, TableProperties, Timer, Upload } from "@lucide/vue";
|
||||
import { Check, ChevronDown, Copy, Eye, Loader2, Plus, RefreshCcw, RotateCcw, Rows3, Save, TableProperties, Timer, Trash2, Upload } from "@lucide/vue";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
|
||||
@@ -28,6 +28,7 @@ const props = defineProps<{
|
||||
refresh: DataGridToolbarActionCapability;
|
||||
autoRefresh?: DataGridToolbarAutoRefreshCapability;
|
||||
addRow?: DataGridToolbarAddRowCapability;
|
||||
deleteRow?: DataGridToolbarActionCapability;
|
||||
copyData?: DataGridToolbarCopyCapability;
|
||||
exportData?: DataGridToolbarExportCapability;
|
||||
transpose?: DataGridToolbarActionCapability;
|
||||
@@ -148,6 +149,16 @@ function actionLabelClass() {
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
|
||||
<Tooltip v-if="isDataGridToolbarCapabilityVisible(deleteRow)">
|
||||
<TooltipTrigger as-child>
|
||||
<Button variant="ghost" size="sm" :class="actionButtonClass" :disabled="isDataGridToolbarCapabilityDisabled(deleteRow)" @click="void triggerDataGridToolbarAction(deleteRow)">
|
||||
<Trash2 class="data-grid-topbar-action-icon h-3 w-3" />
|
||||
<span class="data-grid-topbar-action-label" :class="actionLabelClass()">{{ deleteRow?.label }}</span>
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="bottom">{{ deleteRow?.tooltip ?? deleteRow?.label }}</TooltipContent>
|
||||
</Tooltip>
|
||||
|
||||
<DropdownMenu v-if="isDataGridToolbarCapabilityVisible(exportData)">
|
||||
<Tooltip>
|
||||
<TooltipTrigger as-child>
|
||||
|
||||
@@ -10,7 +10,8 @@ import type { ObjectSourceKind, TableInfo, TableNameFilter, TreeNode, TreeNodeTy
|
||||
import { filterSidebarSearchRootsByConnectionState, filterSidebarTree, filterSidebarTreeToConnectedConnections, resolveSidebarFilterGuards, reuseLiveSidebarTreeNodes } from "@/lib/sidebar/sidebarSearchTree";
|
||||
import { matchSidebarLabel } from "@/lib/sidebar/sidebarSearch";
|
||||
import { buildTableTreeNodes } from "@/lib/table/tableTree";
|
||||
import { isCancelSearchShortcut, isCopySidebarSelectionShortcut, isEditSidebarConnectionShortcut, isPasteSidebarSelectionShortcut } from "@/lib/editor/keyboardShortcuts";
|
||||
import { isCancelSearchShortcut, isCopySidebarSelectionShortcut, isEditSidebarConnectionShortcut, isPasteSidebarSelectionShortcut, isViewTableDdlShortcut } from "@/lib/editor/keyboardShortcuts";
|
||||
import { sidebarNodeSupportsDdlView } from "@/lib/sidebar/sidebarTreeDdlShortcut";
|
||||
import { copyNameForTreeNode, objectSourceKindForTreeNode } from "@/lib/sidebar/treeNodeClick";
|
||||
import { copyToClipboard } from "@/lib/common/clipboard";
|
||||
import { connectionPasteTargetGroupId, copySelectedConnectionsToClipboards, selectedConnectionEditTarget } from "@/lib/sidebar/sidebarConnectionSelection";
|
||||
@@ -1264,6 +1265,14 @@ function openSidebarDdl(node: TreeNode) {
|
||||
sidebarDdlOpen.value = true;
|
||||
}
|
||||
|
||||
function openSidebarDdlForSelection(): boolean {
|
||||
const selectedNodeId = store.selectedTreeNodeId;
|
||||
const node = selectedNodeId ? flatTreeIndex.value.nodeById.get(selectedNodeId) : null;
|
||||
if (!node || !sidebarNodeSupportsDdlView(node)) return false;
|
||||
openSidebarDdl(node);
|
||||
return true;
|
||||
}
|
||||
|
||||
function openSidebarObjectSource(node: TreeNode, initialEditing: boolean) {
|
||||
if (!node.connectionId || !node.database || !objectSourceKindForTreeNode(node.type)) return;
|
||||
const target = createSidebarActionTarget(node);
|
||||
@@ -1530,6 +1539,13 @@ function onWindowKeydown(event: KeyboardEvent) {
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (sidebarShortcutTargetAllowsAppShortcut(event.target) && isViewTableDdlShortcut(event, settingsStore.editorSettings.shortcuts)) {
|
||||
if (openSidebarDdlForSelection()) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!pointerInsideTree.value || isEditableSidebarTypeSearchTarget(event.target) || isEditableSidebarTypeSearchTarget(document.activeElement)) return;
|
||||
|
||||
Reference in new issue
Block a user