feat(plex): Collections Phase 2 — admin collection editing (write-back to Plex)

Admins can curate Plex collections from a movie's info page ("Collections"
button → PlexCollectionEditor dialog): create a collection (seeded with the
movie), add/remove the movie to/from editable collections, delete a collection,
and "take over" an existing plain Plex collection (mark it editable). All writes
go to Plex (POST/PUT/DELETE via new PlexClient methods) and are reflected on
every client; a targeted single-collection re-sync (sync.resync_collection /
delete_collection_local) updates the local mirror without the full ~4-min sync.

Gating (per the design decisions): editing is ADMIN-ONLY (collections are shared
library-wide); only plain manual collections are editable — smart + external
auto-lists (IMDb/TMDb/…) are always read-only (can_edit = editable && !smart &&
source=="collection"). New admin endpoints under /api/plex/collections
(create/items add+remove/rename/delete/editable). Verified end-to-end incl. the
live Plex write API (create/add/rename/remove/delete all 200, self-cleaned) and
the editor UI (create + delete with confirm) on localdev.
This commit is contained in:
npeter83 2026-07-06 17:33:16 +02:00
parent 4b053a55da
commit 8291f06525
12 changed files with 602 additions and 13 deletions

View file

@ -726,7 +726,9 @@ export interface PlexCollection {
thumb?: string | null;
child_count?: number | null;
smart: boolean;
source?: string;
editable: boolean;
can_edit?: boolean; // effective: admin-marked editable AND a plain (non-smart/non-auto) collection
}
export interface PlexCastMember {
name: string;
@ -1149,6 +1151,19 @@ export const api = {
req(`/api/plex/people?library=${encodeURIComponent(library)}&q=${encodeURIComponent(q)}`),
plexCollections: (library: string, q?: string): Promise<{ collections: PlexCollection[] }> =>
req(`/api/plex/collections?library=${encodeURIComponent(library)}${q ? `&q=${encodeURIComponent(q)}` : ""}`),
// --- Collection editing (admin only; writes back to Plex) ---
plexCreateCollection: (library: string, title: string, item_rating_key: string): Promise<PlexCollection> =>
req(`/api/plex/collections`, { method: "POST", body: JSON.stringify({ library, title, item_rating_key }) }),
plexCollectionAddItem: (rk: string, itemRk: string): Promise<PlexCollection> =>
req(`/api/plex/collections/${encodeURIComponent(rk)}/items/${encodeURIComponent(itemRk)}`, { method: "POST" }),
plexCollectionRemoveItem: (rk: string, itemRk: string): Promise<PlexCollection> =>
req(`/api/plex/collections/${encodeURIComponent(rk)}/items/${encodeURIComponent(itemRk)}`, { method: "DELETE" }),
plexRenameCollection: (rk: string, title: string): Promise<PlexCollection> =>
req(`/api/plex/collections/${encodeURIComponent(rk)}`, { method: "PATCH", body: JSON.stringify({ title }) }),
plexDeleteCollection: (rk: string): Promise<{ deleted: string }> =>
req(`/api/plex/collections/${encodeURIComponent(rk)}`, { method: "DELETE" }),
plexSetCollectionEditable: (rk: string, editable: boolean): Promise<PlexCollection> =>
req(`/api/plex/collections/${encodeURIComponent(rk)}/editable`, { method: "POST", body: JSON.stringify({ editable }) }),
plexShow: (id: string): Promise<PlexShowDetail> =>
req(`/api/plex/show/${encodeURIComponent(id)}`),
plexItem: (id: string): Promise<PlexItemDetail> =>

View file

@ -14,6 +14,15 @@ export interface ReleaseEntry {
}
export const RELEASE_NOTES: ReleaseEntry[] = [
{
version: "0.29.0",
date: "2026-07-06",
summary: "Plex collections — admins can now create and curate them.",
features: [
"Plex collections (admin): a movie's info page has a “Collections” button to create a new collection (seeded with that movie), add or remove the movie from your collections, and delete a collection. Changes are written back to Plex, so they show up on every client and for everyone.",
"Plex collections (admin): existing plain Plex collections can be “taken over” (marked as yours to manage) from the same dialog. Smart collections and external auto-lists (IMDb Top 250, TMDb Trending, …) stay read-only — they're regenerated outside Plex. Editing is admin-only, since collections are shared library-wide.",
],
},
{
version: "0.28.3",
date: "2026-07-06",