AyCode.Blazor/AyCode.Blazor.Components/docs/MGGRID/MGGRID_LAYOUT.md

67 lines
3.5 KiB
Markdown

# MgGrid — Layout Persistence
> Part of the MgGrid system. See `README.md` for overview and component hierarchy.
## Storage Keys
Grid layouts are stored in **localStorage** with structured keys:
```
AutoSave: {AutoSaveLayoutName}_{MasterOrParentTypeName}_AutoSave_{UserId}
UserSave: {AutoSaveLayoutName}_{MasterOrParentTypeName}_UserSave_{UserId}
Splitter: Splitter_{grid.AutomaticLayoutStorageKey}
```
**Examples:**
```
GridOrder_Master_AutoSave_42 ← master grid, user #42
GridOrder_Order_AutoSave_42 ← detail grid under Order parent
GridOrder_Master_UserSave_42 ← manually saved layout
Splitter_GridOrder_Master_AutoSave_42 ← splitter pane size
```
## Three Layout Tiers
| Tier | Key Contains | When Saved | When Loaded |
|---|---|---|---|
| **Default** | (in-memory `_defaultLayoutJson`) | First `LayoutAutoLoading` — captures layout before any load | `ResetLayoutAsync()` — restores original |
| **AutoSave** | `_AutoSave_` | Every `LayoutAutoSaving` event (on any layout change) | Every `LayoutAutoLoading` event (on grid init, wrapped in `BeginUpdate`/`EndUpdate`) |
| **UserSave** | `_UserSave_` | `SaveUserLayoutAsync()` — explicit user action | `LoadUserLayoutAsync()` — explicit user action |
## Layout Operations
| Method | Behavior |
|---|---|
| `SaveUserLayoutAsync()` | Saves to the local UserSave key first (the AutoSave key is already current — `LayoutAutoSaving` fires on every user-made layout change), then (when `EnableServerLayouts`) pushes the layout JSON to the server |
| `LoadUserLayoutAsync()` | Prefers the server copy (when `EnableServerLayouts`) — writing it back to the local UserSave + AutoSave keys so it survives a page refresh — and falls back to the local UserSave copy; then applies the layout |
| `ResetLayoutAsync()` | Removes AutoSave key, restores in-memory `_defaultLayoutJson` (never touches the server copy) |
| `HasUserLayoutAsync()` | Local check; when `EnableServerLayouts` and no local copy exists, returns `true` optimistically — no server round-trip |
## Server Roaming (UserSave tier)
`EnableServerLayouts` (default `true`) roams the **UserSave** tier through the grid's own `SignalRClient`,
using the framework tags defined in `AcSignalRTags` (AyCode.Services):
| Tag | Value | Params (in order) | Returns |
|---|---|---|---|
| `GetGridLayoutTag` | 90010 | `key` (string), `userId` (int) | layout JSON, or null |
| `SaveGridLayoutTag` | 90011 | `key`, `layoutJson`, `userId` | bool |
| `DeleteGridLayoutTag` | 90012 | `key`, `userId` | bool |
- The `key` is the full composite UserSave storage key (it already contains the user id); the server treats
it as an opaque string. `userId` comes from `GetLayoutUserId()`.
- **Server communication happens exclusively on user clicks** (Save/Load layout toolbar buttons) — never on
grid init, toolbar init, detail-row expand, or prerender.
- All server calls are **best-effort** (`try/catch`): offline, or when the server does not implement the
tags, behavior degrades to the local-only flow without errors.
- The server must implement the three tags; the storage schema is the consumer's choice.
- The `AutoSave` and `Splitter` tiers never touch the server.
## Persisted State
The layout (`GridPersistentLayout`) includes: column order, column widths, sort descriptors, group descriptors, filter row values, page size — serialized as JSON via `System.Text.Json`.
## User Identification
`GetLayoutUserId()` is virtual — defaults to `0`. Override in project adapter to provide the logged-in user's ID.