feat(adminui): add DriverTypePicker landing page

Adds /clusters/{ClusterId}/drivers/new picker page (Task 3.1). Renders
a 9-card Bootstrap grid — one card per driver type — each linking to
/clusters/{ClusterId}/drivers/new/{slug}. No data fetch; type list is
hardcoded. Route collides with DriverEdit.razor's same directive; Task
3.3 removes the duplicate to resolve the runtime ambiguity.
This commit is contained in:
Joseph Doherty
2026-05-28 09:36:54 -04:00
parent a28f4cdd25
commit c0ce5d02bd
@@ -0,0 +1,51 @@
@* TODO(3.3): This route collides with DriverEdit.razor's @page "/clusters/{ClusterId}/drivers/new".
Task 3.3 removes the /drivers/new directive from DriverEdit.razor so this page takes over.
Blazor resolves route conflicts at runtime, not compile time, so the build succeeds now. *@
@page "/clusters/{ClusterId}/drivers/new"
@attribute [Microsoft.AspNetCore.Authorization.Authorize]
<div class="d-flex justify-content-between align-items-center mb-3">
<h4 class="mb-0">New driver &middot; <span class="mono">@ClusterId</span></h4>
<a href="/clusters/@ClusterId/drivers" class="btn btn-outline-secondary btn-sm">Cancel</a>
</div>
<ClusterNav ClusterId="@ClusterId" ActiveTab="drivers" />
<section class="panel rise mt-3" style="animation-delay:.08s">
<div class="panel-head">Pick a driver type</div>
<div style="padding:1rem">
<div class="row g-3">
@foreach (var t in _types)
{
<div class="col-md-4 col-lg-3">
<a href="/clusters/@ClusterId/drivers/new/@t.Slug" class="card h-100 text-decoration-none">
<div class="card-body">
<div class="text-muted small mono">@t.Icon</div>
<div class="card-title mt-1"><strong>@t.DisplayName</strong></div>
<div class="card-text small text-muted">@t.Description</div>
</div>
</a>
</div>
}
</div>
</div>
</section>
@code {
[Parameter] public string ClusterId { get; set; } = "";
private sealed record DriverTypeEntry(string DisplayName, string Slug, string Icon, string Description);
private static readonly IReadOnlyList<DriverTypeEntry> _types = new[]
{
new DriverTypeEntry("ModbusTcp", "modbustcp", "[M]", "Modbus/TCP — generic registers/coils via port 502."),
new DriverTypeEntry("AbCip", "abcip", "[CIP]", "Allen-Bradley CompactLogix/ControlLogix via CIP."),
new DriverTypeEntry("AbLegacy", "ablegacy", "[AB]", "Allen-Bradley PLC-5/SLC-500/MicroLogix via DF1."),
new DriverTypeEntry("S7", "s7", "[S7]", "Siemens S7-300/400/1200/1500 via ISO-on-TCP."),
new DriverTypeEntry("TwinCat", "twincat", "[TC]", "Beckhoff TwinCAT via ADS."),
new DriverTypeEntry("Focas", "focas", "[FOC]", "Fanuc CNC via FOCAS library."),
new DriverTypeEntry("OpcUaClient", "opcuaclient", "[OPC]", "Upstream OPC UA server pull."),
new DriverTypeEntry("Galaxy", "galaxy", "[Gx]", "AVEVA System Platform (Wonderware) via mxaccessgw."),
new DriverTypeEntry("Historian.Wonderware", "historianwonderware","[Hx]", "Wonderware Historian replay/cyclic reads."),
};
}