Episode highlights per series: tag by lane, group on Episodes page, move to Finished Book when series ends; v2.9.1
Publish Container / build (push) Successful in 15m21s
Publish Container / build (push) Successful in 15m21s
- Highlights get a Series field (Lane A / Lane B / General); legacy highlights count as Lane A - Episodes page groups highlights under each series' title - Ending a series (scheduled or manual) moves only that series' highlights onto its Finished Book page; other lane and General stay - Archived highlights keep working: detail pages, sitemap, scripture index and search include them Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ddcaec0ddf
commit
652b003bd9
9 files changed
+133
-57
No files matched your search
@@ -141,6 +141,7 @@ export function sanitizeFeaturedLinks(value) {
|
||||
|
||||
return {
|
||||
id: typeof item.id === 'string' && item.id.trim() ? item.id.trim() : randomUUID(),
|
||||
lane: item.lane === 'second' || item.lane === 'general' ? item.lane : 'primary',
|
||||
title: typeof item.title === 'string' ? item.title.trim().slice(0, 140) : '',
|
||||
episodeNumber: typeof item.episodeNumber === 'string' ? item.episodeNumber.trim().slice(0, 20) : '',
|
||||
summary: typeof item.summary === 'string' ? item.summary.trim().slice(0, 600) : '',
|
||||
|
||||
@@ -82,6 +82,12 @@ function applySeriesTransition(content, sched, lane = 'primary') {
|
||||
const newSeason = Number.isInteger(sched.newSeason) ? sched.newSeason : undefined
|
||||
const newStudySlug = typeof sched.newStudySlug === 'string' ? sched.newStudySlug.trim().toLowerCase() : ''
|
||||
|
||||
// Highlights for the ending series move onto its Finished Book; the other lane's and general ones stay.
|
||||
const allHighlights = Array.isArray(content.podcastFeaturedLinks) ? content.podcastFeaturedLinks : []
|
||||
const isThisLane = link => (link.lane === 'second' ? 'second' : link.lane === 'general' ? 'general' : 'primary') === lane
|
||||
const endingHighlights = current.title.trim() ? allHighlights.filter(isThisLane) : []
|
||||
const keptHighlights = current.title.trim() ? allHighlights.filter(link => !isThisLane(link)) : allHighlights
|
||||
|
||||
const archivedBook = current.title.trim()
|
||||
? {
|
||||
id: Date.now().toString(36),
|
||||
@@ -90,6 +96,7 @@ function applySeriesTransition(content, sched, lane = 'primary') {
|
||||
imageUrl: current.imageUrl,
|
||||
season: current.season ?? ((newSeason ?? 2) - 1 || 1),
|
||||
...(current.studySlug ? { studySlug: current.studySlug } : {}),
|
||||
...(endingHighlights.length > 0 ? { highlights: endingHighlights.map(({ lane: _lane, ...link }) => link) } : {}),
|
||||
}
|
||||
: null
|
||||
|
||||
@@ -126,10 +133,6 @@ function applySeriesTransition(content, sched, lane = 'primary') {
|
||||
return study
|
||||
})
|
||||
|
||||
const hasOtherLane = lane === 'second'
|
||||
? Boolean(content.seriesTitle?.trim())
|
||||
: Boolean(content.secondSeries?.title?.trim())
|
||||
|
||||
const lanePatch = lane === 'second'
|
||||
? {
|
||||
secondSeries: {
|
||||
@@ -155,8 +158,7 @@ function applySeriesTransition(content, sched, lane = 'primary') {
|
||||
...content,
|
||||
...lanePatch,
|
||||
studies,
|
||||
// Highlights belong to whatever is playing now; don't wipe them while the other lane is still running.
|
||||
podcastFeaturedLinks: hasOtherLane ? content.podcastFeaturedLinks : [],
|
||||
podcastFeaturedLinks: keptHighlights,
|
||||
finishedBooks: [...(Array.isArray(content.finishedBooks) ? content.finishedBooks : []), ...(archivedBook ? [archivedBook] : [])],
|
||||
...patch,
|
||||
})
|
||||
|
||||
@@ -102,7 +102,10 @@ export function register(app) {
|
||||
}
|
||||
}
|
||||
// Dynamic episode highlight URLs
|
||||
const highlights = Array.isArray(state.cachedSiteContent?.podcastFeaturedLinks) ? state.cachedSiteContent.podcastFeaturedLinks : []
|
||||
const highlights = [
|
||||
...(Array.isArray(state.cachedSiteContent?.podcastFeaturedLinks) ? state.cachedSiteContent.podcastFeaturedLinks : []),
|
||||
...(Array.isArray(state.cachedSiteContent?.finishedBooks) ? state.cachedSiteContent.finishedBooks.flatMap(book => (Array.isArray(book?.highlights) ? book.highlights : [])) : []),
|
||||
]
|
||||
for (const ep of highlights) {
|
||||
if (ep.id) urls.push(`${root}/episodes/${encodeURIComponent(ep.id)}`)
|
||||
}
|
||||
@@ -195,7 +198,10 @@ export function register(app) {
|
||||
app.get('/api/public/scripture-index', async (_req, res) => {
|
||||
const content = state.cachedSiteContent
|
||||
const allStudies = Array.isArray(content?.studies) ? content.studies : []
|
||||
const allEpisodes = Array.isArray(content?.podcastFeaturedLinks) ? content.podcastFeaturedLinks : []
|
||||
const allEpisodes = [
|
||||
...(Array.isArray(content?.podcastFeaturedLinks) ? content.podcastFeaturedLinks : []),
|
||||
...(Array.isArray(content?.finishedBooks) ? content.finishedBooks.flatMap(book => (Array.isArray(book?.highlights) ? book.highlights : [])) : []),
|
||||
]
|
||||
const cutoff = new Date()
|
||||
const entries = []
|
||||
|
||||
|
||||
Reference in new issue
Block a user