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:
@@ -2,100 +2,104 @@
|
||||
@using ZB.MOM.WW.OtOpcUa.Configuration.Entities
|
||||
@inject UnsService UnsSvc
|
||||
|
||||
<div class="alert alert-info small mb-3">
|
||||
<section class="panel notice rise" style="animation-delay:.02s">
|
||||
Drag any line in the <strong>UNS Lines</strong> table onto an area row in <strong>UNS Areas</strong>
|
||||
to re-parent it. A preview modal shows the impact (equipment re-home count) + lets you confirm
|
||||
or cancel. If another operator modifies the draft while you're confirming, you'll see a 409
|
||||
refresh-required modal instead of clobbering their work.
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="row">
|
||||
<div class="row mt-3">
|
||||
<div class="col-md-6">
|
||||
<div class="d-flex justify-content-between mb-2">
|
||||
<h4>UNS Areas</h4>
|
||||
<button class="btn btn-sm btn-primary" @onclick="() => _showAreaForm = true">Add area</button>
|
||||
</div>
|
||||
<section class="panel rise" style="animation-delay:.08s">
|
||||
<div class="panel-head d-flex justify-content-between align-items-center">
|
||||
<span>UNS Areas</span>
|
||||
<button class="btn btn-sm btn-primary" @onclick="() => _showAreaForm = true">Add area</button>
|
||||
</div>
|
||||
|
||||
@if (_areas is null) { <p>Loading…</p> }
|
||||
else if (_areas.Count == 0) { <p class="text-muted">No areas yet.</p> }
|
||||
else
|
||||
{
|
||||
<table class="table table-sm">
|
||||
<thead><tr><th>AreaId</th><th>Name</th><th class="small text-muted">(drop target)</th></tr></thead>
|
||||
<tbody>
|
||||
@foreach (var a in _areas)
|
||||
{
|
||||
<tr class="@(_hoverAreaId == a.UnsAreaId ? "table-primary" : "")"
|
||||
@ondragover="e => OnAreaDragOver(e, a.UnsAreaId)"
|
||||
@ondragover:preventDefault
|
||||
@ondragleave="() => _hoverAreaId = null"
|
||||
@ondrop="() => OnLineDroppedAsync(a.UnsAreaId)"
|
||||
@ondrop:preventDefault>
|
||||
<td><code>@a.UnsAreaId</code></td>
|
||||
<td>@a.Name</td>
|
||||
<td class="small text-muted">drop here</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
}
|
||||
@if (_areas is null) { <p class="p-3">Loading…</p> }
|
||||
else if (_areas.Count == 0) { <p class="p-3 text-muted">No areas yet.</p> }
|
||||
else
|
||||
{
|
||||
<div class="table-wrap">
|
||||
<table class="data-table">
|
||||
<thead><tr><th>AreaId</th><th>Name</th><th class="text-muted">(drop target)</th></tr></thead>
|
||||
<tbody>
|
||||
@foreach (var a in _areas)
|
||||
{
|
||||
<tr class="@(_hoverAreaId == a.UnsAreaId ? "table-primary" : "")"
|
||||
@ondragover="e => OnAreaDragOver(e, a.UnsAreaId)"
|
||||
@ondragover:preventDefault
|
||||
@ondragleave="() => _hoverAreaId = null"
|
||||
@ondrop="() => OnLineDroppedAsync(a.UnsAreaId)"
|
||||
@ondrop:preventDefault>
|
||||
<td><span class="mono">@a.UnsAreaId</span></td>
|
||||
<td>@a.Name</td>
|
||||
<td class="text-muted">drop here</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (_showAreaForm)
|
||||
{
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="mb-2"><label class="form-label">Name (lowercase segment)</label><input class="form-control" @bind="_newAreaName"/></div>
|
||||
@if (_showAreaForm)
|
||||
{
|
||||
<div class="p-3 border-top">
|
||||
<div class="mb-2"><label class="form-label">Name (lowercase segment)</label><input class="form-control form-control-sm" @bind="_newAreaName"/></div>
|
||||
<button class="btn btn-sm btn-primary" @onclick="AddAreaAsync">Save</button>
|
||||
<button class="btn btn-sm btn-secondary ms-2" @onclick="() => _showAreaForm = false">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="d-flex justify-content-between mb-2">
|
||||
<h4>UNS Lines</h4>
|
||||
<button class="btn btn-sm btn-primary" @onclick="() => _showLineForm = true" disabled="@(_areas is null || _areas.Count == 0)">Add line</button>
|
||||
</div>
|
||||
<section class="panel rise" style="animation-delay:.14s">
|
||||
<div class="panel-head d-flex justify-content-between align-items-center">
|
||||
<span>UNS Lines</span>
|
||||
<button class="btn btn-sm btn-primary" @onclick="() => _showLineForm = true" disabled="@(_areas is null || _areas.Count == 0)">Add line</button>
|
||||
</div>
|
||||
|
||||
@if (_lines is null) { <p>Loading…</p> }
|
||||
else if (_lines.Count == 0) { <p class="text-muted">No lines yet.</p> }
|
||||
else
|
||||
{
|
||||
<table class="table table-sm">
|
||||
<thead><tr><th>LineId</th><th>Area</th><th>Name</th></tr></thead>
|
||||
<tbody>
|
||||
@foreach (var l in _lines)
|
||||
{
|
||||
<tr draggable="true"
|
||||
@ondragstart="() => _dragLineId = l.UnsLineId"
|
||||
@ondragend="() => { _dragLineId = null; _hoverAreaId = null; }"
|
||||
style="cursor: grab;">
|
||||
<td><code>@l.UnsLineId</code></td>
|
||||
<td><code>@l.UnsAreaId</code></td>
|
||||
<td>@l.Name</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
}
|
||||
@if (_lines is null) { <p class="p-3">Loading…</p> }
|
||||
else if (_lines.Count == 0) { <p class="p-3 text-muted">No lines yet.</p> }
|
||||
else
|
||||
{
|
||||
<div class="table-wrap">
|
||||
<table class="data-table">
|
||||
<thead><tr><th>LineId</th><th>Area</th><th>Name</th></tr></thead>
|
||||
<tbody>
|
||||
@foreach (var l in _lines)
|
||||
{
|
||||
<tr draggable="true"
|
||||
@ondragstart="() => _dragLineId = l.UnsLineId"
|
||||
@ondragend="() => { _dragLineId = null; _hoverAreaId = null; }"
|
||||
style="cursor: grab;">
|
||||
<td><span class="mono">@l.UnsLineId</span></td>
|
||||
<td><span class="mono">@l.UnsAreaId</span></td>
|
||||
<td>@l.Name</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (_showLineForm && _areas is not null)
|
||||
{
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
@if (_showLineForm && _areas is not null)
|
||||
{
|
||||
<div class="p-3 border-top">
|
||||
<div class="mb-2">
|
||||
<label class="form-label">Area</label>
|
||||
<select class="form-select" @bind="_newLineAreaId">
|
||||
<select class="form-select form-select-sm" @bind="_newLineAreaId">
|
||||
@foreach (var a in _areas) { <option value="@a.UnsAreaId">@a.Name (@a.UnsAreaId)</option> }
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-2"><label class="form-label">Name</label><input class="form-control" @bind="_newLineName"/></div>
|
||||
<div class="mb-2"><label class="form-label">Name</label><input class="form-control form-control-sm" @bind="_newLineName"/></div>
|
||||
<button class="btn btn-sm btn-primary" @onclick="AddLineAsync">Save</button>
|
||||
<button class="btn btn-sm btn-secondary ms-2" @onclick="() => _showLineForm = false">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -117,11 +121,11 @@
|
||||
</p>
|
||||
@if (_pendingPreview.CascadeWarnings.Count > 0)
|
||||
{
|
||||
<div class="alert alert-warning small mb-0">
|
||||
<section class="panel notice small mb-0">
|
||||
<ul class="mb-0">
|
||||
@foreach (var w in _pendingPreview.CascadeWarnings) { <li>@w</li> }
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
}
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
|
||||
Reference in New Issue
Block a user