feat(centralui): single-select Channel filter on the Audit Log page
Channel narrows the Kind options to the chosen channel, so filtering by more than one channel at a time is incoherent. Replace the Channel multi-select dropdown with a native single-select (matching the Time range control); Kind, Status and Site stay multi-select. The query filter contract is unchanged — Channels just carries 0 or 1 value.
This commit is contained in:
@@ -6,20 +6,23 @@
|
||||
|
||||
<div class="card mb-3" data-test="audit-filter-bar">
|
||||
<div class="card-body py-2">
|
||||
@* All filters sit in one wrapped row. The four multi-value dimensions
|
||||
(Channel / Kind / Status / Site) use compact MultiSelectDropdown
|
||||
controls so the bar stays a row or two tall instead of four stacked
|
||||
blocks of chip buttons. *@
|
||||
@* All filters sit in one wrapped row. Kind / Status / Site use compact
|
||||
MultiSelectDropdown controls; Channel is a single-select because the
|
||||
Kind options narrow to the chosen channel — so the bar stays a row or
|
||||
two tall instead of four stacked blocks of chip buttons. *@
|
||||
<div class="row g-2 align-items-end">
|
||||
@* Single-select: one channel at a time, so the Kind options below
|
||||
narrow cleanly to that channel. "All channels" clears it. *@
|
||||
<div class="col-auto" data-test="filter-channel">
|
||||
<label class="form-label small mb-1">Channel</label>
|
||||
<div>
|
||||
<MultiSelectDropdown TValue="AuditChannel"
|
||||
Items="_channels"
|
||||
Selected="_model.Channels"
|
||||
SelectionChanged="OnChannelsChanged"
|
||||
DataTest="filter-channel-ms" />
|
||||
</div>
|
||||
<label class="form-label small mb-1" for="audit-channel">Channel</label>
|
||||
<select id="audit-channel" data-test="filter-channel-select"
|
||||
class="form-select form-select-sm" @bind="SelectedChannel">
|
||||
<option value="">All channels</option>
|
||||
@foreach (var channel in _channels)
|
||||
{
|
||||
<option value="@channel">@channel</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
@* Kind options are narrowed by the Channel selection (VisibleKinds). *@
|
||||
|
||||
@@ -8,13 +8,14 @@ namespace ScadaLink.CentralUI.Components.Audit;
|
||||
/// <summary>
|
||||
/// Filter bar for the central Audit Log page (#23 M7-T2). Owns the
|
||||
/// <see cref="AuditQueryModel"/> binding state and renders the filter controls
|
||||
/// — Channel / Kind / Status / Site as compact
|
||||
/// — Channel as a single-select (one channel at a time, so the Kind options
|
||||
/// narrow to it cleanly); Kind / Status / Site as compact
|
||||
/// <see cref="ScadaLink.CentralUI.Components.Shared.MultiSelectDropdown{TValue}"/>
|
||||
/// controls, plus the time range, free-text searches and the Errors-only
|
||||
/// controls; plus the time range, free-text searches and the Errors-only
|
||||
/// toggle — and publishes an <see cref="AuditLogQueryFilter"/> via
|
||||
/// <see cref="OnFilterChanged"/> when the user clicks Apply. The four
|
||||
/// multi-value dimensions map straight through to the filter's list fields;
|
||||
/// see <see cref="AuditQueryModel"/> for the Errors-only and time-range rules.
|
||||
/// <see cref="OnFilterChanged"/> when the user clicks Apply. The selected
|
||||
/// dimensions map through to the filter's list fields; see
|
||||
/// <see cref="AuditQueryModel"/> for the Errors-only and time-range rules.
|
||||
/// </summary>
|
||||
public partial class AuditFilterBar
|
||||
{
|
||||
@@ -82,8 +83,29 @@ public partial class AuditFilterBar
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Runs after a Channel selection changes. Drops any Kind selections that fell
|
||||
/// outside the new visible set — without this, removing a channel could leave
|
||||
/// Single-select Channel binding for the filter bar. The Audit Log filters one
|
||||
/// channel at a time so the Kind options narrow cleanly to it; the model still
|
||||
/// stores the selection as a set (0 or 1 entry) so <see cref="AuditQueryModel.ToFilter"/>
|
||||
/// and <see cref="AuditQueryModel.VisibleKinds"/> are unchanged. <c>null</c> = all channels.
|
||||
/// </summary>
|
||||
private AuditChannel? SelectedChannel
|
||||
{
|
||||
get => _model.Channels.Count > 0 ? _model.Channels.First() : null;
|
||||
set
|
||||
{
|
||||
_model.Channels.Clear();
|
||||
if (value is { } channel)
|
||||
{
|
||||
_model.Channels.Add(channel);
|
||||
}
|
||||
|
||||
OnChannelsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Runs after the Channel selection changes. Drops any Kind selections that fell
|
||||
/// outside the new visible set — without this, changing the channel could leave
|
||||
/// stale Kind selections that no longer match any visible option.
|
||||
/// </summary>
|
||||
private void OnChannelsChanged()
|
||||
|
||||
Reference in New Issue
Block a user