diff --git a/db/crud.py b/db/crud.py index 5a00138..beaf5e0 100644 --- a/db/crud.py +++ b/db/crud.py @@ -809,6 +809,8 @@ async def get_tv_meta(meta_id: str): async def get_existing_metadata( metadata: dict, model: Type[MediaFusionMovieMetaData | MediaFusionSeriesMetaData] ) -> Optional[MediaFusionMovieMetaData | MediaFusionSeriesMetaData]: + if metadata.get("id"): + return await model.get(metadata["id"]) title = metadata["title"] year = metadata.get("year") if isinstance(year, str): @@ -1590,6 +1592,11 @@ async def update_metadata(imdb_ids: list[str], metadata_type: str): ) # Get existing metadata to preserve values existing_metadata = await meta_class.get(meta_id) + if not existing_metadata: + logging.warning( + f"Metadata not found for {metadata_type} {meta_id}. Skipping update." + ) + continue # Merge new data with existing data, preserving existing values when new ones are None/empty update_data = { diff --git a/resources/css/styles.css b/resources/css/styles.css index 8881a94..c95904a 100644 --- a/resources/css/styles.css +++ b/resources/css/styles.css @@ -11,6 +11,7 @@ body, html { background-position: center center; background-repeat: no-repeat; } + .mode-switch { background: rgba(20, 20, 35, 0.7); padding: 1.5rem; @@ -51,16 +52,19 @@ body, html { background: rgba(74, 71, 163, 0.4); transform: translateY(-2px); } + .mode-btn:focus-visible { outline: 2px solid #fff; outline-offset: 2px; } + .mode-btn[aria-pressed="true"] { background: #4a47a3; color: white; border-color: #4a47a3; box-shadow: 0 4px 12px rgba(74, 71, 163, 0.3); } + .mode-btn.active { background: #4a47a3; color: white; @@ -100,18 +104,136 @@ body, html { } .section-container { - margin-bottom: 1rem; - padding: 1rem; - background: rgba(0, 0, 0, 0.37); - border-radius: 8px; + padding: 1.5rem; + margin-bottom: 1.5rem; + background: rgba(20, 20, 35, 0.85); + border-radius: 12px; transition: margin-bottom 0.3s ease, padding 0.3s ease; } +.section-container .card { + background: rgba(30, 30, 50, 0.9); + border: 1px solid rgba(74, 71, 163, 0.3); + margin-bottom: 1.5rem; +} + +.section-container .card-header { + background: rgba(74, 71, 163, 0.2); + border-bottom: 1px solid rgba(74, 71, 163, 0.3); + padding: 1rem 1.5rem; +} + +.section-container .card-header h5 { + color: #ffffff; /* Bright white for headers */ + font-weight: 500; + margin: 0; +} + +.section-container .card-body { + padding: 1.5rem; +} + .section-header { color: #E0E0E0; margin-bottom: 0.5rem; } +.list-group-item-action { + transition: all 0.2s ease; + border: 1px solid rgba(74, 71, 163, 0.2); + background: rgba(30, 30, 50, 0.95); /* Slightly more opaque */ + color: #ffffff; /* Bright white for main text */ +} + +.list-group-item-action:hover { + transform: translateY(-2px); + border-color: rgba(74, 71, 163, 0.4); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); + background: rgba(40, 40, 60, 0.98); /* Even more opaque on hover */ +} + +/* Title and year */ +.list-group-item h5 { + color: #ffffff; + font-weight: 500; +} + +.list-group-item h5 .text-muted { + color: #bdbdbd !important; /* Lighter gray for year */ +} + +/* Description and other text */ +.list-group-item .text-muted { + color: #bdbdbd !important; /* Lighter gray for better readability */ +} + +/* Meta information */ +.list-group-item .small, +.list-group-item small { + color: #e0e0e0; /* Light gray for small text */ +} + +/* Genre badges */ +.badge.bg-primary { + background-color: rgba(74, 71, 163, 0.3) !important; + color: #ffffff !important; + border: 1px solid rgba(74, 71, 163, 0.5); +} + +/* Icons */ +.list-group-item i { + color: #4a47a3; /* Accent color for icons */ +} + +/* Rating */ +.badge.bg-secondary { + background-color: rgba(158, 158, 158, 0.3) !important; + color: #e0e0e0 !important; +} + +/* Meta sections */ +.list-group-item .d-flex.align-items-center { + color: #e0e0e0; /* Light gray for meta information */ +} + +/* Content type labels (Comedy, Romance, etc.) */ +.genre-tag { + background: rgba(74, 71, 163, 0.2); + color: #ffffff; + padding: 0.25rem 0.75rem; + border-radius: 4px; + font-size: 0.9rem; + margin-right: 0.5rem; + border: 1px solid rgba(74, 71, 163, 0.3); +} + +/* IMDb rating */ +.text-warning { + color: #ffd700 !important; /* Brighter yellow for rating stars */ +} + +.list-group-item img { + transition: transform 0.2s ease; +} + +.list-group-item:hover img { + transform: scale(1.05); +} + +.badge { + font-weight: 500; + padding: 0.5em 0.8em; +} + +.gap-2 { + gap: 0.5rem !important; +} + +.gap-3 { + gap: 1rem !important; +} + + .section-divider { border: 0; height: 2px; @@ -126,12 +248,14 @@ body, html { transform: translateY(-10px); transition: all 0.3s ease-in-out; } + @media (prefers-reduced-motion: reduce) { .pro-mode-section { transform: none; transition: opacity 0.3s ease-in-out; } } + .pro-mode-section[style*="display: block"] { opacity: 1; transform: translateY(0); @@ -220,6 +344,7 @@ input[type="text"]:focus, input[type="password"]:focus, select.form-control:focu display: block; align-items: center; border: 2px solid transparent; + margin-top: 1rem; margin-bottom: 0.5rem; padding: 0.2rem; border-radius: 5px; @@ -250,6 +375,7 @@ input[type="text"]:focus, input[type="password"]:focus, select.form-control:focu display: flex; align-items: center; gap: 1rem; + color: #e0e0e0; min-height: 36px; /* Minimum touch target size */ } @@ -257,6 +383,11 @@ input[type="text"]:focus, input[type="password"]:focus, select.form-control:focu content: none; /* Remove the round indicator */ } +.form-check-input:checked { + background-color: #4a47a3; + border-color: #4a47a3; +} + .form-check-input:checked + .form-check-label { background: #4a47a3; border-color: #4a47a3; @@ -274,6 +405,10 @@ input[type="text"]:focus, input[type="password"]:focus, select.form-control:focu color: white; } +.form-check-input:checked ~ .form-check-label { + color: #ffffff; +} + /* Style for disabled checkboxes */ .form-check.disabled-checkbox { opacity: 0.5; @@ -288,6 +423,11 @@ input[type="text"]:focus, input[type="password"]:focus, select.form-control:focu pointer-events: none; } +.form-label { + color: #e0e0e0; + font-weight: 500; + margin-bottom: 0.5rem; +} .form-control { display: block; @@ -307,6 +447,19 @@ input[type="text"]:focus, input[type="password"]:focus, select.form-control:focu transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out; } + +.form-control, .form-select { + background: rgba(255, 255, 255, 0.9); /* More opaque white background */ + border: 1px solid rgba(74, 71, 163, 0.3); + color: #000; /* Black text for better contrast */ +} + +.form-control:focus, .form-select:focus { + background: #ffffff; + border-color: #4a47a3; + box-shadow: 0 0 0 0.25rem rgba(74, 71, 163, 0.25); +} + /* Styling for the range slider */ .form-range { -webkit-appearance: none; /* Override default look for Chrome, Safari */ @@ -433,6 +586,12 @@ input[type="text"]:focus, input[type="password"]:focus, select.form-control:focu margin-bottom: 10px; } +.alert-info { + background: rgba(74, 71, 163, 0.15); + border-color: rgba(74, 71, 163, 0.3); + color: #e0e0e0; +} + .loading-overlay { position: fixed; top: 0; @@ -480,16 +639,16 @@ input[type="text"]:focus, input[type="password"]:focus, select.form-control:focu } .configured-field { - background-color: #f8f9fa; + background-color: #f8f9fa; } .reset-config-btn { - margin-left: 0.5rem; + margin-left: 0.5rem; } .input-group .reset-config-btn { - border-top-left-radius: 0; - border-bottom-left-radius: 0; + border-top-left-radius: 0; + border-bottom-left-radius: 0; } .sort-item { @@ -514,6 +673,183 @@ input[type="text"]:focus, input[type="password"]:focus, select.form-control:focu margin-bottom: 0.75rem; } +.advanced-toggle { + background: rgba(74, 71, 163, 0.15); + padding: 0.75rem 1rem; + border-radius: 8px; + border: 1px solid rgba(74, 71, 163, 0.2); + color: #e0e0e0; + cursor: pointer; + display: flex; + align-items: center; + gap: 0.5rem; + margin: 1rem 0; + transition: all 0.3s ease; +} + +.advanced-toggle:hover { + background: rgba(74, 71, 163, 0.25); +} + +.advanced-toggle i { + transition: transform 0.3s ease; + margin-right: 0.5rem; +} + +.advanced-toggle.active i { + transform: rotate(180deg); +} + +.advanced-section { + display: none; + opacity: 0; + transform: translateY(-10px); + transition: all 0.3s ease; +} + +.advanced-section.show { + display: block; + opacity: 1; + transform: translateY(0); +} + +.parsed-value { + color: #4a47a3; + font-size: 0.9rem; + margin-top: 0.25rem; +} + +.technical-specs-basic { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: 1rem; + margin-bottom: 1.5rem; +} + +.technical-specs-basic .spec-item { + background: rgba(74, 71, 163, 0.1); + padding: 0.75rem; + border-radius: 6px; + display: flex; + align-items: center; + gap: 0.5rem; +} + +.spec-item { + background: rgba(74, 71, 163, 0.15); + padding: 1rem; + border-radius: 8px; + border: 1px solid rgba(74, 71, 163, 0.2); +} + +.spec-item i { + color: #4a47a3; +} + + +.spec-label { + color: #e0e0e0; + font-size: 0.9rem; + margin-bottom: 0.25rem; +} + +.spec-value { + color: #ffffff; + font-weight: 500; +} + + +.not-available { + color: #6c757d; + font-style: italic; +} + +/* Catalog Section Styles */ +.catalogs-section { + border-top: 1px solid rgba(74, 71, 163, 0.2); + padding-top: 1.5rem; +} + +.section-title { + color: #4a47a3; + margin-bottom: 1rem; + font-weight: 500; +} + +.catalog-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); + gap: 1rem; + margin-top: 1rem; +} + +.catalog-item { + background: rgba(74, 71, 163, 0.1); + border-radius: 6px; + padding: 0.5rem; + transition: all 0.3s ease; +} + +.catalog-item:hover { + background: rgba(74, 71, 163, 0.2); + transform: translateY(-2px); +} + +.catalog-item .form-check { + margin: 0; + padding: 0.25rem; +} + +.catalog-group { + margin-bottom: 1.5rem; +} + +.catalog-group .alert { + margin-bottom: 1rem; + border-left: 4px solid #4a47a3; +} + + +/* Text utility classes for dark theme */ +.text-muted { + color: #9e9e9e !important; /* Lighter gray for better visibility */ +} + +/* Other text utility classes that might need adjustment */ +.text-secondary { + color: #b0b0b0 !important; +} + +.text-body-secondary { + color: #a0a0a0 !important; +} + +/* Form text and help text */ +.form-text { + color: #9e9e9e !important; +} + +/* Subtitle styling */ +.card-subtitle { + color: #b0b0b0 !important; +} + +/* Description text */ +.description-text { + color: #9e9e9e !important; +} + +/* Optional help text */ +small.text-muted, +.small.text-muted { + color: #9e9e9e !important; +} + +/* Alert text */ +.alert .text-muted { + color: #b0b0b0 !important; +} + @media (max-width: 576px) { .sort-direction-toggle { min-width: auto; diff --git a/resources/html/scraper.html b/resources/html/scraper.html index 0638c8c..ddc8a0e 100644 --- a/resources/html/scraper.html +++ b/resources/html/scraper.html @@ -109,49 +109,53 @@ - +