Widget registry and "add widget" picker #21
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
GridStackView.addWidget()only ever creates a placeholder:So "Widget hinzufügen" adds an empty card with the text "Frei platzierbare Karte." — a layout demo, not a dashboard feature.
Worse, the combination with #14 (closable widgets) is lossy: closing the revenue-trend widget removes it permanently, and there is no way to get it back short of a full page reload. The user can destroy the dashboard but not rebuild it.
Proposal
Introduce a widget registry:
WidgetDefinitionrecord: stable type id, i18n title key, default grid size (w/h), and aSupplier<Component>factory.Dialoglisting the registered definitions instead of blindly appending a placeholder.addWidget()applies: a closed widget's id must never be handed to a new widget, or the new one inherits the closed one's saved position.Acceptance criteria
./mvnw testgreen, with coverage for "add widget of type X appears in the grid".Depends on
The dashboard merge, and ideally the data service layer (widget factories should pull from it rather than re-introducing literals).
Scope
Medium. Likely > 200 lines — split if needed (registry first, picker dialog second).
needs human — AI-Autofix bricht ohne Codeänderung ab.
Gründe (siehe
CLAUDE.md→ "AI-Autofix – Regeln"):ai-ready-Label. Das Issue trägt aktuell nurenhancement. Die Autofix-Regeln erlauben ausschließlich die Bearbeitung von Issues mitai-ready.WidgetDefinition-Record, eine Registry als Spring-Bean, ein Picker-Dialog, die Umstellung vonDashboardViewauf die Registry plus Tests liegen realistisch darüber.src/main/java/com/example/enthält nurcomponents/undviews/, keinen Service). Ohne sie würden die Widget-Factories die Literale ausDashboardViewerneut duplizieren statt sie zu zentralisieren — genau das, was das Issue vermeiden will.Ergänzende Beobachtung zum Issue-Text:
GridStackViewexistiert nicht mehr. Mit #19 (Merge vonDashboardViewundGridStackView) ist die zitierte Methode nachDashboardView.addWidget()gewandert (src/main/java/com/example/views/DashboardView.java:79). Inhaltlich ist die Beschreibung weiter korrekt — es wird nach wie vor nur ein Platzhalter-Cardmitgridstack.widgetTextangelegt.Vorschlag für die Aufteilung, damit die Teile einzeln autofix-fähig werden:
List.of(30.0, 40.0, ...), Monats- und Regionslisten) ausDashboardView.WidgetDefinition(Typ-Id, i18n-Key, Default-w/h,Supplier<Component>) plus Registry-Bean;DashboardViewlegt seine vier Startwidgets darüber an. Rein additiv, kein UI-Wechsel.addWidget()beschreibt die Anforderung: ein geschlossenes Widget darf seine Id nie an ein neues weitergeben) und das Akzeptanzkriterium "geschlossenes Widget lässt sich wieder hinzufügen".Jeder Teil bleibt für sich unter der Zeilengrenze. Nach dem Zuschnitt bitte
ai-readyan die Teil-Issues vergeben.PR: #35
Die beiden harten Blocker aus dem vorigen Kommentar sind weg:
ai-readyist gesetzt, und die Data-Service-Schicht existiert seit #20 (com.example.data.ChartDataService), die Widget-Factories ziehen ihre Zahlen daraus.Umgesetzt in einem PR statt in zwei Teilen:
widgets/WidgetDefinition(Typ-Id, i18n-Key, Default-w/h,Supplier<Component>) undwidgets/WidgetRegistryals@Service.DashboardViewin die Registry-Factories;DashboardViewbaut auch seine Start-Widgets darüber (Ids und Platzierung unverändert, damit gespeicherte Layouts weiter passen).Dialogüber der Registry.<typ>-<n>aus einem nur wachsenden, typübergreifenden Zähler — die Id eines geschlossenen Widgets wird nie erneut vergeben.gridstack.pickerTitle, die ungenutztengridstack.widget/gridstack.widgetTextentfallen../mvnw test: 31 Tests grün. Neue Abdeckung u.a. "Widget vom Typ X hinzufügen erscheint im Grid", "geschlossenes Widget lässt sich wieder hinzufügen", "gleicher Typ zweimal → verschiedene Ids".Scope-Hinweis: ~320 hinzugefügte Zeilen, also über der ~200-Zeilen-Grenze aus
CLAUDE.md(ca. ein Drittel davon Tests und Javadoc). Registry und Picker getrennt zu liefern hätte im ersten Schritt eine Registry ohne Nutzer bzw. im zweiten einen Picker ohne Inhalt bedeutet — deshalb zusammen, aber hiermit explizit gemeldet. Auf Wunsch teile ich den PR in "nur Registry" und "Picker" auf.