Zwei Teile, ein Treffer — und einer verschwand
Du hast drei Filme vermisst, und die Zahlen sagten schon, wo sie sind: 448 Filme plus 13 zweite Fassungen sind genau die 461 Dateien. Es fehlte keine Datei; drei Filme steckten als Fassung in einem anderen. Gemessen, warum. Der Dateinamenleser ist unschuldig — „Teil 2" bleibt im Titel. TMDB aber liefert für „Heiligtümer des Todes Teil 1" wie für „Teil 2" denselben Treffer zuerst, sobald ohne Jahr gesucht werden muss. Und weil zwei Einträge dieselbe Kennung nicht teilen dürfen, wurde der zweite geschluckt. Zwei Dateien, deren Namen verschiedene Jahre nennen, sind jetzt verschiedene Filme. Der erste Anlauf hatte ein Jahr Abstand als Toleranz erlaubt — für Dezember-Erstaufführungen — und verschluckte damit genau den Fall, um den es geht: Teil 1 ist von 2010, Teil 2 von 2011. Dazu sieht man endlich, was nicht zugeordnet werden konnte. „Nicht zugeordnet" listete bisher nur Dateien ganz ohne Titel, und die gibt es bei Filmen nie — deshalb standen dort nur Serien. Daneben eine Liste der Titel mit mehreren Dateien: zwei Fassungen sind die Regel, zwei verschiedene Filme der Fehler, und an den Dateinamen sieht man es sofort. Der Bearbeiten-Dialog hat jetzt Reiter statt Knöpfe, die weitere Fenster öffnen — ein Fenster über einem Fenster, und man wusste nicht mehr, was man zumacht. „Titel ändern" und „Bilder bearbeiten" sind aus dem Kontextmenü raus; über „Bearbeiten" kommt man an beides. Beim Prüfen gefunden: ein Dialog blieb nach einem Seitenwechsel über der neuen Seite stehen. Er hängt an body, nicht am Inhaltsbereich. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
fcf40e4394
commit
c3124ba27c
+117
-2
@@ -9,7 +9,7 @@ import {
|
||||
benutzer, benutzerAnlegen, metadatenEinstellung, metadatenSetzen,
|
||||
servernameSetzen, systemauskunft,
|
||||
laufendeWiedergaben, serverzustand, bildAdresse,
|
||||
speicherorte, bildspeicherLeeren, unzugeordnet,
|
||||
speicherorte, bildspeicherLeeren, unzugeordnet, ohneZuordnung, mehrfachfassungen,
|
||||
sprachverteilung, abweichendeAuffrischen,
|
||||
type Bibliothek, type Wiedergabe, ApiFehler,
|
||||
} from '../api';
|
||||
@@ -38,7 +38,8 @@ export function verwaltung(
|
||||
const wurzel = document.createElement('div');
|
||||
wurzel.append(dashboard(signal), sprachbereich(), pruefbereich(geaendert),
|
||||
vermisstenbereich(geaendert), bibliotheksbereich(geaendert, signal), benutzerbereich(),
|
||||
serverbereich(geaendert), speicherbereich(), unzugeordnetbereich(),
|
||||
serverbereich(geaendert), speicherbereich(), ohneZuordnungBereich(),
|
||||
unzugeordnetbereich(),
|
||||
protokollbereich());
|
||||
return wurzel;
|
||||
}
|
||||
@@ -407,6 +408,120 @@ function pruefbereich(geaendert: () => void): HTMLElement {
|
||||
* fehlt die Folgennummer, muss umbenannt werden; fehlt der Serienname, genügt
|
||||
* ein Ordner darum herum.
|
||||
*/
|
||||
/** Titel, zu denen die Metadatenquelle nichts hergab.
|
||||
*
|
||||
* **Weil die Zahl allein nichts erklärt.** In der Übersicht standen 448
|
||||
* Filme, in Plex 451 — und nirgends, welche drei fehlen oder warum. Ein Film
|
||||
* ohne Zuordnung steht zwar in der Mediathek, aber unter seinem Dateinamen
|
||||
* und ohne Plakat; wer ihn sucht, findet ihn nicht, weil er anders heisst.
|
||||
*
|
||||
* Daneben: Titel mit mehr als einer Datei. Zwei Dateien an einem Film sind
|
||||
* meist zwei Fassungen und in Ordnung — manchmal aber zwei verschiedene
|
||||
* Filme, die bei der Quelle auf denselben Treffer liefen. An den Dateinamen
|
||||
* sieht man das in zwei Sekunden.
|
||||
*/
|
||||
function ohneZuordnungBereich(): HTMLElement {
|
||||
const bereich = document.createElement('section');
|
||||
bereich.classList.add('hidden');
|
||||
bereich.appendChild(abschnitt('Ohne Zuordnung'));
|
||||
|
||||
const liste = document.createElement('div');
|
||||
liste.className = 'einstellungen';
|
||||
bereich.appendChild(liste);
|
||||
|
||||
void laden();
|
||||
|
||||
async function laden(): Promise<void> {
|
||||
let alle;
|
||||
try { alle = await bibliotheken(); }
|
||||
catch { return; }
|
||||
|
||||
const ergebnisse = await Promise.all(alle.map(async b => {
|
||||
try {
|
||||
const [offen, mehrfach] = await Promise.all([
|
||||
ohneZuordnung(b.id), mehrfachfassungen(b.id),
|
||||
]);
|
||||
return { b, offen, mehrfach };
|
||||
} catch { return null; }
|
||||
}));
|
||||
|
||||
const mitFunden = ergebnisse
|
||||
.filter(e => e !== null)
|
||||
.filter(e => e!.offen.length > 0 || e!.mehrfach.gesamt > 0);
|
||||
|
||||
if (mitFunden.length === 0) { bereich.classList.add('hidden'); return; }
|
||||
bereich.classList.remove('hidden');
|
||||
|
||||
liste.innerHTML = '';
|
||||
|
||||
mitFunden.forEach(e => {
|
||||
const { b, offen, mehrfach } = e!;
|
||||
|
||||
if (offen.length > 0) {
|
||||
liste.appendChild(gruppe(
|
||||
`${b.name} — ${anzahl(offen.length, 'Titel')} ohne Zuordnung`,
|
||||
'Diese stehen unter ihrem Dateinamen in der Mediathek. '
|
||||
+ 'Über „Zuordnung korrigieren" lassen sie sich geradeziehen.',
|
||||
offen.map(t => ({
|
||||
titel: t.titel + (t.jahr ? ` (${t.jahr})` : ''),
|
||||
dazu: t.beispiel ?? `${anzahl(t.dateien, 'Datei')}`,
|
||||
// **Hier bearbeiten, nicht woandershin springen.** Wer eine
|
||||
// Liste durchgeht, will nach dem Geradeziehen beim nächsten
|
||||
// weitermachen — nicht jedes Mal zurücknavigieren.
|
||||
tun: () => bearbeiten(t.art === 'series' ? 'series' : 'movies', t.id, () => void laden()),
|
||||
}))));
|
||||
}
|
||||
|
||||
if (mehrfach.gesamt > 0) {
|
||||
liste.appendChild(gruppe(
|
||||
`${b.name} — ${anzahl(mehrfach.gesamt, 'Titel')} mit mehreren Dateien`,
|
||||
'Meist zwei Fassungen desselben Films. Stehen hier aber zwei '
|
||||
+ 'verschiedene Filme, lief einer von beiden auf den falschen Treffer — '
|
||||
+ 'dann hilft „Zuordnung korrigieren".',
|
||||
mehrfach.titel.map(t => ({
|
||||
titel: t.titel + (t.jahr ? ` (${t.jahr})` : ''),
|
||||
dazu: t.dateien.join(' · '),
|
||||
tun: () => bearbeiten(t.art === 'series' ? 'series' : 'movies', t.id, () => void laden()),
|
||||
}))));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function anzahl(n: number, wort: string): string {
|
||||
return `${n} ${n === 1 ? wort : (wort === 'Datei' ? 'Dateien' : wort)}`;
|
||||
}
|
||||
|
||||
function gruppe(
|
||||
ueberschrift: string, hinweis: string,
|
||||
zeilen: { titel: string; dazu: string; tun: () => void }[],
|
||||
): HTMLElement {
|
||||
const d = document.createElement('div');
|
||||
d.className = 'einstellung';
|
||||
|
||||
const kopf = document.createElement('div');
|
||||
kopf.className = 'zeile';
|
||||
kopf.innerHTML = `<strong>${esc(ueberschrift)}</strong>`
|
||||
+ `<span class="winzig">${esc(hinweis)}</span>`;
|
||||
d.appendChild(kopf);
|
||||
|
||||
const innen = document.createElement('div');
|
||||
innen.className = 'ohnezuordnung';
|
||||
zeilen.forEach(z => {
|
||||
const b = document.createElement('button');
|
||||
b.className = 'ohnezuordnung-zeile';
|
||||
b.innerHTML = `<span class="oz-titel">${esc(z.titel)}</span>`
|
||||
+ `<span class="oz-dazu">${esc(z.dazu)}</span>`;
|
||||
b.onclick = z.tun;
|
||||
innen.appendChild(b);
|
||||
});
|
||||
d.appendChild(innen);
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
return bereich;
|
||||
}
|
||||
|
||||
function unzugeordnetbereich(): HTMLElement {
|
||||
const bereich = document.createElement('section');
|
||||
const kopf = abschnitt('Nicht zugeordnet');
|
||||
|
||||
Reference in New Issue
Block a user