fix search/filter bugs in game and TV libraries
- Game series: filter now checks child games for both search and tag matches instead of always passing series through - TV episodes: tag selector no longer closes after picking a tag - TV episodes: filter panel now filters episodes within a season view - TV series list: series now appear when any of their episodes match the active tag filter (via new /api/tv/series-episode-tags endpoint backed by media_items) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -215,6 +215,42 @@ export function getTagAssignmentsForLibrary(libraryId: string): Record<string, s
|
||||
return result
|
||||
}
|
||||
|
||||
// Returns seriesId -> tagIds[] aggregated from all episodes in each series.
|
||||
// Requires media_items to be populated by the scanner. Returns {} if not yet scanned.
|
||||
export function getSeriesEpisodeTagMap(libraryId: string): Record<string, string[]> {
|
||||
const db = getDb()
|
||||
const prefix = `${libraryId}:tv_episode:`
|
||||
const episodes = db
|
||||
.prepare('SELECT item_key FROM media_items WHERE library_id = ? AND item_type = ?')
|
||||
.all(libraryId, 'tv_episode') as { item_key: string }[]
|
||||
if (episodes.length === 0) return {}
|
||||
|
||||
const tagRows = db
|
||||
.prepare('SELECT media_key, tag_id FROM media_tags WHERE media_key LIKE ?')
|
||||
.all(`${libraryId}:%`) as { media_key: string; tag_id: string }[]
|
||||
const tagsByMediaKey: Record<string, string[]> = {}
|
||||
for (const row of tagRows) {
|
||||
;(tagsByMediaKey[row.media_key] ??= []).push(row.tag_id)
|
||||
}
|
||||
|
||||
const result: Record<string, string[]> = {}
|
||||
for (const { item_key } of episodes) {
|
||||
if (!item_key.startsWith(prefix)) continue
|
||||
// item_key: "libraryId:tv_episode:seriesId:seasonId:episodeId"
|
||||
const parts = item_key.split(':')
|
||||
if (parts.length < 5) continue
|
||||
const seriesId = parts[2]
|
||||
const episodeId = parts[parts.length - 1]
|
||||
const episodeTags = tagsByMediaKey[`${libraryId}:${episodeId}`]
|
||||
if (!episodeTags) continue
|
||||
const seriesTags = (result[seriesId] ??= [])
|
||||
for (const tagId of episodeTags) {
|
||||
if (!seriesTags.includes(tagId)) seriesTags.push(tagId)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
export function removeAllAssignmentsForLibrary(libraryId: string): void {
|
||||
const db = getDb()
|
||||
db.prepare("DELETE FROM media_tags WHERE media_key LIKE ?").run(`${libraryId}:%`)
|
||||
|
||||
Reference in New Issue
Block a user