mirror of
https://github.com/stashapp/stash.git
synced 2026-04-21 06:22:29 +02:00
Expand folder select for the initial value
This commit is contained in:
parent
bf50679986
commit
07492e045a
2 changed files with 133 additions and 5 deletions
|
|
@ -22,3 +22,20 @@ query FindFoldersForQuery(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
query FindFolderHierarchyForIDs($ids: [ID!]!) {
|
||||
findFolders(ids: $ids) {
|
||||
count
|
||||
folders {
|
||||
...SelectFolderData
|
||||
|
||||
parent_folders {
|
||||
...SelectFolderData
|
||||
# the parent folders will be expanded, so we need the child folders
|
||||
sub_folders {
|
||||
...SelectFolderData
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import {
|
||||
FolderDataFragment,
|
||||
useFindFolderHierarchyForIDsQuery,
|
||||
useFindFoldersForQueryQuery,
|
||||
useFindRootFoldersForSelectQuery,
|
||||
} from "src/core/generated-graphql";
|
||||
|
|
@ -141,7 +142,30 @@ function replaceFolder(folder: IFolder): (f: IFolder) => IFolder {
|
|||
};
|
||||
}
|
||||
|
||||
function useFolderMap(query: string, skip?: boolean) {
|
||||
function mergeFolderMaps(base: IFolder[], update: IFolder[]): IFolder[] {
|
||||
const ret = [...base];
|
||||
|
||||
update.forEach((updateFolder) => {
|
||||
const existingIndex = ret.findIndex((f) => f.id === updateFolder.id);
|
||||
if (existingIndex === -1) {
|
||||
// not found, add to the end
|
||||
ret.push(updateFolder);
|
||||
} else {
|
||||
// found, replace
|
||||
ret[existingIndex] = updateFolder;
|
||||
}
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
function useFolderMap(
|
||||
query: string,
|
||||
skip?: boolean,
|
||||
initialSelected?: string[]
|
||||
) {
|
||||
const [cachedInitialSelected] = useState<string[]>(initialSelected ?? []);
|
||||
|
||||
const { data: rootFoldersResult } = useFindRootFoldersForSelectQuery({
|
||||
skip,
|
||||
});
|
||||
|
|
@ -153,11 +177,94 @@ function useFolderMap(query: string, skip?: boolean) {
|
|||
},
|
||||
});
|
||||
|
||||
const { data: initialSelectedResult } = useFindFolderHierarchyForIDsQuery({
|
||||
skip: !initialSelected || cachedInitialSelected.length === 0,
|
||||
variables: {
|
||||
ids: cachedInitialSelected ?? [],
|
||||
},
|
||||
});
|
||||
|
||||
const rootFolders: IFolder[] = useMemo(() => {
|
||||
const ret = rootFoldersResult?.findFolders.folders ?? [];
|
||||
return ret.map((f) => ({ ...f, expanded: false, children: undefined }));
|
||||
}, [rootFoldersResult]);
|
||||
|
||||
const initialSelectedFolders: IFolder[] = useMemo(() => {
|
||||
const ret: IFolder[] = [];
|
||||
(initialSelectedResult?.findFolders.folders ?? []).forEach((folder) => {
|
||||
if (!folder.parent_folders.length) {
|
||||
// add root folder if not present
|
||||
if (!ret.find((f) => f.id === folder.id)) {
|
||||
ret.push({ ...folder, expanded: true, children: [] });
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
let currentParent: IFolder | undefined;
|
||||
|
||||
for (let i = folder.parent_folders.length - 1; i >= 0; i--) {
|
||||
const thisFolder = folder.parent_folders[i];
|
||||
let existing: IFolder | undefined;
|
||||
|
||||
if (i === folder.parent_folders.length - 1) {
|
||||
// last parent, add the folder as root if not present
|
||||
existing = ret.find((f) => f.id === thisFolder.id);
|
||||
if (!existing) {
|
||||
existing = {
|
||||
...folder.parent_folders[i],
|
||||
expanded: true,
|
||||
children: folder.parent_folders[i].sub_folders.map((f) => ({
|
||||
...f,
|
||||
expanded: false,
|
||||
children: undefined,
|
||||
})),
|
||||
};
|
||||
ret.push(existing);
|
||||
}
|
||||
currentParent = existing;
|
||||
continue;
|
||||
}
|
||||
|
||||
const existingIndex =
|
||||
currentParent!.children?.findIndex((f) => f.id === thisFolder.id) ??
|
||||
-1;
|
||||
if (existingIndex === -1) {
|
||||
// should be guaranteed
|
||||
throw new Error(
|
||||
`Parent folder ${thisFolder.id} not found in children of ${
|
||||
currentParent!.id
|
||||
}`
|
||||
);
|
||||
}
|
||||
|
||||
existing = currentParent!.children![existingIndex];
|
||||
|
||||
// replace children
|
||||
existing = {
|
||||
...existing,
|
||||
expanded: true,
|
||||
children: thisFolder.sub_folders.map((f) => ({
|
||||
...f,
|
||||
expanded: false,
|
||||
children: undefined,
|
||||
})),
|
||||
};
|
||||
|
||||
currentParent!.children![existingIndex] = existing;
|
||||
currentParent = existing;
|
||||
}
|
||||
});
|
||||
return ret;
|
||||
}, [initialSelectedResult]);
|
||||
|
||||
const mergedRootFolders = useMemo(() => {
|
||||
if (query) {
|
||||
return rootFolders;
|
||||
}
|
||||
|
||||
return mergeFolderMaps(rootFolders, initialSelectedFolders);
|
||||
}, [rootFolders, initialSelectedFolders, query]);
|
||||
|
||||
const queryFolders: IFolder[] = useMemo(() => {
|
||||
// construct the folder list from the query result
|
||||
const ret: IFolder[] = [];
|
||||
|
|
@ -229,11 +336,11 @@ function useFolderMap(query: string, skip?: boolean) {
|
|||
|
||||
useEffect(() => {
|
||||
if (!query) {
|
||||
setFolderMap(rootFolders);
|
||||
setFolderMap(mergedRootFolders);
|
||||
} else {
|
||||
setFolderMap(queryFolders);
|
||||
}
|
||||
}, [query, rootFolders, queryFolders]);
|
||||
}, [query, mergedRootFolders, queryFolders]);
|
||||
|
||||
async function onToggleExpanded(folder: IFolder) {
|
||||
setFolderMap(folderMap.map(toggleExpandedFn(folder)));
|
||||
|
|
@ -472,8 +579,6 @@ export const SidebarFolderFilter: React.FC<
|
|||
props.onOpen?.();
|
||||
}
|
||||
|
||||
const { folderMap, onToggleExpanded } = useFolderMap(query, skip);
|
||||
|
||||
const option = props.criterionOption ?? FolderCriterionOption;
|
||||
const { filter, setFilter } = props;
|
||||
|
||||
|
|
@ -494,6 +599,12 @@ export const SidebarFolderFilter: React.FC<
|
|||
const multipleSelected =
|
||||
criterion.value.items.length > 1 || criterion.value.excluded.length > 0;
|
||||
|
||||
const { folderMap, onToggleExpanded } = useFolderMap(
|
||||
query,
|
||||
skip,
|
||||
criterion.value.items.map((i) => i.id)
|
||||
);
|
||||
|
||||
function onSelect(folder: IFolder) {
|
||||
// maintain sub-folder select if present
|
||||
const depth = subDirsSelected ? -1 : 0;
|
||||
|
|
|
|||
Loading…
Reference in a new issue