451 gegen 461, und ein Band für das, was noch wartet
Drei Zahlen, die alle stimmen und Verschiedenes meinen: Plex zählte 451 Filme, Flaro 449, und der Scan lief über 461 Dateien. Die Mediathekszeile nennt sie jetzt getrennt — Titel, Folgen, Dateien, zweite Fassungen und nicht Zugeordnetes. Damit beantwortet sich die Frage selbst, statt offen zu bleiben. Die Rechnung dahinter war beim ersten Versuch falsch: sie verglich gegen alle Folgen und kam auf 1223 Titel bei 324 Dateien. Gezählt wird jetzt, zu wie vielen Titeln überhaupt noch eine Datei daliegt — dann geht Dateien = Titel + Fassungen + ohne auf, auch wenn etwas vermisst wird. Nachgemessen mit einer echten Plex-Kopie: 3 Titel, 4 Dateien, 1 zweite Fassung. Dazu trägt eine Kachel, die noch auf Freigabe wartet, jetzt ein Band — „Wartet" oder „Geplant". Für einen Administrator standen wartende Titel bisher mitten zwischen den freigegebenen, ohne dass etwas sie unterschied; wer einen suchte, fand ihn nur über die Prüfliste. Dafür reicht `PublishAt` jetzt bis in die Kachel durch. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
5a5cf3d006
commit
c854c4a09a
@@ -94,7 +94,27 @@ public sealed record LibraryResponse(
|
|||||||
/// scannt, sieht das Ergebnis an ihr — dass zwanzig Titel irgendwo anders
|
/// scannt, sieht das Ergebnis an ihr — dass zwanzig Titel irgendwo anders
|
||||||
/// warten, erfährt er sonst nur, wenn er weiterscrollt.
|
/// warten, erfährt er sonst nur, wenn er weiterscrollt.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
int PendingCount = 0);
|
int PendingCount = 0,
|
||||||
|
|
||||||
|
/// <summary>Wie viele Mediendateien in dieser Mediathek liegen.</summary>
|
||||||
|
///
|
||||||
|
/// <remarks>
|
||||||
|
/// <b>Weil „455 Filme" und „461 Dateien" beide stimmen können.</b> Plex
|
||||||
|
/// zählte 451, Flaro 449 — und der Scan lief über 461 Dateien. Drei
|
||||||
|
/// Zahlen für drei verschiedene Dinge, und keine davon falsch. Nebeneinander
|
||||||
|
/// zu sehen, wie sie sich aufteilen, beendet die Frage; eine davon allein
|
||||||
|
/// zu zeigen hält sie offen.
|
||||||
|
/// </remarks>
|
||||||
|
int FileCount = 0,
|
||||||
|
|
||||||
|
/// <summary>Wie viele Folgen — nur bei Serien, sonst <c>null</c>.</summary>
|
||||||
|
int? EpisodeCount = null,
|
||||||
|
|
||||||
|
/// <summary>Dateien, die an keinem Titel hängen.</summary>
|
||||||
|
int UnassignedCount = 0,
|
||||||
|
|
||||||
|
/// <summary>Dateien über die erste je Titel hinaus — zweite Fassungen.</summary>
|
||||||
|
int ExtraVersionCount = 0);
|
||||||
|
|
||||||
public sealed record RenameLibraryRequest(string Name);
|
public sealed record RenameLibraryRequest(string Name);
|
||||||
|
|
||||||
@@ -253,7 +273,17 @@ public sealed record MovieResponse(
|
|||||||
IReadOnlyList<CreditResponse>? Credits = null,
|
IReadOnlyList<CreditResponse>? Credits = null,
|
||||||
|
|
||||||
/// <summary>Der Titel in der Sprache des Originals, wenn er abweicht.</summary>
|
/// <summary>Der Titel in der Sprache des Originals, wenn er abweicht.</summary>
|
||||||
string? OriginalTitle = null);
|
string? OriginalTitle = null,
|
||||||
|
|
||||||
|
/// <summary>Ab wann sichtbar — <c>null</c> heisst: wartet auf Freigabe.</summary>
|
||||||
|
///
|
||||||
|
/// <remarks>
|
||||||
|
/// <b>Damit die Mediathek es zeigen kann.</b> Für einen Administrator
|
||||||
|
/// stehen wartende Titel mitten zwischen den freigegebenen, ohne dass
|
||||||
|
/// etwas sie unterscheidet — und wer einen davon sucht, findet ihn nur
|
||||||
|
/// über die Prüfliste.
|
||||||
|
/// </remarks>
|
||||||
|
DateTimeOffset? PublishAt = null);
|
||||||
|
|
||||||
public sealed record CreditResponse(
|
public sealed record CreditResponse(
|
||||||
Guid Id, string Name, string Role, string? Character, string? Image);
|
Guid Id, string Name, string Role, string? Character, string? Image);
|
||||||
@@ -279,7 +309,17 @@ public sealed record SeriesResponse(
|
|||||||
IReadOnlyList<CreditResponse>? Credits = null,
|
IReadOnlyList<CreditResponse>? Credits = null,
|
||||||
|
|
||||||
/// <summary>Der Titel in der Sprache des Originals, wenn er abweicht.</summary>
|
/// <summary>Der Titel in der Sprache des Originals, wenn er abweicht.</summary>
|
||||||
string? OriginalTitle = null);
|
string? OriginalTitle = null,
|
||||||
|
|
||||||
|
/// <summary>Ab wann sichtbar — <c>null</c> heisst: wartet auf Freigabe.</summary>
|
||||||
|
///
|
||||||
|
/// <remarks>
|
||||||
|
/// <b>Damit die Mediathek es zeigen kann.</b> Für einen Administrator
|
||||||
|
/// stehen wartende Titel mitten zwischen den freigegebenen, ohne dass
|
||||||
|
/// etwas sie unterscheidet — und wer einen davon sucht, findet ihn nur
|
||||||
|
/// über die Prüfliste.
|
||||||
|
/// </remarks>
|
||||||
|
DateTimeOffset? PublishAt = null);
|
||||||
|
|
||||||
public sealed record EpisodeResponse(
|
public sealed record EpisodeResponse(
|
||||||
Guid Id, int Season, int Episode, string? Title, string? Overview, string? StillImage,
|
Guid Id, int Season, int Episode, string? Title, string? Overview, string? StillImage,
|
||||||
|
|||||||
@@ -311,6 +311,7 @@ public static class LibraryContentEndpoints
|
|||||||
.Select(t => t.Overview).FirstOrDefault() ?? m.Overview,
|
.Select(t => t.Overview).FirstOrDefault() ?? m.Overview,
|
||||||
m.PosterImage, m.BackdropImage,
|
m.PosterImage, m.BackdropImage,
|
||||||
m.LogoImage, m.RuntimeMinutes, m.Rating, m.ContentRating,
|
m.LogoImage, m.RuntimeMinutes, m.Rating, m.ContentRating,
|
||||||
|
m.PublishAt,
|
||||||
})
|
})
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
@@ -331,7 +332,8 @@ public static class LibraryContentEndpoints
|
|||||||
.Select(f => Datei(f.Id, f.Path, f.SizeBytes, f.Container, f.Duration, spuren, f.VersionLabel)).ToList(),
|
.Select(f => Datei(f.Id, f.Path, f.SizeBytes, f.Container, f.Duration, spuren, f.VersionLabel)).ToList(),
|
||||||
stände.GetValueOrDefault(m.Id),
|
stände.GetValueOrDefault(m.Id),
|
||||||
m.LogoImage, m.RuntimeMinutes, m.Rating, null, m.ContentRating,
|
m.LogoImage, m.RuntimeMinutes, m.Rating, null, m.ContentRating,
|
||||||
OriginalTitle: m.OriginalTitle)).ToList();
|
OriginalTitle: m.OriginalTitle,
|
||||||
|
PublishAt: m.PublishAt)).ToList();
|
||||||
|
|
||||||
return Results.Ok(new Page<MovieResponse>(items, gesamt));
|
return Results.Ok(new Page<MovieResponse>(items, gesamt));
|
||||||
}).RequireAuthorization();
|
}).RequireAuthorization();
|
||||||
@@ -381,6 +383,11 @@ public static class LibraryContentEndpoints
|
|||||||
.Select(t => t.Overview).FirstOrDefault() ?? s.Overview,
|
.Select(t => t.Overview).FirstOrDefault() ?? s.Overview,
|
||||||
s.PosterImage, s.BackdropImage,
|
s.PosterImage, s.BackdropImage,
|
||||||
s.LogoImage, s.RuntimeMinutes, s.Rating, s.ContentRating,
|
s.LogoImage, s.RuntimeMinutes, s.Rating, s.ContentRating,
|
||||||
|
// **Eine Serie wartet, solange keine Folge sichtbar ist.**
|
||||||
|
// Der früheste Zeitpunkt sagt, ab wann überhaupt etwas da
|
||||||
|
// ist; steht dort nichts, wartet alles.
|
||||||
|
PublishAt = db.Episodes.Where(f => f.SeriesId == s.Id)
|
||||||
|
.Min(f => f.PublishAt),
|
||||||
})
|
})
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
@@ -403,7 +410,8 @@ public static class LibraryContentEndpoints
|
|||||||
meine.Select(f => f.SeasonNumber).Distinct().Order().ToList(),
|
meine.Select(f => f.SeasonNumber).Distinct().Order().ToList(),
|
||||||
meine.Count(f => !gesehen.Contains(f.Id)),
|
meine.Count(f => !gesehen.Contains(f.Id)),
|
||||||
s.LogoImage, s.RuntimeMinutes, s.Rating, null, s.ContentRating,
|
s.LogoImage, s.RuntimeMinutes, s.Rating, null, s.ContentRating,
|
||||||
OriginalTitle: s.OriginalTitle);
|
OriginalTitle: s.OriginalTitle,
|
||||||
|
PublishAt: s.PublishAt);
|
||||||
}).ToList();
|
}).ToList();
|
||||||
|
|
||||||
return Results.Ok(new Page<SeriesResponse>(items, gesamt));
|
return Results.Ok(new Page<SeriesResponse>(items, gesamt));
|
||||||
|
|||||||
@@ -101,7 +101,51 @@ public static class ManagementEndpoints
|
|||||||
.Select(g => new { Id = g.Key, Anzahl = g.Count() })
|
.Select(g => new { Id = g.Key, Anzahl = g.Count() })
|
||||||
.ToDictionaryAsync(x => x.Id, x => x.Anzahl);
|
.ToDictionaryAsync(x => x.Id, x => x.Anzahl);
|
||||||
|
|
||||||
return Results.Ok(liste.Select(l => new LibraryResponse(
|
// **Drei Zahlen, die alle stimmen und Verschiedenes meinen.**
|
||||||
|
//
|
||||||
|
// Plex zählte 451 Filme, Flaro 449, und der Scan lief über 461
|
||||||
|
// Dateien. Keine davon ist falsch — es sind Titel, Dateien und
|
||||||
|
// zweite Fassungen. Nebeneinander beantwortet sich die Frage von
|
||||||
|
// selbst; einzeln bleibt sie offen.
|
||||||
|
var folgen = await db.Episodes.AsNoTracking()
|
||||||
|
.GroupBy(f => db.Series.Where(x => x.Id == f.SeriesId)
|
||||||
|
.Select(x => x.LibraryId).First())
|
||||||
|
.Select(g => new { Id = g.Key, Anzahl = g.Count() })
|
||||||
|
.ToDictionaryAsync(x => x.Id, x => x.Anzahl);
|
||||||
|
|
||||||
|
// Vermisste zählen nicht mit: sie liegen nicht mehr auf der Platte,
|
||||||
|
// und der Scan hat sie deshalb auch nicht gesehen.
|
||||||
|
//
|
||||||
|
// **`MitTitel` zählt Titel, nicht Dateien** — und zwar nur solche,
|
||||||
|
// zu denen wirklich noch eine Datei daliegt. Ohne das ginge die
|
||||||
|
// Rechnung schief, sobald etwas vermisst wird: ein erster Versuch
|
||||||
|
// verglich gegen alle Folgen und kam auf 1223 Titel bei 324
|
||||||
|
// Dateien.
|
||||||
|
var dateien = await db.MediaFiles.AsNoTracking()
|
||||||
|
.Where(f => f.MissingSince == null)
|
||||||
|
.GroupBy(f => f.LibraryId)
|
||||||
|
.Select(g => new
|
||||||
|
{
|
||||||
|
Id = g.Key,
|
||||||
|
Alle = g.Count(),
|
||||||
|
Ohne = g.Count(f => f.MovieId == null && f.EpisodeId == null),
|
||||||
|
MitTitel = g.Where(f => f.MovieId != null).Select(f => f.MovieId).Distinct().Count()
|
||||||
|
+ g.Where(f => f.EpisodeId != null).Select(f => f.EpisodeId).Distinct().Count(),
|
||||||
|
})
|
||||||
|
.ToDictionaryAsync(x => x.Id, x => x);
|
||||||
|
|
||||||
|
return Results.Ok(liste.Select(l =>
|
||||||
|
{
|
||||||
|
var zaehler = dateien.GetValueOrDefault(l.Id);
|
||||||
|
var alleDateien = zaehler?.Alle ?? 0;
|
||||||
|
var ohneTitel = zaehler?.Ohne ?? 0;
|
||||||
|
|
||||||
|
// Jeder Titel, zu dem noch eine Datei daliegt, hat mindestens
|
||||||
|
// eine. Was darüber liegt, sind zweite Fassungen — Plex'
|
||||||
|
// „Optimized for Mobile" etwa.
|
||||||
|
var mitTitel = zaehler?.MitTitel ?? 0;
|
||||||
|
|
||||||
|
return new LibraryResponse(
|
||||||
l.Id, l.Name, l.Kind.ToString(), l.Path,
|
l.Id, l.Name, l.Kind.ToString(), l.Path,
|
||||||
l.Kind == LibraryKind.Shows
|
l.Kind == LibraryKind.Shows
|
||||||
? serien.GetValueOrDefault(l.Id)
|
? serien.GetValueOrDefault(l.Id)
|
||||||
@@ -109,7 +153,12 @@ public static class ManagementEndpoints
|
|||||||
l.ReviewNewItems,
|
l.ReviewNewItems,
|
||||||
l.Kind == LibraryKind.Shows
|
l.Kind == LibraryKind.Shows
|
||||||
? wartendeFolgen.GetValueOrDefault(l.Id)
|
? wartendeFolgen.GetValueOrDefault(l.Id)
|
||||||
: wartendeFilme.GetValueOrDefault(l.Id))).ToList());
|
: wartendeFilme.GetValueOrDefault(l.Id),
|
||||||
|
FileCount: alleDateien,
|
||||||
|
EpisodeCount: l.Kind == LibraryKind.Shows ? folgen.GetValueOrDefault(l.Id) : null,
|
||||||
|
UnassignedCount: ohneTitel,
|
||||||
|
ExtraVersionCount: Math.Max(0, alleDateien - ohneTitel - mitTitel));
|
||||||
|
}).ToList());
|
||||||
}).RequireAuthorization();
|
}).RequireAuthorization();
|
||||||
|
|
||||||
// **Was nicht mehr da ist, aber noch in der Mediathek steht.**
|
// **Was nicht mehr da ist, aber noch in der Mediathek steht.**
|
||||||
|
|||||||
@@ -47,6 +47,8 @@ export type Film = {
|
|||||||
/** Leer in Listen, gefüllt beim Einzelabruf. */
|
/** Leer in Listen, gefüllt beim Einzelabruf. */
|
||||||
genres: string[] | null;
|
genres: string[] | null;
|
||||||
credits: Mitwirkender[] | null;
|
credits: Mitwirkender[] | null;
|
||||||
|
/** `null` heisst: wartet auf Freigabe. Ein Zeitpunkt in der Zukunft: geplant. */
|
||||||
|
publishAt: string | null;
|
||||||
/** Der Titel in der Sprache des Originals, wenn er abweicht. */
|
/** Der Titel in der Sprache des Originals, wenn er abweicht. */
|
||||||
originalTitle: string | null;
|
originalTitle: string | null;
|
||||||
};
|
};
|
||||||
@@ -61,6 +63,8 @@ export type Serie = {
|
|||||||
contentRating: string | null;
|
contentRating: string | null;
|
||||||
genres: string[] | null;
|
genres: string[] | null;
|
||||||
credits: Mitwirkender[] | null;
|
credits: Mitwirkender[] | null;
|
||||||
|
/** `null` heisst: wartet auf Freigabe. Ein Zeitpunkt in der Zukunft: geplant. */
|
||||||
|
publishAt: string | null;
|
||||||
/** Der Titel in der Sprache des Originals, wenn er abweicht. */
|
/** Der Titel in der Sprache des Originals, wenn er abweicht. */
|
||||||
originalTitle: string | null;
|
originalTitle: string | null;
|
||||||
};
|
};
|
||||||
@@ -91,6 +95,15 @@ export type Bibliothek = {
|
|||||||
|
|
||||||
/** Wie viele Titel hier noch auf Freigabe warten. */
|
/** Wie viele Titel hier noch auf Freigabe warten. */
|
||||||
pendingCount: number;
|
pendingCount: number;
|
||||||
|
|
||||||
|
/** Mediendateien in dieser Mediathek — ohne die vermissten. */
|
||||||
|
fileCount: number;
|
||||||
|
/** Nur bei Serien: wie viele Folgen. */
|
||||||
|
episodeCount: number | null;
|
||||||
|
/** Dateien, die an keinem Titel hängen. */
|
||||||
|
unassignedCount: number;
|
||||||
|
/** Dateien über die erste je Titel hinaus — zweite Fassungen. */
|
||||||
|
extraVersionCount: number;
|
||||||
};
|
};
|
||||||
export type Seite<T> = { items: T[]; total: number };
|
export type Seite<T> = { items: T[]; total: number };
|
||||||
export type Lieferung = {
|
export type Lieferung = {
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ export type Kachel = {
|
|||||||
stand?: Stand | null;
|
stand?: Stand | null;
|
||||||
/** Die Zahl offener Folgen, als Plakette oben rechts. */
|
/** Die Zahl offener Folgen, als Plakette oben rechts. */
|
||||||
offen?: number | null;
|
offen?: number | null;
|
||||||
|
/** `null` heisst: wartet auf Freigabe. Ein Zeitpunkt in der Zukunft: geplant. */
|
||||||
|
freigabe?: string | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ---------- Umwandlungen ---------- */
|
/* ---------- Umwandlungen ---------- */
|
||||||
@@ -35,6 +37,7 @@ export const alsKachel = (e: Film | Serie): Kachel => ({
|
|||||||
bild: e.posterImage,
|
bild: e.posterImage,
|
||||||
stand: 'state' in e ? e.state : null,
|
stand: 'state' in e ? e.state : null,
|
||||||
offen: 'unwatchedCount' in e ? e.unwatchedCount : null,
|
offen: 'unwatchedCount' in e ? e.unwatchedCount : null,
|
||||||
|
freigabe: e.publishAt,
|
||||||
});
|
});
|
||||||
|
|
||||||
/** Eine Kachel aus „Weiterschauen" — bei Folgen dreizeilig, wie bei Plex. */
|
/** Eine Kachel aus „Weiterschauen" — bei Folgen dreizeilig, wie bei Plex. */
|
||||||
@@ -110,6 +113,23 @@ export function kachel(k: Kachel, oeffnen: (art: 'filme' | 'serien', id: string)
|
|||||||
rahmen.appendChild(bild);
|
rahmen.appendChild(bild);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// **Was noch wartet, trägt ein Band.**
|
||||||
|
//
|
||||||
|
// Für einen Administrator stehen wartende Titel mitten zwischen den
|
||||||
|
// freigegebenen, ohne dass etwas sie unterscheidet — und wer einen davon
|
||||||
|
// sucht, findet ihn nur über die Prüfliste. Für alle anderen ist er gar
|
||||||
|
// nicht da, dann erscheint das Band auch nie.
|
||||||
|
if (k.freigabe === null || (k.freigabe && new Date(k.freigabe) > new Date())) {
|
||||||
|
const band = document.createElement('span');
|
||||||
|
band.className = 'wartet';
|
||||||
|
band.textContent = k.freigabe === null ? 'Wartet' : 'Geplant';
|
||||||
|
band.title = k.freigabe === null
|
||||||
|
? 'Wartet auf Freigabe — nur für Administratoren sichtbar'
|
||||||
|
: `Erscheint am ${new Date(k.freigabe).toLocaleString('de-CH',
|
||||||
|
{ dateStyle: 'medium', timeStyle: 'short' })}`;
|
||||||
|
rahmen.appendChild(band);
|
||||||
|
}
|
||||||
|
|
||||||
// **Der Haken sitzt in der Ecke, nicht in der Beschriftung.** So wie bei
|
// **Der Haken sitzt in der Ecke, nicht in der Beschriftung.** So wie bei
|
||||||
// Plex: ein Blick über das Raster zeigt, was noch offen ist, ohne eine
|
// Plex: ein Blick über das Raster zeigt, was noch offen ist, ohne eine
|
||||||
// einzige Zeile zu lesen.
|
// einzige Zeile zu lesen.
|
||||||
|
|||||||
@@ -1063,6 +1063,16 @@ h2 { font-size: var(--t-abschnitt); font-weight: 700; letter-spacing: -.015em; m
|
|||||||
* Abbrechen noch zu Bestätigen. */
|
* Abbrechen noch zu Bestätigen. */
|
||||||
.dlg-weiterer { margin-right: auto; }
|
.dlg-weiterer { margin-right: auto; }
|
||||||
|
|
||||||
|
/* Das Band an einer Kachel, die noch nicht freigegeben ist. Unten links,
|
||||||
|
* damit es weder dem Haken oben rechts noch dem Fortschrittsbalken am
|
||||||
|
* unteren Rand in die Quere kommt. */
|
||||||
|
.wartet {
|
||||||
|
position: absolute; left: 0; bottom: 0;
|
||||||
|
padding: 3px 8px; border-top-right-radius: var(--r-knopf);
|
||||||
|
background: color-mix(in srgb, var(--accent) 88%, black);
|
||||||
|
color: #fff; font-size: 11px; font-weight: 700; letter-spacing: .02em;
|
||||||
|
}
|
||||||
|
|
||||||
.bildblock { display: flex; flex-direction: column; gap: var(--s-snug); }
|
.bildblock { display: flex; flex-direction: column; gap: var(--s-snug); }
|
||||||
.bildblock h3 { margin: 0; font-size: var(--t-gross); font-weight: 600; flex: 1; }
|
.bildblock h3 { margin: 0; font-size: var(--t-gross); font-weight: 600; flex: 1; }
|
||||||
|
|
||||||
|
|||||||
+26
-11
@@ -808,20 +808,35 @@ function bibliotheksbereich(
|
|||||||
|
|
||||||
function kopfSchreiben(): void {
|
function kopfSchreiben(): void {
|
||||||
const serie = aktuell.kind === 'Shows';
|
const serie = aktuell.kind === 'Shows';
|
||||||
// „1 Filme" ist der Satz, an dem man sieht, dass niemand hingeschaut hat.
|
|
||||||
const anzahl = aktuell.itemCount == null ? ''
|
|
||||||
: ` · ${aktuell.itemCount} ` + (aktuell.itemCount === 1
|
|
||||||
? (serie ? 'Serie' : 'Film')
|
|
||||||
: (serie ? 'Serien' : 'Filme'));
|
|
||||||
|
|
||||||
// Was wartet, gehört in dieselbe Zeile — sonst erfährt man es nur, wenn
|
// **Alle Zahlen nebeneinander, weil sie Verschiedenes meinen.**
|
||||||
// man bis zur Prüfliste weiterscrollt.
|
//
|
||||||
const wartet = aktuell.pendingCount > 0
|
// Plex zählte 451 Filme, Flaro 449, und der Scan lief über 461 Dateien.
|
||||||
? ` · ${aktuell.pendingCount} wartet${aktuell.pendingCount === 1 ? '' : 'en'} auf Freigabe`
|
// Keine davon war falsch — es sind Titel, Dateien und zweite Fassungen.
|
||||||
: '';
|
// Einzeln gezeigt bleibt die Frage offen, nebeneinander beantwortet sie
|
||||||
|
// sich.
|
||||||
|
const teile: string[] = [aktuell.path];
|
||||||
|
|
||||||
|
if (aktuell.itemCount != null) {
|
||||||
|
teile.push(`${aktuell.itemCount} ` + (aktuell.itemCount === 1
|
||||||
|
? (serie ? 'Serie' : 'Film')
|
||||||
|
: (serie ? 'Serien' : 'Filme')));
|
||||||
|
}
|
||||||
|
if (serie && aktuell.episodeCount != null) {
|
||||||
|
teile.push(`${aktuell.episodeCount} ${aktuell.episodeCount === 1 ? 'Folge' : 'Folgen'}`);
|
||||||
|
}
|
||||||
|
teile.push(`${aktuell.fileCount} ${aktuell.fileCount === 1 ? 'Datei' : 'Dateien'}`);
|
||||||
|
if (aktuell.extraVersionCount > 0) {
|
||||||
|
teile.push(`${aktuell.extraVersionCount} zweite Fassung`
|
||||||
|
+ (aktuell.extraVersionCount === 1 ? '' : 'en'));
|
||||||
|
}
|
||||||
|
if (aktuell.unassignedCount > 0) teile.push(`${aktuell.unassignedCount} nicht zugeordnet`);
|
||||||
|
if (aktuell.pendingCount > 0) {
|
||||||
|
teile.push(`${aktuell.pendingCount} wartet${aktuell.pendingCount === 1 ? '' : 'en'} auf Freigabe`);
|
||||||
|
}
|
||||||
|
|
||||||
kopf.innerHTML = `<strong>${esc(aktuell.name)}</strong>`
|
kopf.innerHTML = `<strong>${esc(aktuell.name)}</strong>`
|
||||||
+ `<span class="winzig">${esc(aktuell.path)}${esc(anzahl)}${esc(wartet)}</span>`;
|
+ `<span class="winzig">${esc(teile.join(' · '))}</span>`;
|
||||||
}
|
}
|
||||||
kopfSchreiben();
|
kopfSchreiben();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user