feat(sql-library): support nested folders

This commit is contained in:
zipg authored and GitHub committed 2026-07-20 01:23:24 +08:00
1 parent 84745bb349
commit b43be528e1
10 files changed
+101 -4

No files matched your search

@@ -421,13 +421,19 @@ function isFolderExpanded(folderId: string) {
async function openNewFolderInput(parentFolderId?: string) {
const parent = parentFolderId ? savedSqlStore.allFolders.find((folder) => folder.id === parentFolderId) : undefined;
if (parentFolderId && !parent) return;
const connectionId = parent?.connectionId || connectionStore.connections[0]?.id;
if (!connectionId) return;
if (parent?.id) {
collapsedFolders.value = new Set([...collapsedFolders.value].filter((id) => id !== parent.id));
}
const folder = await savedSqlStore.createFolder(connectionId, t("savedSql.newFolderDefault"), parent?.id);
startRenameFolder(folder);
try {
const folder = await savedSqlStore.createFolder(connectionId, t("savedSql.newFolderDefault"), parent?.id);
searchText.value = "";
startRenameFolder(folder);
} catch (e: any) {
toast(t("savedSql.createFolderFailed", { message: e?.message || String(e) }), 5000);
}
}
async function openNewQueryInFolder(folder?: SavedSqlFolder) {
@@ -892,7 +898,7 @@ const contextMenuItems = computed<CtxMenuItem[]>(() => {
];
}
return [
{ label: t("savedSql.newFolder"), action: () => openNewFolderInput(target.id), icon: FolderPlus },
{ label: t("savedSql.newSubfolder"), action: () => openNewFolderInput(target.id), icon: FolderPlus },
{ label: t("savedSql.newQuery"), action: () => openNewQueryInFolder(target), icon: FilePlus },
{ label: t("sqlLibrary.importIntoFolder"), action: () => importDirectoryIntoLibrary(target), icon: Download },
{ label: t("sqlLibrary.exportFolder"), action: () => exportFolderContents(target), icon: Upload },
@@ -1150,7 +1156,7 @@ function showDropInside(targetId: string) {
</Button>
</LightTooltip>
<LightTooltip :text="t('savedSql.newFolder')" side="bottom" :delay="0" :close-delay="0" nowrap>
<Button variant="ghost" size="icon" class="h-5 w-5" @click="openNewFolderInput">
<Button variant="ghost" size="icon" class="h-5 w-5" @click="openNewFolderInput()">
<FolderPlus class="h-3 w-3" />
</Button>
</LightTooltip>
@@ -1225,6 +1231,18 @@ function showDropInside(targetId: string) {
{{ item.item.name }}
<span class="ml-1 text-muted-foreground">({{ folderFileCount(item.item.id) }})</span>
</span>
<LightTooltip v-if="!isRenamingFolder(item.item.id)" :text="t('savedSql.newSubfolder')" side="left" :delay="0" :close-delay="0" nowrap>
<button
type="button"
data-no-drag="true"
class="flex h-5 w-5 shrink-0 items-center justify-center rounded text-muted-foreground/70 hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
:aria-label="t('savedSql.newSubfolder')"
@mousedown.stop
@click.stop="openNewFolderInput(item.item.id)"
>
<FolderPlus class="h-3.5 w-3.5" />
</button>
</LightTooltip>
</div>
<div
@@ -1298,6 +1316,18 @@ function showDropInside(targetId: string) {
{{ row.folder.name }}
<span class="ml-1 text-muted-foreground">({{ folderFileCount(row.folder.id) }})</span>
</span>
<LightTooltip v-if="!isRenamingFolder(row.folder.id)" :text="t('savedSql.newSubfolder')" side="left" :delay="0" :close-delay="0" nowrap>
<button
type="button"
data-no-drag="true"
class="flex h-5 w-5 shrink-0 items-center justify-center rounded text-muted-foreground/70 hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
:aria-label="t('savedSql.newSubfolder')"
@mousedown.stop
@click.stop="openNewFolderInput(row.folder.id)"
>
<FolderPlus class="h-3.5 w-3.5" />
</button>
</LightTooltip>
</div>
<div