@if (Detail.Groups.Count > 0) { @foreach (var group in visibleGroups) {
@group.Label
} } @foreach (var displayColumn in displayColumns) {
@displayColumn.ColumnLabel
} @foreach (var rollBand in Detail.RollBands) {
@rollBand.Label
@foreach (var displayColumn in displayColumns) { if (TryGetCell(rollBand.Label, displayColumn.GroupKey, displayColumn.ColumnKey, out var resolvedCell) && resolvedCell is not null) { var cell = resolvedCell; var isSelectedCell = IsSelectedCell(cell); @if (MatchesModeFilter(cell)) {
@if (string.Equals(CurrentMode, TablesReferenceMode.Reference, StringComparison.Ordinal)) { } else if (cell.IsCurated) { Curated } else { Needs Curation } @if (isSelectedCell) { Selected }
} else {
Filtered
} } else {
} } }
@code { private readonly Dictionary<(string RollBand, string? GroupKey, string ColumnKey), CriticalTableCellDetail> cellIndex = new(); private readonly List<(string? GroupKey, string ColumnKey, string ColumnLabel)> displayColumns = new(); private readonly List visibleGroups = new(); private readonly List visibleColumns = new(); private string gridTemplateStyle = string.Empty; [Parameter, EditorRequired] public CriticalTableDetail Detail { get; set; } = default!; [Parameter] public string CurrentMode { get; set; } = TablesReferenceMode.Reference; [Parameter] public string SelectedGroupKey { get; set; } = string.Empty; [Parameter] public string SelectedColumnKey { get; set; } = string.Empty; [Parameter] public string RollJumpValue { get; set; } = string.Empty; [Parameter] public string DensityMode { get; set; } = TablesDensityMode.Comfortable; [Parameter] public TablesCellSelection? SelectedCell { get; set; } [Parameter] public EventCallback OnSelectCell { get; set; } protected override void OnParametersSet() { cellIndex.Clear(); displayColumns.Clear(); visibleGroups.Clear(); visibleColumns.Clear(); foreach (var cell in Detail.Cells) { cellIndex[(cell.RollBand, cell.GroupKey, cell.ColumnKey)] = cell; } var columnsToDisplay = ResolveVisibleColumns(); if (Detail.Groups.Count == 0) { foreach (var column in columnsToDisplay) { visibleColumns.Add(column); displayColumns.Add((null, column.Key, column.Label)); } } else { var groupsToDisplay = ResolveVisibleGroups(); foreach (var group in groupsToDisplay) { visibleGroups.Add(group); } foreach (var column in columnsToDisplay) { visibleColumns.Add(column); } foreach (var group in visibleGroups) { foreach (var column in visibleColumns) { displayColumns.Add((group.Key, column.Key, column.Label)); } } } var dataColumnCount = displayColumns.Count; gridTemplateStyle = $"grid-template-columns: max-content repeat({dataColumnCount}, minmax(0, 1fr));"; } private bool TryGetCell(string rollBand, string? groupKey, string columnKey, out CriticalTableCellDetail? cell) => cellIndex.TryGetValue((rollBand, groupKey, columnKey), out cell); private bool MatchesGroupFilter(CriticalGroupReference group) => string.IsNullOrWhiteSpace(SelectedGroupKey) || string.Equals(group.Key, SelectedGroupKey, StringComparison.OrdinalIgnoreCase); private bool MatchesColumnFilter(CriticalColumnReference column) => string.IsNullOrWhiteSpace(SelectedColumnKey) || string.Equals(column.Key, SelectedColumnKey, StringComparison.OrdinalIgnoreCase); private IReadOnlyList ResolveVisibleGroups() { var filteredGroups = Detail.Groups.Where(MatchesGroupFilter).ToList(); return filteredGroups.Count > 0 ? filteredGroups : Detail.Groups; } private IReadOnlyList ResolveVisibleColumns() { var filteredColumns = Detail.Columns.Where(MatchesColumnFilter).ToList(); return filteredColumns.Count > 0 ? filteredColumns : Detail.Columns; } private bool MatchesModeFilter(CriticalTableCellDetail cell) => CurrentMode switch { TablesReferenceMode.NeedsCuration => !cell.IsCurated, TablesReferenceMode.Curated => cell.IsCurated, _ => true }; private string? ActiveRollBand => !string.IsNullOrWhiteSpace(SelectedCell?.RollBand) ? SelectedCell.RollBand : ResolveRollJumpBandLabel(); private string? ActiveColumnKey => !string.IsNullOrWhiteSpace(SelectedCell?.ColumnKey) ? SelectedCell.ColumnKey : (!string.IsNullOrWhiteSpace(SelectedColumnKey) ? SelectedColumnKey : null); private string? ActiveGroupKey => !string.IsNullOrWhiteSpace(SelectedCell?.GroupKey) ? SelectedCell.GroupKey : (!string.IsNullOrWhiteSpace(SelectedGroupKey) ? SelectedGroupKey : null); private string BuildGridCssClass() { var classes = new List { string.Equals(DensityMode, TablesDensityMode.Dense, StringComparison.Ordinal) ? "is-dense" : "is-comfortable", Detail.Groups.Count > 0 ? "has-groups" : "has-no-groups" }; return string.Join(' ', classes); } private string BuildGroupHeaderCssClass(string groupKey) { var classes = new List { "critical-table-grid-header-cell", "critical-table-grid-group-header" }; if (string.Equals(groupKey, ActiveGroupKey, StringComparison.OrdinalIgnoreCase)) { classes.Add("is-active-group"); } return string.Join(' ', classes); } private string BuildColumnHeaderCssClass(string? groupKey, string columnKey) { var classes = new List { "critical-table-grid-header-cell", "critical-table-grid-column-header" }; if (string.Equals(columnKey, ActiveColumnKey, StringComparison.OrdinalIgnoreCase)) { classes.Add("is-active-column"); } if (!string.IsNullOrWhiteSpace(groupKey) && string.Equals(groupKey, ActiveGroupKey, StringComparison.OrdinalIgnoreCase)) { classes.Add("is-active-group"); } return string.Join(' ', classes); } private string BuildRollBandCssClass(string rollBandLabel) { var classes = new List { "critical-table-grid-header-cell", "critical-table-grid-roll-band" }; if (string.Equals(rollBandLabel, ActiveRollBand, StringComparison.OrdinalIgnoreCase)) { classes.Add("is-active-row"); } if (string.Equals(rollBandLabel, ResolveRollJumpBandLabel(), StringComparison.OrdinalIgnoreCase)) { classes.Add("is-roll-target"); } return string.Join(' ', classes); } private string GetCellCssClass(CriticalTableCellDetail cell, string? groupKey) { var classes = new List { "critical-table-cell", cell.IsCurated ? "is-curated" : "needs-curation" }; if (string.Equals(cell.RollBand, ActiveRollBand, StringComparison.OrdinalIgnoreCase)) { classes.Add("is-active-row"); } if (string.Equals(cell.ColumnKey, ActiveColumnKey, StringComparison.OrdinalIgnoreCase)) { classes.Add("is-active-column"); } if (!string.IsNullOrWhiteSpace(groupKey) && string.Equals(groupKey, ActiveGroupKey, StringComparison.OrdinalIgnoreCase)) { classes.Add("is-active-group"); } if (SelectedCell is not null && cell.ResultId == SelectedCell.ResultId) { classes.Add("is-selected-cell"); } if (string.Equals(cell.RollBand, ResolveRollJumpBandLabel(), StringComparison.OrdinalIgnoreCase)) { classes.Add("is-roll-target"); } return string.Join(' ', classes); } private string? ResolveRollJumpBandLabel() { if (!int.TryParse(RollJumpValue, out var targetRoll)) { return null; } foreach (var rollBand in Detail.RollBands) { if (targetRoll < rollBand.MinRoll) { continue; } if (rollBand.MaxRoll is null || targetRoll <= rollBand.MaxRoll.Value) { return rollBand.Label; } } return null; } private Task SelectCell(CriticalTableCellDetail cell) => OnSelectCell.InvokeAsync(new TablesCellSelection(cell.ResultId, cell.RollBand, cell.ColumnKey, cell.GroupKey)); private bool IsSelectedCell(CriticalTableCellDetail cell) => SelectedCell is not null && cell.ResultId == SelectedCell.ResultId; private Task HandleCellKeyDown(KeyboardEventArgs args, CriticalTableCellDetail cell) { if (string.Equals(args.Key, "Enter", StringComparison.Ordinal) || string.Equals(args.Key, " ", StringComparison.Ordinal) || string.Equals(args.Key, "Spacebar", StringComparison.Ordinal)) { return SelectCell(cell); } return Task.CompletedTask; } private static string BuildColumnSpanStyle(int span) => $"grid-column: span {span};"; }