- Import-Jobs koennen geloescht werden (Uebersicht + Preview) - TVDB-Validierung als Pflicht: Ohne Match wird Item als 'pending' markiert - Erkennung von "Staffel X" / "Season X" Ordnernamen fuer Serien-Zuordnung - Verhindert Ghost-Serien durch Scene-Release-Prefixes (z.B. jajunge-24) - Import-Button gesperrt solange nicht alle Items zugeordnet sind - Favicon in base.html eingebunden Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
546 lines
26 KiB
HTML
546 lines
26 KiB
HTML
{% extends "base.html" %}
|
|
|
|
{% block title %}Bibliothek - VideoKonverter{% endblock %}
|
|
|
|
{% block content %}
|
|
<section class="library-section">
|
|
<div class="library-header">
|
|
<h2>Video-Bibliothek</h2>
|
|
<div class="library-actions">
|
|
<button class="btn-primary" onclick="startScan()">Scan starten</button>
|
|
<button class="btn-secondary" onclick="openPathsModal()">Pfade verwalten</button>
|
|
<button class="btn-secondary" onclick="openCleanModal()">Aufraeumen</button>
|
|
<button class="btn-secondary" onclick="openImportModal()">Importieren</button>
|
|
<button class="btn-secondary" onclick="showDuplicates()">Duplikate</button>
|
|
<button class="btn-secondary" onclick="startAutoMatch()">TVDB Auto-Match</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Scan-Progress -->
|
|
<div id="scan-progress" class="scan-progress" style="display:none">
|
|
<div class="progress-container">
|
|
<div class="progress-bar" id="scan-bar"></div>
|
|
</div>
|
|
<span class="scan-status" id="scan-status">Scanne...</span>
|
|
</div>
|
|
|
|
<!-- Auto-Match Progress -->
|
|
<div id="auto-match-progress" class="scan-progress" style="display:none">
|
|
<div class="progress-container">
|
|
<div class="progress-bar" id="auto-match-bar"></div>
|
|
</div>
|
|
<span class="scan-status" id="auto-match-status">TVDB Auto-Match...</span>
|
|
</div>
|
|
|
|
<!-- Statistik-Leiste -->
|
|
<div class="library-stats" id="library-stats">
|
|
<div class="lib-stat"><span class="lib-stat-value" id="stat-videos">-</span><span class="lib-stat-label">Videos</span></div>
|
|
<div class="lib-stat"><span class="lib-stat-value" id="stat-series">-</span><span class="lib-stat-label">Serien</span></div>
|
|
<div class="lib-stat"><span class="lib-stat-value" id="stat-size">-</span><span class="lib-stat-label">Gesamt</span></div>
|
|
<div class="lib-stat"><span class="lib-stat-value" id="stat-duration">-</span><span class="lib-stat-label">Spielzeit</span></div>
|
|
</div>
|
|
|
|
<div class="library-layout">
|
|
<!-- Pfad-Navigation -->
|
|
<nav class="library-nav" id="library-nav">
|
|
<h3>Bibliotheken</h3>
|
|
<div id="nav-paths-list">
|
|
<div class="loading-msg" style="padding:0.5rem;font-size:0.75rem">Lade...</div>
|
|
</div>
|
|
</nav>
|
|
|
|
<!-- Filter-Sidebar -->
|
|
<aside class="library-filters" id="filters">
|
|
<h3>Filter</h3>
|
|
|
|
<!-- Schnellfilter / Presets -->
|
|
<div class="filter-group filter-presets">
|
|
<label>Schnellfilter</label>
|
|
<select id="filter-preset" onchange="applyPreset()">
|
|
<option value="">-- Alle anzeigen --</option>
|
|
<option value="not_converted">Nicht konvertiert</option>
|
|
<option value="old_formats">Alte Formate (kein AV1)</option>
|
|
<option value="missing_episodes">Fehlende Episoden</option>
|
|
</select>
|
|
<div class="preset-actions">
|
|
<button class="btn-small" onclick="saveCurrentFilter()" title="Aktuellen Filter speichern">Speichern</button>
|
|
<button class="btn-small" onclick="setAsDefault()" title="Als Standard setzen">Standard</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="filter-group">
|
|
<label>Suche</label>
|
|
<input type="text" id="filter-search" placeholder="Dateiname..." oninput="debounceFilter()">
|
|
</div>
|
|
|
|
<div class="filter-group">
|
|
<label>Aufloesung</label>
|
|
<select id="filter-resolution" onchange="applyFilters()">
|
|
<option value="">Alle</option>
|
|
<option value="3840">4K (3840+)</option>
|
|
<option value="1920">1080p (1920+)</option>
|
|
<option value="1280">720p (1280+)</option>
|
|
<option value="720">SD (720+)</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="filter-group">
|
|
<label>Video-Codec</label>
|
|
<select id="filter-codec" onchange="applyFilters()">
|
|
<option value="">Alle</option>
|
|
<option value="hevc">HEVC/H.265</option>
|
|
<option value="h264">H.264</option>
|
|
<option value="av1">AV1</option>
|
|
<option value="mpeg4">MPEG-4</option>
|
|
<option value="mpeg2video">MPEG-2</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="filter-group">
|
|
<label>Container</label>
|
|
<select id="filter-container" onchange="applyFilters()">
|
|
<option value="">Alle</option>
|
|
<option value="mkv">MKV</option>
|
|
<option value="mp4">MP4</option>
|
|
<option value="avi">AVI</option>
|
|
<option value="webm">WebM</option>
|
|
<option value="ts">TS</option>
|
|
<option value="wmv">WMV</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="filter-group">
|
|
<label>Audio-Sprache</label>
|
|
<select id="filter-audio-lang" onchange="applyFilters()">
|
|
<option value="">Alle</option>
|
|
<option value="ger">Deutsch</option>
|
|
<option value="eng">Englisch</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="filter-group">
|
|
<label>Audio-Kanaele</label>
|
|
<select id="filter-audio-ch" onchange="applyFilters()">
|
|
<option value="">Alle</option>
|
|
<option value="2">Stereo (2.0)</option>
|
|
<option value="6">5.1 Surround</option>
|
|
<option value="8">7.1 Surround</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="filter-group">
|
|
<label><input type="checkbox" id="filter-10bit" onchange="applyFilters()"> Nur 10-Bit</label>
|
|
</div>
|
|
|
|
<div class="filter-group">
|
|
<label><input type="checkbox" id="filter-not-converted" onchange="applyFilters()"> Nicht konvertiert</label>
|
|
</div>
|
|
|
|
<div class="filter-group">
|
|
<label>Sortierung</label>
|
|
<select id="filter-sort" onchange="applyFilters()">
|
|
<option value="file_name">Name</option>
|
|
<option value="file_size">Groesse</option>
|
|
<option value="width">Aufloesung</option>
|
|
<option value="duration_sec">Dauer</option>
|
|
<option value="video_codec">Codec</option>
|
|
<option value="scanned_at">Scan-Datum</option>
|
|
</select>
|
|
<select id="filter-order" onchange="applyFilters()">
|
|
<option value="asc">Aufsteigend</option>
|
|
<option value="desc">Absteigend</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="filter-group">
|
|
<button class="btn-secondary btn-block" onclick="resetFilters()">Filter zuruecksetzen</button>
|
|
</div>
|
|
</aside>
|
|
|
|
<!-- Hauptbereich: Dynamische Bereiche pro Library-Pfad -->
|
|
<div class="library-content" id="library-content">
|
|
<div class="loading-msg">Lade Bibliothek...</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- === MODALS === -->
|
|
|
|
<!-- Pfade-Verwaltung Modal -->
|
|
<div id="paths-modal" class="modal-overlay" style="display:none">
|
|
<div class="modal">
|
|
<div class="modal-header">
|
|
<h2>Scan-Pfade verwalten</h2>
|
|
<button class="btn-close" onclick="closePathsModal()">×</button>
|
|
</div>
|
|
<div class="modal-body" style="padding:1rem">
|
|
<div id="paths-list"></div>
|
|
<hr style="border-color:#333; margin:1rem 0">
|
|
<h3 style="font-size:0.9rem; margin-bottom:0.5rem">Neuen Pfad hinzufuegen</h3>
|
|
<div class="form-grid">
|
|
<div class="form-group">
|
|
<label>Name</label>
|
|
<input type="text" id="new-path-name" placeholder="z.B. Serien">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Pfad</label>
|
|
<input type="text" id="new-path-path" placeholder="/mnt/30 - Media/10 - Serien">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Typ</label>
|
|
<select id="new-path-type">
|
|
<option value="series">Serien</option>
|
|
<option value="movie">Filme</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="form-actions">
|
|
<button class="btn-primary" onclick="addPath()">Hinzufuegen</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- TVDB Such-Modal -->
|
|
<div id="tvdb-modal" class="modal-overlay" style="display:none">
|
|
<div class="modal modal-small">
|
|
<div class="modal-header">
|
|
<h2>TVDB zuordnen</h2>
|
|
<button class="btn-close" onclick="closeTvdbModal()">×</button>
|
|
</div>
|
|
<div class="modal-body" style="padding:1rem">
|
|
<input type="hidden" id="tvdb-series-id">
|
|
<div class="form-group">
|
|
<label>Serie suchen</label>
|
|
<input type="text" id="tvdb-search-input" placeholder="Serienname..."
|
|
oninput="debounceTvdbSearch()">
|
|
</div>
|
|
<div class="form-group" style="margin-top:0.5rem">
|
|
<label style="display:inline-flex; align-items:center; gap:0.5rem; cursor:pointer">
|
|
<input type="checkbox" id="tvdb-search-english" onchange="searchTvdb()">
|
|
Englische Titel durchsuchen
|
|
</label>
|
|
</div>
|
|
<div id="tvdb-results" class="tvdb-results"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Duplikate-Modal -->
|
|
<div id="duplicates-modal" class="modal-overlay" style="display:none">
|
|
<div class="modal">
|
|
<div class="modal-header">
|
|
<h2>Duplikate</h2>
|
|
<button class="btn-close" onclick="closeDuplicatesModal()">×</button>
|
|
</div>
|
|
<div class="modal-body" style="padding:1rem">
|
|
<div id="duplicates-list" class="duplicates-list">
|
|
<div class="loading-msg">Suche Duplikate...</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Serien-Detail-Modal -->
|
|
<div id="series-modal" class="modal-overlay" style="display:none">
|
|
<div class="modal" style="max-width:1000px">
|
|
<div class="modal-header">
|
|
<div style="flex:1">
|
|
<h2 id="series-modal-title">Serie</h2>
|
|
<span id="series-modal-genres" class="series-genres-line"></span>
|
|
</div>
|
|
<div class="modal-header-actions">
|
|
<button class="btn-small btn-primary" id="btn-convert-series" onclick="openConvertSeriesModal()">Serie konvertieren</button>
|
|
<button class="btn-small btn-secondary" id="btn-tvdb-refresh" onclick="tvdbRefresh()" style="display:none">TVDB aktualisieren</button>
|
|
<button class="btn-small btn-secondary" id="btn-tvdb-unlink" onclick="tvdbUnlink()" style="display:none">TVDB loesen</button>
|
|
<button class="btn-small btn-secondary" id="btn-metadata-dl" onclick="downloadMetadata()" style="display:none">Metadaten laden</button>
|
|
<button class="btn-small btn-secondary" id="btn-cleanup-series" onclick="cleanupSeriesFolder()">Alte Dateien loeschen</button>
|
|
<button class="btn-small btn-secondary" id="btn-series-delete-db" onclick="deleteSeries(false)">Aus DB loeschen</button>
|
|
<button class="btn-small btn-danger" id="btn-series-delete-all" onclick="deleteSeries(true)">Komplett loeschen</button>
|
|
<button class="btn-close" onclick="closeSeriesModal()">×</button>
|
|
</div>
|
|
</div>
|
|
<div class="modal-body" style="padding:0">
|
|
<!-- Detail-Tabs -->
|
|
<div class="detail-tabs">
|
|
<button class="detail-tab active" onclick="switchDetailTab('episodes')">Episoden</button>
|
|
<button class="detail-tab" onclick="switchDetailTab('cast')">Darsteller</button>
|
|
<button class="detail-tab" onclick="switchDetailTab('artworks')">Bilder</button>
|
|
</div>
|
|
<div id="series-modal-body" style="padding:1rem">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Film-Detail-Modal -->
|
|
<div id="movie-modal" class="modal-overlay" style="display:none">
|
|
<div class="modal" style="max-width:900px">
|
|
<div class="modal-header">
|
|
<div style="flex:1">
|
|
<h2 id="movie-modal-title">Film</h2>
|
|
<span id="movie-modal-genres" class="series-genres-line"></span>
|
|
</div>
|
|
<div class="modal-header-actions">
|
|
<button class="btn-small btn-secondary" id="btn-movie-tvdb-unlink" onclick="movieTvdbUnlink()" style="display:none">TVDB loesen</button>
|
|
<button class="btn-small btn-secondary" onclick="deleteMovie(false)">Aus DB loeschen</button>
|
|
<button class="btn-small btn-danger" onclick="deleteMovie(true)">Komplett loeschen</button>
|
|
<button class="btn-close" onclick="closeMovieModal()">×</button>
|
|
</div>
|
|
</div>
|
|
<div class="modal-body" style="padding:1rem">
|
|
<div id="movie-modal-body"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Film-TVDB Such-Modal -->
|
|
<div id="movie-tvdb-modal" class="modal-overlay" style="display:none">
|
|
<div class="modal modal-small">
|
|
<div class="modal-header">
|
|
<h2>Film TVDB zuordnen</h2>
|
|
<button class="btn-close" onclick="closeMovieTvdbModal()">×</button>
|
|
</div>
|
|
<div class="modal-body" style="padding:1rem">
|
|
<input type="hidden" id="movie-tvdb-id">
|
|
<div class="form-group">
|
|
<label>Film suchen</label>
|
|
<input type="text" id="movie-tvdb-search-input" placeholder="Filmname..."
|
|
oninput="debounceMovieTvdbSearch()">
|
|
</div>
|
|
<div id="movie-tvdb-results" class="tvdb-results"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Clean-Modal -->
|
|
<div id="clean-modal" class="modal-overlay" style="display:none">
|
|
<div class="modal" style="max-width:1000px">
|
|
<div class="modal-header">
|
|
<h2>Bibliothek aufraeumen</h2>
|
|
<button class="btn-close" onclick="closeCleanModal()">×</button>
|
|
</div>
|
|
<div class="modal-body" style="padding:1rem">
|
|
<div class="clean-actions" style="margin-bottom:1rem; display:flex; gap:0.5rem; align-items:center;">
|
|
<button class="btn-primary" onclick="scanForJunk()">Junk scannen</button>
|
|
<button class="btn-secondary" onclick="deleteSelectedJunk()">Ausgewaehlte loeschen</button>
|
|
<button class="btn-secondary" onclick="deleteEmptyDirs()">Leere Ordner loeschen</button>
|
|
<span id="clean-info" class="text-muted" style="margin-left:auto"></span>
|
|
</div>
|
|
<div class="clean-filter" style="margin-bottom:0.5rem">
|
|
<label style="font-size:0.8rem; color:#aaa;">Filter Extension:</label>
|
|
<select id="clean-ext-filter" onchange="filterCleanList()" style="background:#252525;color:#ddd;border:1px solid #333;border-radius:4px;padding:0.2rem;font-size:0.8rem;">
|
|
<option value="">Alle</option>
|
|
</select>
|
|
<label style="margin-left:0.5rem; font-size:0.8rem; cursor:pointer; color:#ccc;">
|
|
<input type="checkbox" id="clean-select-all" onchange="toggleCleanSelectAll()"> Alle auswaehlen
|
|
</label>
|
|
</div>
|
|
<div id="clean-list" class="clean-list">
|
|
<div class="loading-msg">Klicke "Junk scannen" um zu starten</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Import-Modal -->
|
|
<div id="import-modal" class="modal-overlay" style="display:none">
|
|
<div class="modal" style="max-width:1100px">
|
|
<div class="modal-header">
|
|
<h2>Videos importieren</h2>
|
|
<button class="btn-close" onclick="closeImportModal()">×</button>
|
|
</div>
|
|
<div class="modal-body" style="padding:0">
|
|
<!-- Bestehende Import-Jobs -->
|
|
<div id="import-existing" style="display:none; padding:0.8rem; border-bottom:1px solid #2a2a2a; background:#1a1a1a;">
|
|
<div style="margin-bottom:0.5rem; font-size:0.85rem; color:#888;">Offene Import-Jobs:</div>
|
|
<div id="import-jobs-list" style="display:flex; flex-wrap:wrap; gap:0.5rem;"></div>
|
|
</div>
|
|
<!-- Schritt 1: Ordner waehlen -->
|
|
<div id="import-setup">
|
|
<!-- Filebrowser -->
|
|
<div class="import-browser-bar">
|
|
<input type="text" id="import-source" placeholder="/mnt/..." oninput="debounceImportPath()"
|
|
style="flex:1;background:#252525;color:#ddd;border:1px solid #333;border-radius:5px;padding:0.4rem 0.6rem;font-size:0.85rem">
|
|
<button class="btn-small btn-secondary" onclick="importBrowse(document.getElementById('import-source').value || '/mnt')">Oeffnen</button>
|
|
</div>
|
|
<div id="import-browser" class="import-browser"></div>
|
|
<!-- Einstellungen + Analysieren -->
|
|
<div class="import-setup-footer">
|
|
<div class="import-setup-opts">
|
|
<label>Ziel:</label>
|
|
<select id="import-target"></select>
|
|
<label>Modus:</label>
|
|
<select id="import-mode">
|
|
<option value="copy">Kopieren</option>
|
|
<option value="move">Verschieben</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<span id="import-folder-info" class="text-muted"></span>
|
|
<button class="btn-primary" id="btn-analyze-import" onclick="createImportJob()" disabled>Analysieren</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- Schritt 2: Vorschau -->
|
|
<div id="import-preview" style="display:none">
|
|
<div class="import-actions" style="padding:0.6rem 1rem; display:flex; gap:0.5rem; align-items:center; border-bottom:1px solid #2a2a2a;">
|
|
<button class="btn-primary" id="btn-start-import" onclick="executeImport()">Import starten</button>
|
|
<button class="btn-secondary" onclick="resetImport()">Zurueck</button>
|
|
<button class="btn-danger" onclick="deleteCurrentImportJob()" title="Job loeschen">Job loeschen</button>
|
|
<span id="import-info" class="text-muted" style="margin-left:auto"></span>
|
|
</div>
|
|
<div id="import-items-list" class="import-items-list"></div>
|
|
</div>
|
|
<!-- Schritt 3: Fortschritt -->
|
|
<div id="import-progress" style="display:none; padding:1rem;">
|
|
<div class="progress-container">
|
|
<div class="progress-bar" id="import-bar"></div>
|
|
</div>
|
|
<span class="text-muted" id="import-status-text">Importiere...</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- TVDB Review-Modal -->
|
|
<div id="tvdb-review-modal" class="modal-overlay" style="display:none">
|
|
<div class="modal" style="max-width:1100px">
|
|
<div class="modal-header">
|
|
<div style="flex:1">
|
|
<h2>TVDB Vorschlaege pruefen</h2>
|
|
<span id="tvdb-review-info" class="text-muted" style="font-size:0.8rem"></span>
|
|
</div>
|
|
<div class="modal-header-actions">
|
|
<button class="btn-small btn-secondary" id="btn-review-skip-all" onclick="skipAllReviewItems()">Alle ueberspringen</button>
|
|
<button class="btn-close" onclick="closeTvdbReviewModal()">×</button>
|
|
</div>
|
|
</div>
|
|
<div class="modal-body" style="padding:0">
|
|
<div id="tvdb-review-list" class="tvdb-review-list">
|
|
<div class="loading-msg">Keine Vorschlaege</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- Serie konvertieren Modal -->
|
|
<div id="convert-series-modal" class="modal-overlay" style="display:none">
|
|
<div class="modal modal-small">
|
|
<div class="modal-header">
|
|
<h2>Serie konvertieren</h2>
|
|
<button class="btn-close" onclick="closeConvertSeriesModal()">×</button>
|
|
</div>
|
|
<div class="modal-body" style="padding:1rem">
|
|
<div id="convert-series-status" style="margin-bottom:1rem"></div>
|
|
|
|
<div class="form-group">
|
|
<label>Ziel-Codec</label>
|
|
<select id="convert-target-codec">
|
|
<option value="av1">AV1 (empfohlen)</option>
|
|
<option value="hevc">HEVC / H.265</option>
|
|
<option value="h264">H.264</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label>
|
|
<input type="checkbox" id="convert-force-all">
|
|
Alle Episoden neu konvertieren (auch bereits passende)
|
|
</label>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label>
|
|
<input type="checkbox" id="convert-delete-old">
|
|
Quelldateien nach Konvertierung loeschen
|
|
</label>
|
|
</div>
|
|
|
|
<div class="form-actions" style="margin-top:1rem">
|
|
<button class="btn-primary" onclick="executeConvertSeries()">Konvertierung starten</button>
|
|
<button class="btn-secondary" onclick="closeConvertSeriesModal()">Abbrechen</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Bestaetigungs-Dialog -->
|
|
<div id="confirm-modal" class="modal-overlay" style="display:none">
|
|
<div class="modal modal-small">
|
|
<div class="modal-header">
|
|
<h2 id="confirm-title">Bestaetigung</h2>
|
|
<button class="btn-close" onclick="closeConfirmModal()">×</button>
|
|
</div>
|
|
<div class="modal-body" style="padding:1.2rem">
|
|
<div id="confirm-icon" style="text-align:center; font-size:3rem; margin-bottom:0.8rem">⚠</div>
|
|
<div id="confirm-message" style="text-align:center; margin-bottom:1rem"></div>
|
|
<div id="confirm-detail" style="text-align:center; font-size:0.85rem; color:#888; margin-bottom:1.2rem"></div>
|
|
<div class="form-actions" style="justify-content:center">
|
|
<button class="btn-danger" id="confirm-btn-ok" onclick="confirmAction()">Loeschen</button>
|
|
<button class="btn-secondary" onclick="closeConfirmModal()">Abbrechen</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- Video-Player Modal -->
|
|
<div id="player-modal" class="modal-overlay player-overlay" style="display:none">
|
|
<div class="player-container">
|
|
<div class="player-header">
|
|
<span id="player-title">Video</span>
|
|
<button class="btn-close" onclick="closePlayer()">×</button>
|
|
</div>
|
|
<video id="player-video" controls preload="metadata">
|
|
Dein Browser unterstuetzt kein HTML5-Video.
|
|
</video>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Import-Zuordnungs-Modal -->
|
|
<div id="import-assign-modal" class="modal-overlay" style="display:none">
|
|
<div class="modal modal-small">
|
|
<div class="modal-header">
|
|
<h2>Datei zuordnen</h2>
|
|
<button class="btn-close" onclick="closeImportAssignModal()">×</button>
|
|
</div>
|
|
<div class="modal-body" style="padding:1rem">
|
|
<div class="text-muted" style="margin-bottom:0.8rem;font-size:0.85rem">
|
|
Datei: <strong id="import-assign-filename"></strong>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label>Serie suchen (TVDB)</label>
|
|
<input type="text" id="import-assign-search" placeholder="Serienname..."
|
|
oninput="debounceAssignSearch()"
|
|
style="width:100%;background:#252525;color:#ddd;border:1px solid #333;border-radius:5px;padding:0.4rem 0.6rem">
|
|
</div>
|
|
<div id="import-assign-results" class="tvdb-results" style="max-height:200px;overflow-y:auto"></div>
|
|
|
|
<div id="import-assign-selected" style="display:none; margin:0.5rem 0; padding:0.5rem; background:#1a3a1a; border:1px solid #2a5a2a; border-radius:5px">
|
|
Ausgewaehlt: <strong id="import-assign-selected-name"></strong>
|
|
<button class="btn-small btn-secondary" onclick="selectAssignSeries(null, '')" style="float:right;font-size:0.7rem">Loesen</button>
|
|
</div>
|
|
|
|
<div style="display:grid; grid-template-columns:1fr 1fr; gap:0.5rem; margin-top:0.8rem">
|
|
<div class="form-group">
|
|
<label>Staffel</label>
|
|
<input type="number" id="import-assign-season" min="0" max="99" placeholder="1"
|
|
style="width:100%;background:#252525;color:#ddd;border:1px solid #333;border-radius:5px;padding:0.4rem 0.6rem">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Episode</label>
|
|
<input type="number" id="import-assign-episode" min="0" max="999" placeholder="1"
|
|
style="width:100%;background:#252525;color:#ddd;border:1px solid #333;border-radius:5px;padding:0.4rem 0.6rem">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-actions" style="margin-top:1rem">
|
|
<button class="btn-primary" onclick="submitImportAssign()">Zuordnen</button>
|
|
<button class="btn-secondary" onclick="closeImportAssignModal()">Abbrechen</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block scripts %}
|
|
<script src="/static/js/library.js"></script>
|
|
{% endblock %}
|