67 lines
3.5 KiB
Markdown
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.
|