# MOSAIC easyGrid Entwicklerdokumentation

## Zweck

`_pgm/show_egrid.php` ist der kanonische MOSAIC-Einstieg fuer tabellarische Inline-Bearbeitung.
Die interne Runtime liegt weiterhin in `_pgm/egrid.php`.
`egrid` steht fuer `easyGrid`: leichtgewichtig, direkt editierbar, ohne komplexe Zusatzfunktionen.

## Dateistruktur

- Konfiguration: `*_egrid.cfg`
- Hook-Datei: `*_egrid_function.php`
- Runner: `_pgm/show_egrid.php`
- Runtime: `_pgm/egrid.php`

Es gibt keine Legacy-Kompatibilitaet mehr zum alten easyGrid-Modell.
Veraltete egrid-Konfigurationen muessen aktiv auf das neue MOSAIC-Schema umgestellt werden.

## Bewusste Abgrenzung zu `grid.php`

`easyGrid` ist fuer einfache Bearbeitung gedacht und enthaelt bewusst nicht:

- keinen Advanced Filter
- keinen PDF/XLS/Excel-Export
- keine Marker
- keine User-Buttons
- keine Form-Anwendung als Detail-/Edit-Maske

Stattdessen erfolgt die Bearbeitung direkt zeilenweise in der Tabelle.

## Erstellung

Es gibt keinen eigenen eGrid-Builder im MOSAIC-Kern mehr.
Neue eGrids werden direkt als `*_egrid.cfg` erzeugt, typischerweise durch KI-gestuetzte Modulerstellung.
Der Kern stellt nur Runtime, Runner, Security und Hook-Ausfuehrung bereit.

## Pflichtstruktur der `*_egrid.cfg`

- `title`
- `table`
- `primary_key`
- `connection`
- `columns`

`primary_key` wird in MOSAIC immer als Array gespeichert:

```php
'primary_key' => ['id']
```

oder bei zusammengesetzten Schluesseln:

```php
'primary_key' => ['mandant_id', 'beleg_nr']
```

`columns` muss als assoziatives Array vorliegen:

```php
'columns' => [
    'name' => [
        'label' => 'Name',
        'type' => 'text',
        'quicksearch' => true,
        'sort' => true,
        'editable' => true,
    ],
]
```

## Optionale Konfigbereiche

- `sql`
  - optionales Lese-SQL fuer die Tabellenanzeige
- `search`
  - einfache Suche
  - `enabled`
  - `placeholder`
  - `fields`
- `groups`
  - Gruppierung nach einem oder mehreren Feldern
- `permissions`
  - `create`, `read`, `update`, `delete`
  - `permissions` ist die verbindliche Schreibweise fuer neue Konfigurationen
  - Grid-Aliase `add`, `view`, `edit`, `delete` werden auf `create`, `read`, `update`, `delete` gemappt
- `check_security`
- `sql_where`
  - statischer Zusatzfilter fuer die Datenauswahl
  - wird wie bei `grid.php` mit `AND` an Suchbedingungen angehaengt
  - enthaelt eine Bedingung gegen die sichtbaren Quellspalten; ein fuehrendes `WHERE` oder `AND` wird toleriert, aber nicht benoetigt
  - Beispiel: `'sql_where' => 'active = 1'`

## Nicht mehr erlaubt

Folgende Legacy-Schluessel werden in `egrid.php` bewusst nicht mehr akzeptiert:

- `advanced_search`
- `filters`
- `marker`
- `user_buttons`
- `show_new_button`
- `sequence_name`
- `db_typ`
- `debug`
- `permissions.copy`
- `permissions.xls_export`
- `permissions.pdf_export`
- `permissions.select_xls_fields`
- `permissions.select_pdf_fields`

## Unterstuetzte Feldtypen

- `text`
- `textarea`
- `number`
- `date`
- `datetime`
- `datetime-local`
- `select`
- `radio`
- `checkbox`

### `radio`

`radio` rendert pro editierbarer eGrid-Zeile eine Radio-Gruppe. Alle Optionen einer Spalte verwenden denselben Feldnamen, daher kann pro Zeile genau ein Wert gespeichert werden.

Die Optionen koennen wie bei `select` definiert werden:

- `options` als assoziatives Array `wert => label`
- `lookup_method` = `manual` mit `lookup_label`, `lookup_value` und optional `delimiter`
- `lookup_method` = `automatic` mit `lookup_sql` und optional `lookup_conn`

Optionale Parameter:

- `required` unterdrueckt die Leerauswahl
- `radio_empty` aktiviert eine explizite Leerauswahl
- `radio_empty_label` setzt deren Anzeige

Im nicht editierbaren Zustand zeigt eGrid bei `select` und `radio` das gefundene Label an; falls kein Label gefunden wird, wird der gespeicherte Rohwert angezeigt.

## Spalten-Styles

eGrid unterstuetzt wie `grid.php` statische und wertabhaengige Styles direkt in der Spaltenkonfiguration.
Die Styles werden auf die Tabellenzelle (`td`) bzw. Kopfzelle (`th`) angewendet.

```php
'columns' => [
    'status' => [
        'label' => 'Status',
        'type' => 'select',
        'style' => [
            'background-color' => '#fff3cd',
            'color' => '#7a4b00',
        ],
        'header_style' => [
            'background-color' => '#7a4b00',
            'color' => '#ffffff',
            'font-weight' => '700',
        ],
        'value_styles' => [
            'kritisch' => [
                'background-color' => '#f8d7da',
                'color' => '#842029',
                'font-weight' => '700',
            ],
        ],
    ],
]
```

Unterstuetzte Schluessel:

- `style`
- `header_style`
- `value_styles`
- `class` oder `cell_class`
- `header_class`
- `value_classes`

Erlaubte Inline-CSS-Eigenschaften:

- `background`, `background-color`, `color`
- `font-family`, `font-size`, `font-weight`, `font-style`
- `text-decoration`, `text-align`, `vertical-align`, `white-space`
- `width`, `min-width`, `max-width`

In `onRecord` koennen Styles je Datensatz dynamisch gesetzt werden:

```php
$row['_cell_style']['status'] = [
    'background-color' => '#d1e7dd',
    'color' => '#0f5132',
];

$row['_cell_class']['status'] = 'status-ok';
```

## Hook-Lifecycle

Grid-nahe Hooks:

- `onApplicationInit(&$context, &$modulConfig)`
- `onCheckSecurity(&$context, &$modulConfig)`
- `onLoad(&$context, &$modulConfig)`
- `onBeforeQuery(&$context, &$queryPayload, &$modulConfig)`
- `onRecord(&$context, &$row, &$modulConfig)`
- `onFooter(&$context, &$footer, &$modulConfig)`
- `onBeforeRender(&$context, &$renderPayload, &$modulConfig)`
- `onAfterRender(&$context, &$renderPayload, &$modulConfig)`

EasyGrid-spezifische Hooks:

- `onBeforeFieldRender(&$context, $field, &$value, &$def, &$row, &$modulConfig)`
- `onValidate(&$context, &$data, $id, &$modulConfig)`
- `onValidateSuccess(&$context, &$data, $id, &$modulConfig)`
- `onValidateFailure(&$context, &$data, $id, &$modulConfig, &$message)`
- `onBeforeInsert(&$context, &$data, &$modulConfig)`
- `onAfterInsert(&$context, $newId, &$data, &$modulConfig)`
- `onBeforeUpdate(&$context, $id, &$data, &$modulConfig)`
- `onAfterUpdate(&$context, $id, &$data, &$modulConfig)`
- `onBeforeDelete(&$context, $id, &$modulConfig)`
- `onAfterDelete(&$context, $id, &$modulConfig)`

`onValidate` und `onValidateSuccess` laufen bei `insert_row` und `save_row` vor den Before-Hooks. `onValidateFailure` laeuft, wenn einer dieser Validierungshooks abbricht, und darf die Rueckmeldung in `$message` anpassen.

Wichtig: Diese Hooks sind bewusst zeilenbezogen. eGrid speichert keinen Sammel-Batch, sondern pro Zeile genau einen AJAX-Request. Wenn mehrere Zeilen geaendert wurden, wird jede Zeile separat gespeichert und jeder Hook bekommt nur die Daten dieser Zeile. Im `$context` steht dazu `row_action` mit `insert` oder `update`.

Hooks duerfen `false` oder einen Fehlertext zurueckgeben, um eine Aktion abzubrechen.

`$newId` bzw. `$id` ist bei einem einfachen Primary Key weiter ein Skalarwert.
Bei zusammengesetzten Primary Keys liefert MOSAIC dort ein assoziatives Array mit allen PK-Feldern.

## Suche

`easyGrid` bietet nur eine einfache Suche.
Wenn `search.fields` nicht gesetzt ist, werden automatisch alle Spalten mit `quicksearch => true` verwendet.

## CRUD-Verhalten

- neue Zeile direkt in der Tabelle anlegen
- bestehende Zeile direkt speichern
- bestehende Zeile direkt loeschen

Die Schreiboperationen laufen immer gegen `table` und `primary_key`.
Wenn fuer das Lesen ein eigenes `sql` verwendet wird, sollten die bearbeitbaren Spalten trotzdem zur Basistabelle passen.
Bei eigenem `sql` muessen ausserdem alle Primary-Key-Felder im Resultset enthalten sein, damit Update und Delete eindeutig gegen die Zieltabelle aufgeloest werden koennen.
## Runner-Stand im Kern

Stand April 2026 gilt im MOSAIC-Kern ein einheitliches Runner-Schema:

- `grid.php` und `form.php` bleiben direkte generische CRUD-Runner
- `show_egrid.php` ist der kanonische eGrid-Einstieg und delegiert intern an `egrid.php`
- alle anderen fachlichen Runner verwenden konsequent das Praefix `show_`
- typische Beispiele sind `show_menu.php`, `show_dashboard.php`, `show_report.php`, `show_chart.php`, `show_login.php` und `show_v_menu.php`
- fruehere Alt-Namen sind nicht mehr Bestandteil des aktiven Kernbereichs
