On replie par defaut les série dans le catalogue.

Un bouton permet de déplier/replier toutes les séries d'un coup.
This commit is contained in:
mathieu
2026-09-10 01:39:17 +02:00
parent 61d4fb1678
commit 47d371fa3a
2 changed files with 59 additions and 17 deletions
+12 -13
View File
@@ -4,9 +4,9 @@
Un bloc de série au catalogue, replié ou déplié — et récursif, parce qu'un cycle est une Un bloc de série au catalogue, replié ou déplié — et récursif, parce qu'un cycle est une
série de séries : chaque niveau porte sa propre bascule. série de séries : chaque niveau porte sa propre bascule.
⚠️ Tout est PLIÉ par défaut, et l'on replie ce dont on ne veut pas. C'est la règle déjà ⚠️ Tout est REPLIÉ par défaut ici (2026-09-10), à l'inverse de l'arbre des séries : le
tenue par l'arbre des séries : l'inverse obligerait à ouvrir chaque bloc pour retrouver un catalogue liste D'ABORD les livres, une série n'y est qu'un détail qu'on ouvre au besoin —
livre qu'on voyait très bien avant. alors que l'écran des séries EST la liste des séries, où les masquer toutes viderait l'écran.
⚠️ Replié, le bloc annonce toujours ce qu'il contient : sans ce compte, le compteur du haut ⚠️ Replié, le bloc annonce toujours ce qu'il contient : sans ce compte, le compteur du haut
du catalogue paraîtrait mentir. du catalogue paraîtrait mentir.
@@ -43,7 +43,7 @@
<ul class="liste-livres"> <ul class="liste-livres">
@foreach (var sous in Entree.SousEntrees) @foreach (var sous in Entree.SousEntrees)
{ {
<GroupeCatalogue Entree="sous" Replies="Replies" Totaux="Totaux" /> <GroupeCatalogue Entree="sous" Ouverts="Ouverts" Totaux="Totaux" />
} }
</ul> </ul>
} }
@@ -66,15 +66,14 @@
[Parameter, EditorRequired] public EntreeCatalogue Entree { get; set; } = default!; [Parameter, EditorRequired] public EntreeCatalogue Entree { get; set; } = default!;
/// <summary> /// <summary>
/// Blocs REPLIÉS, par identifiant de série — et non pliés : le défaut est de tout montrer. /// Blocs OUVERTS, par identifiant de série — et non repliés : le défaut est de tout replier.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// État local de l'écran, volontairement non persistant, comme celui de l'arbre des séries : /// État local de l'écran, volontairement non persistant : c'est un confort de lecture, pas
/// c'est un confort de lecture, pas une propriété de la série. Il survit en revanche aux /// une propriété de la série. Il survit en revanche aux rechargements du catalogue (frappe
/// rechargements du catalogue (frappe dans la recherche, filtre), le jeu appartenant à /// dans la recherche, filtre), le jeu appartenant à l'écran et non au bloc.
/// l'écran et non au bloc.
/// </remarks> /// </remarks>
[Parameter, EditorRequired] public ISet<int> Replies { get; set; } = new HashSet<int>(); [Parameter, EditorRequired] public ISet<int> Ouverts { get; set; } = new HashSet<int>();
/// <summary> /// <summary>
/// Compteurs par série, descendance comprise : ce qu'on possède, et ce que la série recense. /// Compteurs par série, descendance comprise : ce qu'on possède, et ce que la série recense.
@@ -95,13 +94,13 @@
private int Total => Compte.Total; private int Total => Compte.Total;
private bool Deplie => !Replies.Contains(Entree.Serie!.Id); private bool Deplie => Ouverts.Contains(Entree.Serie!.Id);
private void Basculer() private void Basculer()
{ {
if (!Replies.Add(Entree.Serie!.Id)) if (!Ouverts.Add(Entree.Serie!.Id))
{ {
Replies.Remove(Entree.Serie!.Id); Ouverts.Remove(Entree.Serie!.Id);
} }
} }
} }
+47 -4
View File
@@ -32,6 +32,14 @@
Filtrer@(FiltresActifs > 0 ? $" ({FiltresActifs})" : "") Filtrer@(FiltresActifs > 0 ? $" ({FiltresActifs})" : "")
</button> </button>
@if (_grouper && Entrees.Any(e => e.EstGroupe))
{
<button type="button" class="bouton bouton-discret bouton-compact"
@onclick="() => { if (AuMoinsUneSerieOuverte) { ToutReplier(); } else { ToutDeplier(); } }">
@(AuMoinsUneSerieOuverte ? "Replier les séries" : "Déplier les séries")
</button>
}
@if (Reseau.EnLigne) @if (Reseau.EnLigne)
{ {
<a class="bouton bouton-principal bouton-compact" href="ajout">Ajouter un ouvrage</a> <a class="bouton bouton-principal bouton-compact" href="ajout">Ajouter un ouvrage</a>
@@ -228,13 +236,18 @@ else if (_livres is not null)
tomes occupait tout l'écran alors qu'on cherchait un livre rangé après lui. Replier ne tomes occupait tout l'écran alors qu'on cherchait un livre rangé après lui. Replier ne
retire rien de la liste — le compteur du haut ne bouge pas, et le bloc replié dit retire rien de la liste — le compteur du haut ne bouge pas, et le bloc replié dit
toujours ce qu'il contient. toujours ce qu'il contient.
⚠️ Ici, contrairement à l'arbre des séries, tout est REPLIÉ par défaut (2026-09-10) :
le catalogue liste des livres, pas des séries — une série n'y est qu'un regroupement
qu'on ouvre au besoin. Le bouton qui bascule tout l'arbre est dans l'en-tête, à côté
de « Filtrer », pas ici : c'est un réglage d'affichage, pas une action sur la liste.
*@ *@
<ul class="liste-livres"> <ul class="liste-livres">
@foreach (var entree in Entrees) @foreach (var entree in Entrees)
{ {
@if (entree.EstGroupe) @if (entree.EstGroupe)
{ {
<GroupeCatalogue Entree="entree" Replies="_replies" Totaux="_totauxSeries" /> <GroupeCatalogue Entree="entree" Ouverts="_ouverts" Totaux="_totauxSeries" />
} }
else else
{ {
@@ -269,15 +282,45 @@ else if (_livres is not null)
private bool _grouper = true; private bool _grouper = true;
/// <summary> /// <summary>
/// Blocs repliés à la main, par identifiant de série. Tout est plié par défaut. /// Blocs ouverts à la main, par identifiant de série. Tout est replié par défaut.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// ⚠️ Le jeu appartient à l'ÉCRAN, et non aux blocs : le catalogue se relit à chaque frappe /// ⚠️ Le jeu appartient à l'ÉCRAN, et non aux blocs : le catalogue se relit à chaque frappe
/// dans la recherche, et un état porté par les composants se perdrait à chaque caractère. /// dans la recherche, et un état porté par les composants se perdrait à chaque caractère.
/// Il n'est pas persistant d'une visite à l'autre pour autant — c'est un confort de /// Il n'est pas persistant d'une visite à l'autre pour autant — c'est un confort de
/// lecture, pas une propriété de la série, même règle que l'arbre des séries. /// lecture, pas une propriété de la série.
/// </remarks> /// </remarks>
private readonly HashSet<int> _replies = []; private readonly HashSet<int> _ouverts = [];
private bool AuMoinsUneSerieOuverte => _ouverts.Count > 0;
private void ToutReplier() => _ouverts.Clear();
private void ToutDeplier()
{
foreach (var id in IdentifiantsSeries(Entrees))
{
_ouverts.Add(id);
}
}
private static IEnumerable<int> IdentifiantsSeries(IEnumerable<EntreeCatalogue> entrees)
{
foreach (var entree in entrees)
{
if (!entree.EstGroupe)
{
continue;
}
yield return entree.Serie!.Id;
foreach (var id in IdentifiantsSeries(entree.SousEntrees))
{
yield return id;
}
}
}
/// <summary> /// <summary>
/// Ce que chaque série possède et recense, descendance comprise. /// Ce que chaque série possède et recense, descendance comprise.