410349767d
T34c only fixed the bounded modal-surface offenders. Bootstrap 5.3's bg-light
and bg-white are fixed light values that do NOT flip under [data-bs-theme=dark],
so every remaining use was a dark-mode contrast break. 35 swaps across 19 files:
surface / <pre> / <code> bg-light -> bg-body-secondary
panel bg-white -> bg-body
neutral badge bg-light text-dark -> bg-secondary-subtle text-secondary-emphasis
muted badge / input group bg-light text-muted -> bg-body-secondary text-body-secondary
DELIBERATELY LEFT (7 sites): the neutral member of a status-badge switch or
ternary whose siblings are all solid, non-theme-aware colours (bg-success,
bg-danger, bg-warning) — swapping only the neutral one to a subtle token breaks
the visual weight of the set, so these stay until the whole family is retoned:
Topology.razor:513 (Current badge) and :588 (InstanceState.NotDeployed)
InstanceConfigure.razor:1520 (same InstanceState switch)
NotificationReport.razor StatusBadgeClass fallback
TransportImport.razor ConflictKind badge fallback
SecuredWrites.razor text-bg-light fallback (a text-bg-* family with no
theme-aware member at all)
Health.razor:377 depth ternary
Also untouched by design: SchemaBuilder.razor:88 (already bg-light-subtle,
theme-aware), bg-dark text-light console panels, and site.css / #reconnect-modal.
InstanceConfigure.razor is edited concurrently elsewhere; its change here is 5
pure class-string swaps on existing lines, no reflow. No test asserted any of
these classes. Also marks all four M10 residuals done in the plan doc.
169 lines
6.8 KiB
Plaintext
169 lines
6.8 KiB
Plaintext
@using ZB.MOM.WW.ScadaBridge.CentralUI.Services
|
|
@using ZB.MOM.WW.ScadaBridge.Commons.Types.Enums
|
|
|
|
@* Reusable single-AuditEvent detail body.
|
|
Extracted from AuditDrilldownDrawer so the drawer and the execution-tree
|
|
node-detail modal share one rendering of a row's detail.
|
|
All form/field rendering follows the form-layout memory:
|
|
read-only fields first (definition list), then subsections stacked,
|
|
action buttons at the bottom. *@
|
|
|
|
@* Read-only field list — primary identification + provenance. *@
|
|
<dl class="row mb-3" data-test="drawer-fields">
|
|
<dt class="col-4 text-muted fw-normal">Channel / Kind</dt>
|
|
<dd class="col-8" data-test="field-Channel">@Event.Channel / @Event.Kind</dd>
|
|
|
|
<dt class="col-4 text-muted fw-normal">Status</dt>
|
|
<dd class="col-8" data-test="field-Status">@Event.Status</dd>
|
|
|
|
<dt class="col-4 text-muted fw-normal">HttpStatus</dt>
|
|
<dd class="col-8 font-monospace" data-test="field-HttpStatus">@(Event.HttpStatus?.ToString() ?? "—")</dd>
|
|
|
|
<dt class="col-4 text-muted fw-normal">Target</dt>
|
|
<dd class="col-8" data-test="field-Target">@(Event.Target ?? "—")</dd>
|
|
|
|
<dt class="col-4 text-muted fw-normal">Actor</dt>
|
|
<dd class="col-8" data-test="field-Actor">@(Event.Actor ?? "—")</dd>
|
|
|
|
<dt class="col-4 text-muted fw-normal">SourceSiteId</dt>
|
|
<dd class="col-8" data-test="field-SourceSiteId">@(Event.SourceSiteId ?? "—")</dd>
|
|
|
|
<dt class="col-4 text-muted fw-normal">SourceNode</dt>
|
|
<dd class="col-8" data-test="field-SourceNode">@(Event.SourceNode ?? "—")</dd>
|
|
|
|
<dt class="col-4 text-muted fw-normal">SourceInstanceId</dt>
|
|
<dd class="col-8" data-test="field-SourceInstanceId">@(Event.SourceInstanceId ?? "—")</dd>
|
|
|
|
<dt class="col-4 text-muted fw-normal">SourceScript</dt>
|
|
<dd class="col-8" data-test="field-SourceScript">@(Event.SourceScript ?? "—")</dd>
|
|
|
|
<dt class="col-4 text-muted fw-normal">CorrelationId</dt>
|
|
<dd class="col-8 font-monospace" data-test="field-CorrelationId">@(Event.CorrelationId?.ToString() ?? "—")</dd>
|
|
|
|
<dt class="col-4 text-muted fw-normal">ExecutionId</dt>
|
|
<dd class="col-8 font-monospace" data-test="field-ExecutionId">@(Event.ExecutionId?.ToString() ?? "—")</dd>
|
|
|
|
<dt class="col-4 text-muted fw-normal">ParentExecutionId</dt>
|
|
<dd class="col-8 font-monospace" data-test="field-ParentExecutionId">@(Event.ParentExecutionId?.ToString() ?? "—")</dd>
|
|
|
|
<dt class="col-4 text-muted fw-normal">OccurredAtUtc</dt>
|
|
<dd class="col-8 font-monospace" data-test="field-OccurredAtUtc">@FormatTimestamp(Event.OccurredAtUtc)</dd>
|
|
|
|
<dt class="col-4 text-muted fw-normal">IngestedAtUtc</dt>
|
|
<dd class="col-8 font-monospace" data-test="field-IngestedAtUtc">@(Event.IngestedAtUtc.HasValue ? FormatTimestamp(Event.IngestedAtUtc.Value) : "—")</dd>
|
|
|
|
<dt class="col-4 text-muted fw-normal">DurationMs</dt>
|
|
<dd class="col-8 font-monospace" data-test="field-DurationMs">@(Event.DurationMs?.ToString() ?? "—")</dd>
|
|
</dl>
|
|
|
|
@* Error subsection — only shown when there is something to report. *@
|
|
@if (!string.IsNullOrEmpty(Event.ErrorMessage) || !string.IsNullOrEmpty(Event.ErrorDetail))
|
|
{
|
|
<section class="mb-3" data-test="section-error">
|
|
<h6 class="text-uppercase text-muted small fw-semibold mb-1">Error</h6>
|
|
@if (!string.IsNullOrEmpty(Event.ErrorMessage))
|
|
{
|
|
<p class="text-danger mb-1">@Event.ErrorMessage</p>
|
|
}
|
|
@if (!string.IsNullOrEmpty(Event.ErrorDetail))
|
|
{
|
|
<pre class="bg-body-secondary border rounded p-2 mb-0 drawer-pre">@Event.ErrorDetail</pre>
|
|
}
|
|
</section>
|
|
}
|
|
|
|
@* Request body (channel-aware renderer). *@
|
|
@if (!string.IsNullOrEmpty(Event.RequestSummary))
|
|
{
|
|
<section class="mb-3" data-test="section-request">
|
|
<h6 class="text-uppercase text-muted small fw-semibold mb-1 d-flex align-items-center gap-2">
|
|
<span>Request</span>
|
|
@if (IsRedacted(Event.RequestSummary))
|
|
{
|
|
<span data-test="redaction-badge-request"
|
|
class="badge bg-warning text-dark"
|
|
title="Sensitive values redacted by audit pipeline">
|
|
Redacted
|
|
</span>
|
|
}
|
|
</h6>
|
|
<div data-test="request-body">
|
|
@RenderBody(Event.RequestSummary!, Event.Channel)
|
|
</div>
|
|
</section>
|
|
}
|
|
|
|
@* Response body (channel-aware renderer). *@
|
|
@if (!string.IsNullOrEmpty(Event.ResponseSummary))
|
|
{
|
|
<section class="mb-3" data-test="section-response">
|
|
<h6 class="text-uppercase text-muted small fw-semibold mb-1 d-flex align-items-center gap-2">
|
|
<span>Response</span>
|
|
@if (IsRedacted(Event.ResponseSummary))
|
|
{
|
|
<span data-test="redaction-badge-response"
|
|
class="badge bg-warning text-dark"
|
|
title="Sensitive values redacted by audit pipeline">
|
|
Redacted
|
|
</span>
|
|
}
|
|
</h6>
|
|
<div data-test="response-body">
|
|
@RenderBody(Event.ResponseSummary!, Event.Channel)
|
|
</div>
|
|
</section>
|
|
}
|
|
|
|
@* Extra is always JSON when present. *@
|
|
@if (!string.IsNullOrEmpty(Event.Extra))
|
|
{
|
|
<section class="mb-3" data-test="section-extra">
|
|
<h6 class="text-uppercase text-muted small fw-semibold mb-1">Extra</h6>
|
|
<pre class="bg-body-secondary border rounded p-2 mb-0 drawer-pre json">@PrettyPrintJson(Event.Extra!)</pre>
|
|
</section>
|
|
}
|
|
|
|
@* Action buttons at the bottom per form-layout memory. *@
|
|
<div class="d-flex gap-2 flex-wrap" data-test="audit-event-detail-actions">
|
|
@if (IsApiChannel(Event.Channel))
|
|
{
|
|
<button class="btn btn-outline-secondary btn-sm"
|
|
data-test="copy-as-curl"
|
|
@onclick="CopyCurl">
|
|
Copy as cURL
|
|
</button>
|
|
}
|
|
@if (Event.CorrelationId is not null)
|
|
{
|
|
<button class="btn btn-outline-secondary btn-sm"
|
|
data-test="show-all-events"
|
|
@onclick="ShowAllForOperation">
|
|
Show all events for this operation
|
|
</button>
|
|
}
|
|
@if (Event.ExecutionId is not null)
|
|
{
|
|
<button class="btn btn-outline-secondary btn-sm"
|
|
data-test="view-this-execution"
|
|
@onclick="ViewThisExecution">
|
|
View this execution
|
|
</button>
|
|
}
|
|
@if (Event.ParentExecutionId is not null)
|
|
{
|
|
<button class="btn btn-outline-secondary btn-sm"
|
|
data-test="view-parent-execution"
|
|
@onclick="ViewParentExecution">
|
|
View parent execution
|
|
</button>
|
|
}
|
|
@if (Event.ExecutionId is not null)
|
|
{
|
|
<button class="btn btn-outline-secondary btn-sm"
|
|
data-test="view-execution-chain"
|
|
@onclick="ViewExecutionChain">
|
|
View execution chain
|
|
</button>
|
|
}
|
|
</div>
|