Files
ersatztv/web/src/api/libraryBrowse.ts
T
timothyandClaude Fable 5 d05e442605
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 5m8s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 5m16s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
fix(web): stop season-tile flooding in channel builder and collections (#180)
Part of the #180 library picker fixes (SPA side).

Channel builder: TelevisionSeason is removed from the library grid fan-out, so a
multi-season show renders as one tile instead of one tile per season. Show tiles
gain a "Seasons" drill-in affordance (both grid and compact layouts) that opens a
dialog listing that show's seasons (via the new GET /api/library/browse?parentId=
&mediaType=TelevisionSeason), each with title, artwork and an Add button that
drops the specific season into the lineup.

Collections add-items dialog: the default search fan-out now excludes seasons,
and a media-kind filter row (All / Movies / Shows / Seasons / Artists,
default = All-without-seasons) keeps seasons reachable when explicitly selected.

Client: getLibraryBrowseItems gains an optional parentId param. Tests cover the
param mapping, the builder no longer requesting TelevisionSeason, and the
collections dialog default-excluding vs explicitly-including seasons.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 21:42:18 +02:00

61 lines
1.8 KiB
TypeScript

import { ApiError, request } from './client';
import type { components } from './generated/v1';
export type LibraryBrowseItem = components['schemas']['LibraryBrowseItemResponseModel'];
export type LibraryBrowseMediaType = components['schemas']['LibraryBrowseMediaType'];
export type PagedLibraryBrowseItems = components['schemas']['PagedLibraryBrowseItemsResponseModel'];
export interface GetLibraryBrowseItemsParams {
libraryId?: number;
mediaType?: LibraryBrowseMediaType;
pageNum?: number;
pageSize?: number;
// Only meaningful with mediaType 'TelevisionSeason': filters seasons to the given show id.
parentId?: number;
query?: string;
}
export function getLibraryBrowseItems(params: GetLibraryBrowseItemsParams = {}): Promise<PagedLibraryBrowseItems> {
const searchParams = new URLSearchParams();
if (params.query) {
searchParams.set('query', params.query);
}
if (params.libraryId != null) {
searchParams.set('libraryId', String(params.libraryId));
}
if (params.mediaType) {
searchParams.set('mediaType', params.mediaType);
}
if (params.pageNum != null) {
searchParams.set('pageNum', String(params.pageNum));
}
if (params.pageSize != null) {
searchParams.set('pageSize', String(params.pageSize));
}
if (params.parentId != null) {
searchParams.set('parentId', String(params.parentId));
}
const queryString = searchParams.toString();
return request<PagedLibraryBrowseItems>(`/api/library/browse${queryString ? `?${queryString}` : ''}`);
}
export function messageFromLibraryBrowseError(error: unknown, fallback = 'Unable to load library items'): string {
if (error instanceof ApiError) {
return error.detail ?? error.message;
}
if (error instanceof Error) {
return error.message;
}
return fallback;
}