From 69d445013a7a20b40ced23e722bfd602eb4ea491 Mon Sep 17 00:00:00 2001 From: nmemmert Date: Mon, 12 Oct 2026 10:34:44 -0400 Subject: [PATCH] Podcast workflow: Finished seasons section grouping fully released seasons; v2.18.0 Co-Authored-By: Claude Sonnet 5.5 --- package-lock.json | 4 ++-- package.json | 2 +- src/AdminPage.tsx | 28 +++++++++++++++++++++++++++- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7f269f5..a88df13 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "siteforge", - "version": "2.17.3", + "version": "2.18.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "siteforge", - "version": "2.17.3", + "version": "2.18.0", "dependencies": { "@aws-sdk/client-s3": "^3.1135.0", "@dnd-kit/core": "^6.3.1", diff --git a/package.json b/package.json index fda0376..0dd6462 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "siteforge", "private": true, - "version": "2.17.3", + "version": "2.18.0", "type": "module", "scripts": { "dev": "vite", diff --git a/src/AdminPage.tsx b/src/AdminPage.tsx index 29f5cd7..835a269 100644 --- a/src/AdminPage.tsx +++ b/src/AdminPage.tsx @@ -1875,7 +1875,17 @@ function PodcastWorkflowAdmin({ laneA, laneB }: { laneA: { title: string }; lane const hasOther = items.some(i => i.lane === 'other') const inLane = items.filter(i => i.lane === lane) const upcoming = inLane.filter(i => !i.released) - const released = inLane.filter(i => i.released) + // A season is finished once none of its episodes are still in progress. Only the "Other seasons" + // tab groups these away; a lane's own season is always shown as current. + const seasonGroups = new Map() + if (lane === 'other') { + for (const i of inLane) seasonGroups.set(i.season, [...(seasonGroups.get(i.season) ?? []), i]) + } + const finishedSeasons = [...seasonGroups.entries()] + .filter(([, eps]) => eps.every(e => e.released)) + .sort(([a], [b]) => (Number(b) || 0) - (Number(a) || 0)) + const finishedKeys = new Set(finishedSeasons.flatMap(([, eps]) => eps.map(e => e.key))) + const released = inLane.filter(i => i.released && !finishedKeys.has(i.key)) const selected = items.find(i => i.key === selectedKey) ?? null const save = async (key: string, patch: Record) => { @@ -2024,6 +2034,22 @@ function PodcastWorkflowAdmin({ laneA, laneB }: { laneA: { title: string }; lane setShowReleased(e.target.checked)} /> Show released ({released.length}) {showReleased && released.map(row)} + {finishedSeasons.length > 0 && ( +
+ Finished seasons + {finishedSeasons.map(([season, eps]) => { + const last = eps.map(e => e.releaseDate ?? '').sort().pop() + return ( +
+ + {season ? `Season ${season}` : 'No season number'} — {eps.length} episode{eps.length === 1 ? '' : 's'}{last ? ` · last released ${last}` : ''} + + {eps.map(row)} +
+ ) + })} +
+ )}