Implement SignalR DataSource split & virtualization base

Implements client half of ADR 0004: splits SignalR DataSource into new base class (AcSignalRDataSourceBase), collection sibling (AcSignalRDataSource), and new virtualized sibling (AcSignalRVirtualizedDataSource) for server-side grid paging. Refactors context, sync, and save logic to the base; updates all related docs, contracts, and TODOs. Adds SIGNALR_VIRTUALIZED_DATASOURCE topic, updates ADR 0004, introduces ADR 0006 for PopulateMerge, and clarifies terminology. No grids/endpoints yet migrated; groundwork for server virtualization is complete.
This commit is contained in:
2026-07-19 18:37:08 +02:00
parent 3928022252
commit a52fbe9174
10 changed files with 73 additions and 18 deletions
@@ -6,7 +6,7 @@ namespace AyCode.Blazor.Components.Components.Grids;
/// <para>
/// SCAFFOLDING STATUS (2026-07-18): declaration only. <see cref="Local"/> is the only implemented behavior, and
/// the mode is deliberately NOT yet exposed as a grid parameter — a settable-but-ignored mode would be a silent
/// misconfiguration trap. The parameter arrives together with the ServerVirtualized wiring (windowing
/// misconfiguration trap. The parameter arrives together with the ServerVirtualized wiring (virtualized
/// datasource + request carriage), so selecting the mode and getting the behavior stay atomic.
/// </para>
/// </summary>
@@ -21,8 +21,8 @@ public enum GridDataMode
/// <summary>
/// PLANNED (ADR 0004 — not yet wired): filter + sort + page + count on the server as ONE capability, via a
/// purpose-built windowing <c>GridCustomDataSource</c> and a round-trip <c>AcGridDataQuery&lt;T&gt;</c> —
/// the client sends it and gets the SAME object back, filled by the dispatcher with the window
/// purpose-built virtualized <c>GridCustomDataSource</c> and a round-trip <c>AcGridDataQuery&lt;T&gt;</c> —
/// the client sends it and gets the SAME object back, filled by the dispatcher with the page
/// (<c>Items</c>) and the total (<c>TotalRecords</c>); endpoints keep returning <c>List&lt;T&gt;</c>. There
/// is deliberately no intermediate "server-filtered load-all" mode.
/// <para>
@@ -4,12 +4,12 @@ Core grid system built on DevExpress `DxGrid`. For the full technical reference
## Key Files
- **`MgGridBase.cs`** — `MgGridBase<TSignalRDataSource, TDataItem, TId, TLoggerClient>`, the main abstract grid component. Extends `DxGrid` with SignalR CRUD, layout persistence, master-detail hierarchy, edit state tracking, fullscreen toggle, and a quick-filter `FilterPanel` slot (renders `MgTagBox` controls below the toolbar in a styled `.mg-grid-filter-panel` container; toolbar Show/Hide toggle).
- **`MgGridBase.cs`** — `MgGridBase<TSignalRDataSource, TDataItem, TId, TLoggerClient>`, the main abstract grid component. Extends `DxGrid` with SignalR CRUD, layout persistence, master-detail hierarchy, edit state tracking, fullscreen toggle, and a quick-filter `FilterPanel` slot (renders `MgGridFilterPanelTagBox` controls below the toolbar in a styled `.mg-grid-filter-panel` container; toolbar Show/Hide toggle).
- **`MgGridWithInfoPanel.razor`** — `DxSplitter` wrapper: grid (left) + InfoPanel (right), fullscreen overlay, splitter size persistence.
- **`MgGridToolbarBase.cs`** — Extends `DxToolbar` with `Grid`, `RefreshClick`, and `ShowOnlyIcon` parameters.
- **`MgGridToolbarTemplate.razor`** — Full toolbar template: New/Edit/Delete/Save/Cancel, row navigation, layout menu (Load/Save/Reset), column chooser, export, reload, filter-panel toggle (visible only when the grid has a `FilterPanel`), fullscreen. Extensible via `ToolbarItemsExtended`.
- **`MgGridDataColumn.cs`** — Extends `DxGridDataColumn` with InfoPanel parameters (`ShowInInfoPanel`, `InfoPanelOrder`, `InfoPanelDisplayFormat`) and `UrlLink` template with `{Property}` placeholder substitution via compiled accessors.
- **`MgGridInfoPanel.razor`** / **`.razor.cs`** — `MgGridInfoPanel` implementing `IInfoPanelBase`. Responsive column layout (1-4 columns with breakpoints), edit/view mode with typed editors, template system, sticky positioning via JS interop.
- **`MgGridSignalRDataSource.cs`** — `GridCustomDataSource` wrapping `AcSignalRDataSource`. Local cache for seen filter criteria, background refresh.
- **`MgGridSignalRDataSource.cs`** — ⚠️ **Unused prototype, scheduled for deletion** (ADR 0004 client-half step ④). `GridCustomDataSource` wrapping `AcSignalRDataSource`: local cache for seen filter criteria, background refresh. Zero instantiation sites; do not build on it — see `docs/MGGRID/MGGRID_DATASOURCE.md`.
- **`GridEditMode.cs`** — `MgGridEditState` enum: `None`, `New`, `Edit`.
- **`MgGridHelper.cs`**, **`MgGridToolbarHelper.cs`**, **`MgGridInfoPanelHelper.cs`** — Placeholder helpers (empty).
+10 -1
View File
@@ -13,10 +13,19 @@ DevExpress component wrappers and grid infrastructure for the AyCode Blazor comp
- **`AcMaskedInput.cs`** -- Generic wrapper for `DxMaskedInput<T>`.
- **`AcMemo.cs`** -- Extends `DxMemo`.
- **`AcSpinEdit.cs`** -- Generic wrapper for `DxSpinEdit<T>`.
- **`MgTagBox.cs`** -- Generic wrapper for `DxTagBox<TData, TValue>` with grid quick-filter support: a `FieldName` parameter + the grid cascade let a selection apply a per-field `IN` filter via `IMgGridBase.SetFieldQuickFilter` (see `Grids/` and `docs/MGGRID/MGGRID_PARAMETERS.md`Quick-Filter Panel).
- **`MgTagBox.cs`** -- Generic wrapper for `DxTagBox<TData, TValue>` — a pure, behavior-free seam (no grid wiring). The grid filter component derives from it: `MgGridFilterPanelTagBox` in `Grids/` (see `docs/MGGRID/MGGRID_PARAMETERS.md` → Filter Panel).
- **`MgComponentsHelper.cs`** -- Placeholder helper class (currently empty).
## Subfolders
- **`CardViews/`** -- Generic card-based view component with pagination.
- **`Grids/`** -- Core grid system with SignalR data binding, toolbar, info panel, and layout persistence.
## External references
- **DevExpress official examples** (~2.5k runnable repos — every component family, source readable):
<https://github.com/orgs/DevExpress-Examples/repositories?q=mirror%3Afalse+fork%3Afalse+archived%3Afalse>
Search via the GitHub API instead of paging the listing:
`https://api.github.com/search/repositories?q=org:DevExpress-Examples+blazor+<component>+<topic>`
Raw source: `https://raw.githubusercontent.com/DevExpress-Examples/<repo>/master/<path>`
+3 -3
View File
@@ -7,11 +7,11 @@
]
}
Blazor Razor component library targeting .NET 10. Provides reusable DevExpress-based UI components, a SignalR-powered grid system, and LINQ expression serialization services.
Blazor Razor component library targeting .NET 10. Provides reusable DevExpress-based UI components and a SignalR-powered grid system. (It also still contains a **deprecated** LINQ expression serialization service — see `Services/ExpressionHelpers/README.md`.)
## Documentation
`docs/MGGRID/` — the MgGrid system (overview, parameters, CRUD/edit flow, layout persistence + server roaming, master-detail, rendering, InfoPanel, toolbar, columns, data source). Entry point: `docs/MGGRID/README.md` — its table indexes every sub-file.
`docs/MGGRID/` — the MgGrid system (overview, parameters, filter panel, CRUD/edit flow, layout persistence + server roaming, master-detail, rendering, InfoPanel, toolbar, columns, data source). Entry point: `docs/MGGRID/README.md` — its table indexes every sub-file.
## Dependencies
@@ -27,4 +27,4 @@ Blazor Razor component library targeting .NET 10. Provides reusable DevExpress-b
## Subfolders
- **`Components/`** -- DevExpress component wrappers and grid infrastructure.
- **`Services/`** -- Authentication, grid data source, and LINQ expression serialization helpers.
- **`Services/`** -- Authentication, grid data source prototype, and the deprecated LINQ expression serialization helpers.
@@ -1,5 +1,11 @@
# ExpressionHelpers
> ⚠️ **DEPRECATED / test-only — being phased out.** A serializable LINQ expression tree executed
> server-side is an RCE-shaped injection surface. This is **NOT** the grid-filter mechanism —
> ADR 0004 (AyCode.Core repo, `docs/adr/0004-signalr-datasource-server-side-filtering.md`) rejected it;
> grid filtering travels as a DevExpress criteria string, parsed and whitelisted server-side.
> **Do not build new features on it.** See `docs/GLOSSARY.md` → `AcExpressionNode`.
LINQ expression tree serialization and deserialization to JSON, enabling expression transport over SignalR or HTTP. Converts `Expression` trees to a recursive `AcExpressionNode` DTO and back, supporting binary, unary, lambda, member access, method calls, conditionals, new/member-init, and array expressions.
## Key Files
+3 -3
View File
@@ -1,12 +1,12 @@
# Services
Application services including authentication, grid data source prototyping, and LINQ expression tree serialization for SignalR/HTTP transport.
Application services: authentication, grid data source prototyping, and the deprecated LINQ expression tree serialization.
## Key Files
- **`AcGridDataSource.cs`** -- Commented-out prototype of a `GridCustomDataSource` wrapping an `AcSignalRDataSource` with OData-style filtering. Not currently active; the working implementation lives in `Components/Grids/MgGridSignalRDataSource.cs`.
- **`AcGridDataSource.cs`** -- Commented-out prototype of a `GridCustomDataSource` wrapping an `AcSignalRDataSource` with OData-style filtering. Not active. Its sibling prototype `Components/Grids/MgGridSignalRDataSource.cs` is likewise unused and **scheduled for deletion** (see `docs/MGGRID/MGGRID_DATASOURCE.md`); the server-side data path is ADR 0004's virtualized datasource (AyCode.Core repo).
## Subfolders
- **`Logins/`** -- Web authentication service.
- **`ExpressionHelpers/`** -- LINQ expression tree serialization and deserialization to JSON for transport over SignalR or HTTP.
- **`ExpressionHelpers/`** -- ⚠️ **Deprecated / test-only** LINQ expression tree serialization (RCE-shaped injection surface; rejected as the grid-filter mechanism by ADR 0004). Do not build new features on it — see its README.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -20,7 +20,7 @@
| File | Topics |
|---|---|
| `MGGRID_PARAMETERS.md` | Component parameters (required, CRUD tags, data & context, display), quick-filter panel (`FilterPanel` slot + `MgTagBox`), event callbacks, default grid settings |
| `MGGRID_PARAMETERS.md` | Component parameters (required, CRUD tags, data & context, display), Filter Panel (`FilterPanel` slot + `MgGridFilterPanelTagBox`), event callbacks, default grid settings |
| `MGGRID_CRUD.md` | Lifecycle, CRUD operations, ID generation, edit flow, disposal |
| `MGGRID_LAYOUT.md` | Layout persistence (storage keys, three tiers, operations, persisted state) |
| `MGGRID_DETAIL.md` | Master-detail hierarchy |
@@ -28,7 +28,7 @@
| `MGGRID_INFOPANEL.md` | MgGridInfoPanel, MgGridWithInfoPanel wrapper, responsive layout, templates, editors |
| `MGGRID_TOOLBAR.md` | MgGridToolbarBase, MgGridToolbarTemplate (buttons, parameters, state) |
| `MGGRID_COLUMNS.md` | MgGridDataColumn (InfoPanel params, UrlLink) |
| `MGGRID_DATASOURCE.md` | MgGridSignalRDataSource (server-side data, local cache, background refresh) |
| `MGGRID_DATASOURCE.md` | MgGridSignalRDataSource (local cache, background refresh) — ⚠️ unused prototype, scheduled for deletion |
| `MGGRID_ISSUES.md` | Known issues (`ACBLAZOR-GRID-I-*`, `ACBLAZOR-GRID-B-*`) |
| `MGGRID_TODO.md` | Planned work (`ACBLAZOR-GRID-T-*`) — refactors, missing features, optimizations |
+1 -1
View File
@@ -27,7 +27,7 @@ For full technical reference see `AyCode.Blazor.Components/docs/MGGRID/README.md
| **MgGridToolbarTemplate** | Full toolbar: New/Edit/Delete/Save/Cancel, row navigation, layout menu, export, filter-panel toggle (when the grid has a `FilterPanel`), fullscreen. Extensible via `ToolbarItemsExtended`. |
| **MgGridDataColumn** | Extended `DxGridDataColumn` with InfoPanel parameters and `UrlLink` template (`{Property}` placeholders). |
| **MgGridInfoPanel** | Default InfoPanel: column-value pairs for focused row, responsive columns, edit mode with typed editors, template system. |
| **MgGridSignalRDataSource** | `GridCustomDataSource` wrapping `AcSignalRDataSource`. Local cache, background refresh. |
| **MgGridSignalRDataSource** | ⚠️ **Unused prototype — scheduled for deletion.** `GridCustomDataSource` wrapping `AcSignalRDataSource` (local cache, background refresh). Zero instantiation sites; not the future virtualized source — that is ADR 0004's `AcSignalRVirtualizedDataSource`. Do not build on it. |
| **IMgGridBase** | Public interface: `IsSyncing`, `GridEditState`, `ParentGrid`, `StepPrevRow/NextRow`, layout persistence, filter panel (`SetFilterPanelCriteria`, `GetFilterPanelCriteria`, `RegisterFilterPanelComponent`, `ClearFilterPanel`, `RefreshFilterPanel`, `HasFilterPanel`, `IsFilterPanelVisible`, `ToggleFilterPanel`), `GridSizeMode`. |
| **MgGridEditState** | Enum: `None` (no edit), `New` (adding item), `Edit` (modifying item). |
| **SignalRCrudTags** | Bundle of 5 integer message tags (GetAll, GetItem, Add, Update, Remove) for one entity type. See `AyCode.Services/docs/SIGNALR_DATASOURCE/README.md` in AyCode.Core repo. |