diff --git a/frontend/src/lib/api/categories.ts b/frontend/src/lib/api/categories.ts new file mode 100644 index 0000000..b428111 --- /dev/null +++ b/frontend/src/lib/api/categories.ts @@ -0,0 +1,28 @@ +import { get } from 'svelte/store'; +import { api } from '$lib/api/client'; +import type { Category, CategoryOffsetPage } from '$lib/api/types'; +import { categorySorting } from '$lib/stores/sorting'; + +// The /categories endpoint caps limit at 200 per request. Category dropdowns +// show the whole list, so page through to get them all — otherwise categories +// past the first 200 are missing from the picker. +const PAGE = 200; + +/** + * Fetches every category, paging past the server's per-request cap. Ordered by + * the sort the user picked on the categories page (categorySorting). + */ +export async function fetchAllCategories(): Promise { + const { sort, order } = get(categorySorting); + const all: Category[] = []; + for (let offset = 0; ; offset += PAGE) { + const page = await api.get( + `/categories?limit=${PAGE}&offset=${offset}&sort=${sort}&order=${order}` + ); + const items = page.items ?? []; + all.push(...items); + const total = page.total ?? all.length; + if (items.length < PAGE || all.length >= total) break; + } + return all; +} diff --git a/frontend/src/lib/api/tags.ts b/frontend/src/lib/api/tags.ts new file mode 100644 index 0000000..26245c4 --- /dev/null +++ b/frontend/src/lib/api/tags.ts @@ -0,0 +1,30 @@ +import { get } from 'svelte/store'; +import { api } from '$lib/api/client'; +import type { Tag, TagOffsetPage } from '$lib/api/types'; +import { tagSorting } from '$lib/stores/sorting'; + +// The /tags endpoint caps limit at 200 per request. Pickers and the filter bar +// filter the tag list client-side, so they need the *whole* list — otherwise +// tags past the first 200 are invisible and unsearchable. Page through until we +// have them all. +const PAGE = 200; + +/** + * Fetches every tag, paging past the server's per-request cap. Ordered by the + * sort the user picked on the tags page (tagSorting), so the pickers and filter + * bar show tags in the same order as that page. + */ +export async function fetchAllTags(): Promise { + const { sort, order } = get(tagSorting); + const all: Tag[] = []; + for (let offset = 0; ; offset += PAGE) { + const page = await api.get( + `/tags?limit=${PAGE}&offset=${offset}&sort=${sort}&order=${order}` + ); + const items = page.items ?? []; + all.push(...items); + const total = page.total ?? all.length; + if (items.length < PAGE || all.length >= total) break; + } + return all; +} diff --git a/frontend/src/lib/components/file/BulkTagEditor.svelte b/frontend/src/lib/components/file/BulkTagEditor.svelte index a4d82a9..8c8b994 100644 --- a/frontend/src/lib/components/file/BulkTagEditor.svelte +++ b/frontend/src/lib/components/file/BulkTagEditor.svelte @@ -1,6 +1,7 @@