Compare commits
20 Commits
79eceff47a
...
92296c479b
| Author | SHA1 | Date |
|---|---|---|
|
|
92296c479b | |
|
|
b61b8085df | |
|
|
3cee1e20d7 | |
|
|
b4d68e1fa4 | |
|
|
1a7bb3bc10 | |
|
|
806c6e5351 | |
|
|
5d4f078906 | |
|
|
161ef4bba9 | |
|
|
b39d624406 | |
|
|
f1e93f939f | |
|
|
bcea6b3205 | |
|
|
d5fdd57ddd | |
|
|
045b8e1526 | |
|
|
da11df5384 | |
|
|
b062c4c712 | |
|
|
d1567323d8 | |
|
|
453e21a844 | |
|
|
52131fdf25 | |
|
|
6cce23a124 | |
|
|
b80b117a38 |
|
|
@ -0,0 +1,43 @@
|
||||||
|
# Topic Codes — registry for AyCode.Blazor's own topics (`ACBLAZOR`)
|
||||||
|
|
||||||
|
Per the Framework-First Design Principle, this Layer 1 registry lists **only AyCode.Blazor's own (`ACBLAZOR`) topics**. Lower-layer (inherited) topics live in their own repos' registries — at runtime, the `docs-check` skill walks `own-dep-repos` from the invocation point to gather all inherited topics. AyCode.Blazor inherits from `AyCode.Core` (see this repo's `@repo.own-dep-repos`).
|
||||||
|
|
||||||
|
Full ID format: `<PREFIX>-<TOPIC>-<TYPE>-<RAND>` — see `AyCode.Core/.github/REPO_PREFIXES.md` for the format spec.
|
||||||
|
|
||||||
|
## ACBLAZOR topic codes
|
||||||
|
|
||||||
|
| Code | Topic | Scope | Docs location |
|
||||||
|
|---------|-----------------------------|-----------------------------------------------------------------------------------|------------------------------------------------------------------------|
|
||||||
|
| `GRID` | MGGRID (grid component) | MgGrid component family: layout, CRUD, columns, toolbar, rendering | `AyCode.Blazor.Components/docs/MGGRID/` |
|
||||||
|
|
||||||
|
## Type codes (universal — see framework registry)
|
||||||
|
|
||||||
|
Type codes (`I`, `T`, `B`, `C`, `DEC`) are universal across all repos and defined in the framework's `TOPIC_CODES.md` (`AyCode.Core/.github/skills/docs-check/references/TOPIC_CODES.md`). This file does not duplicate them.
|
||||||
|
|
||||||
|
## ID format rules
|
||||||
|
|
||||||
|
See the framework's `TOPIC_CODES.md` (`AyCode.Core/.github/skills/docs-check/references/TOPIC_CODES.md`) for the full ID format rules and Status conventions. This file only registers ACBLAZOR's own topic codes; ACCORE topics are inherited via this repo's `own-dep-repos`.
|
||||||
|
|
||||||
|
## Examples (ACBLAZOR only)
|
||||||
|
|
||||||
|
```
|
||||||
|
ACBLAZOR-GRID-T-V4P7 # AyCode.Blazor's MgGrid TODO (e.g., "Generic ID generation in MgGridBase.SetNewId")
|
||||||
|
ACBLAZOR-GRID-T-S2L9 # AyCode.Blazor's MgGrid TODO (e.g., "Implement local grouping")
|
||||||
|
ACBLAZOR-GRID-I-XXXX # placeholder for the first MgGrid issue once one is observed
|
||||||
|
```
|
||||||
|
|
||||||
|
## Adding a new ACBLAZOR topic
|
||||||
|
|
||||||
|
1. Propose the code (2-5 uppercase chars), short and mnemonic, scoped to AyCode.Blazor's UI-framework domain.
|
||||||
|
2. Check it doesn't collide with C# class-name prefixes (`Ac*` / `Mg*`).
|
||||||
|
3. Check it doesn't collide with existing ACBLAZOR topic codes in the table above.
|
||||||
|
4. Check it doesn't visually collide with framework (`ACCORE-*`) topic codes that this repo references — though the `<PREFIX>` component disambiguates, visual distinction helps readers.
|
||||||
|
5. Add a row to the table above.
|
||||||
|
6. Create the topic folder under the relevant project: `AyCode.Blazor.<Project>/docs/{TOPIC_FOLDER_NAME}/` with `README.md`, optional `{TOPIC_FOLDER_NAME}_ISSUES.md`, `{TOPIC_FOLDER_NAME}_TODO.md`.
|
||||||
|
7. Optional: add an `LLMP-DEC-N` entry in the workspace-level `LLM_PROTOCOL_DECISIONS.md` if the new topic is workspace-meta-significant.
|
||||||
|
|
||||||
|
## Cross-references
|
||||||
|
|
||||||
|
- **Framework registry** (universal type codes, ID format spec, Status conventions): `AyCode.Core/.github/skills/docs-check/references/TOPIC_CODES.md` (resolved via this repo's `own-dep-repos`).
|
||||||
|
- **Repo prefix scheme**: `AyCode.Core/.github/REPO_PREFIXES.md`.
|
||||||
|
- **Decision Log**: `AyCode.Core/.github/LLM_PROTOCOL_DECISIONS.md`.
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -15,6 +15,3 @@ Grid component integration tests for `MgGridBase` layout persistence, column ren
|
||||||
- Master grid detection.
|
- Master grid detection.
|
||||||
- Reflection-based column building (verifies Id, ProductName, Quantity columns).
|
- Reflection-based column building (verifies Id, ProductName, Quantity columns).
|
||||||
- `MgGridDataColumn.UrlLink` rendering with token replacement.
|
- `MgGridDataColumn.UrlLink` rendering with token replacement.
|
||||||
|
|
||||||
---
|
|
||||||
> **LLM Maintenance:** If you modify code in this folder, update this README to reflect the changes. If you notice the README content does not match the current code, automatically update the README to match the code.
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,9 @@
|
||||||
# AyCode.Blazor.Components.Tests
|
# AyCode.Blazor.Components.Tests
|
||||||
|
|
||||||
|
@project {
|
||||||
|
type = "test"
|
||||||
|
}
|
||||||
|
|
||||||
bUnit + MSTest component test project targeting net10.0. Tests Blazor component behavior including grid layout persistence and column rendering.
|
bUnit + MSTest component test project targeting net10.0. Tests Blazor component behavior including grid layout persistence and column rendering.
|
||||||
|
|
||||||
## Key Files
|
## Key Files
|
||||||
|
|
@ -15,6 +19,3 @@ bUnit + MSTest component test project targeting net10.0. Tests Blazor component
|
||||||
| MSTest | 4.0.2 | NuGet |
|
| MSTest | 4.0.2 | NuGet |
|
||||||
| AyCode.Blazor.Components | -- | ProjectReference |
|
| AyCode.Blazor.Components | -- | ProjectReference |
|
||||||
| AyCode.Services.Server.Tests | -- | ProjectReference |
|
| AyCode.Services.Server.Tests | -- | ProjectReference |
|
||||||
|
|
||||||
---
|
|
||||||
> **LLM Maintenance:** If you modify code in this folder, update this README to reflect the changes. If you notice the README content does not match the current code, automatically update the README to match the code.
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk.Razor">
|
<Project Sdk="Microsoft.NET.Sdk.Razor">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<RunAOTCompilation>true</RunAOTCompilation>
|
<RunAOTCompilation>true</RunAOTCompilation>
|
||||||
|
|
@ -55,6 +55,11 @@
|
||||||
<Folder Include="Services\Logins\" />
|
<Folder Include="Services\Logins\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="docs\**\*.md" />
|
||||||
|
<None Include="**\README.md" Exclude="$(DefaultItemExcludes);docs\**" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\AyCode.Blazor.Models.Server\AyCode.Blazor.Models.Server.csproj" />
|
<ProjectReference Include="..\AyCode.Blazor.Models.Server\AyCode.Blazor.Models.Server.csproj" />
|
||||||
<ProjectReference Include="..\AyCode.Blazor.Models\AyCode.Blazor.Models.csproj" />
|
<ProjectReference Include="..\AyCode.Blazor.Models\AyCode.Blazor.Models.csproj" />
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,3 @@ Generic card-based view component that renders items in a responsive CSS Grid la
|
||||||
## Key Files
|
## Key Files
|
||||||
|
|
||||||
- **`MgCardView.razor.cs`** -- `MgCardView<TItem>` component. Accepts `Data`, `CardTemplate`, responsive column counts (`ColumnCountXs/Sm/Lg`), optional pager (`ShowPager`, `PageSize` default 12), optional filter panel, container height, and `ScrollToItem` with JS interop for auto-scrolling. Fires `OnCardClick` when a card is tapped.
|
- **`MgCardView.razor.cs`** -- `MgCardView<TItem>` component. Accepts `Data`, `CardTemplate`, responsive column counts (`ColumnCountXs/Sm/Lg`), optional pager (`ShowPager`, `PageSize` default 12), optional filter panel, container height, and `ScrollToItem` with JS interop for auto-scrolling. Fires `OnCardClick` when a card is tapped.
|
||||||
|
|
||||||
---
|
|
||||||
> **LLM Maintenance:** If you modify code in this folder, update this README to reflect the changes. If you notice the README content does not match the current code, automatically update the README to match the code.
|
|
||||||
|
|
|
||||||
|
|
@ -770,13 +770,10 @@ public abstract class MgGridBase<TSignalRDataSource, TDataItem, TId, TLoggerClie
|
||||||
|
|
||||||
private async Task Grid_LayoutAutoLoading(GridPersistentLayoutEventArgs e)
|
private async Task Grid_LayoutAutoLoading(GridPersistentLayoutEventArgs e)
|
||||||
{
|
{
|
||||||
BeginUpdate();
|
|
||||||
|
|
||||||
// Save the default layout before loading any saved layout
|
// Save the default layout before loading any saved layout
|
||||||
_defaultLayoutJson ??= JsonSerializer.Serialize(SaveLayout());
|
_defaultLayoutJson ??= JsonSerializer.Serialize(SaveLayout());
|
||||||
|
|
||||||
e.Layout = await LoadLayoutFromLocalStorageAsync(AutomaticLayoutStorageKey);
|
e.Layout = await LoadLayoutFromLocalStorageAsync(AutomaticLayoutStorageKey);
|
||||||
EndUpdate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task Grid_LayoutAutoSaving(GridPersistentLayoutEventArgs e)
|
private async Task Grid_LayoutAutoSaving(GridPersistentLayoutEventArgs e)
|
||||||
|
|
@ -805,9 +802,7 @@ public abstract class MgGridBase<TSignalRDataSource, TDataItem, TId, TLoggerClie
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
BeginUpdate();
|
|
||||||
var json = JsonSerializer.Serialize(layout);
|
var json = JsonSerializer.Serialize(layout);
|
||||||
EndUpdate();
|
|
||||||
|
|
||||||
await JSRuntime.InvokeVoidAsync("localStorage.setItem", localStorageKey, json);
|
await JSRuntime.InvokeVoidAsync("localStorage.setItem", localStorageKey, json);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,15 @@
|
||||||
# Grids
|
# Grids
|
||||||
|
|
||||||
Core grid system built on DevExpress `DxGrid` with SignalR-based data binding, CRUD operations, layout persistence, fullscreen mode, and an info panel for row details.
|
Core grid system built on DevExpress `DxGrid`. For the full technical reference see `AyCode.Blazor.Components/docs/MGGRID/README.md`.
|
||||||
|
|
||||||
## Key Files
|
## Key Files
|
||||||
|
|
||||||
- **`MgGridBase.cs`** -- `MgGridBase<TSignalRDataSource, TDataItem, TId, TLoggerClient>`, the main abstract grid component. Extends `DxGrid` and binds to an `AcSignalRDataSource` for real-time CRUD via SignalR message tags. Supports master-detail hierarchy (`ParentGrid`, `GetRootGrid`), row navigation, edit state tracking, layout auto-save/load/reset via localStorage, and fullscreen 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.
|
||||||
- **`MgGridSignalRDataSource.cs`** -- `MgGridSignalRDataSource<TDataItem, TId>`, a `GridCustomDataSource` that wraps `AcSignalRDataSource`. Returns local data instantly for previously-seen filter criteria while refreshing from the server in the background. Handles filter, sort, paging, unique values, and summary calculations locally.
|
- **`MgGridWithInfoPanel.razor`** — `DxSplitter` wrapper: grid (left) + InfoPanel (right), fullscreen overlay, splitter size persistence.
|
||||||
- **`MgGridDataColumn.cs`** -- Extends `DxGridDataColumn` with InfoPanel visibility/order parameters and a `UrlLink` template that renders cells as hyperlinks with `{Property}` placeholder substitution via compiled accessors.
|
- **`MgGridToolbarBase.cs`** — Extends `DxToolbar` with `Grid`, `RefreshClick`, and `ShowOnlyIcon` parameters.
|
||||||
- **`MgGridInfoPanel.razor.cs`** -- `MgGridInfoPanel` component implementing `IInfoPanelBase`. Displays focused-row details with responsive column layout, edit/view mode, sticky positioning via JS interop, and cached column/display-text lookups.
|
- **`MgGridToolbarTemplate.razor`** — Full toolbar template: New/Edit/Delete/Save/Cancel, row navigation, layout menu (Load/Save/Reset), column chooser, export, reload, fullscreen. Extensible via `ToolbarItemsExtended`.
|
||||||
- **`MgGridToolbarBase.cs`** -- Extends `DxToolbar` with `Grid`, `RefreshClick`, and `ShowOnlyIcon` parameters.
|
- **`MgGridDataColumn.cs`** — Extends `DxGridDataColumn` with InfoPanel parameters (`ShowInInfoPanel`, `InfoPanelOrder`, `InfoPanelDisplayFormat`) and `UrlLink` template with `{Property}` placeholder substitution via compiled accessors.
|
||||||
- **`GridEditMode.cs`** -- `MgGridEditState` enum: `None`, `New`, `Edit`.
|
- **`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.
|
||||||
- **`MgGridHelper.cs`** -- Placeholder helper (empty).
|
- **`MgGridSignalRDataSource.cs`** — `GridCustomDataSource` wrapping `AcSignalRDataSource`. Local cache for seen filter criteria, background refresh.
|
||||||
- **`MgGridToolbarHelper.cs`** -- Placeholder helper (empty).
|
- **`GridEditMode.cs`** — `MgGridEditState` enum: `None`, `New`, `Edit`.
|
||||||
- **`MgGridInfoPanelHelper.cs`** -- Placeholder helper (empty).
|
- **`MgGridHelper.cs`**, **`MgGridToolbarHelper.cs`**, **`MgGridInfoPanelHelper.cs`** — Placeholder helpers (empty).
|
||||||
|
|
||||||
---
|
|
||||||
> **LLM Maintenance:** If you modify code in this folder, update this README to reflect the changes. If you notice the README content does not match the current code, automatically update the README to match the code.
|
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,3 @@ DevExpress component wrappers and grid infrastructure for the AyCode Blazor comp
|
||||||
|
|
||||||
- **`CardViews/`** -- Generic card-based view component with pagination.
|
- **`CardViews/`** -- Generic card-based view component with pagination.
|
||||||
- **`Grids/`** -- Core grid system with SignalR data binding, toolbar, info panel, and layout persistence.
|
- **`Grids/`** -- Core grid system with SignalR data binding, toolbar, info panel, and layout persistence.
|
||||||
|
|
||||||
---
|
|
||||||
> **LLM Maintenance:** If you modify code in this folder, update this README to reflect the changes. If you notice the README content does not match the current code, automatically update the README to match the code.
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,29 @@
|
||||||
# AyCode.Blazor.Components
|
# AyCode.Blazor.Components
|
||||||
|
|
||||||
|
@project {
|
||||||
|
type = "framework"
|
||||||
|
own-dep-projects = [
|
||||||
|
"AyCode.Core, AyCode.Entities, AyCode.Interfaces, AyCode.Models, AyCode.Services, AyCode.Services.Server, AyCode.Utils (in AyCode.Core repo)"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
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, a SignalR-powered grid system, and LINQ expression serialization services.
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
| Document | Topic |
|
||||||
|
|---|---|
|
||||||
|
| `MGGRID/README.md` | MgGrid system — overview, hierarchy, generic params, IMgGridBase interface |
|
||||||
|
| `MGGRID/MGGRID_PARAMETERS.md` | Component parameters, event callbacks, default grid settings |
|
||||||
|
| `MGGRID/MGGRID_CRUD.md` | Lifecycle, CRUD operations, edit flow, disposal |
|
||||||
|
| `MGGRID/MGGRID_LAYOUT.md` | Layout persistence (storage keys, tiers, operations) |
|
||||||
|
| `MGGRID/MGGRID_DETAIL.md` | Master-detail hierarchy |
|
||||||
|
| `MGGRID/MGGRID_RENDERING.md` | Fullscreen mode, rendering |
|
||||||
|
| `MGGRID/MGGRID_INFOPANEL.md` | MgGridInfoPanel, MgGridWithInfoPanel wrapper |
|
||||||
|
| `MGGRID/MGGRID_TOOLBAR.md` | MgGridToolbarTemplate (buttons, parameters, state) |
|
||||||
|
| `MGGRID/MGGRID_COLUMNS.md` | MgGridDataColumn (InfoPanel params, UrlLink) |
|
||||||
|
| `MGGRID/MGGRID_DATASOURCE.md` | MgGridSignalRDataSource (server-side data, local cache) |
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
|
|
||||||
- **DevExpress.Blazor** 25.1.3, **DevExpress.Data** 25.1.3
|
- **DevExpress.Blazor** 25.1.3, **DevExpress.Data** 25.1.3
|
||||||
|
|
@ -17,6 +39,3 @@ Blazor Razor component library targeting .NET 10. Provides reusable DevExpress-b
|
||||||
|
|
||||||
- **`Components/`** -- DevExpress component wrappers and grid infrastructure.
|
- **`Components/`** -- DevExpress component wrappers and grid infrastructure.
|
||||||
- **`Services/`** -- Authentication, grid data source, and LINQ expression serialization helpers.
|
- **`Services/`** -- Authentication, grid data source, and LINQ expression serialization helpers.
|
||||||
|
|
||||||
---
|
|
||||||
> **LLM Maintenance:** If you modify code in this folder, update this README to reflect the changes. If you notice the README content does not match the current code, automatically update the README to match the code.
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,3 @@ LINQ expression tree serialization and deserialization to JSON, enabling express
|
||||||
- **`AcExpressionHelper.cs`** -- Static facade for serializing/deserializing expressions and `IQueryable` query trees. Provides `ExpressionToJson`, `ExpressionFromJson`, `QueryToJson`, and `ApplyQueryFromJson` methods.
|
- **`AcExpressionHelper.cs`** -- Static facade for serializing/deserializing expressions and `IQueryable` query trees. Provides `ExpressionToJson`, `ExpressionFromJson`, `QueryToJson`, and `ApplyQueryFromJson` methods.
|
||||||
- **`AcExpressionSerializerVisitor.cs`** -- `ExpressionVisitor` subclass that walks an expression tree and builds the `AcExpressionNode` graph using a stack-based approach. Handles closure variable evaluation and constant serialization.
|
- **`AcExpressionSerializerVisitor.cs`** -- `ExpressionVisitor` subclass that walks an expression tree and builds the `AcExpressionNode` graph using a stack-based approach. Handles closure variable evaluation and constant serialization.
|
||||||
- **`AcExpressionDeserializer.cs`** -- Reconstructs `Expression` trees from `AcExpressionNode` DTOs. Resolves types, parameters, methods, and member bindings. Handles nullable type mismatches in binary expressions.
|
- **`AcExpressionDeserializer.cs`** -- Reconstructs `Expression` trees from `AcExpressionNode` DTOs. Resolves types, parameters, methods, and member bindings. Handles nullable type mismatches in binary expressions.
|
||||||
|
|
||||||
---
|
|
||||||
> **LLM Maintenance:** If you modify code in this folder, update this README to reflect the changes. If you notice the README content does not match the current code, automatically update the README to match the code.
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,3 @@ Web authentication service for the Blazor application.
|
||||||
## Key Files
|
## Key Files
|
||||||
|
|
||||||
- **`AcWebAuthService.cs`** -- `AcWebAuthService` class with a virtual `Logout()` method. Intended as a base class for application-specific auth services to override with concrete logout logic.
|
- **`AcWebAuthService.cs`** -- `AcWebAuthService` class with a virtual `Logout()` method. Intended as a base class for application-specific auth services to override with concrete logout logic.
|
||||||
|
|
||||||
---
|
|
||||||
> **LLM Maintenance:** If you modify code in this folder, update this README to reflect the changes. If you notice the README content does not match the current code, automatically update the README to match the code.
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,3 @@ Application services including authentication, grid data source prototyping, and
|
||||||
|
|
||||||
- **`Logins/`** -- Web authentication service.
|
- **`Logins/`** -- Web authentication service.
|
||||||
- **`ExpressionHelpers/`** -- LINQ expression tree serialization and deserialization to JSON for transport over SignalR or HTTP.
|
- **`ExpressionHelpers/`** -- LINQ expression tree serialization and deserialization to JSON for transport over SignalR or HTTP.
|
||||||
|
|
||||||
---
|
|
||||||
> **LLM Maintenance:** If you modify code in this folder, update this README to reflect the changes. If you notice the README content does not match the current code, automatically update the README to match the code.
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
# MgGrid — Columns
|
||||||
|
|
||||||
|
> Part of the MgGrid system. See `README.md` for overview and component hierarchy.
|
||||||
|
|
||||||
|
## MgGridDataColumn
|
||||||
|
|
||||||
|
Extended `DxGridDataColumn` with InfoPanel and URL link support.
|
||||||
|
|
||||||
|
| Parameter | Type | Default | Description |
|
||||||
|
|---|---|---|---|
|
||||||
|
| `ShowInInfoPanel` | `bool` | `true` | Whether this column is visible in InfoPanel |
|
||||||
|
| `InfoPanelDisplayFormat` | `string?` | `null` | Custom display format for InfoPanel |
|
||||||
|
| `InfoPanelOrder` | `int` | `int.MaxValue` | Column order in InfoPanel (lower = earlier) |
|
||||||
|
| `UrlLink` | `string?` | `null` | URL template with `{Property}` placeholders |
|
||||||
|
|
||||||
|
**UrlLink example:** `https://admin.example.com/Entity/Edit/{Id}` — renders cell as `<a href="..." target="_blank">`.
|
||||||
|
|
||||||
|
Uses compiled property accessors (`ConcurrentDictionary` cache) for performance.
|
||||||
|
|
@ -0,0 +1,101 @@
|
||||||
|
# MgGrid — Lifecycle & CRUD
|
||||||
|
|
||||||
|
> Part of the MgGrid system. See `README.md` for overview and component hierarchy.
|
||||||
|
|
||||||
|
## Lifecycle
|
||||||
|
|
||||||
|
```
|
||||||
|
1. OnInitializedAsync()
|
||||||
|
├── Validate Logger, SignalRClient (throw if null)
|
||||||
|
├── Create SignalRCrudTags from message tag parameters
|
||||||
|
├── Create TSignalRDataSource via Activator.CreateInstance(SignalRClient, crudTags, ContextIds)
|
||||||
|
├── Set DataSource.FilterText
|
||||||
|
├── Bind grid Data to data source inner list
|
||||||
|
└── Subscribe to: OnDataSourceLoaded, OnDataSourceItemChanged, OnSyncingStateChanged
|
||||||
|
|
||||||
|
2. SetParametersAsyncCore() [first time]
|
||||||
|
├── Set KeyFieldName = "Id"
|
||||||
|
├── Wire 6 DxGrid events → internal handlers (see MGGRID_PARAMETERS.md)
|
||||||
|
├── Add OnCustomizeElement handler (edit row highlighting, detail cell styling)
|
||||||
|
└── Set defaults: TextWrapEnabled=false, AllowSelectRowByClick=true, etc.
|
||||||
|
|
||||||
|
3. OnParametersSet() [first time]
|
||||||
|
├── Set GridName default: "{TDataItem.Name}Grid"
|
||||||
|
├── Set AutoSaveLayoutName default: "Grid{TDataItem.Name}"
|
||||||
|
├── Wire layout auto-loading/saving handlers
|
||||||
|
└── Register with GridWrapper via GridWrapper.RegisterGrid(this)
|
||||||
|
|
||||||
|
4. OnAfterRenderAsync(firstRender: true)
|
||||||
|
├── If DataSource parameter was provided: LoadDataSource(dataSourceParam, sync, notify)
|
||||||
|
└── Else: LoadDataSourceAsync(notify) — fires SignalR GetAll request
|
||||||
|
```
|
||||||
|
|
||||||
|
## CRUD Operations
|
||||||
|
|
||||||
|
### Adding Items
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
await grid.AddDataItem(item); // local add, sync later
|
||||||
|
await grid.AddDataItemAsync(item); // immediate server sync
|
||||||
|
|
||||||
|
await grid.InsertDataItem(0, item); // insert at index, sync later
|
||||||
|
await grid.InsertDataItemAsync(0, item); // insert at index, immediate sync
|
||||||
|
```
|
||||||
|
|
||||||
|
### Other CRUD Methods
|
||||||
|
|
||||||
|
| Method | Description |
|
||||||
|
|---|---|
|
||||||
|
| `UpdateDataItem(item)` | Local update, sync later |
|
||||||
|
| `UpdateDataItemAsync(item)` | Immediate server sync |
|
||||||
|
| `AddOrUpdateDataItem(item)` | Add if new, update if existing |
|
||||||
|
| `RemoveDataItem(item)` | Remove by entity reference |
|
||||||
|
| `RemoveDataItem(id)` | Remove by ID |
|
||||||
|
| `ReloadDataSourceAsync()` | Re-fetch all data from server |
|
||||||
|
| `ForceRenderAsync()` | Force grid re-initialization via new render key |
|
||||||
|
|
||||||
|
### ID Generation for New Items
|
||||||
|
|
||||||
|
New items get **temporary client-side IDs** until the server assigns real ones:
|
||||||
|
|
||||||
|
| TId Type | Strategy | Example |
|
||||||
|
|---|---|---|
|
||||||
|
| `Guid` | `Guid.NewGuid()` | `a1b2c3d4-...` |
|
||||||
|
| `int` | `-1 * AcDomain.NextUniqueInt32` | `-1`, `-2`, `-3`, ... |
|
||||||
|
|
||||||
|
**Convention:** Negative integer IDs indicate unsaved items. The server replaces them with real auto-increment IDs.
|
||||||
|
|
||||||
|
### Edit Flow (Inline)
|
||||||
|
|
||||||
|
```
|
||||||
|
User clicks Edit → OnEditStart → OnCustomizeEditModel
|
||||||
|
├── Set GridEditState = New/Edit
|
||||||
|
├── For new items: assign temp ID, set parent FK if detail grid
|
||||||
|
├── Notify InfoPanel: SetEditMode()
|
||||||
|
└── Fire OnGridCustomizeEditModel callback
|
||||||
|
|
||||||
|
User clicks Save → OnItemSaving
|
||||||
|
├── Fire OnGridEditModelSaving callback (can cancel)
|
||||||
|
├── If new: AddDataItemAsync / InsertDataItemAsync
|
||||||
|
├── If existing: UpdateDataItemAsync
|
||||||
|
├── Reset GridEditState = None
|
||||||
|
└── Clear InfoPanel edit mode
|
||||||
|
|
||||||
|
User clicks Cancel → OnEditCanceling
|
||||||
|
├── Reset GridEditState = None
|
||||||
|
└── Clear InfoPanel edit mode
|
||||||
|
```
|
||||||
|
|
||||||
|
### Edit Row Highlighting
|
||||||
|
|
||||||
|
When `GridEditState != None`, the focused row and its cells get `background-color: #fffbeb` (warm yellow) via `OnCustomizeElement`.
|
||||||
|
|
||||||
|
## Disposal
|
||||||
|
|
||||||
|
`DisposeAsync()` handles cleanup:
|
||||||
|
1. Set `_isDisposed = true` (guards all async callbacks)
|
||||||
|
2. Unsubscribe from `OnDataSourceLoaded`, `OnDataSourceItemChanged`, `OnSyncingStateChanged`
|
||||||
|
3. Remove `OnCustomizeElement` handler
|
||||||
|
4. `GC.SuppressFinalize(this)`
|
||||||
|
|
||||||
|
All async callbacks check `_isDisposed` before proceeding.
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
# MgGrid — DataSource
|
||||||
|
|
||||||
|
> Part of the MgGrid system. See `README.md` for overview and component hierarchy.
|
||||||
|
> For the underlying `AcSignalRDataSource`: `AyCode.Services.Server/docs/SIGNALR_DATASOURCE/README.md` (in AyCode.Core repo)
|
||||||
|
|
||||||
|
## MgGridSignalRDataSource
|
||||||
|
|
||||||
|
`GridCustomDataSource` wrapper around `AcSignalRDataSource` for server-side data operations.
|
||||||
|
|
||||||
|
- Returns local data instantly for previously-seen filter criteria
|
||||||
|
- Refreshes from the server in the background
|
||||||
|
- Handles filter, sort, paging, unique values, and summary calculations locally
|
||||||
|
- `OnBackgroundRefreshCompleted` event fires when background refresh completes
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
# MgGrid — Master-Detail
|
||||||
|
|
||||||
|
> Part of the MgGrid system. See `README.md` for overview and component hierarchy.
|
||||||
|
|
||||||
|
## How It Works
|
||||||
|
|
||||||
|
1. `MgGridBase.BuildRenderTree` wraps content in `CascadingValue<IMgGridBase>`
|
||||||
|
2. Child grids receive this via `[CascadingParameter] IMgGridBase? ParentGrid`
|
||||||
|
3. `IsMasterGrid` = `ParentDataItem == null`
|
||||||
|
4. `GetRootGrid()` walks the `ParentGrid` chain to find the topmost grid
|
||||||
|
|
||||||
|
## Detail Grid Setup
|
||||||
|
|
||||||
|
```razor
|
||||||
|
<DetailRowTemplate>
|
||||||
|
@{
|
||||||
|
var parent = (ParentEntity)context.DataItem;
|
||||||
|
<GridChildEntity ParentDataItem="@parent"
|
||||||
|
KeyFieldNameToParentId="ParentEntityId"
|
||||||
|
ContextIds="@(new object[] { parent.Id })" />
|
||||||
|
}
|
||||||
|
</DetailRowTemplate>
|
||||||
|
```
|
||||||
|
|
||||||
|
When `ParentDataItem` is set and `KeyFieldNameToParentId` is provided, new items automatically get their parent FK set via reflection.
|
||||||
|
|
@ -0,0 +1,98 @@
|
||||||
|
# MgGrid — InfoPanel
|
||||||
|
|
||||||
|
> Part of the MgGrid system. See `README.md` for overview and component hierarchy.
|
||||||
|
|
||||||
|
## MgGridWithInfoPanel Wrapper
|
||||||
|
|
||||||
|
```razor
|
||||||
|
<MgGridWithInfoPanel ShowInfoPanel="true" InfoPanelSize="400px">
|
||||||
|
<GridContent>
|
||||||
|
<GridMyEntityBase @ref="Grid" ... />
|
||||||
|
</GridContent>
|
||||||
|
<ChildContent>
|
||||||
|
@* Optional: custom InfoPanel — if omitted, default MgGridInfoPanel is used *@
|
||||||
|
</ChildContent>
|
||||||
|
</MgGridWithInfoPanel>
|
||||||
|
```
|
||||||
|
|
||||||
|
| Parameter | Type | Default | Description |
|
||||||
|
|---|---|---|---|
|
||||||
|
| `GridContent` | `RenderFragment` | — | The grid to display in the left pane |
|
||||||
|
| `ChildContent` | `RenderFragment?` | `null` | Custom InfoPanel. If `null`, renders `MgGridInfoPanel` |
|
||||||
|
| `ShowInfoPanel` | `bool` | `true` | Whether to show the right pane |
|
||||||
|
| `InfoPanelSize` | `string` | `"400px"` | Initial right pane size |
|
||||||
|
|
||||||
|
The wrapper provides:
|
||||||
|
- `DxSplitter` with collapsible right pane
|
||||||
|
- Fullscreen overlay (`mg-fullscreen-overlay`)
|
||||||
|
- Splitter size persistence (`Splitter_{key}` in localStorage)
|
||||||
|
- `RegisterGrid(grid)` — called by MgGridBase in `OnParametersSet`
|
||||||
|
- `RegisterInfoPanel(infoPanel)` — called by MgGridInfoPanel in `OnAfterRenderAsync`
|
||||||
|
|
||||||
|
## MgGridInfoPanel
|
||||||
|
|
||||||
|
Default InfoPanel component implementing `IInfoPanelBase`. Displays focused-row details with edit support.
|
||||||
|
|
||||||
|
### IInfoPanelBase Interface
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public interface IInfoPanelBase
|
||||||
|
{
|
||||||
|
void RefreshData(IMgGridBase grid, object? dataItem, int visibleIndex = -1);
|
||||||
|
void SetEditMode(IMgGridBase grid, object editModel);
|
||||||
|
void ClearEditMode();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### InfoPanel Data Flow
|
||||||
|
|
||||||
|
```
|
||||||
|
FocusedRowChanged → InfoPanelInstance.RefreshData(grid, dataItem, visibleIndex)
|
||||||
|
Edit starts → InfoPanelInstance.SetEditMode(grid, editModel)
|
||||||
|
Edit ends/cancel → InfoPanelInstance.ClearEditMode()
|
||||||
|
```
|
||||||
|
|
||||||
|
`InfoPanelInstance` resolution: own `GridWrapper.InfoPanelInstance` → root grid's `GridWrapper.InfoPanelInstance` → `null`.
|
||||||
|
|
||||||
|
### Responsive Column Layout
|
||||||
|
|
||||||
|
| Breakpoint Parameter | Default | Columns |
|
||||||
|
|---|---|---|
|
||||||
|
| — | < 400px | 1 column |
|
||||||
|
| `TwoColumnBreakpoint` | 400px | 2 columns |
|
||||||
|
| `ThreeColumnBreakpoint` | 800px | 3 columns |
|
||||||
|
| `FourColumnBreakpoint` | 1300px | 4 columns |
|
||||||
|
|
||||||
|
`FixedColumnCount` (1-4) overrides responsive breakpoints if set.
|
||||||
|
|
||||||
|
### Template System
|
||||||
|
|
||||||
|
| Template | Context | Purpose |
|
||||||
|
|---|---|---|
|
||||||
|
| `HeaderTemplate` | `InfoPanelContext` | Custom header (default: grid Caption) |
|
||||||
|
| `BeforeColumnsTemplate` | `InfoPanelContext` | Content before column-value pairs |
|
||||||
|
| `ColumnsTemplate` | `InfoPanelContext` | Replace default column rendering entirely |
|
||||||
|
| `AfterColumnsTemplate` | `InfoPanelContext` | Content after column-value pairs |
|
||||||
|
| `FooterTemplate` | `InfoPanelContext` | Custom footer |
|
||||||
|
|
||||||
|
`InfoPanelContext` = `record(object? DataItem, bool IsEditMode)`.
|
||||||
|
|
||||||
|
### Edit Mode Editors (by property type)
|
||||||
|
|
||||||
|
| Type | Editor Component |
|
||||||
|
|---|---|
|
||||||
|
| `bool` | `DxCheckBox<bool>` |
|
||||||
|
| `DateTime` / `DateTime?` | `DxDateEdit<DateTime>` / `DxDateEdit<DateTime?>` |
|
||||||
|
| `DateOnly` / `DateOnly?` | `DxDateEdit<DateOnly>` / `DxDateEdit<DateOnly?>` |
|
||||||
|
| `int` | `DxSpinEdit<int>` |
|
||||||
|
| `decimal` | `DxSpinEdit<decimal>` |
|
||||||
|
| `double` | `DxSpinEdit<double>` |
|
||||||
|
| ComboBox (via `DxComboBoxSettings`) | `DxComboBox<TValue, TItem>` |
|
||||||
|
| Memo (via `EditSettingsType.Memo`) | `DxMemo` |
|
||||||
|
| Other | `DxTextBox` |
|
||||||
|
|
||||||
|
### Additional Features
|
||||||
|
|
||||||
|
- **Sticky positioning** via JS interop (`MgGridInfoPanel.initSticky`)
|
||||||
|
- **Built-in toolbar** with `MgGridToolbarTemplate` (`OnlyGridEditTools=true`)
|
||||||
|
- **OnDataItemChanged** callback when focused row changes
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
# MGGRID — Known Issues
|
||||||
|
|
||||||
|
For planned/actionable work see `MGGRID_TODO.md`.
|
||||||
|
|
||||||
|
No formally-tracked issues yet. In-code TODOs are recorded as TODO entries (`ACBLAZOR-GRID-T-*`) in `MGGRID_TODO.md`, since they describe unfinished work rather than confirmed broken behaviour.
|
||||||
|
|
||||||
|
Add the first `## ACBLAZOR-GRID-I-XXXX: ...` entry below when a concrete issue is observed.
|
||||||
|
|
||||||
|
## Issue entry template
|
||||||
|
|
||||||
|
```
|
||||||
|
## ACBLAZOR-GRID-I-XXXX: Short title
|
||||||
|
|
||||||
|
**Severity:** Trivial / Low / Minor / Major · **Status:** Open / Documented / Mitigated · **Area:** <subsystem>
|
||||||
|
|
||||||
|
### Description
|
||||||
|
What breaks, and under what conditions.
|
||||||
|
|
||||||
|
### Root cause
|
||||||
|
Why it happens (code location + design mismatch).
|
||||||
|
|
||||||
|
### Known workaround
|
||||||
|
Steps a consumer can take until fixed.
|
||||||
|
|
||||||
|
### Related TODO
|
||||||
|
`MGGRID_TODO.md#acblazor-grid-t-XXXX` (if applicable).
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
# 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 current layout to both UserSave AND AutoSave keys |
|
||||||
|
| `LoadUserLayoutAsync()` | Loads from UserSave key (if exists) |
|
||||||
|
| `ResetLayoutAsync()` | Removes AutoSave key, restores in-memory `_defaultLayoutJson` |
|
||||||
|
| `HasUserLayoutAsync()` | Checks if UserSave key exists in localStorage |
|
||||||
|
|
||||||
|
## 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.
|
||||||
|
|
@ -0,0 +1,82 @@
|
||||||
|
# MgGrid — Parameters & Events
|
||||||
|
|
||||||
|
> Part of the MgGrid system. See `README.md` for overview and component hierarchy.
|
||||||
|
|
||||||
|
## Required Parameters
|
||||||
|
|
||||||
|
| Parameter | Type | Description |
|
||||||
|
|---|---|---|
|
||||||
|
| `SignalRClient` | `AcSignalRClientBase` | SignalR client for server communication |
|
||||||
|
| `Logger` | `TLoggerClient` | Logger instance |
|
||||||
|
| `GetAllMessageTag` | `int` | SignalR tag for loading all items |
|
||||||
|
|
||||||
|
## CRUD Message Tags
|
||||||
|
|
||||||
|
| Parameter | Type | Description |
|
||||||
|
|---|---|---|
|
||||||
|
| `GetAllMessageTag` | `int` | Tag for "get all items" request |
|
||||||
|
| `GetItemMessageTag` | `int` | Tag for "get single item" request |
|
||||||
|
| `AddMessageTag` | `int` | Tag for "add item" request |
|
||||||
|
| `UpdateMessageTag` | `int` | Tag for "update item" request |
|
||||||
|
| `RemoveMessageTag` | `int` | Tag for "remove item" request |
|
||||||
|
|
||||||
|
These are bundled into a `SignalRCrudTags` during `OnInitializedAsync`. See `AyCode.Services.Server/docs/SIGNALR_DATASOURCE/README.md` (in AyCode.Core repo) for details.
|
||||||
|
|
||||||
|
## Data & Context Parameters
|
||||||
|
|
||||||
|
| Parameter | Type | Description |
|
||||||
|
|---|---|---|
|
||||||
|
| `DataSource` | `IList<TDataItem>` | Bind with `AcObservableCollection<TDataItem>` for external data. If not set, grid creates its own. |
|
||||||
|
| `ParentDataItem` | `IId<TId>?` | Parent entity for detail grids. `null` = master grid. |
|
||||||
|
| `KeyFieldNameToParentId` | `string?` | Property name on `TDataItem` that references the parent's ID |
|
||||||
|
| `ContextIds` | `object[]?` | Additional context passed to `AcSignalRDataSource` constructor |
|
||||||
|
| `FilterText` | `string?` | Text filter — propagated to data source, triggers reload |
|
||||||
|
|
||||||
|
## Display & Behavior Parameters
|
||||||
|
|
||||||
|
| Parameter | Type | Default | Description |
|
||||||
|
|---|---|---|---|
|
||||||
|
| `Caption` | `string` | `typeof(TDataItem).Name` | Grid title (shown in fullscreen header) |
|
||||||
|
| `GridName` | `string` | `"{TDataItem.Name}Grid"` | Name used in log messages |
|
||||||
|
| `AutoSaveLayoutName` | `string?` | `"Grid{TDataItem.Name}"` | Base name for layout storage keys |
|
||||||
|
|
||||||
|
## Event Callbacks
|
||||||
|
|
||||||
|
All grid events are re-exposed with `OnGrid` prefix to avoid collisions with `DxGrid` base events:
|
||||||
|
|
||||||
|
| Event | DxGrid Equivalent | When Fired |
|
||||||
|
|---|---|---|
|
||||||
|
| `OnGridItemDeleting` | `DataItemDeleting` | Before item removal (can cancel via `e.Cancel`) |
|
||||||
|
| `OnGridEditModelSaving` | `EditModelSaving` | Before item save (can cancel via `e.Cancel`) |
|
||||||
|
| `OnGridEditStart` | `EditStart` | When edit mode begins |
|
||||||
|
| `OnGridCustomizeEditModel` | `CustomizeEditModel` | When edit model is being prepared |
|
||||||
|
| `OnGridFocusedRowChanged` | `FocusedRowChanged` | When focused row changes |
|
||||||
|
| `OnDataSourceChanged` | — | After data source is loaded/reloaded |
|
||||||
|
| `OnGridItemChanged` | — | After server confirms a CRUD operation |
|
||||||
|
| `OnGridItemChanging` | — | Before a CRUD operation is sent to server |
|
||||||
|
|
||||||
|
Internal event wiring (in `SetParametersAsyncCore`, first call):
|
||||||
|
|
||||||
|
| DxGrid Event | → Internal Handler |
|
||||||
|
|---|---|
|
||||||
|
| `DataItemDeleting` | `OnItemDeleting` |
|
||||||
|
| `EditModelSaving` | `OnItemSaving` |
|
||||||
|
| `CustomizeEditModel` | `OnCustomizeEditModel` |
|
||||||
|
| `FocusedRowChanged` | `OnFocusedRowChanged` |
|
||||||
|
| `EditStart` | `OnEditStart` |
|
||||||
|
| `EditCanceling` | `OnEditCanceling` |
|
||||||
|
|
||||||
|
## Default Grid Settings
|
||||||
|
|
||||||
|
Set in `SetParametersAsyncCore` (first call only):
|
||||||
|
|
||||||
|
| Setting | Value |
|
||||||
|
|---|---|
|
||||||
|
| `KeyFieldName` | `"Id"` |
|
||||||
|
| `TextWrapEnabled` | `false` |
|
||||||
|
| `AllowSelectRowByClick` | `true` |
|
||||||
|
| `HighlightRowOnHover` | `true` |
|
||||||
|
| `AutoCollapseDetailRow` | `true` |
|
||||||
|
| `AutoExpandAllGroupRows` | `false` |
|
||||||
|
|
||||||
|
Project adapters typically add more defaults in `OnParametersSet` (e.g., `EditMode`, `FocusedRowEnabled`, `PageSize`, `ShowFilterRow`, `SizeMode` based on `IsMasterGrid`).
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
# MgGrid — Fullscreen & Rendering
|
||||||
|
|
||||||
|
> Part of the MgGrid system. See `README.md` for overview and component hierarchy.
|
||||||
|
|
||||||
|
## Fullscreen Mode
|
||||||
|
|
||||||
|
Two modes depending on whether `MgGridWithInfoPanel` wraps the grid:
|
||||||
|
|
||||||
|
| Scenario | Behavior |
|
||||||
|
|---|---|
|
||||||
|
| **With wrapper** | `ToggleFullscreen()` delegates to wrapper — fullscreen includes grid + InfoPanel |
|
||||||
|
| **Standalone** | Grid renders its own `mg-fullscreen-overlay` with header (Caption + close button) and body |
|
||||||
|
|
||||||
|
## Rendering
|
||||||
|
|
||||||
|
`BuildRenderTree` uses manual render tree building (not Razor markup):
|
||||||
|
|
||||||
|
1. Outer `CascadingValue<IMgGridBase>` — provides this grid as `ParentGrid` to children
|
||||||
|
2. If standalone fullscreen: `div.mg-fullscreen-overlay` > `div.mg-fullscreen-header` + `div.mg-fullscreen-body` > `base.BuildRenderTree`
|
||||||
|
3. If normal: `div[style=display:contents]` > `base.BuildRenderTree`
|
||||||
|
4. `_gridRenderKey` (Guid) used as element key — changed by `ForceRenderAsync()` to force re-initialization
|
||||||
|
|
@ -0,0 +1,81 @@
|
||||||
|
# MGGRID — TODO
|
||||||
|
|
||||||
|
For known issues / bugs see `MGGRID_ISSUES.md`.
|
||||||
|
|
||||||
|
## Priority legend
|
||||||
|
- **P0** blocker · **P1** important · **P2** nice-to-have · **P3** idea
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 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`.
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
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 for `Guid` and `int`. `MgGridBase` takes it via DI or generic parameter. Consumer-specific `TId` types register their generator.
|
||||||
|
- **(b)** Virtual protected method: `protected virtual TId GenerateNewId()` on `MgGridBase`, with default implementations for `Guid` and `int` preserved. Consumer overrides for custom `TId`.
|
||||||
|
- **(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 unregistered `TId` types.
|
||||||
|
- Existing `Guid` and `int` consumers 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`
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
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 needed` comment.
|
||||||
|
|
||||||
|
## 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.
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
# MgGrid — Toolbar
|
||||||
|
|
||||||
|
> Part of the MgGrid system. See `README.md` for overview and component hierarchy.
|
||||||
|
|
||||||
|
## MgGridToolbarTemplate
|
||||||
|
|
||||||
|
The standard toolbar rendered inside grid's `ToolbarTemplate`. Provides all standard grid operations.
|
||||||
|
|
||||||
|
### Toolbar Buttons
|
||||||
|
|
||||||
|
| Group | Buttons | Visible |
|
||||||
|
|---|---|---|
|
||||||
|
| **CRUD** | New, Edit, Delete | When NOT editing |
|
||||||
|
| **Edit mode** | Save, Cancel | When editing |
|
||||||
|
| **Navigation** | Prev Row, Next Row | When NOT editing |
|
||||||
|
| **Layout** | Column Chooser, Layout (Load/Save/Reset) | When `OnlyGridEditTools=false` |
|
||||||
|
| **Actions** | Export (CSV/XLSX/XLS/PDF), Reload Data, Fullscreen | When `OnlyGridEditTools=false` |
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
|
||||||
|
| Parameter | Type | Default | Description |
|
||||||
|
|---|---|---|---|
|
||||||
|
| `Grid` | `IMgGridBase` | required | The grid to control |
|
||||||
|
| `OnlyGridEditTools` | `bool` | `false` | Show only CRUD + navigation (used by InfoPanel) |
|
||||||
|
| `ShowOnlyIcon` | `bool` | `false` | Hide button text, show only icons |
|
||||||
|
| `EnableNew` | `bool` | `true` | Enable "New" button |
|
||||||
|
| `EnableEdit` | `bool` | `true` | Enable "Edit" button |
|
||||||
|
| `EnableDelete` | `bool` | `false` | Enable "Delete" button |
|
||||||
|
| `ToolbarItemsExtended` | `RenderFragment?` | `null` | Extra toolbar items after standard buttons |
|
||||||
|
| `OnReloadDataClick` | `EventCallback` | — | Callback for "Reload Data" button |
|
||||||
|
|
||||||
|
### State Properties (computed from Grid)
|
||||||
|
|
||||||
|
| Property | Source |
|
||||||
|
|---|---|
|
||||||
|
| `IsEditing` | `Grid.GridEditState != MgGridEditState.None` |
|
||||||
|
| `IsSyncing` | `Grid.IsSyncing` |
|
||||||
|
| `HasFocusedRow` | `Grid.GetFocusedRowIndex() >= 0` |
|
||||||
|
| `IsFullscreenMode` | `Grid.IsFullscreen` |
|
||||||
|
|
@ -0,0 +1,118 @@
|
||||||
|
# MgGrid System
|
||||||
|
|
||||||
|
> Comprehensive documentation for the **MgGrid** component family — the primary UI data grid pattern in the AyCode.Blazor framework.
|
||||||
|
> Source: `Components/Grids/`
|
||||||
|
> For SignalR transport: `AyCode.Services/docs/SIGNALR/README.md` (in AyCode.Core repo)
|
||||||
|
> For `AcSignalRDataSource`: `AyCode.Services.Server/docs/SIGNALR_DATASOURCE/README.md` (in AyCode.Core repo)
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
**MgGridBase** is an abstract generic Blazor component that extends DevExpress `DxGrid` with:
|
||||||
|
- **Automatic SignalR CRUD** via `AcSignalRDataSource` (see AyCode.Core docs)
|
||||||
|
- **Layout persistence** — column order, widths, sorting, grouping auto-saved to `localStorage`
|
||||||
|
- **Master-detail hierarchy** — nested grids share context via `CascadingParameter`
|
||||||
|
- **InfoPanel integration** — side panel shows focused row details, supports edit mode
|
||||||
|
- **Fullscreen mode** — standalone overlay or via `MgGridWithInfoPanel` wrapper
|
||||||
|
- **Change tracking** — client-side tracking with server sync via `SaveChangesAsync`
|
||||||
|
|
||||||
|
## Detailed Documentation
|
||||||
|
|
||||||
|
| File | Topics |
|
||||||
|
|---|---|
|
||||||
|
| `MGGRID_PARAMETERS.md` | Component parameters (required, CRUD tags, data & context, display), 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 |
|
||||||
|
| `MGGRID_RENDERING.md` | Fullscreen mode, rendering |
|
||||||
|
| `MGGRID_INFOPANEL.md` | MgGridInfoPanel, MgGridWithInfoPanel wrapper, responsive layout, templates, editors |
|
||||||
|
| `MGGRID_TOOLBAR.md` | MgGridToolbarTemplate (buttons, parameters, state) |
|
||||||
|
| `MGGRID_COLUMNS.md` | MgGridDataColumn (InfoPanel params, UrlLink) |
|
||||||
|
| `MGGRID_DATASOURCE.md` | MgGridSignalRDataSource (server-side data, local cache, background refresh) |
|
||||||
|
| `MGGRID_ISSUES.md` | Known issues (`ACBLAZOR-GRID-I-*`, `ACBLAZOR-GRID-B-*`) — currently none formally tracked |
|
||||||
|
| `MGGRID_TODO.md` | Planned work (`ACBLAZOR-GRID-T-*`) — refactors, missing features, optimizations |
|
||||||
|
|
||||||
|
## Component Hierarchy
|
||||||
|
|
||||||
|
```
|
||||||
|
DxGrid (DevExpress)
|
||||||
|
└── MgGridBase<TSignalRDataSource, TDataItem, TId, TLoggerClient> (AyCode.Blazor — abstract)
|
||||||
|
└── [Project-specific adapter] ← consumer fixes TSignalRDataSource, TId, TLoggerClient
|
||||||
|
└── [Concrete entity grid] ← consumer sets CRUD tags in constructor
|
||||||
|
```
|
||||||
|
|
||||||
|
### Companion Components
|
||||||
|
|
||||||
|
| Component | Purpose | Docs |
|
||||||
|
|---|---|---|
|
||||||
|
| **MgGridWithInfoPanel** | `DxSplitter` wrapper: grid + InfoPanel, fullscreen, splitter persistence | `MGGRID_INFOPANEL.md` |
|
||||||
|
| **MgGridToolbarBase** | `DxToolbar` base with `Grid` reference, `RefreshClick` callback | `MGGRID_TOOLBAR.md` |
|
||||||
|
| **MgGridToolbarTemplate** | Full toolbar: CRUD, navigation, layout menu, fullscreen, export | `MGGRID_TOOLBAR.md` |
|
||||||
|
| **MgGridDataColumn** | Extended `DxGridDataColumn` with InfoPanel params and `UrlLink` | `MGGRID_COLUMNS.md` |
|
||||||
|
| **MgGridInfoPanel** | Default InfoPanel: column-value pairs, edit mode, typed editors | `MGGRID_INFOPANEL.md` |
|
||||||
|
| **MgGridSignalRDataSource** | `GridCustomDataSource` wrapper: server-side filter/sort/page, local cache | `MGGRID_DATASOURCE.md` |
|
||||||
|
|
||||||
|
## Generic Type Parameters
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
MgGridBase<TSignalRDataSource, TDataItem, TId, TLoggerClient>
|
||||||
|
```
|
||||||
|
|
||||||
|
| Parameter | Constraint | Purpose |
|
||||||
|
|---|---|---|
|
||||||
|
| `TSignalRDataSource` | `: AcSignalRDataSource<…>` | SignalR-backed data source (see `AyCode.Services.Server/docs/SIGNALR_DATASOURCE/README.md` in AyCode.Core repo) |
|
||||||
|
| `TDataItem` | `: class, IId<TId>` | Entity type displayed in the grid |
|
||||||
|
| `TId` | `: struct` | Primary key type (`int`, `Guid`) |
|
||||||
|
| `TLoggerClient` | `: AcLoggerBase` | Logger for diagnostics |
|
||||||
|
|
||||||
|
### Usage Example (Project-Specific Adapter)
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// Project adapter — fixes TSignalRDataSource, TId, TLoggerClient for the entire project
|
||||||
|
public class MyProjectGridBase<TDataItem>
|
||||||
|
: MgGridBase<MySignalRDataSource<TDataItem>, TDataItem, int, MyLoggerClient>
|
||||||
|
where TDataItem : class, IId<int>
|
||||||
|
{
|
||||||
|
[Inject] public required MyLoggedInModel LoggedInModel { get; set; }
|
||||||
|
protected override int GetLayoutUserId() => LoggedInModel.UserId;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Concrete grid — only TDataItem remains open
|
||||||
|
public class GridOrderBase : MyProjectGridBase<Order>
|
||||||
|
{
|
||||||
|
public GridOrderBase()
|
||||||
|
{
|
||||||
|
GetAllMessageTag = MySignalRTags.GetOrders;
|
||||||
|
AddMessageTag = MySignalRTags.AddOrder;
|
||||||
|
UpdateMessageTag = MySignalRTags.UpdateOrder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Interface: IMgGridBase
|
||||||
|
|
||||||
|
The public contract exposed to companion components (toolbar, InfoPanel, wrapper):
|
||||||
|
|
||||||
|
| Member | Type | Description |
|
||||||
|
|---|---|---|
|
||||||
|
| `IsSyncing` | `bool` | Whether SignalR sync is in progress |
|
||||||
|
| `Caption` | `string` | Grid title |
|
||||||
|
| `GridEditState` | `MgGridEditState` | `None` / `New` / `Edit` |
|
||||||
|
| `ParentGrid` | `IMgGridBase?` | Parent in master-detail hierarchy |
|
||||||
|
| `GetRootGrid()` | `IMgGridBase` | Walks to topmost grid |
|
||||||
|
| `StepPrevRow()` | `void` | Navigate to previous visible row |
|
||||||
|
| `StepNextRow()` | `void` | Navigate to next visible row |
|
||||||
|
| `InfoPanelInstance` | `IInfoPanelBase?` | Resolved InfoPanel reference |
|
||||||
|
| `IsFullscreen` | `bool` | Current fullscreen state |
|
||||||
|
| `AutomaticLayoutStorageKey` | `string` | Current auto-save storage key |
|
||||||
|
| `ToggleFullscreen()` | `void` | Toggle fullscreen mode |
|
||||||
|
| `SaveUserLayoutAsync()` | `Task` | Save layout manually |
|
||||||
|
| `LoadUserLayoutAsync()` | `Task` | Load manually saved layout |
|
||||||
|
| `ResetLayoutAsync()` | `Task` | Reset to default layout |
|
||||||
|
| `HasUserLayoutAsync()` | `Task<bool>` | Check if manual save exists |
|
||||||
|
|
||||||
|
## Event Args Classes
|
||||||
|
|
||||||
|
| Class | Base | Extra Properties |
|
||||||
|
|---|---|---|
|
||||||
|
| `GridDataItemChangedEventArgs<T>` | — | `Grid`, `DataItem`, `TrackingState`, `CancelStateChangeInvoke` |
|
||||||
|
| `GridDataItemChangingEventArgs<T>` | `GridDataItemChangedEventArgs<T>` | `IsCanceled` |
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
# AyCode.Blazor.Components documentation
|
||||||
|
|
||||||
|
Topic documentation for the `AyCode.Blazor.Components` project (Blazor component library).
|
||||||
|
|
||||||
|
## Topics
|
||||||
|
|
||||||
|
- [`MGGRID/`](MGGRID/README.md) — MGGRID data grid component family (CRUD, layout, columns, toolbar, rendering, etc.)
|
||||||
|
|
||||||
|
## Navigation
|
||||||
|
|
||||||
|
Per the AI Agent Core Protocol (folder navigation rule), start from this README when browsing `docs/`. Each topic folder has its own `README.md` with the main content, plus `TOPIC_*.md` sub-topic files.
|
||||||
|
|
||||||
|
## See also
|
||||||
|
|
||||||
|
- **Blazor repo conventions**: `../../docs/CONVENTIONS.md`
|
||||||
|
- **Architecture overview**: `../../docs/ARCHITECTURE.md`
|
||||||
|
|
@ -1,5 +1,12 @@
|
||||||
# AyCode.Blazor.Controllers
|
# AyCode.Blazor.Controllers
|
||||||
|
|
||||||
|
@project {
|
||||||
|
type = "framework"
|
||||||
|
own-dep-projects = [
|
||||||
|
"AyCode.Core, AyCode.Core.Server, AyCode.Database, AyCode.Entities, AyCode.Entities.Server, AyCode.Interfaces, AyCode.Interfaces.Server, AyCode.Models, AyCode.Models.Server, AyCode.Services, AyCode.Services.Server, AyCode.Utils (in AyCode.Core repo)"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
Scaffolding project for Blazor controllers and logging infrastructure. Currently contains only a placeholder class with a reserved folder for future logger implementations.
|
Scaffolding project for Blazor controllers and logging infrastructure. Currently contains only a placeholder class with a reserved folder for future logger implementations.
|
||||||
|
|
||||||
## Key Files
|
## Key Files
|
||||||
|
|
@ -18,6 +25,3 @@ Scaffolding project for Blazor controllers and logging infrastructure. Currently
|
||||||
| Microsoft.AspNetCore.SignalR.Client | 9.0.11 | NuGet |
|
| Microsoft.AspNetCore.SignalR.Client | 9.0.11 | NuGet |
|
||||||
| Microsoft.AspNetCore.SignalR.Common | 9.0.11 | NuGet |
|
| Microsoft.AspNetCore.SignalR.Common | 9.0.11 | NuGet |
|
||||||
| AyCode.Core, .Core.Server, .Database, .Entities, .Entities.Server, .Interfaces, .Interfaces.Server, .Models, .Models.Server, .Services, .Services.Server, .Utils | -- | DLL references |
|
| AyCode.Core, .Core.Server, .Database, .Entities, .Entities.Server, .Interfaces, .Interfaces.Server, .Models, .Models.Server, .Services, .Services.Server, .Utils | -- | DLL references |
|
||||||
|
|
||||||
---
|
|
||||||
> **LLM Maintenance:** If you modify code in this folder, update this README to reflect the changes. If you notice the README content does not match the current code, automatically update the README to match the code.
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,12 @@
|
||||||
# AyCode.Blazor.Models.Server
|
# AyCode.Blazor.Models.Server
|
||||||
|
|
||||||
|
@project {
|
||||||
|
type = "framework"
|
||||||
|
own-dep-projects = [
|
||||||
|
"AyCode.Core, AyCode.Core.Server, AyCode.Database, AyCode.Entities, AyCode.Entities.Server, AyCode.Interfaces, AyCode.Interfaces.Server, AyCode.Models.Server, AyCode.Services, AyCode.Services.Server, AyCode.Utils (in AyCode.Core repo)"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
Scaffolding project for server-side Blazor models and services. Currently contains only a placeholder class with reserved folders for future implementation.
|
Scaffolding project for server-side Blazor models and services. Currently contains only a placeholder class with reserved folders for future implementation.
|
||||||
|
|
||||||
## Key Files
|
## Key Files
|
||||||
|
|
@ -24,6 +31,3 @@ Scaffolding project for server-side Blazor models and services. Currently contai
|
||||||
| AyCode.Services | DLL reference |
|
| AyCode.Services | DLL reference |
|
||||||
| AyCode.Services.Server | DLL reference |
|
| AyCode.Services.Server | DLL reference |
|
||||||
| AyCode.Utils | DLL reference |
|
| AyCode.Utils | DLL reference |
|
||||||
|
|
||||||
---
|
|
||||||
> **LLM Maintenance:** If you modify code in this folder, update this README to reflect the changes. If you notice the README content does not match the current code, automatically update the README to match the code.
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,12 @@
|
||||||
# AyCode.Blazor.Models
|
# AyCode.Blazor.Models
|
||||||
|
|
||||||
|
@project {
|
||||||
|
type = "framework"
|
||||||
|
own-dep-projects = [
|
||||||
|
"AyCode.Core, AyCode.Core.Server, AyCode.Entities, AyCode.Entities.Server, AyCode.Interfaces, AyCode.Interfaces.Server, AyCode.Models, AyCode.Models.Server, AyCode.Services, AyCode.Services.Server, AyCode.Utils (in AyCode.Core repo)"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
.NET 10 class library with AOT compilation (`RunAOTCompilation` + `WasmStripILAfterAOT`) providing view model base classes and shared models for the AyCode Blazor UI layer.
|
.NET 10 class library with AOT compilation (`RunAOTCompilation` + `WasmStripILAfterAOT`) providing view model base classes and shared models for the AyCode Blazor UI layer.
|
||||||
|
|
||||||
## Key Files
|
## Key Files
|
||||||
|
|
@ -24,6 +31,3 @@ All referenced as pre-built DLLs from `AyCode.Core\AyCode.Services.Server\bin\`:
|
||||||
| AyCode.Services | DLL reference |
|
| AyCode.Services | DLL reference |
|
||||||
| AyCode.Services.Server | DLL reference |
|
| AyCode.Services.Server | DLL reference |
|
||||||
| AyCode.Utils | DLL reference |
|
| AyCode.Utils | DLL reference |
|
||||||
|
|
||||||
---
|
|
||||||
> **LLM Maintenance:** If you modify code in this folder, update this README to reflect the changes. If you notice the README content does not match the current code, automatically update the README to match the code.
|
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,3 @@ AcViewModelBase
|
||||||
AcDomainViewModel
|
AcDomainViewModel
|
||||||
+-- AcSiteViewModel
|
+-- AcSiteViewModel
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
|
||||||
> **LLM Maintenance:** If you modify code in this folder, update this README to reflect the changes. If you notice the README content does not match the current code, automatically update the README to match the code.
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,3 @@ Platform-specific code for AyCode.Maui.Core. Each subfolder is conditionally com
|
||||||
|
|
||||||
## Key Files
|
## Key Files
|
||||||
- **`{Platform}/PlatformClass1.cs`** -- Empty placeholder class per platform, all in the `AyCode.Maui.Core` namespace.
|
- **`{Platform}/PlatformClass1.cs`** -- Empty placeholder class per platform, all in the `AyCode.Maui.Core` namespace.
|
||||||
|
|
||||||
---
|
|
||||||
> **LLM Maintenance:** If you modify code in this folder, update this README to reflect the changes. If you notice the README content does not match the current code, automatically update the README to match the code.
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,12 @@
|
||||||
# AyCode.Maui.Core
|
# AyCode.Maui.Core
|
||||||
|
|
||||||
|
@project {
|
||||||
|
type = "framework"
|
||||||
|
own-dep-projects = [
|
||||||
|
"AyCode.Core, AyCode.Entities, AyCode.Interfaces, AyCode.Models, AyCode.Services, AyCode.Utils (in AyCode.Core repo)"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
.NET MAUI class library targeting Android (API 33+), iOS (15.0+), and Windows (10.0.19041+). Provides cross-platform shared code with per-platform specialization via the `Platforms/` folder.
|
.NET MAUI class library targeting Android (API 33+), iOS (15.0+), and Windows (10.0.19041+). Provides cross-platform shared code with per-platform specialization via the `Platforms/` folder.
|
||||||
|
|
||||||
## Key Files
|
## Key Files
|
||||||
|
|
@ -16,6 +23,3 @@
|
||||||
| Microsoft.AspNetCore.SignalR.Common | 9.0.11 | NuGet |
|
| Microsoft.AspNetCore.SignalR.Common | 9.0.11 | NuGet |
|
||||||
| MessagePack | 3.1.4 | NuGet |
|
| MessagePack | 3.1.4 | NuGet |
|
||||||
| AyCode.Core, .Entities, .Interfaces, .Models, .Services, .Utils | -- | DLL references |
|
| AyCode.Core, .Entities, .Interfaces, .Models, .Services, .Utils | -- | DLL references |
|
||||||
|
|
||||||
---
|
|
||||||
> **LLM Maintenance:** If you modify code in this folder, update this README to reflect the changes. If you notice the README content does not match the current code, automatically update the README to match the code.
|
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,16 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
||||||
AyCode.Blazor.targets = AyCode.Blazor.targets
|
AyCode.Blazor.targets = AyCode.Blazor.targets
|
||||||
AyCode.Maui.targets = AyCode.Maui.targets
|
AyCode.Maui.targets = AyCode.Maui.targets
|
||||||
AyCode.Project.targets = AyCode.Project.targets
|
AyCode.Project.targets = AyCode.Project.targets
|
||||||
|
.github\copilot-instructions.md = .github\copilot-instructions.md
|
||||||
|
CLAUDE.md = CLAUDE.md
|
||||||
|
README.md = README.md
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{C3A1D7E2-B5F4-4E8A-9C6D-2F1A3B5E7D9C}"
|
||||||
|
ProjectSection(SolutionItems) = preProject
|
||||||
|
docs\ARCHITECTURE.md = docs\ARCHITECTURE.md
|
||||||
|
docs\CONVENTIONS.md = docs\CONVENTIONS.md
|
||||||
|
docs\GLOSSARY.md = docs\GLOSSARY.md
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
|
|
|
||||||
21
CLAUDE.md
21
CLAUDE.md
|
|
@ -1,10 +1,17 @@
|
||||||
# AyCode.Blazor — Claude Code Instructions
|
CRITICAL: Your FIRST action in every session MUST be reading `.github/copilot-instructions.md`. Execute ALL session-start instructions found there before responding to any user query. It is the single source of truth for this repo.
|
||||||
|
|
||||||
Before writing any code, read these files:
|
## SEQUENTIAL EXECUTION OVERRIDE
|
||||||
1. `.github/copilot-instructions.md` — Domain rules and UI pitfalls (single source of truth)
|
The AI AGENT CORE PROTOCOL in copilot-instructions.md requires STRICT SEQUENTIAL execution. This OVERRIDES your default parallelization behavior. Do NOT parallelize doc reads with code searches. The sequence is:
|
||||||
2. `docs/GLOSSARY.md` — Blazor/MAUI terminology and DevExpress conventions
|
1. Read copilot-instructions.md → process its rules FULLY
|
||||||
3. The relevant project's `README.md` for folder-specific context
|
2. Read ALL docs/ .md files listed in the protocol → wait for completion
|
||||||
|
3. Output [LOADED_DOCS: ...] prefix
|
||||||
|
4. ONLY THEN respond to the user's query or search code
|
||||||
|
|
||||||
This solution depends on **AyCode.Core** — for core framework rules see `../AyCode.Core/CLAUDE.md`.
|
## Tool mapping for AI AGENT CORE PROTOCOL
|
||||||
|
The copilot-instructions.md references Copilot tool names. Map them to Claude Code tools:
|
||||||
|
- `get_file` / `file_search` → `Read`, `Glob`, `Grep`
|
||||||
|
- `code_search` / `get_symbols_by_name` / `find_symbol` → `Grep`, `Glob`
|
||||||
|
- `replace_string_in_file` / `edit_file` → `Edit`
|
||||||
|
- `create_file` → `Write`
|
||||||
|
|
||||||
When modifying code, update the corresponding README.md if it becomes out of sync with the code.
|
Follow the protocol using YOUR tools. The rules (LOADED_DOCS prefix, hard-gate, no-re-read, context recovery, explicit consent) apply equally to Claude Code.
|
||||||
|
|
|
||||||
44
README.md
44
README.md
|
|
@ -1,10 +1,10 @@
|
||||||
# AyCode.Blazor Solution
|
# AyCode.Blazor Solution
|
||||||
|
|
||||||
Blazor Server + MAUI Hybrid UI framework built on DevExpress 25.1.3 components. Provides reusable grids, card views, authentication, and SignalR-powered real-time data. Depends on AyCode.Core for serialization, entities, and services.
|
Blazor Server + MAUI Hybrid UI framework built on DevExpress 25.1.3 components. Targets **net10.0** (AyCode.Project.targets). Provides reusable grids, card views, authentication, and SignalR-powered real-time data. Depends on AyCode.Core (net9.0) for serialization, entities, and services — referenced via DLL.
|
||||||
|
|
||||||
## LLM Context
|
## LLM Context
|
||||||
|
|
||||||
Domain rules and UI pitfalls live in a single file: [`.github/copilot-instructions.md`](.github/copilot-instructions.md)
|
Domain rules and UI pitfalls live in a single file: `.github/copilot-instructions.md`
|
||||||
|
|
||||||
| Tool | Auto-loaded | Action needed |
|
| Tool | Auto-loaded | Action needed |
|
||||||
|------|------------|---------------|
|
|------|------------|---------------|
|
||||||
|
|
@ -12,26 +12,34 @@ Domain rules and UI pitfalls live in a single file: [`.github/copilot-instructio
|
||||||
| Claude Code | ✅ `CLAUDE.md` → references above | None |
|
| Claude Code | ✅ `CLAUDE.md` → references above | None |
|
||||||
| Cursor / Windsurf | ✅ `README.md` | Read `copilot-instructions.md` via @file |
|
| Cursor / Windsurf | ✅ `README.md` | Read `copilot-instructions.md` via @file |
|
||||||
|
|
||||||
Detailed docs: [`docs/`](docs/) — GLOSSARY.md, ARCHITECTURE.md
|
Solution-level docs in `docs/`:
|
||||||
|
|
||||||
Core framework rules: [`../AyCode.Core/.github/copilot-instructions.md`](../AyCode.Core/.github/copilot-instructions.md)
|
| Document | Topic |
|
||||||
|
|---|---|
|
||||||
|
| `GLOSSARY.md` | Blazor/MAUI terminology |
|
||||||
|
| `ARCHITECTURE.md` | Solution layers, dependency rules |
|
||||||
|
| `CONVENTIONS.md` | Coding conventions |
|
||||||
|
|
||||||
|
Project-level docs:
|
||||||
|
|
||||||
|
| Project | Documents |
|
||||||
|
|---|---|
|
||||||
|
| `AyCode.Blazor.Components/docs/` | `MGGRID/` — MgGrid system (grid base, toolbar, InfoPanel, layout, CRUD) |
|
||||||
|
|
||||||
|
Core framework rules: `../AyCode.Core/.github/copilot-instructions.md`
|
||||||
|
|
||||||
## Solution Structure
|
## Solution Structure
|
||||||
|
|
||||||
| Project | Purpose | README |
|
| Project | Purpose |
|
||||||
|---|---|---|
|
|---|---|
|
||||||
| [`AyCode.Blazor.Components`](AyCode.Blazor.Components/README.md) | DevExpress UI components, grids, SignalR data sources, expression helpers | [README](AyCode.Blazor.Components/README.md) |
|
| `AyCode.Blazor.Components` | DevExpress UI components, grids, SignalR data sources, expression helpers |
|
||||||
| [`AyCode.Blazor.Models`](AyCode.Blazor.Models/README.md) | Shared view models for Blazor components | [README](AyCode.Blazor.Models/README.md) |
|
| `AyCode.Blazor.Models` | Shared view models for Blazor components |
|
||||||
| [`AyCode.Blazor.Models.Server`](AyCode.Blazor.Models.Server/README.md) | Server-side model scaffolding | [README](AyCode.Blazor.Models.Server/README.md) |
|
| `AyCode.Blazor.Models.Server` | Server-side model scaffolding |
|
||||||
| [`AyCode.Blazor.Controllers`](AyCode.Blazor.Controllers/README.md) | Controller scaffolding (minimal) | [README](AyCode.Blazor.Controllers/README.md) |
|
| `AyCode.Blazor.Controllers` | Controller scaffolding (minimal) |
|
||||||
| [`AyCode.Maui.Core`](AyCode.Maui.Core/README.md) | MAUI cross-platform: Android, iOS, Windows | [README](AyCode.Maui.Core/README.md) |
|
| `AyCode.Maui.Core` | MAUI cross-platform: Android, iOS, Windows |
|
||||||
|
|
||||||
### Test Projects
|
### Test Projects
|
||||||
|
|
||||||
| Project | Purpose | README |
|
| Project | Purpose |
|
||||||
|---|---|---|
|
|---|---|
|
||||||
| [`AyCode.Blazor.Components.Tests`](AyCode.Blazor.Components.Tests/README.md) | Grid and component tests | [README](AyCode.Blazor.Components.Tests/README.md) |
|
| `AyCode.Blazor.Components.Tests` | Grid and component tests |
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
> **LLM Maintenance:** If you modify this solution's structure, update this README to reflect the changes. If you notice the README content does not match the current code, automatically update the README to match the code.
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,20 @@
|
||||||
# Architecture
|
# Architecture
|
||||||
|
|
||||||
|
## Framework vs. Consumer Boundary
|
||||||
|
|
||||||
|
This is **Layer 1 — UI framework**, building on Layer 0 (AyCode.Core) and consumed by Layer 2/3 projects. Full doctrine: `../AyCode.Core/docs/ARCHITECTURE.md#framework-vs-consumer-boundary`.
|
||||||
|
|
||||||
|
### Blazor/MAUI-specific notes
|
||||||
|
|
||||||
|
- Components use **generic type parameters** for consumer types (e.g. the MgGrid generic hierarchy)
|
||||||
|
- DevExpress wrappers stay generic — no consumer-entity specialization in framework components
|
||||||
|
- MAUI platform folders (`AyCode.Maui.Core/Platforms/`) provide platform abstractions only; consumer-app manifest / splash screens / app-specific assets belong in the consumer app
|
||||||
|
- UI patterns maximize **generic base + consumer derives**
|
||||||
|
|
||||||
## Dependency Graph
|
## Dependency Graph
|
||||||
|
|
||||||
```
|
```
|
||||||
AyCode.Core Solution (DLL references)
|
AyCode.Core Solution ../AyCode.Core/AyCode.Core.sln (DLL references)
|
||||||
↑
|
↑
|
||||||
AyCode.Blazor.Models ← AyCode.Blazor.Models.Server
|
AyCode.Blazor.Models ← AyCode.Blazor.Models.Server
|
||||||
↑
|
↑
|
||||||
|
|
@ -13,6 +24,7 @@ AyCode.Maui.Core (MAUI Hybrid host)
|
||||||
```
|
```
|
||||||
|
|
||||||
**Rule:** UI projects reference AyCode.Core via DLL (not ProjectReference). This separates build graphs.
|
**Rule:** UI projects reference AyCode.Core via DLL (not ProjectReference). This separates build graphs.
|
||||||
|
**Context:** When a core type is not found in this solution, browse `../AyCode.Core/` for its definition.
|
||||||
|
|
||||||
## How It Works
|
## How It Works
|
||||||
|
|
||||||
|
|
@ -35,13 +47,29 @@ User → DxGrid → AcSignalRDataSource → SignalR (AcBinary) → Server Hub
|
||||||
User ← DxGrid ← AcSignalRDataSource ← SignalR (AcBinary) ← Server Hub
|
User ← DxGrid ← AcSignalRDataSource ← SignalR (AcBinary) ← Server Hub
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## MgGrid Component System
|
||||||
|
|
||||||
|
The primary UI pattern for data screens. Overview and index: `AyCode.Blazor.Components/docs/MGGRID/README.md`
|
||||||
|
|
||||||
|
```
|
||||||
|
DxGrid (DevExpress)
|
||||||
|
└── MgGridBase<TSignalRDataSource, TDataItem, TId, TLoggerClient>
|
||||||
|
└── [Project adapter, e.g. FruitBankGridBase<TDataItem>]
|
||||||
|
└── [Concrete grid, e.g. GridShippingBase]
|
||||||
|
```
|
||||||
|
|
||||||
|
| Component | Role |
|
||||||
|
|---|---|
|
||||||
|
| **MgGridBase** | Abstract base — SignalR CRUD, layout persistence, master-detail, edit state |
|
||||||
|
| **MgGridWithInfoPanel** | `DxSplitter` wrapper — grid + collapsible InfoPanel + fullscreen |
|
||||||
|
| **MgGridToolbarTemplate** | Full toolbar: CRUD, navigation, layout, export, fullscreen |
|
||||||
|
| **MgGridDataColumn** | `DxGridDataColumn` with InfoPanel parameters and URL template support |
|
||||||
|
| **MgGridInfoPanel** | Default InfoPanel — column-value display with edit mode |
|
||||||
|
| **MgGridSignalRDataSource** | `GridCustomDataSource` with local cache and background refresh |
|
||||||
|
|
||||||
## Key Design Decisions
|
## Key Design Decisions
|
||||||
|
|
||||||
- **DevExpress 25.1.3** exclusively — no mixing with other component libraries
|
- **DevExpress 25.1.3** exclusively — no mixing with other component libraries
|
||||||
- **SignalR over REST** for grid data — enables real-time updates and binary protocol
|
- **SignalR over REST** for grid data — enables real-time updates and binary protocol
|
||||||
- **Expression serialization** — grid filters evaluated server-side, not client-side
|
- **Expression serialization** — grid filters evaluated server-side, not client-side
|
||||||
- **Shared components** — Blazor Server and MAUI Hybrid use the exact same component library
|
- **Shared components** — Blazor Server and MAUI Hybrid use the exact same component library
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
> **LLM Maintenance:** If you modify the architecture, update this document.
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,15 @@
|
||||||
# Conventions
|
# Conventions
|
||||||
|
|
||||||
For core framework conventions (Ac prefix, Session/Transaction pattern, etc.) see [`../../AyCode.Core/docs/CONVENTIONS.md`](../../AyCode.Core/docs/CONVENTIONS.md).
|
For core framework conventions (Ac prefix, Session/Transaction pattern, etc.) see `AyCode.Core/docs/CONVENTIONS.md`.
|
||||||
|
|
||||||
|
## Framework-First Placement
|
||||||
|
|
||||||
|
Follow the doctrine in `../AyCode.Core/docs/CONVENTIONS.md#framework-first-placement`. Same verdicts and hard rules apply.
|
||||||
|
|
||||||
|
**Blazor/MAUI-specific additions:**
|
||||||
|
- UI types follow the generic-base pattern — consumer types are type parameters, not hardcoded concrete types
|
||||||
|
- DevExpress-wrapper components stay generic across consumers
|
||||||
|
- MAUI platform code = platform abstractions only, not consumer-app specifics
|
||||||
|
|
||||||
## Naming
|
## Naming
|
||||||
|
|
||||||
|
|
@ -9,6 +18,10 @@ For core framework conventions (Ac prefix, Session/Transaction pattern, etc.) se
|
||||||
- **Services:** `Ac{Domain}ServiceBase` for abstract bases. Platform-specific implementations in consuming projects.
|
- **Services:** `Ac{Domain}ServiceBase` for abstract bases. Platform-specific implementations in consuming projects.
|
||||||
- **ViewModels:** In `AyCode.Blazor.Models/ViewModels/` — suffixed with `ViewModel` or kept as plain model classes.
|
- **ViewModels:** In `AyCode.Blazor.Models/ViewModels/` — suffixed with `ViewModel` or kept as plain model classes.
|
||||||
|
|
||||||
|
## XML Documentation
|
||||||
|
|
||||||
|
`<summary>` — brief, developer-facing, readable in VS IntelliSense tooltip. NO implementation details, NO wire-format / byte-level / perf specifics — those live in `docs/TOPIC/*.md`. Add `<example>` only when usage is non-obvious; otherwise omit.
|
||||||
|
|
||||||
## Component Patterns
|
## Component Patterns
|
||||||
|
|
||||||
- **DevExpress 25.1.3 exclusively** — never mix with other Blazor component libraries.
|
- **DevExpress 25.1.3 exclusively** — never mix with other Blazor component libraries.
|
||||||
|
|
@ -33,13 +46,3 @@ For core framework conventions (Ac prefix, Session/Transaction pattern, etc.) se
|
||||||
|
|
||||||
- All AyCode.Core project references are via **DLL** (not ProjectReference) — this is intentional to separate build graphs.
|
- All AyCode.Core project references are via **DLL** (not ProjectReference) — this is intentional to separate build graphs.
|
||||||
- DevExpress references are NuGet packages pinned to **25.1.3**.
|
- DevExpress references are NuGet packages pinned to **25.1.3**.
|
||||||
|
|
||||||
## Critical Rules
|
|
||||||
|
|
||||||
- Do not suggest removal/rollback as a solution — find a fix for the problem.
|
|
||||||
- SignalR uses **AcBinaryHubProtocol** — never switch to default JSON protocol.
|
|
||||||
- Grid data always flows through SignalR, never direct REST calls.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
> **LLM Maintenance:** If you establish new UI conventions or patterns, document them here.
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# Glossary
|
# Glossary
|
||||||
|
|
||||||
Blazor/MAUI UI terminology. For core framework terms see [`../../AyCode.Core/docs/GLOSSARY.md`](../../AyCode.Core/docs/GLOSSARY.md).
|
Blazor/MAUI UI terminology. For core framework terms see `AyCode.Core/docs/GLOSSARY.md`.
|
||||||
|
|
||||||
## UI Components
|
## UI Components
|
||||||
|
|
||||||
|
|
@ -8,9 +8,28 @@ Blazor/MAUI UI terminology. For core framework terms see [`../../AyCode.Core/doc
|
||||||
|---|---|
|
|---|---|
|
||||||
| **DxGrid** | DevExpress Blazor data grid. Used with `AcSignalRDataSource` for real-time SignalR data. |
|
| **DxGrid** | DevExpress Blazor data grid. Used with `AcSignalRDataSource` for real-time SignalR data. |
|
||||||
| **CardView** | Card-style layout wrapping DxGrid. Mobile-friendly alternative to table grids. |
|
| **CardView** | Card-style layout wrapping DxGrid. Mobile-friendly alternative to table grids. |
|
||||||
| **AcSignalRDataSource** | Grid data source backed by SignalR. Handles load, CRUD, filtering, and change tracking. |
|
| **AcSignalRDataSource** | Grid data source backed by SignalR. Handles load, CRUD, filtering, and change tracking. See `AyCode.Services.Server/docs/SIGNALR_DATASOURCE/README.md` in AyCode.Core repo. |
|
||||||
| **AcExpressionNode** | Serializable LINQ expression tree. Grid filters are serialized as expression nodes and sent to server. |
|
| **AcExpressionNode** | Serializable LINQ expression tree. Grid filters are serialized as expression nodes and sent to server. |
|
||||||
|
|
||||||
|
## MgGrid System
|
||||||
|
|
||||||
|
For full technical reference see `AyCode.Blazor.Components/docs/MGGRID/README.md`.
|
||||||
|
|
||||||
|
| Term | Definition |
|
||||||
|
|---|---|
|
||||||
|
| **MgGridBase** | Abstract generic grid component extending `DxGrid` with SignalR CRUD, layout persistence, master-detail, InfoPanel, fullscreen. |
|
||||||
|
| **MgGridWithInfoPanel** | `DxSplitter` wrapper: grid (left pane) + InfoPanel (right pane), fullscreen overlay, splitter size persistence. |
|
||||||
|
| **MgGridToolbarBase** | `DxToolbar` base with `Grid` (`IMgGridBase`) reference and `RefreshClick` callback. |
|
||||||
|
| **MgGridToolbarTemplate** | Full toolbar: New/Edit/Delete/Save/Cancel, row navigation, layout menu, export, 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. |
|
||||||
|
| **IMgGridBase** | Public interface: `IsSyncing`, `GridEditState`, `ParentGrid`, `StepPrevRow/NextRow`, layout persistence methods. |
|
||||||
|
| **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.Server/docs/SIGNALR_DATASOURCE/README.md` in AyCode.Core repo. |
|
||||||
|
| **IsMasterGrid** | `true` when `ParentDataItem == null` — top-level grid (not detail). |
|
||||||
|
| **AutoSaveLayoutName** | Base name for localStorage layout keys. Default: `"Grid{TDataItem.Name}"`. |
|
||||||
|
|
||||||
## Architecture
|
## Architecture
|
||||||
|
|
||||||
| Term | Definition |
|
| Term | Definition |
|
||||||
|
|
@ -32,7 +51,3 @@ Blazor/MAUI UI terminology. For core framework terms see [`../../AyCode.Core/doc
|
||||||
|---|---|
|
|---|---|
|
||||||
| **Platforms/** | Per-platform code folders: Android, iOS, Windows. MAUI SDK auto-includes based on target. |
|
| **Platforms/** | Per-platform code folders: Android, iOS, Windows. MAUI SDK auto-includes based on target. |
|
||||||
| **API 33+** | Minimum Android API level (Android 13). |
|
| **API 33+** | Minimum Android API level (Android 13). |
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
> **LLM Maintenance:** If you modify code that changes terminology, update this glossary.
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
# AyCode.Blazor documentation
|
||||||
|
|
||||||
|
Top-level documentation for the `AyCode.Blazor` repo (Blazor/MAUI UI framework — Layer 1).
|
||||||
|
|
||||||
|
## Reference docs (flat)
|
||||||
|
|
||||||
|
- [`ARCHITECTURE.md`](ARCHITECTURE.md) — Repo architecture overview
|
||||||
|
- [`CONVENTIONS.md`](CONVENTIONS.md) — Coding conventions
|
||||||
|
- [`GLOSSARY.md`](GLOSSARY.md) — Domain glossary
|
||||||
|
|
||||||
|
## Topic folders
|
||||||
|
|
||||||
|
Topic-specific documentation lives at the sub-project level:
|
||||||
|
|
||||||
|
- **MGGRID** (data grid component family): `../AyCode.Blazor.Components/docs/MGGRID/README.md`
|
||||||
|
|
||||||
|
## Navigation
|
||||||
|
|
||||||
|
Per the AI Agent Core Protocol (folder navigation rule), start from this README when browsing `docs/`. Single-file reference docs remain flat at this level; multi-file topics live in named subfolders.
|
||||||
|
|
||||||
|
## See also
|
||||||
|
|
||||||
|
- **Base framework docs**: `../../AyCode.Core/docs/README.md` (if present) and per-project `docs/` folders under AyCode.Core.
|
||||||
Loading…
Reference in New Issue