9.4 KiB
MGGRID — TODO
For known issues / bugs see MGGRID_ISSUES.md.
Server-side grid filtering — design in ADR 0004 (
AyCode.Core/docs/adr/0004-signalr-datasource-server-side-filtering.md, in AyCode.Core repo).Landed (2026-07-16/17), local mode: the declarative filter panel —
FilterPanelslot,MgGridFilterPanelTagBox(+IMgGridFilterPanelComponent), per-fieldINcriteria viaSetFilterPanelCriteria→ DevExpressSetFieldFilterCriteria, toolbar Show/Hide toggle, built-in Clear button, layout persistence + visibility reconcile. SeeMGGRID_PARAMETERS.md→ Filter Panel.Still open (not yet broken into per-step entries — reference the ADR when implementation begins):
FilterMode(Local/Server) + criteria forwarding intoSignalParams.FilterCriteria;[FilterCriteriaParam]hub injection + registration-time convention validation + mismatch warning (AyCode.Services / .Server); the filter-service (whitelist, parse/length hard-reject);[NotGridFilterable](AyCode.Core, deferred); v2 paging. PlusACBLAZOR-GRID-T-W8Q3below (the layout envelope), which the ADR designates as the successor to the current restore heal.
Priority legend
- P0 blocker · P1 important · P2 nice-to-have · P3 idea
ACBLAZOR-GRID-T-W8Q3: MgGridLayoutSave envelope + pull-model filter-panel restore
Priority: P1 · Type: Refactor (framework-first) · Origin: 2026-07-17 multi-agent restore-race audit · Related: MGGRID_ISSUES.md#acblazor-grid-i-d4t7; design in AyCode.Core/docs/adr/0004-signalr-datasource-server-side-filtering.md → "Planned v2"
Filter-panel criteria currently persists inside the DevExpress layout (GridPersistentLayout.FilterCriteria), so on restore the criteria reaches the grid before the panel can display it. That forces the framework to detect when the editor is able to show it — the source of two shipped edge-gate bugs and of the current level-triggered snapshot heal (MgGridFilterPanelTagBox).
Replace with an envelope that gives each piece of state a single owner:
public class MgGridLayoutSave
{
public int Version { get; set; } = 1; // 0 = legacy raw GridPersistentLayout JSON (no envelope)
public string? GridLayoutJson { get; set; }
public string? FilterPanelLayoutJson { get; set; }
}
- Save: for each registered component whose
OwnsCriteriamatches its field slot, REMOVE that criteria from the DX layout and serialize it intoFilterPanelLayoutJsonasfield → invariant-culture value strings. - Restore (all three funnels —
Grid_LayoutAutoLoading,LoadUserLayoutAsync,ResetLayoutAsync): apply the panel-free DX layout; park the panel map; hand an entry to its component only when it is ready (registered ANDDatanon-empty), which then sets criteria + selection atomically. - Version:
0(absent property) = legacy raw layout → one-time migration extracting owned-shapedINcriteria (the only place shape-sniffing survives). Bump only for semantic changes —System.Text.Jsonignores unknown properties, so additive sections need no bump. - Never-claimed entries stay parked for the session and are re-persisted on save (a temporarily absent panel must not silently destroy a saved filter).
Acceptance criteria
- A restored panel filter never filters rows while its UI cannot show it (closes the rows-filtered/chips-empty window).
ACBLAZOR-GRID-I-D4T7closed by construction (an ownerless entry never reaches the grid).Reload(), the snapshot-heal state, the pending-reconcile flag andIMgGridBase.RefreshFilterPanel()all become deletable;RefreshFilterPanelkept one release as a deprecated no-op shim, consumer call sites removed (e.g.GridShippingDocument.ReloadDataFromDb).- Legacy (v0) layouts in localStorage and on the server still load.
- Interleaving tests: fill-order swap, criteria-before-data, data-before-criteria, no-panel restore.
ACBLAZOR-GRID-T-V4P7: Generic ID generation in MgGridBase.SetNewId
Priority: P2 · Type: Refactor (framework-first) · Origin: 2026-04-24 in-code TODO audit · Area: Components/Grids/MgGridBase.cs:460
SetNewId(TDataItem dataItem) branches on dataItem.Id is Guid vs dataItem.Id is int to produce a new ID, and converts through TypeConverter back to TId. The in-code comment //TODO: int !!! - J. flags this as unfinished — the logic is not cleanly generic over TId.
private void SetNewId(TDataItem dataItem)
{
//TODO: int !!! - J.
if (dataItem.Id is Guid)
{
dataItem.Id = (TId)(_typeConverterId.ConvertTo(Guid.NewGuid(), typeof(TId)))!;
}
else if (dataItem.Id is int)
{
var newId = -1 * AcDomain.NextUniqueInt32;
dataItem.Id = (TId)(_typeConverterId.ConvertTo(newId, typeof(TId)))!;
}
}
Problems:
- Runtime type switch on a generic parameter defeats the point of generics.
- Silent no-op for any other
TId(e.g.,long,short, custom struct) — no compile error, no throw. - The negative-int convention (
-1 * AcDomain.NextUniqueInt32) is not expressed as a contract; consumers cannot override.
Fix options
- (a) Introduce
IAcNewIdGenerator<TId>framework abstraction (in AyCode.Core) with default implementations forGuidandint.MgGridBasetakes it via DI or generic parameter. Consumer-specificTIdtypes register their generator. - (b) Virtual protected method:
protected virtual TId GenerateNewId()onMgGridBase, with default implementations forGuidandintpreserved. Consumer overrides for customTId. - (c) Static strategy map keyed by
typeof(TId)— registered once per app startup, resolved at runtime.
Acceptance criteria
- No runtime type-switch in
MgGridBase. - Throws explicit
NotSupportedException(or similar) for unregisteredTIdtypes. - Existing
Guidandintconsumers unaffected. - Remove the
//TODO: int !!! - J.comment.
ACBLAZOR-GRID-T-S2L9: Implement local grouping in MgGridSignalRDataSource.GetGroupInfoAsync
Priority: P3 · Type: Feature · Origin: 2026-04-24 in-code TODO audit · Area: Components/Grids/MgGridSignalRDataSource.cs:202
public override async Task<IList<GridCustomDataSourceGroupInfo>> GetGroupInfoAsync(
GridCustomDataSourceGroupingOptions options,
CancellationToken cancellationToken)
{
_logger?.Debug("[MgGridSignalRDataSource] GetGroupInfoAsync");
// TODO: Implement local grouping when needed
return await base.GetGroupInfoAsync(options, cancellationToken);
}
Currently delegates to the DevExpress base implementation, which for a server-side GridCustomDataSource triggers a server round-trip. With MgGridSignalRDataSource already holding a local cache (see MGGRID_DATASOURCE.md), grouping over the cached rows would avoid that round-trip.
Not urgent — only light grouping usage so far; the base path works. Promote to P2 if a consumer hits perceptible grouping latency.
Acceptance criteria
- Local grouping computed from the cached list when the full dataset is cached.
- Falls back to base (server) path when the cache is partial / paginated.
- Unit / integration test with a grouped column.
- Remove the
// TODO: Implement local grouping when neededcomment.
ACBLAZOR-GRID-T-E3B6: Fogyasztói template-ek izolálása (ErrorBoundary) + DataItem-kontraktus dokumentálása
Priority: P2 · Type: Resilience + Docs · Origin: 2026-07-13 runtime incidens (fogyasztói InfoPanel-template NRE → WASM renderer crit)
A template-hosztok (MgGridInfoPanel Header/BeforeColumns/Columns/AfterColumns/Footer template-hívásai — pl. MgGridInfoPanel.razor:44 —, és általában a fogyasztói RenderFragment-hívások) védtelenül futnak: egy fogyasztói template-ben dobott kivétel unhandled render exceptionként a WASM renderert üti meg (crit: …WebAssemblyRenderer), rosszabb esetben az egész app-ot viszi — nem csak az érintett panelt.
Trigger-incidens: add/save után a kijelölt sor a szerver-válasz nyers (reláció nélkül betöltött) entitása a grid-reloadig; a fogyasztói template null navigációt dereferált → NRE a renderben. A fogyasztói fix (null-guard a template-ben) megvan, de a keret két hiányossága marad:
- ErrorBoundary a template-hívások köré — a hibás template a panelen belül hibablokká szelídüljön (+ logolás), a grid/app maradjon életben. Figyelem: az
ErrorBoundaryaz eseménykezelő-kivételeket is elkapja; recovery-stratégia kell (pl.Recover()a következő DataItem-váltásnál). - DataItem-kontraktus kimondása a doksiban (
MGGRID_INFOPANEL/ README): a template-nek részlegesen töltött DataItem-mel KELL számolnia (null navigációs property-k) — add/save után a DataItem a szerver-válasz nyers entitása lehet, amíg a reload le nem cseréli.
Acceptance criteria
- Fogyasztói template-kivétel nem eszkalálódik unhandled render exceptionné; a panel hibablokkot mutat és logol.
- A következő sikeres render (pl. DataItem-váltás) után a panel magától helyreáll.
- A DataItem-kontraktus dokumentálva.
TODO entry template
## ACBLAZOR-GRID-T-XXXX: Short title
**Priority:** P0 / P1 / P2 / P3 · **Type:** Bug fix / Feature / Refactor / Docs · **Related:** `MGGRID_ISSUES.md#acblazor-grid-i-XXXX` (if applicable)
Description of what and why, including the trigger (user request, audit finding, incident).
Options / sub-tasks / acceptance criteria.