Skip to content

feat(tautulli): open Plex items in the app-global quick-look modal - #75

Open
ndandan wants to merge 14 commits into
Shoshuo:mainfrom
ndandan:pr/tautulli-global-quicklook
Open

feat(tautulli): open Plex items in the app-global quick-look modal#75
ndandan wants to merge 14 commits into
Shoshuo:mainfrom
ndandan:pr/tautulli-global-quicklook

Conversation

@ndandan

@ndandan ndandan commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Stacked on #69 (one detail modal everywhere). This PR's diff shows #69's commits until that one merges, then collapses to a single commit / 6-file delta: feat(tautulli): open Plex items in the app-global quick-look modal.

Clicking a Plex item on the Tautulli Activity page or the dashboard's Plex-activity widget (they share _plex_info_modal.html.twig) currently opens the bespoke Tautulli metadata pop-up. With the unified quick-look modal from #69 in place, those clicks now open the same global quick-look as everywhere else in the app — one modal, one code path, richer content (poster, dates, cast, providers, Manage/Add actions).

How it works

  • Click → GET /tautulli/api/quicklook/{ratingKey}TautulliClient::resolveTmdbId() → JSON {type, id} → a hidden data-ql-trigger ghost element clicks into the untouched global quick-look handler.
  • Guid resolution rules: movie/show use their own guids; a season uses parent_guids; an episode uses grandparent_guids; one extra metadata hop to the show covers items missing show-level guids.
  • Fallback: items with no TMDb id (music, home video) keep the legacy Plex modal — no dead clicks.
  • Privacy stance kept: only the numeric TMDb id ever reaches the browser (same guid allow-list as the existing sanitised payloads); the API key never leaves the server.

Verification

  • New TautulliQuickLookResolveTest (8 tests: guid rules per media type, the show-hop, no-TMDb fallback) + a TautulliControllerTest endpoint test.
  • make check (lint + Twig lint + full PHPUnit suite) green on this branch.
  • Live-verified on our instance against a real Tautulli/Plex install.

CHANGELOG entry included under [Unreleased].

🤖 Generated with Claude Code

ndandan and others added 14 commits June 26, 2026 20:56
… model

Add movieReleaseChips() and tmdbMovieReleaseDates() private helpers to
DashboardController. Wire releaseDates key into both quickLookLibrary
(from Radarr inCinemasAt/digitalAt/physicalAt fields) and quickLookTmdb
(parsed from TMDb release_dates.results append). Series gets empty list;
movies get fixed-order cinema→digital→physical chips with upcoming flag.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…odel

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds testQuickLookLibrarySeriesEndedShowsEndDate to pin that a Sonarr
series with status=ended emits airStatus='ended', includes both the
first_aired and ended release chips from previousAiring, and must NOT
emit a next_episode chip.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…partial

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…es + Add/Manage

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…s series

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…s emphasis

Adds .ql-dates flex row, .ql-date pill chips (label+value layout), .ql-date.is-upcoming
accent emphasis via var(--tblr-primary), and .ql-airstatus badge with is-continuing
(green) / is-ended (muted) modifiers. Colour strategy follows existing rgba+Tabler-
variable pattern for automatic light/dark adaptation; no new raw hex introduced.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The Continuing/Ended pill sat in a flex row beside the taller two-line
date chips and stretched to their height with its text pinned to the top.
Center the row's items and make the pill an inline-flex that centers its
own label.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Upstream's DashboardController has no DashboardLayoutService dependency
(a fork-only feature), so the new quick-look tests construct it with the
upstream 11-arg signature.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…watchlist

Fold the Discovery (Explorer) modal's richer content into the global
quick-look so one modal serves the dashboard, top-bar search and (next)
the Explorer page — the maintainer's "one modal, more info, less code"
ask, reached by building on the more capable quick-look rather than the
page-bound Explorer modal (keeps library-aware Manage deep-links +
release-date chips).

- quickLookTmdb: extract cast/providers/trailer/imdb via new
  quickLookExtras() — zero extra API calls (data already in the
  append_to_response payload). Carries tmdbId/tmdbType/posterPath.
- _quicklook_body: cast strip, providers row, trailer embed, TMDb/IMDb
  links, watchlist button (all |default-guarded -> library items
  unchanged).
- _quicklook: global watchlist index bootstrap + delegated toggle;
  a MutationObserver reflects state onto the button on each fragment
  load (no per-call-site wiring).
- i18n (en/fr) + CSS; test for cast/providers/trailer scoring + ids.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Slice 3 — repoint the Explorer/Discover page at the app-wide quick-look
and delete its bespoke ex-detail-modal (~270 lines of markup/CSS/JS), so
one modal serves dashboard, search and Explorer. This is the maintainer's
"one modal, more info, less code" ask, reached by enriching the quick-look
rather than adopting the page-bound Explorer modal.

To make that lossless, the quick-look now resolves the action model
server-side:
- quickLookTmdb cross-references the cached Radarr/Sonarr libraries
  (quickLookLibraryMatch) — in-library => Manage deep-link to the exact
  instance + status badge; otherwise the body renders an Add button.
  Fail-open: a library read error degrades to Add, never errors.
- _quicklook_body: Manage link vs Add button (data-ql-add).
- _quicklook: global [data-ql-add] handler resolves TMDb -> *arr then
  hands off to the shared quick-add picker (mirrors the old Explorer Add).
- base.html.twig: drop the now-redundant search decorateAction — the body
  is authoritative (also fixes online-in-library deep-links to the right
  instance instead of the default).
- explorer: card click opens window.prismarrQl; ex-detail-modal removed.
  Grid stars + filters + watchlist bootstrap kept.

Tests: in-library Manage deep-link + fail-open Add paths.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Clicking a title on the Plex Activity page or the dashboard Plex widget
now opens the same rich detail modal used everywhere else instead of
the bespoke Tautulli metadata pop-up.

The click first resolves the item's TMDb id server-side via the new
GET /tautulli/api/quicklook/{ratingKey} (TautulliClient::resolveTmdbId:
one get_metadata call; episodes/seasons resolve to their show via
grandparent_guids/parent_guids, with one metadata hop for older
Tautulli payloads that lack show-level guids). Only the numeric TMDb
id reaches the browser — raw Plex guids stay behind the existing
allow-list sanitization. On a hit, a hidden data-ql-trigger ghost
hands off to the existing global quick-look handler untouched; items
with no TMDb match (music, home videos) fall back to the legacy Plex
metadata modal, so every click keeps working.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ndandan added a commit to ndandan/Prismarr that referenced this pull request Jul 6, 2026
…ests, SABnzbd, Plex activity, Prowlarr), add Deluge coverage, update pending-PR list (Shoshuo#74/Shoshuo#75/Shoshuo#76)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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