diff --git a/apps/desktop/src/components/layout/SqlLibraryPanel.vue b/apps/desktop/src/components/layout/SqlLibraryPanel.vue index a612a4e7b..ac1447892 100644 --- a/apps/desktop/src/components/layout/SqlLibraryPanel.vue +++ b/apps/desktop/src/components/layout/SqlLibraryPanel.vue @@ -13,6 +13,7 @@ import { useConnectionStore } from "@/stores/connectionStore"; import { useQueryStore } from "@/stores/queryStore"; import { useSettingsStore } from "@/stores/settingsStore"; import { focusSidebarRenameInput } from "@/lib/sidebarRenameFocus"; +import { savedSqlFolderBranchFileCount } from "@/lib/savedSqlFolderCounts"; import type { SavedSqlFile, SavedSqlFolder } from "@/types/database"; const { t } = useI18n(); @@ -342,6 +343,11 @@ function filesInFolder(folderId: string) { .filter((file) => includeAllFilesForMatchedFolder || fileMatchesQuery(file)); } +function folderFileCount(folderId: string) { + const visibleFolders = savedSqlStore.allFolders.filter((folder) => isConnectionVisible(folder.connectionId)); + return savedSqlFolderBranchFileCount(folderId, visibleFolders, filesInFolder); +} + type SqlLibraryRow = { type: "folder"; folder: SavedSqlFolder; depth: number; folderIndex: number } | { type: "file"; file: SavedSqlFile; depth: number }; const visibleFolderRows = computed(() => { @@ -1061,7 +1067,7 @@ function showDropInside(targetId: string) { {{ item.item.name }} - ({{ filesInFolder(item.item.id).length }}) + ({{ folderFileCount(item.item.id) }}) @@ -1119,7 +1125,7 @@ function showDropInside(targetId: string) { {{ row.folder.name }} - ({{ filesInFolder(row.folder.id).length }}) + ({{ folderFileCount(row.folder.id) }}) diff --git a/apps/desktop/src/lib/__tests__/savedSqlFolderCounts.spec.ts b/apps/desktop/src/lib/__tests__/savedSqlFolderCounts.spec.ts new file mode 100644 index 000000000..4c810abf4 --- /dev/null +++ b/apps/desktop/src/lib/__tests__/savedSqlFolderCounts.spec.ts @@ -0,0 +1,36 @@ +import { describe, expect, it } from "vitest"; +import { savedSqlFolderBranchFileCount, type SavedSqlFolderCountNode } from "../savedSqlFolderCounts"; + +describe("savedSqlFolderBranchFileCount", () => { + const folders: SavedSqlFolderCountNode[] = [{ id: "root" }, { id: "child", parentFolderId: "root" }, { id: "grandchild", parentFolderId: "child" }, { id: "sibling", parentFolderId: "root" }, { id: "other" }]; + const filesByFolder = new Map([ + ["root", ["root.sql"]], + ["child", []], + ["grandchild", ["nested.sql", "report.sql"]], + ["sibling", ["side.sql"]], + ["other", ["other.sql"]], + ]); + + it("counts files in descendant folders", () => { + const count = savedSqlFolderBranchFileCount("root", folders, (folderId) => filesByFolder.get(folderId) ?? []); + + expect(count).toBe(4); + }); + + it("does not count files outside the folder branch", () => { + const count = savedSqlFolderBranchFileCount("child", folders, (folderId) => filesByFolder.get(folderId) ?? []); + + expect(count).toBe(2); + }); + + it("does not loop on cyclic folder data", () => { + const cyclicFolders: SavedSqlFolderCountNode[] = [ + { id: "a", parentFolderId: "b" }, + { id: "b", parentFolderId: "a" }, + ]; + + const count = savedSqlFolderBranchFileCount("a", cyclicFolders, () => ["file.sql"]); + + expect(count).toBe(2); + }); +}); diff --git a/apps/desktop/src/lib/savedSqlFolderCounts.ts b/apps/desktop/src/lib/savedSqlFolderCounts.ts new file mode 100644 index 000000000..5d98cedd7 --- /dev/null +++ b/apps/desktop/src/lib/savedSqlFolderCounts.ts @@ -0,0 +1,23 @@ +export interface SavedSqlFolderCountNode { + id: string; + parentFolderId?: string; +} + +export function savedSqlFolderBranchFileCount(folderId: string, folders: readonly SavedSqlFolderCountNode[], filesInFolder: (folderId: string) => readonly unknown[]): number { + const visited = new Set(); + + const count = (currentFolderId: string): number => { + if (visited.has(currentFolderId)) return 0; + visited.add(currentFolderId); + + let total = filesInFolder(currentFolderId).length; + for (const child of folders) { + if ((child.parentFolderId || "") === currentFolderId) { + total += count(child.id); + } + } + return total; + }; + + return count(folderId); +}