feat(ui): tri-state MES reportable override on Instance Configure (reportable-only override is a delta)
Claude-Session: https://claude.ai/code/session_01Y5ef34iUUMjmwnMpL9xgmB
This commit is contained in:
+50
-3
@@ -459,6 +459,13 @@
|
||||
<td class="small text-muted text-truncate font-monospace" style="max-width: 280px;"
|
||||
title="@alarm.TriggerConfiguration">
|
||||
@(alarm.TriggerConfiguration ?? "—")
|
||||
@if (alarm.IsMesReportable)
|
||||
{
|
||||
@* The inherited MES-reportable flag; an instance
|
||||
override of it shows in the Override cell's summary. *@
|
||||
<span class="badge bg-success ms-1"
|
||||
data-test="alarm-inherited-mes" title="Template alarm is MES reportable">MES</span>
|
||||
}
|
||||
</td>
|
||||
<td class="small">
|
||||
@if (HasOverride(alarm.Name))
|
||||
@@ -538,6 +545,17 @@
|
||||
placeholder="@_editingAlarm.PriorityLevel"
|
||||
@bind="_editingPriorityText" @bind:event="oninput" />
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
@* Tri-state: blank = inherit the template alarm's flag.
|
||||
"Not reportable" is a real override, not a clear — it
|
||||
pins a reportable template alarm off for this instance. *@
|
||||
<label class="form-label small text-uppercase text-muted fw-semibold mb-1">MES reportable</label>
|
||||
<select class="form-select form-select-sm" data-test="alarm-mes-select" @bind="_editingMesReportableText">
|
||||
<option value="">Inherited (@(_editingAlarm.IsMesReportable ? "reportable" : "not reportable"))</option>
|
||||
<option value="true">Reportable</option>
|
||||
<option value="false">Not reportable</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (_editingError != null)
|
||||
@@ -837,6 +855,9 @@
|
||||
private string? _editingOverrideValue; // current Value parameter for AlarmTriggerEditor
|
||||
private string? _editingInheritedValue; // the inherited config snapshot we diff against on save
|
||||
private string? _editingPriorityText;
|
||||
// Tri-state MES reportable, as the select's string value: "" = inherited,
|
||||
// "true"/"false" = pinned. Parsed back to bool? on save.
|
||||
private string _editingMesReportableText = "";
|
||||
private string? _editingError;
|
||||
private IReadOnlyList<AlarmAttributeChoice> _editingAvailableAttributes = Array.Empty<AlarmAttributeChoice>();
|
||||
|
||||
@@ -1552,10 +1573,23 @@
|
||||
}
|
||||
if (ovr.PriorityLevelOverride.HasValue)
|
||||
parts.Add($"priority={ovr.PriorityLevelOverride.Value}");
|
||||
if (ovr.IsMesReportableOverride is bool m)
|
||||
parts.Add(m ? "mesReportable" : "notMesReportable");
|
||||
|
||||
return parts.Count == 0 ? "(empty)" : string.Join(", ", parts);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The save-time delta rule: does the modal carry anything worth persisting?
|
||||
/// When it does not, <see cref="SaveOverrideFromModal"/> DELETES any existing
|
||||
/// override — so every override term must be represented here or it would be
|
||||
/// silently dropped on save. A <c>false</c> MES-reportable choice counts: it
|
||||
/// pins a reportable template alarm off for this instance, which is a real
|
||||
/// override and not the same as inheriting.
|
||||
/// </summary>
|
||||
internal static bool HasOverrideDelta(string? overrideJson, int? priority, bool? mesReportable)
|
||||
=> !string.IsNullOrWhiteSpace(overrideJson) || priority.HasValue || mesReportable.HasValue;
|
||||
|
||||
/// <summary>
|
||||
/// Opens the override editor modal pre-populated with the merged
|
||||
/// (inherited + existing override) config so the user sees the effective
|
||||
@@ -1577,6 +1611,12 @@
|
||||
: (existing?.TriggerConfigurationOverride ?? alarm.TriggerConfiguration);
|
||||
|
||||
_editingPriorityText = existing?.PriorityLevelOverride?.ToString();
|
||||
_editingMesReportableText = existing?.IsMesReportableOverride switch
|
||||
{
|
||||
true => "true",
|
||||
false => "false",
|
||||
_ => "",
|
||||
};
|
||||
_editingAvailableAttributes = _flattenedAttributes;
|
||||
}
|
||||
|
||||
@@ -1621,11 +1661,18 @@
|
||||
: _editingOverrideValue;
|
||||
}
|
||||
|
||||
bool? mesReportable = _editingMesReportableText switch
|
||||
{
|
||||
"true" => true,
|
||||
"false" => false,
|
||||
_ => null,
|
||||
};
|
||||
|
||||
var user = await GetCurrentUserAsync();
|
||||
var alarmName = _editingAlarm.Name;
|
||||
|
||||
// No diff + no priority → clear any existing override and close.
|
||||
if (string.IsNullOrWhiteSpace(overrideJson) && !priority.HasValue)
|
||||
// Nothing overridden at all → clear any existing override and close.
|
||||
if (!HasOverrideDelta(overrideJson, priority, mesReportable))
|
||||
{
|
||||
if (_existingAlarmOverrides.ContainsKey(alarmName))
|
||||
{
|
||||
@@ -1647,7 +1694,7 @@
|
||||
else
|
||||
{
|
||||
var result = await MutationServices.GetRequiredService<ConfigurationCommandService>().ExecuteInstanceAsync(Id, null, (instanceService, currentUser) => instanceService.SetAlarmOverrideAsync(
|
||||
Id, alarmName, overrideJson, priority, currentUser));
|
||||
Id, alarmName, overrideJson, priority, currentUser, mesReportable));
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
_editingError = result.Error;
|
||||
|
||||
Reference in New Issue
Block a user