From 7b7ac6f179e265528ab024726dffcc6d899eef24 Mon Sep 17 00:00:00 2001 From: sbcrumb Date: Tue, 14 Oct 2025 15:27:40 -0400 Subject: [PATCH] fix: web interface improvments --- api/routes.py | 9 ++++ api/web_routes.py | 7 +++ static/index.html | 4 +- static/js/app.js | 109 +++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 120 insertions(+), 9 deletions(-) diff --git a/api/routes.py b/api/routes.py index 0c4d4e3..129d043 100644 --- a/api/routes.py +++ b/api/routes.py @@ -1068,6 +1068,15 @@ def register_routes(app, dependencies: dict): """Get available date options for an episode""" return await get_episode_date_options(dependencies, imdb_id, season, episode) + @app.get("/api/debug/movie/{imdb_id}/raw") + async def _debug_movie_raw(imdb_id: str): + """Debug endpoint to see raw movie database data""" + db = dependencies["db"] + movie = db.get_movie_dates(imdb_id) + if not movie: + raise HTTPException(status_code=404, detail="Movie not found") + return {"raw_data": dict(movie), "imdb_id": imdb_id} + # --------------------------- # Static Web Interface # --------------------------- diff --git a/api/web_routes.py b/api/web_routes.py index 270b810..cc7d5e9 100644 --- a/api/web_routes.py +++ b/api/web_routes.py @@ -449,6 +449,13 @@ async def get_movie_date_options(dependencies: dict, imdb_id: str): if not movie: raise HTTPException(status_code=404, detail="Movie not found") + # Debug logging to understand the data issue + print(f"🔍 DEBUG: Movie data for {imdb_id}:") + print(f" - released: {movie.get('released')}") + print(f" - dateadded: {movie.get('dateadded')}") + print(f" - source: {movie.get('source')}") + print(f" - path: {movie.get('path')}") + options = [] # Option 1: Current dateadded (if exists and is different from released) diff --git a/static/index.html b/static/index.html index 0611250..9781be1 100644 --- a/static/index.html +++ b/static/index.html @@ -133,8 +133,8 @@ Title IMDb ID - Released - Date Added + Movie Released + Date Added to Library Source Date Type Video File diff --git a/static/js/app.js b/static/js/app.js index 167aa93..19ea468 100644 --- a/static/js/app.js +++ b/static/js/app.js @@ -245,6 +245,9 @@ function updateMoviesTable(data) { + `; @@ -591,7 +594,13 @@ function closeSmartFixModal() { } async function applySmartFix(mediaType, options) { - const selectedIndex = document.querySelector('input[name="date-option"]:checked').value; + const selectedRadio = document.querySelector('input[name="date-option"]:checked'); + if (!selectedRadio) { + showToast('Please select a date option', 'warning'); + return; + } + + const selectedIndex = selectedRadio.value; const selectedOption = options.options[selectedIndex]; let dateadded = selectedOption.date; @@ -601,11 +610,37 @@ async function applySmartFix(mediaType, options) { if (selectedOption.type === 'manual') { const manualDateInput = document.getElementById(`manual-date-${selectedIndex}`); if (manualDateInput && manualDateInput.value) { - dateadded = new Date(manualDateInput.value).toISOString(); + try { + dateadded = new Date(manualDateInput.value).toISOString(); + } catch (e) { + showToast('Invalid date format', 'error'); + return; + } } else { showToast('Please enter a date for manual option', 'warning'); return; } + } else if (dateadded) { + // Fix date format for non-manual options + try { + let dateValue = dateadded; + + // Handle timezone offsets + if (dateValue.includes('+00:00')) { + dateValue = dateValue.replace('+00:00', 'Z'); + } + + const date = new Date(dateValue); + if (isNaN(date.getTime())) { + showToast('Invalid date from server', 'error'); + return; + } + dateadded = date.toISOString(); + } catch (e) { + console.error('Date conversion error:', e, dateadded); + showToast('Date conversion error', 'error'); + return; + } } try { @@ -617,6 +652,7 @@ async function applySmartFix(mediaType, options) { closeSmartFixModal(); } catch (error) { console.error('Smart fix failed:', error); + showToast('Smart fix failed: ' + error.message, 'error'); } } @@ -832,11 +868,26 @@ function updateEditDateFromOption(optionIndex, option) { const sourceSelect = document.getElementById('edit-source'); if (option.date) { - // Convert to datetime-local format + // Convert to datetime-local format with better date parsing try { - const date = new Date(option.date); - dateInput.value = date.toISOString().slice(0, 16); + let dateValue = option.date; + + // Handle timezone offsets by converting to local time + if (dateValue.includes('+00:00') || dateValue.includes('Z')) { + dateValue = dateValue.replace('+00:00', 'Z'); + } + + const date = new Date(dateValue); + if (isNaN(date.getTime())) { + console.error('Invalid date:', dateValue); + dateInput.value = ''; + } else { + // Convert to local datetime-local format + const localDateTime = new Date(date.getTime() - (date.getTimezoneOffset() * 60000)); + dateInput.value = localDateTime.toISOString().slice(0, 16); + } } catch (e) { + console.error('Date parsing error:', e, option.date); dateInput.value = ''; } } else { @@ -857,8 +908,19 @@ async function handleEnhancedEditSubmit(event) { const dateadded = document.getElementById('edit-dateadded').value; const source = document.getElementById('edit-source').value; - // Convert datetime-local to ISO string - const isoDateadded = dateadded ? new Date(dateadded).toISOString() : null; + if (!dateadded) { + showToast('Please enter a date', 'warning'); + return; + } + + // Convert datetime-local to ISO string with error handling + let isoDateadded = null; + try { + isoDateadded = new Date(dateadded).toISOString(); + } catch (e) { + showToast('Invalid date format', 'error'); + return; + } try { if (mediaType === 'movie') { @@ -870,6 +932,7 @@ async function handleEnhancedEditSubmit(event) { closeModal(); } catch (error) { console.error('Enhanced edit failed:', error); + showToast('Update failed: ' + error.message, 'error'); } } @@ -1024,4 +1087,36 @@ function showToast(message, type = 'info') { toast.parentNode.removeChild(toast); } }); +} + +// Debug function +async function debugMovie(imdbId) { + try { + const data = await apiCall(`/api/debug/movie/${imdbId}/raw`); + + const debugInfo = ` +DEBUG INFO for ${imdbId}: + +Raw Database Data: +- imdb_id: ${data.raw_data.imdb_id} +- path: ${data.raw_data.path} +- released: ${data.raw_data.released} +- dateadded: ${data.raw_data.dateadded} +- source: ${data.raw_data.source} +- has_video_file: ${data.raw_data.has_video_file} +- last_updated: ${data.raw_data.last_updated} + +Analysis: +- Movie Released: ${data.raw_data.released || 'Not set'} +- Library Import Date: ${data.raw_data.dateadded || 'Not set'} +- Date Source: ${data.raw_data.source || 'Unknown'} + `; + + alert(debugInfo); + console.log('🔍 Debug data for', imdbId, data); + + } catch (error) { + console.error('Debug failed:', error); + showToast('Debug failed: ' + error.message, 'error'); + } } \ No newline at end of file