feat(api): playlist add-items + search all-items endpoints (#208 #209)

- POST /api/playlists/{id:int}/items wraps the existing AddItemsToPlaylist
  command (mirrors CollectionController.AddItems); controller pre-checks
  playlist existence for a real 404, and the handler now rejects adds to
  system (generated) playlists, matching the guard already applied to
  rename/delete/replace-items so the Blazor path gets the same protection.
- GET /api/search/all-items wraps the existing QuerySearchIndexAllItems
  query, returning a new SearchResultAllItemsResponseModel (never expose
  the VM directly) so the SPA's shared "add all to collection/playlist"
  component can materialize ids before calling the add endpoints, same
  two-step flow Blazor's Search.razor already uses.
- Show-detail DTO check: ShowDetailResponseModel already exposes
  libraryId, title, and mediaSourceKind (serialized as a string enum via
  the global StringEnumConverter) - no changes needed.

Adds controller tests (route table + per-action) for both endpoints and
regenerates the OpenAPI document, endpoint index, and SPA client types.
This commit is contained in:
2026-07-09 23:56:50 +02:00
parent cfabd6f33f
commit 819e751cab
10 changed files with 646 additions and 6 deletions
+24
View File
@@ -20,6 +20,18 @@ export interface components {
"songIds": null | Array<number>;
"imageIds": null | Array<number>;
"remoteStreamIds": null | Array<number>;
};
"AddItemsToPlaylistRequest": {
"movieIds": null | Array<number>;
"showIds": null | Array<number>;
"seasonIds": null | Array<number>;
"episodeIds": null | Array<number>;
"artistIds": null | Array<number>;
"musicVideoIds": null | Array<number>;
"otherVideoIds": null | Array<number>;
"songIds": null | Array<number>;
"imageIds": null | Array<number>;
"remoteStreamIds": null | Array<number>;
};
"AddTraktListRequest": {
"url": null | string;
@@ -1313,6 +1325,18 @@ export interface components {
"SchedulingPickerOptionResponseModel": {
"id": number;
"name": string;
};
"SearchResultAllItemsResponseModel": {
"movieIds": null | Array<number>;
"showIds": null | Array<number>;
"seasonIds": null | Array<number>;
"episodeIds": null | Array<number>;
"artistIds": null | Array<number>;
"musicVideoIds": null | Array<number>;
"otherVideoIds": null | Array<number>;
"songIds": null | Array<number>;
"imageIds": null | Array<number>;
"remoteStreamIds": null | Array<number>;
};
"SearchResultGroupResponseModel": {
"totalCount": number;