feat(sidebar): 添加一键折叠所有节点功能
- 在侧边栏中添加了“折叠所有”按钮,用户可以一键折叠所有展开的节点。 - 更新了相关的国际化文本,支持多语言。 - 增加了 collapseAllGroups 和 collapseExpandedTreeNodes 函数以支持新功能。
This commit is contained in:
19 files changed
+191
-10
No files matched your search
@@ -2,7 +2,7 @@
|
||||
import { computed, ref } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { translateBackendError } from "@/i18n/backend-errors";
|
||||
import { Upload, Download, FolderPlus, RefreshCw, ChevronsLeft } from "@lucide/vue";
|
||||
import { Upload, Download, FolderPlus, RefreshCw, ChevronsLeft, ChevronsUp } from "@lucide/vue";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Tooltip, TooltipTrigger, TooltipContent } from "@/components/ui/tooltip";
|
||||
import LightDropdown from "@/components/ui/LightDropdown.vue";
|
||||
@@ -45,6 +45,10 @@ function createNewGroup() {
|
||||
void connectionTreeRef.value?.createNewGroup();
|
||||
}
|
||||
|
||||
function collapseAllTreeNodes() {
|
||||
connectionTreeRef.value?.collapseAllTreeNodes();
|
||||
}
|
||||
|
||||
function focusSearch(): boolean {
|
||||
return connectionTreeRef.value?.focusSearch() ?? false;
|
||||
}
|
||||
@@ -88,6 +92,14 @@ defineExpose({ focusSearch });
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{{ t("sidebar.export") }}</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger as-child>
|
||||
<Button variant="ghost" size="icon" class="h-5 w-5" @click="collapseAllTreeNodes">
|
||||
<ChevronsUp class="h-3 w-3" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{{ t("sidebar.collapseAll") }}</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger as-child>
|
||||
<Button variant="ghost" size="icon" class="h-5 w-5" @click="createNewGroup">
|
||||
|
||||
@@ -702,6 +702,13 @@ function onSearchToggle(node: TreeNode) {
|
||||
searchCollapsedIds.value = next;
|
||||
}
|
||||
|
||||
function collapseAllTreeNodes() {
|
||||
store.collapseAllTreeNodes();
|
||||
if (isSearching.value) {
|
||||
searchCollapsedIds.value = new Set(flatNodes.value.filter((item) => item.node.children?.length).map((item) => item.id));
|
||||
}
|
||||
}
|
||||
|
||||
function currentTreeScroller(): HTMLElement | null {
|
||||
return ((useVirtualTree.value ? treeScrollerRef.value?.$el : plainTreeScrollerRef.value) as HTMLElement | undefined) ?? null;
|
||||
}
|
||||
@@ -859,7 +866,7 @@ onUnmounted(() => {
|
||||
window.clearTimeout(sidebarScrollingTimer);
|
||||
});
|
||||
|
||||
defineExpose({ focusSearch, createNewGroup });
|
||||
defineExpose({ focusSearch, createNewGroup, collapseAllTreeNodes });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -920,7 +927,7 @@ defineExpose({ focusSearch, createNewGroup });
|
||||
:prerender="SIDEBAR_TREE_PRERENDER_COUNT"
|
||||
:skip-hover="true"
|
||||
key-field="id"
|
||||
type-field="type"
|
||||
type-field="poolType"
|
||||
flow-mode
|
||||
>
|
||||
<template #default="{ item }">
|
||||
|
||||
@@ -76,7 +76,7 @@ import { clearActiveTableReferencePayload, createTableReferencePayload, createTa
|
||||
import { editableRowIdentifierColumns, usesSyntheticRowIdKey } from "@/lib/tableEditing";
|
||||
import { tableOpenPageLimit } from "@/lib/tableOpenPageLimit";
|
||||
import { supportsDatabaseCreation, supportsDatabaseSearch, supportsFieldLineage, supportsObjectBrowserTreeNode, supportsSchemaDiagram, supportsSqlFileExecution, supportsTableImport, supportsTableTruncate, supportsTableStructureEditing, usesTreeSchemaMode } from "@/lib/databaseCapabilities";
|
||||
import { copyNameForTreeNode, objectSourceKindForTreeNode, sidebarSelectionCopyAction, treeNodeRowAction, treeNodeRowDoubleClickAction } from "@/lib/treeNodeClick";
|
||||
import { copyNameForTreeNode, objectSourceKindForTreeNode, shouldRunTreeNodeRowAction, sidebarSelectionCopyAction, treeNodeRowAction, treeNodeRowDoubleClickAction } from "@/lib/treeNodeClick";
|
||||
import { formatSqlInsert } from "@/lib/exportFormats";
|
||||
import { joinExportedDdls } from "@/lib/ddlExport";
|
||||
import { fetchTableDataForExport } from "@/lib/tableDataExport";
|
||||
@@ -636,17 +636,20 @@ async function toggle() {
|
||||
}
|
||||
}
|
||||
|
||||
function runRowClickAction() {
|
||||
function runRowClickAction(clickDetail: number) {
|
||||
const node = props.node;
|
||||
if (node.type === "load-more") {
|
||||
if (clickDetail > 1) return;
|
||||
void loadMoreObjectGroupChildren();
|
||||
return;
|
||||
}
|
||||
if (node.type === "object-browser") {
|
||||
if (clickDetail > 1) return;
|
||||
void openObjectBrowser();
|
||||
return;
|
||||
}
|
||||
const action = treeNodeRowAction(node.type, canExpand.value, settingsStore.editorSettings.sidebarActivation);
|
||||
if (!shouldRunTreeNodeRowAction(action, clickDetail)) return;
|
||||
if (action === "open-data") {
|
||||
openData();
|
||||
} else if (node.type === "mongo-collection") {
|
||||
@@ -680,6 +683,18 @@ async function loadAllObjectGroupChildren() {
|
||||
}
|
||||
}
|
||||
|
||||
function onToggleClick() {
|
||||
selectSingleTreeNode(props.node);
|
||||
rowRef.value?.focus({ preventScroll: true });
|
||||
void toggle();
|
||||
}
|
||||
|
||||
function onToggleMouseDown(event: MouseEvent) {
|
||||
if (event.button !== 0) return;
|
||||
selectSingleTreeNode(props.node);
|
||||
rowRef.value?.focus({ preventScroll: true });
|
||||
}
|
||||
|
||||
function visibleTreeNodes(): TreeNode[] {
|
||||
if (sidebarTreeContext) return sidebarTreeContext.getVisibleNodes();
|
||||
return flattenTree(connectionStore.treeNodes).map((item) => item.node);
|
||||
@@ -749,8 +764,7 @@ function onClick(event: MouseEvent) {
|
||||
selectSingleTreeNode(props.node);
|
||||
rowRef.value?.focus({ preventScroll: true });
|
||||
if (settingsStore.editorSettings.sidebarActivation === "double") return;
|
||||
if (event.detail > 1) return;
|
||||
runRowClickAction();
|
||||
runRowClickAction(event.detail);
|
||||
}
|
||||
|
||||
function onTreeItemContextMenu(event: MouseEvent, openContextMenu: (event: MouseEvent) => void) {
|
||||
@@ -4487,7 +4501,7 @@ function treeItemMenuItems(): ContextMenuItem[] {
|
||||
<div v-if="showDropBefore" class="absolute right-2 top-0 h-0.5 bg-primary rounded-full pointer-events-none" :style="{ left: paddingLeft }" />
|
||||
<div v-if="showDropAfter" class="absolute right-2 bottom-0 h-0.5 bg-primary rounded-full pointer-events-none" :style="{ left: paddingLeft }" />
|
||||
<template v-if="canExpand">
|
||||
<button type="button" class="-m-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded-sm text-muted-foreground hover:bg-muted hover:text-foreground" @click.stop="toggle">
|
||||
<button type="button" class="-m-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded-sm text-muted-foreground hover:bg-muted hover:text-foreground" @mousedown.stop="onToggleMouseDown" @click.stop="onToggleClick">
|
||||
<Loader2 v-if="node.isLoading" class="w-3.5 h-3.5 animate-spin" />
|
||||
<ChevronDown v-else-if="node.isExpanded" class="w-3.5 h-3.5" />
|
||||
<ChevronRight v-else class="w-3.5 h-3.5" />
|
||||
|
||||
Reference in new issue
Block a user