Skip to content

#1414 - Alle Favoriten im Dialog suchen und anwenden, Kurzliste der zuletzt benutzten, eigene Gruppen und Reihenfolge - #1422

Merged
KlausRicharz merged 6 commits into
mainfrom
feature/1414-favoriten-gruppieren
Oct 7, 2026
Merged

KlausRicharz merged 6 commits into
mainfrom
feature/1414-favoriten-gruppieren

Conversation

@KlausRicharz

@KlausRicharz KlausRicharz commented Oct 7, 2026 •

Copy link
Copy Markdown
Member

Beschreibung

Im Kern bringt der PR die vollständige Liste aller Favoriten und die Auswahl daraus. Dazu kommen Sortierung und eigene, benannte Gruppen.

Kurzliste. Das Dropdown „Favorit anwenden“ und die Karte „Favoriten“ der Einzelübersicht zeigen die X zuletzt benutzten Favoriten, ohne Gruppen, den zuletzt angewendeten zuerst. Neu angelegte zählen als gerade benutzt. Darunter bzw. im Kartenkopf steht „Alle Favoriten (N) …“ und öffnet den Dialog, auch wenn N ≤ X ist; dort wird auch geordnet.

X ist eine persönliche Einstellung (Einstellungen → „Favoriten in der Kurzliste“): Standard 10, erlaubt 1–50. Der Wert wird im Service geprüft (FA-0008). Ein Wert außerhalb lehnt das Formular ab und speichert dann nichts. Gespeichert wird er wie die Sortierung in der Benutzereinstellung (Modul favorites).

Dialog „Favoriten“ (FavoriteDialogController, favorites/dialog.html):

  • Auswahl: alle Favoriten nach Gruppen; Gruppen lassen sich einklappen (<details>).
  • Suche: Das Suchfeld oben hat beim Öffnen den Fokus. Es filtert im Browser nach Auftrag/Unterauftrag, Kommentar und Ticket-Referenz, jedes Wort muss vorkommen, Akzente zählen nicht. Treffer in eingeklappten Gruppen klappen die Gruppe auf, Gruppen ohne Treffer verschwinden, ohne Treffer erscheint ein Hinweis.
  • Anwenden: Ein Klick auf einen Favoriten wendet ihn an, ebenso Enter auf einem fokussierten Favoriten oder Enter im Suchfeld beim einzigen Treffer.
    • Es ist derselbe Weg wie aus der Liste: Die Knöpfe des Dialogs gehören über form= zum Formular favoritesApplyForm der Seite. Gleicher Endpunkt (/dailyreport/daily/apply-favourite), gleiche Antwort, gleiche Fehlerbehandlung, „zuletzt benutzt“ wird gesetzt.
    • Danach schließt sich der Dialog, und die Einzelübersicht aktualisiert sich über die htmx-Antwort.
  • Ordnen liegt hinter dem Schalter „Ordnen“. Erst dort erscheinen Griffe, Pfeile, Gruppenverwaltung und die Wahl der Sortierung, und ein Klick wendet nichts an. Solange das Suchfeld einen Begriff enthält, ist der Schalter gesperrt.
    • Gruppen anlegen, umbenennen, löschen. Das Löschen läuft über den gemeinsamen Bestätigungsdialog; die Favoriten bleiben ohne Gruppe erhalten.
    • Sortierung „Zuletzt benutzt“ oder „Eigene Reihenfolge“.
    • Drag & Drop mit SortableJS (WebJar, MIT) mit Maus und Touch, nur am Griff, für Gruppen und Favoriten innerhalb von und zwischen Gruppen.
    • Für die Tastatur Pfeilknöpfe mit sprechendem Namen.
  • Mobil: Der Dialog öffnet im Vollbild, Kopf und „Fertig“ bleiben im sichtbaren Bereich.

Neuer Favorit. „Als Favorit speichern“ bietet eine Gruppenauswahl an, sobald die Person Gruppen hat. Ohne Wahl steht der Favorit oben in „Ohne Gruppe“.

Eigentum. Gruppen, Ordnung und Einstellungen gehören der Person. FavoriteService prüft jede id aus dem Browser: Favorit über seinen Mitarbeiterauftrag (#1369), Gruppe über employee_id.

  • Fremde ids lehnt er ab, inzwischen gelöschte überspringt er, doppelte weist er ab.
  • Abgedeckt durch Unit-Tests, nicht durch E2E.
  • Das Anwenden eines fremden Favoriten wird jetzt ebenfalls abgewiesen.

Smartphone-Breite der Einzelübersicht. Auf 390 px war die Einzelübersicht breiter als der Bildschirm. Behoben ist die Ursache:

Datenbank (Changesets 173–175, hinter 171 aus #1421)

  • 173: Tabelle favorite_group (employee_id mit FK ON DELETE CASCADE, name varchar(64), position, Audit-Spalten) und Unique-Schlüssel uk_favorite_group_employee_id_name (im ConcurrentModificationAspect auf FA-0004 abgebildet).
  • 174: favorite.favorite_group_id, FK ON DELETE SET NULL.
  • 175: favorite.position und favorite.last_used, beide nullable, ohne Datenmigration.

Lokal gegen MySQL geprüft: Vorher war der Stand bis 166; 173–175 liefen durch, Spalten, FKs und Unique-Schlüssel sind angelegt.

ETL / Reports / Views

report_definition (102), etl_definition (9), die Views (9) sowie Routinen und Trigger der lokalen DB wurden auf favorite, favourite, favorite_group und last_used durchsucht: 0 Treffer. Keine Definition liest die Favoriten-Tabellen, und auch kein Generator im Code.

Entscheidungen

  • Kurzliste nach Benutzung, unabhängig von Gruppen und eigener Reihenfolge. Sie soll das Häufige schnell anbieten; das Ordnen betrifft den Dialog.
  • Die Sortierung gilt innerhalb der Gruppen des Dialogs. Die Gruppen stehen in der eigenen Reihenfolge, „Ohne Gruppe“ immer oben.
    • Im Modus „Zuletzt benutzt“ sortieren Ziehen und Pfeile nicht innerhalb einer Gruppe, verschieben aber zwischen Gruppen.
    • Ein verschobener Favorit steht in der eigenen Reihenfolge oben in der neuen Gruppe.
  • Anwenden aus dem Dialog über das Formular der Seite (form=). So bleibt der Dialog im Modul favorites und kennt weder Tag noch Endpunkt, und es gibt keine zweite Implementierung des Anwendens.
    • Ein Anwenden schließt den Dialog ohne Neuladen; die htmx-Antwort aktualisiert den Tag.
    • Nach einer Änderung im Ordnen-Modus lädt das Schließen die Seite neu.
  • Suche im Browser, solange alle Favoriten im Dialog stehen. Das generische Verhalten (data-list-filter, data-filter-*) steht in salat.js, beschrieben im Style Guide §5.10.
  • Ordnen ist bei aktiver Suche gesperrt, weil eine gefilterte Liste beim Ziehen eine Reihenfolge speichern würde, die niemand gesehen hat.
  • Einstellungen über das settings-Modul: Sortierung und X als FavoritePreferences. Dafür darf favorites jetzt settings importieren (ArchitectureTest-Regel angepasst und begründet).
  • Die Reihenfolge steht in der Seite. Versteckte Felder in Dokumentreihenfolge bilden die Anordnung (FavoriteLayout). Generisches data-sortable* in salat.js, siehe AGENTS.md und Style Guide §5.9.
  • REST (/api/favorite): GET liefert alle Favoriten in der Reihenfolge des Dialogs und dazu groupName, nur lesend. PUT legt ohne Gruppe an. Abwärtskompatibel.
  • Kleine Erweiterungen:
    • salat:select kann allowEmptyOption, salat:textInput kann min/max; beides in der AGENTS.md-Tabelle ergänzt.
    • Der Dialog tauscht mit hx-swap="innerHTML settle:0" (Style Guide §5.7).
    • Steht der Bestätigungsdialog vor einem anderen Dialog, bleibt die Seite gesperrt.
  • Favoriten nur am eigenen Tag. Favoriten gehören der angemeldeten Person (Favoriten: Mitarbeiterauftrag als Referenz, transitive Spalte employeeId entfernen #1369). Sieht ein People Lead oder Manager den Tag einer anderen Person, entfallen Dropdown und Karte. Ob der Tag der eigene ist, entscheidet AuthorizedEmployee, wie bei „Als Favorit speichern“. Die Person des Vertrags liest DailyController als Wert über EmployeecontractService.getEmployeeIdOfEmployeecontract. Die Methode ist für jeden Login offen (@Authorized), weil die Klasse sonst Manager verlangt.
  • „Alle Favoriten (N) …“ ist ein einfacher Link (<a href="#favoritesDialog">), ohne Icon und ohne Knopf- oder Menüpunktfläche.
  • Kein eigenes ADR für SortableJS. Die Projekt-ADRs halten Muster fest, keine Bibliotheken. Das Muster data-sortable* steht in AGENTS.md und im Style Guide.

Akzeptanzkriterien / Testplan

  • jenv exec ./mvnw verify: 3702 Tests grün, inklusive ArchitectureTest und MessageResourcesConsistencyTest.
  • Unit-Tests:
    • FavoriteServiceTest: Kurzliste begrenzt auf X und nach Benutzung, Gesamtzahl, Einstellung X mit Standard und Validierung, Sortierung, Gruppen, Anordnen, Eigentumsprüfungen.
    • FavoritePreferencesTest, FavoriteDialogControllerTest (Auswahl- und Ordnen-Modus, Fehler im Dialog), SettingsFavoriteListSizeTest (ungültiges X speichert nichts), FavoriteLayoutTest, FavoriteDTOMapperTest, ApplyFavouriteTicketReferenceTest.
  • E2E gezielt in Chrome grün:
    • neu FavoriteDialogE2ETest: Bedienablauf Suchfeld fokussiert, Ordnen gesperrt bei Suche, Enter auf dem einzigen Treffer bucht und schließt den Dialog.
    • außerdem ConfirmDialogE2ETest, DailyBookingE2ETest, ApplyPreviousBookingE2ETest.
  • Browser Desktop:
    • Kurzliste mit 10 von 13 und „Alle Favoriten (13) …“.
    • Suche nach Ticket und Kommentar, Treffer in eingeklappter Gruppe, leere Gruppen ausgeblendet, Hinweis ohne Treffer.
    • Anwenden per Enter und per Klick: Dialog zu, Buchung da, Kurzliste aktualisiert, kein Neuladen.
    • Ordnen-Modus mit Pfeilen und zurück zur Auswahl.
    • Einstellung X: 0 abgewiesen mit Meldung, 3 gespeichert, Kurzliste zeigt 3.
  • Smartphone-Emulation (390×844, mobil + Touch):
    • Einzelübersicht ohne horizontalen Überlauf (scrollWidth == innerWidth == 390).
    • Dialog im Vollbild, Suchfeld fokussiert, Kopf und „Fertig“ sichtbar.
    • Antippen wendet an; Ordnen-Modus mit Ziehen per Touch zwischen Gruppen gespeichert.
  • DailyFavouritesTest: Der eigene Tag bietet die Favoriten an, der Tag einer anderen Person nicht.
  • Browser, Favoriten nur am eigenen Tag: Ein People Lead sieht sie auf dem eigenen Tag, auf dem Tag einer anderen Person fehlen Dropdown und Karte. Ein Mitarbeiter sieht die eigenen ohne Fehler.
  • Browser: „Alle Favoriten (N) …“ in Karte und Dropdown als Link, öffnet den Dialog, die Adresse bleibt unverändert.
  • Kontrast: Hinweistext in leeren Gruppen und Griff 4,74:1 (hell) und 6,00:1 (dunkel).

Operations / Deployment Notes

  • Liquibase-Changesets 173–175 legen eine Tabelle und drei nullable Spalten an. Kein Handgriff, keine Datenmigration. Ein Release vor diesem startet danach weiter.
  • Neue Laufzeitabhängigkeit: WebJar org.webjars.npm:sortablejs 1.15.7 (MIT).

Reviewed AGENTS.md; changes comply with architecture, view, and security guidelines.

Closes #1414

@KlausRicharz
KlausRicharz force-pushed the feature/1414-favoriten-gruppieren branch from d48c5bc to f964c61 Compare October 7, 2026 21:45
@KlausRicharz KlausRicharz changed the title #1414 - Favoriten nach letzter Benutzung sortieren und in eigene Gruppen ordnen #1414 - Alle Favoriten im Dialog suchen und anwenden, Kurzliste der zuletzt benutzten, eigene Gruppen und Reihenfolge Oct 7, 2026
Klaus Richarz added 3 commits October 8, 2026 00:11
… einordnen und per Drag & Drop oder Pfeilen ordnen

Ohne eigene Ordnung steht der zuletzt angewendete Favorit oben. Der Dialog "Favoriten ordnen",
erreichbar von jeder Favoritenliste, legt benannte Gruppen an, benennt sie um, loescht sie
(Favoriten bleiben ohne Gruppe erhalten) und stellt die Sortierung ein. Gruppen und Favoriten
lassen sich mit SortableJS ziehen, mit Maus und Touch, und mit Pfeilknoepfen per Tastatur
verschieben. Beim Speichern als Favorit laesst sich eine Gruppe waehlen. Gruppen und Ordnung
gehoeren der Person; der Service prueft jede id. Changesets 173 bis 175.
…dschirm: Knopfzeile bricht um, Buchungstext begrenzt die Tabelle, Vollbild-Dialog nimmt die sichtbare Hoehe
… mit Suche und Auswahl, Ordnen als Modus

Einzeluebersicht und "Favorit anwenden" zeigen die X zuletzt benutzten Favoriten ohne Gruppen, X ist
in den Einstellungen waehlbar (1 bis 50, Standard 10, serverseitig geprueft). "Alle Favoriten (N)"
oeffnet den Dialog: alle Favoriten nach Gruppen, Suchfeld ueber Auftrag, Kommentar und Ticket, ein
Klick oder Enter wendet den Favoriten ueber dasselbe Formular und denselben Endpunkt an wie die Liste.
Gruppen, Sortierung und Drag & Drop liegen hinter dem Schalter "Ordnen", der bei aktiver Suche ruht.
@KlausRicharz
KlausRicharz force-pushed the feature/1414-favoriten-gruppieren branch from 072979e to 42e8a25 Compare October 7, 2026 22:11
@KlausRicharz
KlausRicharz merged commit aa49321 into main Oct 7, 2026
6 checks passed
@KlausRicharz
KlausRicharz deleted the feature/1414-favoriten-gruppieren branch October 7, 2026 22:51
@github-actions github-actions Bot added the enhancement New feature or request label Oct 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Favoriten Sortieren und oder Gruppieren

1 participant