mirror of
https://github.com/kmc7468/arkvault.git
synced 2026-02-03 23:56:53 +00:00
즐겨찾기 검색 필터를 재귀적으로 동작하도록 변경
This commit is contained in:
@@ -74,28 +74,6 @@ export const getAllDirectoriesByParent = async (userId: number, parentId: Direct
|
|||||||
return directories.map(toDirectory);
|
return directories.map(toDirectory);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getAllRecursiveDirectoriesByParent = async (userId: number, parentId: DirectoryId) => {
|
|
||||||
const directories = await db
|
|
||||||
.withRecursive("directory_tree", (db) =>
|
|
||||||
db
|
|
||||||
.selectFrom("directory")
|
|
||||||
.selectAll()
|
|
||||||
.$if(parentId === "root", (qb) => qb.where("parent_id", "is", null))
|
|
||||||
.$if(parentId !== "root", (qb) => qb.where("parent_id", "=", parentId as number))
|
|
||||||
.where("user_id", "=", userId)
|
|
||||||
.unionAll((db) =>
|
|
||||||
db
|
|
||||||
.selectFrom("directory")
|
|
||||||
.innerJoin("directory_tree", "directory.parent_id", "directory_tree.id")
|
|
||||||
.selectAll("directory"),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.selectFrom("directory_tree")
|
|
||||||
.selectAll()
|
|
||||||
.execute();
|
|
||||||
return directories.map(toDirectory);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getAllFavoriteDirectories = async (userId: number) => {
|
export const getAllFavoriteDirectories = async (userId: number) => {
|
||||||
const directories = await db
|
const directories = await db
|
||||||
.selectFrom("directory")
|
.selectFrom("directory")
|
||||||
@@ -117,6 +95,61 @@ export const getDirectory = async (userId: number, directoryId: number) => {
|
|||||||
return directory ? toDirectory(directory) : null;
|
return directory ? toDirectory(directory) : null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const searchDirectories = async (
|
||||||
|
userId: number,
|
||||||
|
filters: {
|
||||||
|
parentId: DirectoryId;
|
||||||
|
inFavorites: boolean;
|
||||||
|
},
|
||||||
|
) => {
|
||||||
|
const directories = await db
|
||||||
|
.withRecursive("directory_tree", (db) =>
|
||||||
|
db
|
||||||
|
.selectFrom("directory")
|
||||||
|
.select("id")
|
||||||
|
.where("user_id", "=", userId)
|
||||||
|
.$if(filters.parentId === "root", (qb) => qb.where((eb) => eb.lit(false))) // directory_tree will be empty if parentId is "root"
|
||||||
|
.$if(filters.parentId !== "root", (qb) => qb.where("id", "=", filters.parentId as number))
|
||||||
|
.unionAll(
|
||||||
|
db
|
||||||
|
.selectFrom("directory as d")
|
||||||
|
.innerJoin("directory_tree as dt", "d.parent_id", "dt.id")
|
||||||
|
.select("d.id"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.withRecursive("favorite_directory_tree", (db) =>
|
||||||
|
db
|
||||||
|
.selectFrom("directory")
|
||||||
|
.select("id")
|
||||||
|
.where("user_id", "=", userId)
|
||||||
|
.$if(!filters.inFavorites, (qb) => qb.where((eb) => eb.lit(false))) // favorite_directory_tree will be empty if inFavorites is false
|
||||||
|
.$if(filters.inFavorites, (qb) => qb.where("is_favorite", "=", true))
|
||||||
|
.unionAll((db) =>
|
||||||
|
db
|
||||||
|
.selectFrom("directory as d")
|
||||||
|
.innerJoin("favorite_directory_tree as dt", "d.parent_id", "dt.id")
|
||||||
|
.select("d.id"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.selectFrom("directory")
|
||||||
|
.selectAll()
|
||||||
|
.where("user_id", "=", userId)
|
||||||
|
.$if(filters.parentId !== "root", (qb) =>
|
||||||
|
qb.where((eb) =>
|
||||||
|
eb.exists(eb.selectFrom("directory_tree as dt").whereRef("dt.id", "=", "parent_id")),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.$if(filters.inFavorites, (qb) =>
|
||||||
|
qb.where((eb) =>
|
||||||
|
eb.exists(
|
||||||
|
eb.selectFrom("favorite_directory_tree as dt").whereRef("dt.id", "=", "directory.id"),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.execute();
|
||||||
|
return directories.map(toDirectory);
|
||||||
|
};
|
||||||
|
|
||||||
export const setDirectoryEncName = async (
|
export const setDirectoryEncName = async (
|
||||||
userId: number,
|
userId: number,
|
||||||
directoryId: number,
|
directoryId: number,
|
||||||
|
|||||||
@@ -248,6 +248,7 @@ export const searchFiles = async (
|
|||||||
userId: number,
|
userId: number,
|
||||||
filters: {
|
filters: {
|
||||||
parentId: DirectoryId;
|
parentId: DirectoryId;
|
||||||
|
inFavorites: boolean;
|
||||||
includeCategoryIds: number[];
|
includeCategoryIds: number[];
|
||||||
excludeCategoryIds: number[];
|
excludeCategoryIds: number[];
|
||||||
},
|
},
|
||||||
@@ -258,7 +259,7 @@ export const searchFiles = async (
|
|||||||
.selectFrom("directory")
|
.selectFrom("directory")
|
||||||
.select("id")
|
.select("id")
|
||||||
.where("user_id", "=", userId)
|
.where("user_id", "=", userId)
|
||||||
.where((eb) => eb.val(filters.parentId !== "root")) // directory_tree will be empty if parentId is "root"
|
.$if(filters.parentId === "root", (qb) => qb.where((eb) => eb.lit(false))) // directory_tree will be empty if parentId is "root"
|
||||||
.$if(filters.parentId !== "root", (qb) => qb.where("id", "=", filters.parentId as number))
|
.$if(filters.parentId !== "root", (qb) => qb.where("id", "=", filters.parentId as number))
|
||||||
.unionAll(
|
.unionAll(
|
||||||
db
|
db
|
||||||
@@ -267,6 +268,20 @@ export const searchFiles = async (
|
|||||||
.select("d.id"),
|
.select("d.id"),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
.withRecursive("favorite_directory_tree", (db) =>
|
||||||
|
db
|
||||||
|
.selectFrom("directory")
|
||||||
|
.select("id")
|
||||||
|
.where("user_id", "=", userId)
|
||||||
|
.$if(!filters.inFavorites, (qb) => qb.where((eb) => eb.lit(false))) // favorite_directory_tree will be empty if inFavorites is false
|
||||||
|
.$if(filters.inFavorites, (qb) => qb.where("is_favorite", "=", true))
|
||||||
|
.unionAll((db) =>
|
||||||
|
db
|
||||||
|
.selectFrom("directory as d")
|
||||||
|
.innerJoin("favorite_directory_tree as dt", "d.parent_id", "dt.id")
|
||||||
|
.select("d.id"),
|
||||||
|
),
|
||||||
|
)
|
||||||
.withRecursive("include_category_tree", (db) =>
|
.withRecursive("include_category_tree", (db) =>
|
||||||
db
|
db
|
||||||
.selectFrom("category")
|
.selectFrom("category")
|
||||||
@@ -295,19 +310,31 @@ export const searchFiles = async (
|
|||||||
)
|
)
|
||||||
.selectFrom("file")
|
.selectFrom("file")
|
||||||
.selectAll("file")
|
.selectAll("file")
|
||||||
.$if(filters.parentId === "root", (qb) => qb.where("user_id", "=", userId)) // directory_tree isn't used if parentId is "root"
|
.where("user_id", "=", userId)
|
||||||
.$if(filters.parentId !== "root", (qb) =>
|
.$if(filters.parentId !== "root", (qb) =>
|
||||||
qb.where("parent_id", "in", (eb) => eb.selectFrom("directory_tree").select("id")),
|
qb.where((eb) =>
|
||||||
|
eb.exists(eb.selectFrom("directory_tree as dt").whereRef("dt.id", "=", "file.parent_id")),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.where((eb) =>
|
.$if(filters.inFavorites, (qb) =>
|
||||||
eb.not(
|
qb.where((eb) =>
|
||||||
eb.exists(
|
eb.or([
|
||||||
eb
|
eb("is_favorite", "=", true),
|
||||||
.selectFrom("file_category")
|
eb.exists(
|
||||||
.whereRef("file_id", "=", "file.id")
|
eb.selectFrom("favorite_directory_tree as dt").whereRef("dt.id", "=", "file.parent_id"),
|
||||||
.where("category_id", "in", (eb) =>
|
),
|
||||||
eb.selectFrom("exclude_category_tree").select("id"),
|
]),
|
||||||
),
|
),
|
||||||
|
)
|
||||||
|
.$if(filters.excludeCategoryIds.length > 0, (qb) =>
|
||||||
|
qb.where((eb) =>
|
||||||
|
eb.not(
|
||||||
|
eb.exists(
|
||||||
|
eb
|
||||||
|
.selectFrom("file_category")
|
||||||
|
.innerJoin("exclude_category_tree", "category_id", "exclude_category_tree.id")
|
||||||
|
.whereRef("file_id", "=", "file.id"),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -37,8 +37,8 @@
|
|||||||
includeImages: false,
|
includeImages: false,
|
||||||
includeVideos: false,
|
includeVideos: false,
|
||||||
includeDirectories: false,
|
includeDirectories: false,
|
||||||
searchInFavorites: false,
|
|
||||||
searchInDirectory: false,
|
searchInDirectory: false,
|
||||||
|
searchInFavorites: false,
|
||||||
categories: [],
|
categories: [],
|
||||||
});
|
});
|
||||||
let hasCategoryFilter = $derived(filters.categories.length > 0);
|
let hasCategoryFilter = $derived(filters.categories.length > 0);
|
||||||
@@ -47,7 +47,6 @@
|
|||||||
filters.includeImages ||
|
filters.includeImages ||
|
||||||
filters.includeVideos ||
|
filters.includeVideos ||
|
||||||
filters.includeDirectories ||
|
filters.includeDirectories ||
|
||||||
filters.searchInFavorites ||
|
|
||||||
filters.name.trim().length > 0,
|
filters.name.trim().length > 0,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -84,9 +83,7 @@
|
|||||||
|
|
||||||
return sortEntries(
|
return sortEntries(
|
||||||
[...directories, ...files].filter(
|
[...directories, ...files].filter(
|
||||||
(entry) =>
|
(entry) => !nameFilter || searchString(entry.name, nameFilter),
|
||||||
(!nameFilter || searchString(entry.name, nameFilter)) &&
|
|
||||||
(!filters.searchInFavorites || entry.isFavorite),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -145,6 +142,7 @@
|
|||||||
// Svelte sucks
|
// Svelte sucks
|
||||||
hasAnyFilter;
|
hasAnyFilter;
|
||||||
filters.searchInDirectory;
|
filters.searchInDirectory;
|
||||||
|
filters.searchInFavorites;
|
||||||
filters.categories.length;
|
filters.categories.length;
|
||||||
|
|
||||||
if (untrack(() => isRestoredFromSnapshot)) {
|
if (untrack(() => isRestoredFromSnapshot)) {
|
||||||
@@ -156,6 +154,7 @@
|
|||||||
requestSearch(
|
requestSearch(
|
||||||
{
|
{
|
||||||
ancestorId: filters.searchInDirectory ? data.directoryId! : "root",
|
ancestorId: filters.searchInDirectory ? data.directoryId! : "root",
|
||||||
|
inFavorites: filters.searchInFavorites,
|
||||||
categories: filters.categories,
|
categories: filters.categories,
|
||||||
},
|
},
|
||||||
$masterKeyStore?.get(1)?.key!,
|
$masterKeyStore?.get(1)?.key!,
|
||||||
@@ -216,7 +215,12 @@
|
|||||||
</div>
|
</div>
|
||||||
{#if hasAnyFilter}
|
{#if hasAnyFilter}
|
||||||
<div class="flex flex-grow flex-col space-y-2 bg-white p-4">
|
<div class="flex flex-grow flex-col space-y-2 bg-white p-4">
|
||||||
<p class="text-lg font-bold text-gray-800">검색 결과</p>
|
<p class="text-lg font-bold text-gray-800">
|
||||||
|
검색 결과
|
||||||
|
{#if result.length > 0}
|
||||||
|
{" "}({result.length}개)
|
||||||
|
{/if}
|
||||||
|
</p>
|
||||||
{#if result.length > 0}
|
{#if result.length > 0}
|
||||||
<RowVirtualizer
|
<RowVirtualizer
|
||||||
count={result.length}
|
count={result.length}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { trpc } from "$trpc/client";
|
|||||||
|
|
||||||
export interface SearchFilter {
|
export interface SearchFilter {
|
||||||
ancestorId: DirectoryId;
|
ancestorId: DirectoryId;
|
||||||
|
inFavorites: boolean;
|
||||||
categories: { info: LocalCategoryInfo; type: "include" | "exclude" }[];
|
categories: { info: LocalCategoryInfo; type: "include" | "exclude" }[];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -21,6 +22,7 @@ export interface SearchResult {
|
|||||||
export const requestSearch = async (filter: SearchFilter, masterKey: CryptoKey) => {
|
export const requestSearch = async (filter: SearchFilter, masterKey: CryptoKey) => {
|
||||||
const { directories: directoriesRaw, files: filesRaw } = await trpc().search.search.query({
|
const { directories: directoriesRaw, files: filesRaw } = await trpc().search.search.query({
|
||||||
ancestor: filter.ancestorId,
|
ancestor: filter.ancestorId,
|
||||||
|
inFavorites: filter.inFavorites,
|
||||||
includeCategories: filter.categories
|
includeCategories: filter.categories
|
||||||
.filter(({ type }) => type === "include")
|
.filter(({ type }) => type === "include")
|
||||||
.map(({ info }) => info.id),
|
.map(({ info }) => info.id),
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ const searchRouter = router({
|
|||||||
.input(
|
.input(
|
||||||
z.object({
|
z.object({
|
||||||
ancestor: DirectoryIdSchema.default("root"),
|
ancestor: DirectoryIdSchema.default("root"),
|
||||||
|
inFavorites: z.boolean().default(false),
|
||||||
includeCategories: z.number().positive().array().default([]),
|
includeCategories: z.number().positive().array().default([]),
|
||||||
excludeCategories: z.number().positive().array().default([]),
|
excludeCategories: z.number().positive().array().default([]),
|
||||||
}),
|
}),
|
||||||
@@ -15,10 +16,14 @@ const searchRouter = router({
|
|||||||
.query(async ({ ctx, input }) => {
|
.query(async ({ ctx, input }) => {
|
||||||
const [directories, files] = await Promise.all([
|
const [directories, files] = await Promise.all([
|
||||||
input.includeCategories.length === 0 && input.excludeCategories.length === 0
|
input.includeCategories.length === 0 && input.excludeCategories.length === 0
|
||||||
? DirectoryRepo.getAllRecursiveDirectoriesByParent(ctx.session.userId, input.ancestor)
|
? DirectoryRepo.searchDirectories(ctx.session.userId, {
|
||||||
|
parentId: input.ancestor,
|
||||||
|
inFavorites: input.inFavorites,
|
||||||
|
})
|
||||||
: [],
|
: [],
|
||||||
FileRepo.searchFiles(ctx.session.userId, {
|
FileRepo.searchFiles(ctx.session.userId, {
|
||||||
parentId: input.ancestor,
|
parentId: input.ancestor,
|
||||||
|
inFavorites: input.inFavorites,
|
||||||
includeCategoryIds: input.includeCategories,
|
includeCategoryIds: input.includeCategories,
|
||||||
excludeCategoryIds: input.excludeCategories,
|
excludeCategoryIds: input.excludeCategories,
|
||||||
}),
|
}),
|
||||||
|
|||||||
Reference in New Issue
Block a user