Track repair collection cycles and reconcile request availability
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
- Keep primary actions, secondary controls and destructive actions visually distinct. Do not fade or uppercase every span inside a button: cards also use buttons, often with nested text.
|
||||
- Keep technical IDs and pipeline labels monospace. Use sentence case for ordinary labels and descriptions.
|
||||
- Preserve the six-stage request pipeline: three columns on desktop, two on tablet, one on narrow screens. Issue reports remain a right-hand column on desktop and stack on smaller screens.
|
||||
- A media repair starts a new collection cycle: preserve Requested/Approved and unaffected TV episodes, but do not reuse an old torrent or Jellyfin entry to mark the replacement ready. Show Pending → Downloading → Indexing → Available from collector/file evidence. Subtitle-only repairs must not reset video availability.
|
||||
- Desktop navigation stays at the top; mobile navigation stays at the bottom. Dialogs must remain clear of both.
|
||||
- The guided issue form uses `portal/IssueFlowStep.tsx`: show one expanded step, collapse completed answers into Change rows, and keep repairs behind the final submit action. Movies use the selected title's managed file directly; only TV needs a season/episode picker. Multi-select controls must expose `aria-pressed` and a visible selected state.
|
||||
|
||||
@@ -17,6 +18,7 @@ Build the frontend before reviewing. The scripts in `scripts/` run using Node an
|
||||
- `review_layout_ui.cjs`: page alignment, consistent headings, overflow, redirects, pipeline layout, invite tabs, and fixture-only recovery forms.
|
||||
- `review_account_ui.cjs`: fixture-only login and profile interaction checks.
|
||||
- `review_issue_flow_ui.cjs`: fixture-only movie/TV issue flow, multi-device report payloads, subtitle routing, permissions, and collapsed-step navigation.
|
||||
- `review_repair_pipeline_ui.cjs`: fixture-only movie/TV replacement stages, old-cycle progress rejection, desktop/mobile layout and automatic availability transitions.
|
||||
- `review_settings_ui.cjs`: settings state, region-only saves, secret preservation, responsive controls and issue dialog placement.
|
||||
|
||||
The layout/settings reviews accept `REVIEW_BASE`, `REVIEW_LIVE_BASE`, `REVIEW_PLAYWRIGHT`, and `REVIEW_DIR`. Provide an authorised short-lived session through `REVIEW_SESSION` as `{ "name": "cookie-name", "token": "..." }` in the process environment, never in a committed file. Live writes are blocked; submission checks use fixtures. Screenshots may contain account information and must stay outside the repository.
|
||||
|
||||
@@ -68,6 +68,7 @@ type Snapshot = {
|
||||
actions: RequestAction[]
|
||||
artwork?: { poster_url?: string; backdrop_url?: string }
|
||||
presentation?: {
|
||||
repairCycle?: string | null
|
||||
status?: { label?: string; meaning?: string }
|
||||
download?: {
|
||||
visible?: boolean
|
||||
@@ -121,6 +122,8 @@ type ActionHistory = {
|
||||
}
|
||||
|
||||
type LiveDownloadProgress = {
|
||||
repairCycle?: string | null
|
||||
visible?: boolean
|
||||
request_id: string
|
||||
state: string
|
||||
summary: string
|
||||
@@ -205,15 +208,20 @@ const formatDuration = (duration?: number | null) => {
|
||||
|
||||
const mergeLiveDownload = (current: Snapshot, live: LiveDownloadProgress): Snapshot => {
|
||||
if (String(current.request_id) !== String(live.request_id)) return current
|
||||
if ((current.presentation?.repairCycle ?? null) !== (live.repairCycle ?? null)) return current
|
||||
if (['COMPLETED', 'AVAILABLE'].includes(current.state)) return current
|
||||
const downloadStage = current.presentation?.pipeline?.find((stage) => stage.id === 'download')
|
||||
if (downloadStage?.state === 'complete' && downloadStage.visible === false) return current
|
||||
const visible = live.visible ?? live.state !== 'not_started'
|
||||
const stageState = live.state === 'completed'
|
||||
? 'complete'
|
||||
: ['missing', 'error'].includes(live.state)
|
||||
? 'attention'
|
||||
: 'active'
|
||||
: live.state === 'not_started' ? 'waiting' : 'active'
|
||||
const presentation = current.presentation ?? {}
|
||||
const pipeline = (presentation.pipeline ?? fallbackPipeline(current)).map((stage) =>
|
||||
stage.id === 'download'
|
||||
? { ...stage, state: stageState, summary: live.summary, visible: true, torrents: live.torrents }
|
||||
? { ...stage, state: stageState, stateLabel: undefined, summary: live.summary, visible, torrents: live.torrents }
|
||||
: stage
|
||||
)
|
||||
return {
|
||||
@@ -222,7 +230,7 @@ const mergeLiveDownload = (current: Snapshot, live: LiveDownloadProgress): Snaps
|
||||
...presentation,
|
||||
download: {
|
||||
...(presentation.download ?? {}),
|
||||
visible: true,
|
||||
visible,
|
||||
state: live.state,
|
||||
summary: live.summary,
|
||||
torrents: live.torrents,
|
||||
|
||||
Reference in New Issue
Block a user