Skip to content

fix: catch up with the server's metadata redesign and scheduled actions - #1477

Closed
revam wants to merge 20 commits into
masterfrom
fix/server-metadata-redesign
Closed

revam wants to merge 20 commits into
masterfrom
fix/server-metadata-redesign

Conversation

@revam

@revam revam commented Oct 3, 2026

Copy link
Copy Markdown
Member

Summary

Brings the Web UI in line with the current server daily, after the server's metadata redesign and the move of recurring work to scheduled actions. Each commit fixes one area; several of the bugs predate the redesign. The series linking page now works with any metadata source, not just TMDB.

Requires server 6.0.0-dev.495 or later (the minimum server version is raised to it): the ordering choice uses the generic POST /api/v3/Metadata/{source}/Series/{id}/Orderings/SetPreferred route, and the site URLs, source icons and wider episode search below are new in that daily too.

Changes

Settings

  • Update frequencies and import on start removed. The AniDB calendar, anime, file, notification and MyList frequencies, and the plugin auto-update frequency, became scheduled actions on the server (/api/v3/Action/Scheduled). The selects showed nothing, and changing one made the settings patch fail. Import on start became start-up triggers on the import's scheduled actions, so its toggle is gone too.
  • Metadata settings for every source. The TMDB tab is now Metadata (/settings/metadata): every source and provider with its status, a switch per kind or a provider order (active and standby) when several providers answer one, auto-linking, each provider's own settings inline, per-source image options, and link export/import for any source through /api/v3/Metadata/{source}/CrossReferences/Export and …/Import. The page no longer reads the core TMDB settings.
  • Scheduled actions. A new Scheduled Actions page lists every scheduled action by category with its state, progress, last and next runs, runs or cancels it, and edits, saves or resets its triggers within the server's minimum intervals (/api/v3/Action/Scheduled). The trigger editor offers every server trigger type, the queue-cleared one included, and keeps a type it doesn't know as it is.
  • Secret fields stay hidden. Configuration forms render password fields masked, keep a stored secret unless it is replaced or cleared, and never show the server's masked placeholder.

TMDB linking

  • Each auto-search candidate listed once. The server's preview now returns a candidate once per origin, so the same show or movie could show up twice. Each entry is listed once, with a badge for every origin that found it (search, current link, prequel link, AniDB resource, cross-source link).
  • Rejected suggestions. A candidate the automatic search wouldn't link shows why (the server's Rejection) as a warning badge, with the details in a tooltip; it can still be picked by hand.
  • Match ratings. DateAndNumberMatches and DateOffsetMatches showed a blank badge and were left out of the counts.
  • UnsetAll. The episode mapping body sent ResetAll, which the server never read.

Linking any metadata source

The series linking page (/collection/series/{id}/metadata-linking) takes a source query parameter. It replaces the tmdb-linking route, which is gone.

  • Source picker. Opened without a source, the page lists the sources that can be linked now, from GET /api/v3/Metadata/Source: each with its icon, its name and a short hint (series and movies, movies only, already linked, paused, not configured). Nothing is selected at first. Picking one replaces the history entry with ?source=…, so going back returns to the series. With only one source to link, the page goes straight to it. Once on a source there is no switcher; editing a link from the series page names its source, type and ID and never shows the picker.

  • Site URLs. Search and suggestion rows, the linked entry's header and the series page's links open the entry on its source's site through the server's SiteUrl, for every source; without one, the series page opens the entry on the linking page. The Web UI no longer builds TMDB URLs itself.

  • Source icons. The picker, the search panel's and the linked entry's headers, and the series page's links show GET /api/v3/Metadata/Source/{source}/Icon (as an <img>) for a source that HasIcon, else a generic database icon. The bundled TMDB image is gone; AniDB's stays for AniDB IDs shown elsewhere.

  • Generic routes for every source, TMDB included.

    • Search goes through /api/v3/Metadata/{source}/Search, and an entry is looked up by ID through …/Search/Series/{id} or …/Search/Movie/{id}.
    • The auto-search preview, with its origin and rejection badges, comes from GET /api/v3/Series/{id}/Metadata/{source}/Action/AutoSearch.
    • Series and movies are linked and unlinked through /api/v3/Series/{id}/Metadata/{source}/Series and …/Movie.
    • The existing links come from …/CrossReferences, and the linked movies from …/Movie.
    • A picked candidate is fetched through /api/v3/Metadata/{source}/{Series|Movie}/{id}/Action/Refresh.
  • Series and movies. The Series and Movie toggles follow what the source supports. Movies are mapped to AniDB episodes for any source. Linking a series to a source other than TMDB links it as a whole, and the server matches its episodes.

  • Orderings. The series settings dialog lists the linked series' orderings from GET /api/v3/Metadata/{source}/Series/{id}/Orderings and sets the preferred one through POST …/Orderings/SetPreferred, for every source. This replaces Tmdb/Show/{id}/Ordering.

  • Episode mapping for every source. Mapping episodes by hand works for any source whose linked series has episodes, with string IDs. The links come from GET /api/v3/Series/{id}/Metadata/{source}/CrossReferences/Episode, and for a series not linked yet from …/Episode/Auto?parentID=; changes go to POST …/CrossReferences/Episode. The picker lists GET /api/v3/Metadata/{source}/Series/{id}/Episode, searched by number (5, E5, #5), season (S1, S1E5), special (Special 3, Specials) or title, and the linked episodes come from POST /api/v3/Metadata/{source}/Episode/Bulk. A linked series without episodes is still linked as a whole. This replaces the TMDB routes (Series/{id}/TMDB/Show/CrossReferences/Episode, Tmdb/Show/{id}/Episode, Tmdb/Episode/Bulk).

Series

  • Links to every source. The overview's metadata sites list the series' links to every source after AniDB, TMDB first, read from the series' IDs.Linked, with GET /api/v3/Series/{id}/Metadata/{source}/CrossReferences telling series from movies and giving each entry's SiteUrl (only for sources the series is linked to). One Add link button at the bottom of the list opens the source picker, shown while any source can be linked; it replaces the add row each source had.
  • Partial AniDB air dates. AirDate and EndDate can be a year or a month alone; they showed as January 1st, and a year-only end date counted as past from its first day.

Releases

  • Deprecated releases. The server keeps a superseded release as IsDeprecated, apart from IsCorrupted; the link-files metadata panel shows it.
  • Stray 0. The link-files page rendered {links.length && …}, which drew a 0 once no files were left to link.

SignalR

  • Event names. The handlers listened for anidb:udb.stateUpdate and release:deleted; the server sends anidb:udp.stateUpdate and release:removed.
  • Series refresh. The series events were handled without their payload, so the series they name never refreshed.
  • Restart reasons. Admins join the restart feed and fetch GET /api/v3/Init/RestartReasons on load; the restart prompt lists each reason's plugin or setting and why, beside the configuration:requiresRestart notice, follows restart:reasonsChanged and closes once no reason is left. Other users neither join the feed nor call the route.

Filters

  • Pair picker. It listed PossibleParameters before PossibleParameterPairs, so HasSourceGenre/HasSourceTag offered only the sources and sent picks without a name.
  • Second parameters kept. Editing a saved filter dropped the second value of a condition the editor couldn't show.
  • Two inputs when no pairs come. A condition with a second parameter but no pairs (older servers, HasCharacterWithAppearance, HasCreatorWithRole) takes two inputs: the first from PossibleParameters when sent, the second free text suggesting PossibleSecondParameters.
  • Stale pairs. A saved pair the server no longer offers is flagged, kept on save, and stays pickable until the editor closes.

Theme

  • Color scheme. The default theme sets color-scheme: dark, so the browser's own controls and SVG images that follow prefers-color-scheme (plugin and source icons among them) match the WebUI instead of the OS.

Left to do

Not part of this PR; the server already has the API for each:

  • Quick actions. They still call the legacy /api/v3/Action/* routes (RunImport, ImportNewFiles, SearchForTmdbMatches, …), most of which now just queue the matching scheduled actions; they could start the scheduled and executable actions directly. This waits for the generated-UI work on the server to be finalized.
  • Character and creator filters. HasCharacterWithAppearance and HasCreatorWithRole come without possible parameters, so they take free text; a search-backed picker would fit them better.

Testing

pnpm lint, pnpm tscheck, pnpm test and pnpm build pass.

revam added 20 commits October 3, 2026 18:56
The server turned the AniDB and plugin update frequencies into scheduled
actions (`/api/v3/Action/Scheduled`), so the settings no longer carry
them and a patch of one fails. Its import on start became start-up
triggers on the import's scheduled actions, so the toggle went too.
- The auto search preview lists a candidate once per origin; each entry is now listed once, with a badge for every origin that found it
- Episode links rated `DateAndNumberMatches` or `DateOffsetMatches` showed a blank badge and were left out of the counts
- The episode mapping body sent `ResetAll`, which the server never read; it is `UnsetAll` now
- A suggestion the automatic search would not link shows the server's `Rejection` as a warning badge, with its details in a tooltip; it can still be picked
An AniDB anime's `AirDate` and `EndDate` can be a year or a month alone, which showed as the first of January and counted a year-only end date as past from its first day.
The server now keeps a superseded release as `IsDeprecated` apart from `IsCorrupted`, which used to carry it.
- The handlers listened for `anidb:udb.stateUpdate` and `release:deleted`, while the server sends `anidb:udp.stateUpdate` and `release:removed`
- The series events were handled without their payload, so the `ShokoSeriesIDs` they carry never refreshed those series
- The pair picker lists `PossibleParameterPairs` and a plain widget `PossibleParameters`; picks map back to the leaf's own pairs first, so a saved pair is kept
- A saved condition with a second parameter is kept as it was unless the catalog gives it pairs, instead of losing the second value on save
- Without `PossibleParameterPairs`, a condition with a `SecondParameter` takes two inputs: the first from `PossibleParameters` when sent, the second free text suggesting `PossibleSecondParameters`
- A saved pair without its second value opens with the first filled in; one the server no longer offers shows flagged, is kept on save, and stays pickable until the editor closes
…ource

- Moved search, the auto-search preview, series and movie linking and unlinking, and the cross-reference listing onto the `Metadata/` and `Series/{id}/Metadata/{source}` routes
- Added a source picker fed by `GET Metadata/Source`; the page is at `metadata-linking?source=`, with `tmdb-linking` kept and TMDB as the default
- Moved the ordering choice onto `Metadata/{source}/Series/{id}/Orderings` and its `SetPreferred`, for every source
- Moved the episode mapping onto `Series/{id}/Metadata/{source}/CrossReferences/Episode` (and `…/Auto`), `Metadata/{source}/Series/{id}/Episode` and `Metadata/{source}/Episode/Bulk`, with string IDs, shown for every linked series that has episodes
- Searched episodes by season, special or title (`S1E5`, `Special 3`) in the episode picker
- Removed the TMDB episode hooks and types it replaced
- Listed the series' links to every source after AniDB and TMDB, from `IDs.Linked`, with `Series/{id}/Metadata/{source}/CrossReferences` telling series from movies
- Added a row to link each source `GET Metadata/Source` reports enabled
- Opened other sources' entries on the linking page, as the server sends no site URL for them; TMDB keeps its external link
- Joined the admin-only `restart` feed and fetched `GET Init/RestartReasons` for admins only, as `MAINPAGE_LOADED` now carries `isAdmin`
- Moved the restart prompt into `RestartNotice`, which lists each reason's plugin or setting and description beside the `configuration:requiresRestart` notice, updates with the feed and closes once no reason is left
- Linked search, suggestion and cross-reference rows and the linking page header through the server's `SiteUrl`, for every source
- Listed TMDB's links on the series page from `…/CrossReferences` like the other sources, falling back to the linking page without a `SiteUrl`
- Removed the TMDB URL builders and `getSiteLink`
- Added `MetadataSourceIcon`, loading `Metadata/Source/{source}/Icon` when the source `HasIcon`, else the database icon
- Used it on the series page's links and the linking page's source label
- Dropped the bundled TMDB image; AniDB's stays for AniDB IDs shown elsewhere
- Replaced the series page's add row per source with one "Add link" button, which opens the linking page without a source
- Listed the linkable sources there with their icon and a hint, going straight to the only one when there is one, and replacing the history entry on a pick
- Removed the source dropdown from the search panel; edit links keep naming their source

- Removed the `tmdb-linking` route
- Renamed the TMDB tab to Metadata, listing each source from `GET Metadata/Provider` with its icon and status from `GET Metadata/Source`, and its icon from the providers' `HasIcon` when the source list has none
- Set every kind through `PUT Metadata/Source/{source}/Providers`: a switch where one provider answers, an order where several do, the answering provider marked Active and the other enabled ones Standby; `PUT Metadata/Provider/{providerID}` stays for auto-linking and for servers answering 404
- Moved the auto-linker and the auto-link switches onto the provider route for every source, the first run's TMDB tab included, and added TMDB's network download switch
- Kept the switches, orders and auto-link choices as a draft, counted as unsaved changes, sent on Save after the settings `PATCH` and dropped by Cancel; a part that fails stays in the draft with the server's error
- Rendered a provider's own `Configuration` inline in its source's section with `DynamicForm`, saved with its own button through `PUT Configuration/{id}`
- Replaced TMDB's image switches, counts and language order with `Image.MetadataSourceDefaults`, adding banners, and let each source with an image provider keep its own in `Image.MetadataSources`; a picked image language stays unsaved until Save, and the first run's TMDB tab shows the image defaults
- Added the `Metadata` purge days
- Stopped reading the core `TMDB` settings: removed `TMDBDownloadSettings` and the `TMDB` block from the settings types and defaults
- Picked the source on the metadata page and moved the export and import onto `Metadata/{source}/CrossReferences/Export` and `…/Import`
- Filtered the export by the source's own series, episode and movie IDs as text
- Listed what an import added, updated, kept and replaced in its toast
- Removed the `Tmdb/Export` and `Tmdb/Import` calls
- Rendered the `password` element type as a masked input, empty with an "Unchanged (hidden)" placeholder while the server sends `***SECRET-UNCHANGED…***`, which went into a text box before
- Sent the masked value back when the field is left alone, so the server keeps the secret, what was typed otherwise, and an empty string when cleared
- Added a clear button for a stored secret, an undo back to it, and a show/hide toggle for what was typed
- Listed every scheduled action from `GET Action/Scheduled` by category, with its state and progress, next run, last runs, minimum interval and triggers
- Ran one now through `POST Action/Scheduled/{id}`, asking first when it says so, and cancelled its run through `…/{id}/Cancel`
- Edited the triggers of each type, the queue-cleared one included, saved with `PUT …/{id}/Triggers` and reset with `DELETE …/{id}/Triggers`, showing the server's errors under the trigger they name
- Kept the trigger types in one list, so a new one is one entry, and kept a type it does not know as it is
- Said "Only by hand" for an action without triggers, and "At the next start-up" for one with only a start-up trigger
- Fetched the list again every 2 seconds while a run is in the queue, otherwise every 30
- `Input` rendered `endIcons?.length &&`, which put a `0` on the page for an empty list, as an empty password field passes one
@revam

revam commented Oct 3, 2026

Copy link
Copy Markdown
Member Author

Split into a stack of 12 smaller PRs, to review one at a time from the bottom up. Each shows only its own layer, and the top one's tree is identical to this PR's.

  1. fix(settings): drop the settings that became scheduled actions #1478 fix(settings): drop the settings that became scheduled actions
  2. fix: show partial air dates and deprecated releases, drop stray 0s and mark the theme dark #1479 fix: show partial air dates and deprecated releases, drop stray 0s and mark the theme dark
  3. fix(signalr): listen for the events the server sends #1480 fix(signalr): listen for the events the server sends
  4. fix(configuration): never show a stored secret in a configuration form #1481 fix(configuration): never show a stored secret in a configuration form
  5. fix(filters): edit conditions with two parameters #1482 fix(filters): edit conditions with two parameters
  6. feat(signalr): show the server's restart reasons to admins #1483 feat(signalr): show the server's restart reasons to admins
  7. feat(settings): add a scheduled actions page #1484 feat(settings): add a scheduled actions page
  8. fix(tmdb): match the TMDB linking to the server #1485 fix(tmdb): match the TMDB linking to the server
  9. feat(metadata): link series and map their episodes for any metadata source #1486 feat(metadata): link series and map their episodes for any metadata source
  10. feat(series): list links to every metadata source #1487 feat(series): list links to every metadata source
  11. refactor(metadata): add source site links and icons, pick the source on the linking page #1488 refactor(metadata): add source site links and icons, pick the source on the linking page
  12. refactor(settings): replace the TMDB tab with settings for every metadata source #1489 refactor(settings): replace the TMDB tab with settings for every metadata source

Closing this one in their favour.

@revam revam closed this Oct 3, 2026
@revam
revam deleted the fix/server-metadata-redesign branch October 3, 2026 17:44
harshithmohan pushed a commit that referenced this pull request Oct 6, 2026
…#1478, #1480)

Squashed commits:
- drop the settings that became scheduled actions (#1478)
- show partial AniDB air dates as they are known
- show whether a release is deprecated
- stop showing a stray 0 under inputs and when no files are left to link
- mark the default theme as a dark color scheme
- listen for the signalr events the server sends (#1480)
- never show a stored secret in a configuration form
harshithmohan pushed a commit that referenced this pull request Oct 6, 2026
…#1478, #1480)

Squashed commits:
- drop the settings that became scheduled actions (#1478)
- show partial AniDB air dates as they are known
- show whether a release is deprecated
- stop showing a stray 0 under inputs and when no files are left to link
- mark the default theme as a dark color scheme
- listen for the signalr events the server sends (#1480)
- never show a stored secret in a configuration form
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant