Skip to content

Commit 259607c

Browse files
WelchenRyan Watson
andauthored
MudMapper: Standalone mapper component (#641)
* MudMapper component with the core functionality from MudCsvWrapper. * Refactor MudMapper header logic, cleanup imports Removes unused MudExtensions.Utilities imports from MudCsvMapper.razor and MudMapper.razor. Refactors header confirmation logic in MudMapper.razor for clarity and null safety. Adds XML documentation to IsSourcePoolItem in MudMapper.razor.cs. * Refactor: use constant for "Source" string values Replaced hardcoded "Source" strings with MudMapper.SourcePoolZoneIdentifier constant in CsvMapperTests.cs and MudMapperTests.cs to improve maintainability and reduce string mismatch errors. * Improve test coverage for MudCsvMapper and MudMapper Added unit tests to cover private/internal logic in MudCsvMapper and MudMapper. Verified behaviors include mapping state reset, header updates, item selection, source pool identification, add section opening, form submission, and IncludeUnmappedData updates. Introduced helper methods for invoking private methods and setting private members via reflection to enable testing of non-public members. * Make header check case insensitive --------- Co-authored-by: Ryan Watson <rwatson@milner.com>
1 parent 7b5faf7 commit 259607c

15 files changed

Lines changed: 1918 additions & 429 deletions

File tree

‎docs/CodeBeam.MudBlazor.Extensions.Docs.Wasm/wwwroot/CodeBeam.MudBlazor.Extensions.xml‎

Lines changed: 181 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎docs/CodeBeam.MudBlazor.Extensions.Docs/CodeBeam.MudBlazor.Extensions.Docs.csproj‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,5 @@
3737
<EmbeddedResource Include="Pages/Components/**" />
3838
</ItemGroup>
3939

40+
4041
</Project>
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
@namespace MudExtensions.Docs.Examples
2+
@inject ISnackbar Snackbar
3+
@using MudExtensions.Utilities
4+
5+
<MudGrid>
6+
<MudItem xs="12">
7+
<MudText Typo="Typo.body2" Class="mb-2">
8+
Drag the source columns onto the matching target fields. <b>Email</b> is required.
9+
</MudText>
10+
</MudItem>
11+
<MudItem xs="12">
12+
<MudMapper @ref="_mapper"
13+
SourceItems="_sourceItems"
14+
TargetHeaders="_targetHeaders"
15+
ConfirmLabel="Confirm Mapping"
16+
OnConfirmed="OnMappingConfirmed"
17+
OnReset="OnReset" />
18+
</MudItem>
19+
@if (_mappingSummary.Count > 0)
20+
{
21+
<MudItem xs="12">
22+
<MudAlert Severity="Severity.Success" Elevation="0">
23+
<MudText Typo="Typo.subtitle2" Class="mb-1">Mapping Result</MudText>
24+
@foreach (var (target, source) in _mappingSummary)
25+
{
26+
<MudText Typo="Typo.body2">@source → @target</MudText>
27+
}
28+
</MudAlert>
29+
</MudItem>
30+
}
31+
</MudGrid>
32+
33+
@code {
34+
MudMapper? _mapper;
35+
List<(string Target, string Source)> _mappingSummary = new();
36+
37+
List<MudMapperItem> _sourceItems =
38+
[
39+
new("email_addr"),
40+
new("first_name"),
41+
new("last_name"),
42+
new("phone_num"),
43+
new("zip_code"),
44+
];
45+
46+
List<MudExpectedHeader> _targetHeaders =
47+
[
48+
new("Email", required: true),
49+
new("First Name"),
50+
new("Last Name"),
51+
new("Phone"),
52+
];
53+
54+
private void OnMappingConfirmed()
55+
{
56+
_mappingSummary = _mapper?.SourceItems
57+
.Where(i => i.MappedZone != "Source")
58+
.Select(i => (i.MappedZone, i.Name))
59+
.ToList() ?? [];
60+
61+
Snackbar.Add("Mapping confirmed!", Severity.Success);
62+
}
63+
64+
private void OnReset()
65+
{
66+
_mappingSummary.Clear();
67+
// Re-initialise source items so chips return to the source pool
68+
_sourceItems =
69+
[
70+
new("email_addr"),
71+
new("first_name"),
72+
new("last_name"),
73+
new("phone_num"),
74+
new("zip_code"),
75+
];
76+
_targetHeaders.ForEach(h => h.MatchedFieldCount = 0);
77+
}
78+
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
@namespace MudExtensions.Docs.Examples
2+
@inject ISnackbar Snackbar
3+
@using MudExtensions.Utilities
4+
5+
<MudGrid>
6+
<MudItem xs="12">
7+
<MudText Typo="Typo.body2" Class="mb-2">
8+
Use <b>Create Header</b> to add new target headers on the fly.
9+
Toggle <b>Include unmapped data</b> to keep source items that have no target.
10+
</MudText>
11+
</MudItem>
12+
<MudItem xs="12">
13+
<MudMapper @ref="_mapper"
14+
SourceItems="_sourceItems"
15+
TargetHeaders="_targetHeaders"
16+
AllowCreateTargetHeaders="true"
17+
ShowIncludeUnmappedData="true"
18+
ConfirmLabel="Apply"
19+
OnConfirmed="OnConfirmed"
20+
OnReset="OnReset" />
21+
</MudItem>
22+
@if (_confirmed)
23+
{
24+
<MudItem xs="12">
25+
<MudAlert Severity="Severity.Info" Elevation="0">
26+
<MudText Typo="Typo.subtitle2" Class="mb-1">
27+
Result — Include unmapped: @(_mapper?.IncludeUnmappedData)
28+
</MudText>
29+
@foreach (var item in _mapper?.SourceItems ?? [])
30+
{
31+
<MudText Typo="Typo.body2">
32+
@item.Name → @(item.MappedZone == "Source" ? "(unmapped)" : item.MappedZone)
33+
</MudText>
34+
}
35+
</MudAlert>
36+
</MudItem>
37+
}
38+
</MudGrid>
39+
40+
@code {
41+
MudMapper? _mapper;
42+
bool _confirmed;
43+
44+
List<MudMapperItem> _sourceItems =
45+
[
46+
new("product_id"),
47+
new("product_name"),
48+
new("unit_price"),
49+
new("qty_in_stock"),
50+
new("sku_code"),
51+
new("category"),
52+
];
53+
54+
List<MudExpectedHeader> _targetHeaders =
55+
[
56+
new("Id", required: true),
57+
new("Name", required: true),
58+
new("Price"),
59+
new("Stock"),
60+
];
61+
62+
private void OnConfirmed()
63+
{
64+
_confirmed = true;
65+
Snackbar.Add("Mapping applied!", Severity.Info);
66+
}
67+
68+
private void OnReset()
69+
{
70+
_confirmed = false;
71+
_sourceItems =
72+
[
73+
new("product_id"),
74+
new("product_name"),
75+
new("unit_price"),
76+
new("qty_in_stock"),
77+
new("sku_code"),
78+
new("category"),
79+
];
80+
_targetHeaders.ForEach(h => h.MatchedFieldCount = 0);
81+
}
82+
}

0 commit comments

Comments
 (0)