@page "/reservations" @using ZB.MOM.WW.OtOpcUa.Admin.Services @using ZB.MOM.WW.OtOpcUa.Configuration.Entities @using Microsoft.AspNetCore.Authorization @attribute [Authorize(Policy = "CanPublish")] @inject ReservationService ReservationSvc

External-ID reservations

Fleet-wide ZTag + SAPID reservation state (decision #124). Releasing a reservation is a FleetAdmin-only audit-logged action — only release when the physical asset is permanently retired and its ID needs to be reused by a different equipment.

Active

@if (_active is null) {

Loading…

} else if (_active.Count == 0) {

No active reservations.

} else { @foreach (var r in _active) { }
KindValueEquipmentUuidClusterFirst publishedLast published
@r.Kind @r.Value @r.EquipmentUuid @r.ClusterId @r.FirstPublishedAt.ToString("u") by @r.FirstPublishedBy @r.LastPublishedAt.ToString("u")
}

Released (most recent 100)

@if (_released is null) {

Loading…

} else if (_released.Count == 0) {

No released reservations yet.

} else { @foreach (var r in _released) { }
KindValueReleased atByReason
@r.Kind@r.Value@r.ReleasedAt?.ToString("u")@r.ReleasedBy@r.ReleaseReason
} @if (_releasing is not null) { } @code { private List? _active; private List? _released; private ExternalIdReservation? _releasing; private string _reason = string.Empty; private bool _busy; private string? _error; protected override async Task OnInitializedAsync() => await ReloadAsync(); private async Task ReloadAsync() { _active = await ReservationSvc.ListActiveAsync(CancellationToken.None); _released = await ReservationSvc.ListReleasedAsync(CancellationToken.None); } private void OpenReleaseDialog(ExternalIdReservation r) { _releasing = r; _reason = string.Empty; _error = null; } private async Task ReleaseAsync() { if (_releasing is null || string.IsNullOrWhiteSpace(_reason)) { _error = "Reason is required"; return; } _busy = true; try { await ReservationSvc.ReleaseAsync(_releasing.Kind.ToString(), _releasing.Value, _reason, CancellationToken.None); _releasing = null; await ReloadAsync(); } catch (Exception ex) { _error = ex.Message; } finally { _busy = false; } } }