This commit is contained in:
+7
-3
@@ -177,8 +177,8 @@ async def get_tv_series_list(dependencies: dict,
|
||||
db = dependencies["db"]
|
||||
|
||||
# Validate date_filter values
|
||||
if date_filter and date_filter not in ['complete', 'incomplete', 'none']:
|
||||
raise HTTPException(status_code=422, detail=f"Invalid date_filter: must be 'complete', 'incomplete', or 'none', got '{date_filter}'")
|
||||
if date_filter and date_filter not in ['complete', 'incomplete', 'none', 'skipped']:
|
||||
raise HTTPException(status_code=422, detail=f"Invalid date_filter: must be 'complete', 'incomplete', 'none', or 'skipped', got '{date_filter}'")
|
||||
|
||||
with db.get_connection() as conn:
|
||||
cursor = conn.cursor()
|
||||
@@ -211,6 +211,9 @@ async def get_tv_series_list(dependencies: dict,
|
||||
elif date_filter == "none":
|
||||
# No episodes have dates
|
||||
having_conditions.append("COUNT(e.episode) > 0 AND COUNT(CASE WHEN e.dateadded IS NOT NULL THEN 1 END) = 0")
|
||||
elif date_filter == "skipped":
|
||||
# Has skipped episodes
|
||||
having_conditions.append("COUNT(CASE WHEN e.skipped = TRUE THEN 1 END) > 0")
|
||||
|
||||
where_clause = " AND ".join(where_conditions) if where_conditions else "1=1"
|
||||
having_clause = " AND ".join(having_conditions) if having_conditions else ""
|
||||
@@ -248,7 +251,8 @@ async def get_tv_series_list(dependencies: dict,
|
||||
s.last_updated,
|
||||
COUNT(e.episode) as total_episodes,
|
||||
COUNT(CASE WHEN e.dateadded IS NOT NULL THEN 1 END) as episodes_with_dates,
|
||||
COUNT(CASE WHEN e.has_video_file = TRUE THEN 1 END) as episodes_with_video
|
||||
COUNT(CASE WHEN e.has_video_file = TRUE THEN 1 END) as episodes_with_video,
|
||||
COUNT(CASE WHEN e.skipped = TRUE THEN 1 END) as episodes_skipped
|
||||
FROM series s
|
||||
LEFT JOIN episodes e ON s.imdb_id = e.imdb_id
|
||||
WHERE {where_clause}
|
||||
|
||||
@@ -261,14 +261,16 @@ class DatabasePopulator:
|
||||
for series in all_series:
|
||||
try:
|
||||
imdb_id = series.get('imdbId')
|
||||
if not imdb_id:
|
||||
_log("DEBUG", f"Skipping series without IMDb ID: {series.get('title')}")
|
||||
continue
|
||||
|
||||
series_id = series.get('id')
|
||||
series_path = series.get('path', '')
|
||||
series_title = series.get('title', 'Unknown')
|
||||
|
||||
if not imdb_id:
|
||||
# Generate placeholder IMDb ID using hash of path
|
||||
path_hash = hashlib.md5(series_path.encode()).hexdigest()[:12]
|
||||
imdb_id = f"missing-{path_hash}"
|
||||
_log("DEBUG", f"Series without IMDb ID: {series_title} (path: {series_path}), using placeholder {imdb_id}")
|
||||
|
||||
# Update series record
|
||||
self.db.upsert_series(imdb_id, series_path)
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>NFOGuard - Database Management</title>
|
||||
<link rel="stylesheet" href="/static/css/styles.css?v=2.10.0-skipped-tracking-fix3">
|
||||
<link rel="stylesheet" href="/static/css/styles.css?v=2.10.0-skipped-tracking-v5">
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
@@ -12,7 +12,7 @@
|
||||
<!-- Header -->
|
||||
<header class="app-header">
|
||||
<div class="header-content">
|
||||
<h1><i class="fas fa-shield-alt"></i> NFOGuard <span style="font-size: 0.5em; color: #888;">v2.10.0-skipped-tracking-fix3</span></h1>
|
||||
<h1><i class="fas fa-shield-alt"></i> NFOGuard <span style="font-size: 0.5em; color: #888;">v2.10.0-skipped-tracking-v5</span></h1>
|
||||
<p>Database Management & Reporting</p>
|
||||
</div>
|
||||
<div class="auth-status" id="auth-status" style="display: none;">
|
||||
@@ -210,6 +210,7 @@
|
||||
<option value="complete">Fully Dated</option>
|
||||
<option value="incomplete">Missing Dates</option>
|
||||
<option value="none">No Dates</option>
|
||||
<option value="skipped">Skipped</option>
|
||||
</select>
|
||||
<select id="series-filter-source">
|
||||
<option value="">All Sources</option>
|
||||
@@ -240,6 +241,9 @@
|
||||
<th class="sortable" onclick="sortTable('series-tbody', 4, 'number')" style="cursor: pointer;">
|
||||
With Video <i class="fas fa-sort"></i>
|
||||
</th>
|
||||
<th class="sortable" onclick="sortTable('series-tbody', 5, 'number')" style="cursor: pointer;">
|
||||
Skipped <i class="fas fa-sort"></i>
|
||||
</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -723,6 +727,6 @@
|
||||
<!-- Toast Notifications -->
|
||||
<div class="toast-container" id="toast-container"></div>
|
||||
|
||||
<script src="/static/js/app.js?v=2.10.0-skipped-tracking-fix3"></script>
|
||||
<script src="/static/js/app.js?v=2.10.0-skipped-tracking-v5"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -467,7 +467,7 @@ function updateSeriesTable(data) {
|
||||
const tbody = document.getElementById('series-tbody');
|
||||
|
||||
if (!data.series || data.series.length === 0) {
|
||||
tbody.innerHTML = '<tr><td colspan="6" class="text-center">No series found</td></tr>';
|
||||
tbody.innerHTML = '<tr><td colspan="7" class="text-center">No series found</td></tr>';
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -485,6 +485,7 @@ function updateSeriesTable(data) {
|
||||
<small class="text-muted">(${progressPercent}%)</small>
|
||||
</td>
|
||||
<td>${series.episodes_with_video}</td>
|
||||
<td>${series.episodes_skipped || 0}</td>
|
||||
<td>
|
||||
<button class="btn btn-sm btn-primary" onclick="viewSeriesEpisodes('${series.imdb_id}')">
|
||||
<i class="fas fa-list"></i> Episodes
|
||||
|
||||
Reference in New Issue
Block a user