feat: restyle Admin UI with the technical-light design system

Adopt the technical-light design system across the Admin web UI:

- Vendor theme.css + IBM Plex woff2 fonts into wwwroot; include
  theme.css globally after Bootstrap.
- Rebuild MainLayout: top app-bar (brand mark, breadcrumb, connection
  pill) + hairline-ruled side rail with accent-bordered active link.
- Convert all 33 pages to the component catalog — tables to
  panel + data-table (num/mono columns), KPI cards to agg-grid,
  detail blocks to metric-card/kv rows, badges to chips, alerts to
  panel notice, headings to page-title/panel-head, .rise reveals.
- Buttons/forms stay on Bootstrap; theme.css restyles them via
  --bs-* overrides. View-specific layout lives in app.css; all
  colour/type comes from theme.css tokens.

Also fix a pre-existing /fleet 500: the node-state query ordered on
a property of a constructed FleetNodeRow record, which EF Core
cannot translate. Order the join's columns before projecting.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Joseph Doherty
2026-05-18 02:20:09 -04:00
parent 31b9468102
commit 482d5f5637
40 changed files with 1837 additions and 1206 deletions

View File

@@ -9,27 +9,27 @@
<div class="modbus-options-editor">
<h5>Connection</h5>
<div class="panel-head">Connection</div>
<div class="row mb-3">
<div class="col-sm-6">
<label class="form-label">Host</label>
<input class="form-control" @bind="Model.Host"/>
<input class="form-control form-control-sm" @bind="Model.Host"/>
</div>
<div class="col-sm-3">
<label class="form-label">Port</label>
<input type="number" class="form-control" @bind="Model.Port"/>
<input type="number" class="form-control form-control-sm" @bind="Model.Port"/>
</div>
<div class="col-sm-3">
<label class="form-label">Default UnitId</label>
<input type="number" class="form-control" @bind="Model.UnitId"/>
<input type="number" class="form-control form-control-sm" @bind="Model.UnitId"/>
</div>
</div>
<h5>Family (#144)</h5>
<div class="panel-head">Family (#144)</div>
<div class="row mb-3">
<div class="col-sm-6">
<label class="form-label">PLC family</label>
<select class="form-select" @bind="Model.Family">
<select class="form-select form-select-sm" @bind="Model.Family">
@foreach (var f in Enum.GetValues<ModbusFamily>())
{
<option value="@f">@f</option>
@@ -40,7 +40,7 @@
{
<div class="col-sm-6">
<label class="form-label">MELSEC sub-family</label>
<select class="form-select" @bind="Model.MelsecSubFamily">
<select class="form-select form-select-sm" @bind="Model.MelsecSubFamily">
@foreach (var f in Enum.GetValues<MelsecFamily>())
{
<option value="@f">@f</option>
@@ -50,7 +50,7 @@
}
</div>
<h5>Keep-alive (#139)</h5>
<div class="panel-head">Keep-alive (#139)</div>
<div class="row mb-3">
<div class="col-sm-3">
<div class="form-check mt-4">
@@ -60,51 +60,51 @@
</div>
<div class="col-sm-3">
<label class="form-label">Time (s)</label>
<input type="number" class="form-control" @bind="Model.KeepAliveTimeSec"/>
<input type="number" class="form-control form-control-sm" @bind="Model.KeepAliveTimeSec"/>
</div>
<div class="col-sm-3">
<label class="form-label">Interval (s)</label>
<input type="number" class="form-control" @bind="Model.KeepAliveIntervalSec"/>
<input type="number" class="form-control form-control-sm" @bind="Model.KeepAliveIntervalSec"/>
</div>
<div class="col-sm-3">
<label class="form-label">Retry count</label>
<input type="number" class="form-control" @bind="Model.KeepAliveRetryCount"/>
<input type="number" class="form-control form-control-sm" @bind="Model.KeepAliveRetryCount"/>
</div>
</div>
<h5>Reconnect (#139)</h5>
<div class="panel-head">Reconnect (#139)</div>
<div class="row mb-3">
<div class="col-sm-4">
<label class="form-label">Initial delay (ms)</label>
<input type="number" class="form-control" @bind="Model.ReconnectInitialDelayMs"/>
<input type="number" class="form-control form-control-sm" @bind="Model.ReconnectInitialDelayMs"/>
</div>
<div class="col-sm-4">
<label class="form-label">Max delay (ms)</label>
<input type="number" class="form-control" @bind="Model.ReconnectMaxDelayMs"/>
<input type="number" class="form-control form-control-sm" @bind="Model.ReconnectMaxDelayMs"/>
</div>
<div class="col-sm-4">
<label class="form-label">Backoff multiplier</label>
<input type="number" step="0.1" class="form-control" @bind="Model.ReconnectBackoffMultiplier"/>
<input type="number" step="0.1" class="form-control form-control-sm" @bind="Model.ReconnectBackoffMultiplier"/>
</div>
</div>
<h5>Protocol (#140)</h5>
<div class="panel-head">Protocol (#140)</div>
<div class="row mb-3">
<div class="col-sm-3">
<label class="form-label">Max regs / read</label>
<input type="number" class="form-control" @bind="Model.MaxRegistersPerRead"/>
<input type="number" class="form-control form-control-sm" @bind="Model.MaxRegistersPerRead"/>
</div>
<div class="col-sm-3">
<label class="form-label">Max regs / write</label>
<input type="number" class="form-control" @bind="Model.MaxRegistersPerWrite"/>
<input type="number" class="form-control form-control-sm" @bind="Model.MaxRegistersPerWrite"/>
</div>
<div class="col-sm-3">
<label class="form-label">Max coils / read</label>
<input type="number" class="form-control" @bind="Model.MaxCoilsPerRead"/>
<input type="number" class="form-control form-control-sm" @bind="Model.MaxCoilsPerRead"/>
</div>
<div class="col-sm-3">
<label class="form-label">Max read gap (#143)</label>
<input type="number" class="form-control" @bind="Model.MaxReadGap"/>
<input type="number" class="form-control form-control-sm" @bind="Model.MaxReadGap"/>
</div>
</div>