Skip to content

Commit 0b53ec8

Browse files
Feature/tree (#980)
* init moox/demo * update moox/category seeder * update moox/user seeder * Fix styling * update draft seeder * Add record seeder * add item seeder * add tag seeder * Fix styling * Add moox/product seeder * update seeder logic * Fix styling * Update TagSeeder.php * remove files * update moox/demo language values * Update CategorySeeder.php * Update DraftSeeder.php * Update ItemSeeder.php * Update ProductSeeder.php * Update RecordSeeder.php * Update TagSeeder.php * Update UserSeeder.php * Fix styling * remove FAKER_LOCALE_MAP * Fix phpstan errors * Fix phpstan errors * Fix phpstan errors * Fix phpstan errors * Fix phpstan errors * Fix phpstan errors * Fix styling * update package default local values * update max faker string length * Fixx css for tree view * add moox/tree feature searching, filter and language switcher * Fix styling * Update README.md * update options for tools * add skill moox/tree * Fix create form * Refactoring + test * Fix styling * Fix Chevron button * update language switcher * update create position * clear step * Update TitleWithSlugInput.php Problem: Nutzer gibt Titel ein → speichert sofort → Slug ist noch leer → required auf dem Slug schlägt fehl, bevor Dehydration läuft. Sie löst ein generisches Filament-Problem. Ihr könnt es anders lösen, aber die aktuelle Lösung in moox/slug ist die sauberste. * update moox/tree new version * Fix styling * Update media-picker.blade.php --------- Co-authored-by: Reinhold-Jesse <88349887+Reinhold-Jesse@users.noreply.github.com>
1 parent a69f282 commit 0b53ec8

88 files changed

Lines changed: 6082 additions & 993 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
---
2+
description: After package changes, review and update the matching Cursor skill (registry-driven)
3+
globs: packages/**
4+
alwaysApply: false
5+
---
6+
7+
# Package ↔ Skill sync
8+
9+
When you **change or finish work** under `packages/{package}/**`, check whether that package has a Cursor skill. **Only packages listed in `.cursor/skills/registry.yaml` require sync.**
10+
11+
## 1. Resolve package name
12+
13+
From the edited path: `packages/tree/src/...` → `tree`.
14+
15+
## 2. Look up the registry
16+
17+
Read `.cursor/skills/registry.yaml`. If `{package}` is **not** listed under `packages:`, **stop** — no skill sync for this package.
18+
19+
If listed, note `skill`, `skill_path`, `package_readme`, and `skill_files`.
20+
21+
## 3. Decide if the skill needs updates
22+
23+
**Update the skill** when the package change affects anything documented for integrators:
24+
25+
| Change in package | Review / update in skill |
26+
|-------------------|--------------------------|
27+
| `TreeServiceProvider`, Filament assets, CSS/JS, publish tags, Composer `require` | `installation.md`, verification checklists |
28+
| Public API: config fluent methods, traits, contracts, page classes, hooks | `integration.md` templates, `decisions.md`, `SKILL.md` references |
29+
| New toolbar / locale / inspector behavior or decision branches | `decisions.md`, `integration.md` § toolbar |
30+
| Renames, removals, breaking behavior | All listed `skill_files` + checklists |
31+
| Gold-standard consumer pattern changed | `SKILL.md` references table, `integration.md` examples |
32+
33+
**Skip skill updates** when:
34+
35+
- Internal refactor with **no** public API, install, or integrator-facing behavior change
36+
- Tests-only, comments-only, or formatting-only diffs
37+
38+
When unsure, read the changed classes and compare against the skill docs — update if anything integrators rely on is now wrong or missing.
39+
40+
## 4. How to update (minimal scope)
41+
42+
1. Read the skill's `SKILL.md` and the files listed in `skill_files`.
43+
2. Read `{package_readme}` for canonical package documentation.
44+
3. Patch **only** sections that are stale — do not rewrite unrelated skill content.
45+
4. Keep skill language consistent with existing files in that skill (e.g. `moox-tree` uses English for install/integration checklists).
46+
5. If install/API sections in `{package_readme}` changed materially, mirror the facts in the skill; do not duplicate the full README.
47+
48+
## 5. Report in the session
49+
50+
If a registry package was edited and the skill was updated, briefly state which skill files changed and why. If no skill update was needed, no extra report required.
51+
52+
## 6. Adding a new package skill (future)
53+
54+
When creating a skill for another package:
55+
56+
1. Add folder `.cursor/skills/{skill-name}/` with `SKILL.md`.
57+
2. Add an entry under `packages:` in `registry.yaml` (`skill`, `skill_path`, `package_readme`, `skill_files`).
58+
3. Optionally add a package-specific rule under `.cursor/rules/` — it does **not** replace this sync rule.
59+
60+
## Current registry
61+
62+
| Package | Skill |
63+
|---------|-------|
64+
| `tree` | `moox-tree` |
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
---
2+
description: Filament-Resources an Moox Tree anbinden (Consumer außerhalb packages/tree)
3+
globs: "**/*TreeResource.php,**/TreeList*.php,**/TreeInspector*.php"
4+
alwaysApply: false
5+
---
6+
7+
# Moox Tree – Resource-Integration
8+
9+
Wenn eine Resource einen Baum-Index statt einer Tabelle nutzt.
10+
11+
## Zentrale Nutzung (keine Duplikation)
12+
13+
**Tree-Funktionen nicht in Consumer-Packages neu bauen** — kein eigenes Livewire für Baum-CRUD, keine kopierten Move/Reorder-Skripte, keine parallelen Action-Klassen.
14+
15+
Consumer liefert nur:
16+
17+
- `treeIndex(): TreeIndexConfiguration` mit `->forwardFromResource(static::class, useFilamentTableToolbar: true)` — **1:1** wie die Liste: Filament-`EmbeddedTable` (Tabs, Filter, Suche, Language-Switcher in `TOOLBAR_SEARCH_BEFORE`) + `applyFiltersToTableQuery()` / `applySearchToTableQuery()` auf der List-Page; kein separater Lang-Switcher in der Baum-Spalte
18+
- dünne Filament-Pages (`TreeIndexListRecords` als einziger Livewire-Host; optional standalone `TreeInspectorXxx` für Route `tree-inspector`)
19+
- ggf. `modifyQuery` / `applySearchUsing` / `applyLanguageUsing` als **Closures** (nur Datenfilter, keine Tree-Mechanik)
20+
21+
Braucht eine Resource ein Verhalten, das andere Bäume auch brauchen könnten → **Feature ins `packages/tree`**, dann per Config aktivieren.
22+
23+
## Eloquent-Models
24+
25+
**Models nicht um Tree-Funktionen erweitern** — keine Hilfsmethoden, Interfaces oder Traits nur für das Tree-Package (z. B. `getTreeLabel()`, `toTreeNode()`, `implements TreeNodeContract`).
26+
27+
Erlaubt am Model:
28+
29+
- Spalten/`$fillable` für `parent_id`, Sortierung, Label (oder konfigurierte Namen)
30+
- Bei Nested Set: Kalnoy **`NodeTrait`** (Pflicht für `nestedSet()`, sonst nichts Tree-spezifisches)
31+
- Domänen-Relations/Accessors, die ohnehin zur App gehören; Label-Accessor → `->labelColumnQueryable(false)` in der Resource
32+
33+
Tree-Mechanik gehört ins **Tree-Package**; die Resource **verdrahtet** nur über `treeIndex()`. Domänen-Inhalte (Tabs, Relationen, Medien) nur im **Inspector** (Filament Edit-Page), nicht als eigene Baum-Logik.
34+
35+
## Pflichten
36+
37+
1. Resource: `implements Moox\Tree\Contracts\ConfiguresTreeIndex` + `treeIndex(): TreeIndexConfiguration`.
38+
2. List-Page: `extends Moox\Tree\Filament\Pages\TreeIndexListRecords` (registriert Config in `mount()`).
39+
3. Routing: `'index' => TreeListXxx::route('/')`. Bei Moox-Parent-Resources: `...Arr::except(parent::getPages(), ['index'])` beibehalten.
40+
4. `modifyQuery` muss dieselbe Sicht wie `Resource::getEloquentQuery()` abbilden (Policies, Soft-Deletes, Mandanten).
41+
42+
## Inspector (empfohlen)
43+
44+
- In Config: `->inspectorPage(TreeInspectorXxx::class)`.
45+
- **Inline** (Standard): `TreeIndexListRecords` rendert `Resource::form()` rechts; Form-Actions via `TreeInlineFormResourceAdapter` — kein Consumer-Trait.
46+
- **Standalone** Route `tree-inspector`: Edit-Page mit `RendersAsTreeIndexInspector`; `$resource` = Basis-Resource (nicht Tree-Resource).
47+
- Create: Header-Action `createRootNode()` öffnet Resource-Create inline, wenn Create-Route in `getPages()` der Forward-Resource existiert; sonst `stubCreate()` oder Stub-Knoten.
48+
- Ohne `inspectorPage()`: eingebautes Minimalformular (Label + Parent).
49+
50+
## Nested Set & Label
51+
52+
- Accessor-Labels (z. B. `title` aus Translation): `->labelColumnQueryable(false)`.
53+
- Nested Set: `->nestedSet()->sortColumn('_lft')->reorderable(true)` und `kalnoy/nestedset` am Model.
54+
55+
## Toolbar (Suche / Sprache)
56+
57+
- Mit `useFilamentTableToolbar: true`: Suche, Filter und `localization::lang-selector` in der **Filament-Tabellen-Toolbar** (Render-Hook im Tree-Package); keine Tabellen-Sortierung („Sort by“), keine Zeilen-/Bulk-Actions — Reihenfolge nur im Baum (`sortColumn` / Drag).
58+
- Ohne Table-Toolbar: `toolbarSearch` / `toolbarLanguageSwitcher` in der Baum-Spalte; Resource liefert ggf. `applySearchUsing` / `applyLanguageUsing` — keine zweite Toolbar-Implementierung.
59+
60+
## Checkliste neue Resource
61+
62+
Model-Spalten (ohne Tree-Methoden) → `treeIndex()` → `TreeIndexListRecords` → Pages/Routes → optional Inspector → Feature-Test für Config oder `TreeIndexListRecords` / `TestTreeIndexHost`.
63+
64+
## UI-Schaltflächen & Formular
65+
66+
Inspector nutzt **1:1** `CategoryResource::form()` (bzw. `::form()` der Quell-Resource) — gleiche Felder, gleiche Actions, gleiches Verhalten (Save, Cancel, Redirects). Keine zusätzlichen Buttons und **keine** Form-/Action-Overrides in Tree-Pages ohne **ausdrückliche Nutzerfreigabe** (siehe `moox-tree-package.mdc`).
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
---
2+
description: Architektur und Konventionen für packages/tree (Moox Tree / filament-tree-index)
3+
globs: packages/tree/**
4+
alwaysApply: false
5+
---
6+
7+
# Moox Tree Package
8+
9+
Internes Filament-Resource-Index-UI für hierarchische Eloquent-Modelle (Baum links, Inspector rechts). Namespace: `Moox\Tree`. Views/Config-Tag: `filament-tree-index`.
10+
11+
## Zentrale Tree-Funktionen (Single Source of Truth)
12+
13+
**Alle Baum-Funktionen liegen in `packages/tree`** und werden von Consumer-Resources nur **konfiguriert**, nicht neu implementiert:
14+
15+
| Bereich | Zentrale Klassen/Komponenten |
16+
|--------|------------------------------|
17+
| CRUD / Verschieben | `Actions/Tree/*` |
18+
| Baumstruktur | `Support/TreeStructure` |
19+
| UI / Interaktion | `TreeIndexListRecords` + Concerns, `tree-index-content` Blade, Alpine `$store.filamentTreeIndex` |
20+
| Filament-Anbindung | `TreeIndexListRecords`, `Contracts\ConfiguresTreeIndex`, `HostsInlineResourceForm`, `InteractsWithResourceTreeIndex`, `InteractsWithTreeResourceInspectorForm` |
21+
| Inline Form-Actions | `TreeInlineFormResourceAdapter`, `ProvidesInlineResourceFormActions` (generiert, nicht im Consumer) |
22+
| Inspector-Persistenz | `PersistTreeResourceCreateAction`, `PersistTreeResourceUpdateAction`, `TreeResourcePageExecutor` |
23+
| Anpassung | `TreeIndexConfiguration` (Spalten, Modus, Hooks, Labels, Toolbar) |
24+
| Locale / Toolbar-i18n | `Support/TreeLocale`, `toolbarLocalizedTranslations()` |
25+
| List-Forwarding | `forwardFromResource()`, `Support/ResourceListForwarder` |
26+
27+
**Flexibel nutzbar** heißt: gleicher Code für jedes hierarchische Model — Unterschiede nur über `TreeIndexConfiguration::make()` (Spaltennamen, `nestedSet()`, `reorderable`, `inspectorPage`, Closures). Fehlt eine generische Fähigkeit (z. B. Toolbar-Suche), **im Package erweitern** und per Config/API freischalten — nicht in `category`, `menu-builder` o. Ä. duplizieren.
28+
29+
## Architektur (nicht verletzen)
30+
31+
- **Geschäftslogik in Actions**, nicht in Livewire oder Blade: `CreateTreeNodeAction`, `UpdateTreeNodeAction`, `MoveTreeNodeAction`, `DeleteTreeNodeAction`. Bei `nestedSet()` delegieren Create/Move an `*NestedSet*`-Actions (Kalnoy `NodeTrait`).
32+
- **`TreeIndexListRecords`** (einziger Livewire-Host) orchestriert nur (Auth, Query, Delegation an Actions, Events). Baum-UI via `table()->content(tree-index-content)` — **kein** separates Livewire-Component, **keine** Livewire-Aliase im Provider.
33+
- **Baumaufbau** nur über `TreeStructure` + `TreeIndexConfiguration`. Konfiguration ist **immutable** (Fluent API mit `cloneWith`); neue Optionen brauchen Unit-Tests in `TreeIndexConfigurationTest`.
34+
- **Registry**: List-Pages registrieren Config unter dem **Resource-Klassennamen** (`TreeIndexConfigurationRegistry`). Schlüssel nicht umbenennen ohne Migration aller Aufrufer.
35+
36+
## Zwei Baum-Modi
37+
38+
| Modus | Spalten | Konfiguration |
39+
|-------|---------|---------------|
40+
| Adjacency List (Default) | `parent_id`, `sort_order`, Label-Spalte | Standard-`make()` |
41+
| Nested Set | `_lft`, `_rgt`, optional `parent_id` | `->nestedSet()->sortColumn('_lft')`, Model mit `NodeTrait` |
42+
43+
Adjacency- und Nested-Set-Logik **nicht mischen** in einer Action.
44+
45+
## UI & Frontend
46+
47+
- Blade unter `resources/views`, Prefix `filament-tree-index::`.
48+
- **Filament-Komponenten** (`x-filament::*`) und `fi-*`-Klassen; Layout/Scroll in `resources/css/tree.css` (Klassen `fi-tree-*`). Kein separates Theme-CSS außerhalb des Packages für Tree-Layout.
49+
- Alpine-Baumzustand nur über **`$store.filamentTreeIndex`** (`scripts/alpine-tree-store.blade.php`). Keinen zweiten Store oder duplizierte Expand/Collapse-Logik in Partials.
50+
- Drag & Drop nur wenn `reorderable(true)`; Verschiebe-Validierung (nicht unter sich selbst / eigenes Kind) beibehalten.
51+
52+
## Eloquent-Models (Vertrag)
53+
54+
Das Package darf **keine eigenen Model-Methoden, Interfaces oder Contracts** voraussetzen. Nutzung nur über:
55+
56+
- **Spalten/Attribute**: `parent_id`, Sort-Spalte, Label-Spalte (konfigurierbar), bei Nested Set `_lft`/`_rgt`
57+
- **Eloquent-Standard**: `getKey()`, `getAttribute()`, `update()`, `delete()`, `setAttribute()`
58+
- **Nested Set**: ausschließlich Kalnoy `NodeTrait` (`appendToNode`, `beforeNode`, …) — kein zusätzliches Tree-Trait im Moox-Package
59+
60+
Neue Features im Package müssen über **Config/Actions/Resource-Hooks** lösbar sein, nicht über `if (method_exists($model, …))` oder Model-APIs.
61+
62+
## Package-Grenzen
63+
64+
- **Keine domänenspezifischen Daten** im Package (keine `Category`-, `Localization`- oder Mandanten-Queries). Domänenfilter nur über **konfigurierbare Closures** (`modifyQuery`, `applySearchUsing`, `applyLanguageUsing`).
65+
- **Generische Tree-UI und -Abläufe** (Toolbar, Reorder, Expand, Inspector-Einbettung, Validierung) gehören ins Package — auch wenn heute nur eine Resource sie nutzt.
66+
- Abhängigkeit `moox/core` ist erlaubt; weitere Moox-Packages nur wenn unvermeidbar und zyklusfrei.
67+
68+
## Code-Stil
69+
70+
- `declare(strict_types=1);` in jeder PHP-Datei.
71+
- PHP ^8.3, Laravel ^12, Filament ^4/5 wie im Host-Projekt, Livewire ^3/4.
72+
- Typisierte Closures für Query-Hooks: `fn (Builder $query): Builder`.
73+
74+
## Tests
75+
76+
- Tests nur unter `packages/tree/tests/` (Pest). Feature = `TreeIndexListRecords`; isolierte Baum-Logik = `TestTreeIndexHost` (nutzt `InteractsWithResourceTreeIndex`); Unit = Config, `TreeStructure`, `TreeInlineFormResourceAdapter`, Registry.
77+
- Auth in Tests: `config(['filament-tree-index.authorization.enabled' => false])` und Registry-Register mit Test-Key.
78+
- Nach Verhalten ändern: `php artisan test --compact packages/tree/tests`
79+
80+
## Referenz-Integration (außerhalb des Packages)
81+
82+
Consumer-Resources (`implements ConfiguresTreeIndex`) gehören **nicht** in dieses Package — siehe Regel `moox-tree-integration`. Referenz: `CategoryTreeResource`, `TreeListCategories`, `TreeInspectorCategory`.
83+
84+
## Skill-Sync (nach Package-Änderungen)
85+
86+
`packages/tree` ist in `.cursor/skills/registry.yaml` eingetragen. Nach Änderungen an **öffentlicher API**, **Installation/Assets** (`TreeServiceProvider`, CSS, Alpine-Store, `filament:assets`) oder **integrator-relevantem Verhalten**: Regel **`moox-package-skill-sync`** anwenden und Skill **`moox-tree`** (`installation.md`, `integration.md`, `decisions.md`, `SKILL.md`) auf den aktuellen Stand bringen.
87+
88+
## UI-Schaltflächen & Formular (verbindlich)
89+
90+
- **Keine neuen Buttons, Footer-Actions oder Blade-`wire:click`-Schaltflächen** im Tree-Package oder in Consumer-Tree-Pages hinzufügen, ändern oder duplizieren — **ohne vorherige Rückfrage und ausdrückliche Bestätigung** durch den Nutzer.
91+
- Inspector-Formular = **unverändert** `Resource::form()` der Quell-Resource (Felder + Actions 1:1). **Keine** Action-Umverdrahtung, **keine** zusätzlichen Buttons.
92+
- Inspector inline auf `TreeIndexListRecords`: `InteractsWithTreeResourceInspectorForm`, `TreeInlineFormResourceAdapter` (Form-Actions ohne Redirect), `PersistTreeResourceCreateAction` / `PersistTreeResourceUpdateAction`. Consumer-Resources **ohne** zusätzliche Traits; Forward-Resource **nicht** `final`.
93+
- Create inline: `usesResourceCreateInspector()` wenn `inspectorPage` + Create-Route in `getPages()`; sonst `stubCreate()` oder `CreateTreeNodeAction`.
94+
- Standalone Route `tree-inspector`: `RendersAsTreeIndexInspector` + `RendersAsTreeIndexEmbeddedPage` (Redirect-Suppression, `lang`). Nur für direkte URL — Hauptpfad ist inline auf der List-Page.

.cursor/rules/senior-developer.mdc

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
description: Senior Developer — Clean Code, DRY, keine doppelten Funktionen (global)
3+
alwaysApply: true
4+
---
5+
6+
# Senior Developer (global)
7+
8+
Vollständige Agent-Anweisungen: `AGENTS.md` im Repo-Root.
9+
10+
## Kurzregeln
11+
12+
1. **Senior-Niveau** — architektonisch denken, produktionsreif, minimaler Scope.
13+
2. **Vor Implementierung suchen** — bestehende Funktionen/Klassen wiederverwenden oder im richtigen Package zentral erweitern; **keine Duplikate**.
14+
3. **Clean Code** — eine Verantwortlichkeit pro Einheit, Logik in Actions/Services, UI nur orchestrieren, `declare(strict_types=1);`, keine leeren catches, keine unnötigen Abstraktionen.
15+
4. **Konventionen** — Code im Ziel-Package lesen und dessen Patterns übernehmen.
16+
5. **Tests** — Verhaltensänderungen brauchen Pest-Tests im Package; `composer lint` + `composer analyse` + betroffene Tests vor Commit.
17+
6. **Filament 4** — Moox-Basisklassen (`BaseResource`, `BaseItemResource`, …), `Schema` statt `Form`, Actions aus `Filament\Actions\*`.
18+
7. **Git** — nur auf Anfrage committen/PR; kurze imperative Messages, ein Commit = eine Änderung.
19+
8. Package-Regeln in `.cursor/rules/` (z. B. `moox-tree-*`) ergänzen diese Regel, ersetzen sie nicht.
20+
9. **Package-Skills** — Packages mit Eintrag in `.cursor/skills/registry.yaml`: nach relevanten Änderungen Skill prüfen/anpassen (Regel `moox-package-skill-sync`).

0 commit comments

Comments
 (0)