239 lines
11 KiB
Plaintext
239 lines
11 KiB
Plaintext
@page "/dock-station-config"
|
|
@rendermode InteractiveWebAssemblyNoPrerender
|
|
@using RobotNet10.RobotApp.Client.Services
|
|
@using RobotNet10.RobotApp.Client.Dialogs
|
|
@using RobotNet10.RobotApp.Shared.DockStation
|
|
@inject DockStationConfigState State
|
|
@inject IDialogService DialogService
|
|
@inject ISnackbar Snackbar
|
|
@implements IDisposable
|
|
|
|
<PageTitle>Dock Station Config</PageTitle>
|
|
|
|
<MudContainer MaxWidth="MaxWidth.ExtraLarge" Class="mt-4">
|
|
<MudText Typo="Typo.h5" Class="mb-4">Dock Station Configuration</MudText>
|
|
|
|
@if (!string.IsNullOrEmpty(State.ErrorMessage))
|
|
{
|
|
<MudAlert Severity="Severity.Error" Class="mb-3">
|
|
@State.ErrorMessage
|
|
</MudAlert>
|
|
}
|
|
|
|
<MudGrid>
|
|
@* Left Panel - Config List *@
|
|
<MudItem xs="12" md="5" lg="4">
|
|
<MudPaper Class="pa-3" Elevation="2">
|
|
<MudStack Row AlignItems="AlignItems.Center" Class="mb-3">
|
|
<MudText Typo="Typo.h6">Stations</MudText>
|
|
<MudSpacer />
|
|
<MudButton Variant="Variant.Filled" Color="Color.Primary" StartIcon="@Icons.Material.Filled.Add"
|
|
OnClick="OpenCreateDialog" Disabled="State.IsSaving">
|
|
New
|
|
</MudButton>
|
|
</MudStack>
|
|
|
|
@if (State.IsLoading && State.Configs.Count == 0)
|
|
{
|
|
<MudProgressLinear Indeterminate />
|
|
}
|
|
else if (State.Configs.Count == 0)
|
|
{
|
|
<MudText Typo="Typo.body2" Color="Color.Tertiary" Align="Align.Center" Class="pa-4">
|
|
No dock station configs found.
|
|
</MudText>
|
|
}
|
|
else
|
|
{
|
|
<MudList T="DockStationConfigSummaryDto" Dense SelectedValueChanged="OnConfigSelected">
|
|
@foreach (var config in State.Configs)
|
|
{
|
|
<MudListItem Value="config"
|
|
Icon="@(config.IsActive ? Icons.Material.Filled.EvStation : Icons.Material.Outlined.EvStation)"
|
|
IconColor="@(config.IsActive ? Color.Success : Color.Default)">
|
|
<MudStack Spacing="0">
|
|
<MudText Typo="Typo.body1"><b>@config.StationId</b></MudText>
|
|
<MudText Typo="Typo.caption" Color="Color.Tertiary">
|
|
@(string.IsNullOrEmpty(config.ConfigName) ? "No name" : config.ConfigName)
|
|
· @config.MarkerEntryCount marker(s)
|
|
</MudText>
|
|
</MudStack>
|
|
</MudListItem>
|
|
}
|
|
</MudList>
|
|
}
|
|
</MudPaper>
|
|
</MudItem>
|
|
|
|
@* Right Panel - Detail View *@
|
|
<MudItem xs="12" md="7" lg="8">
|
|
@if (State.SelectedConfig is not null)
|
|
{
|
|
var cfg = State.SelectedConfig;
|
|
<MudPaper Class="pa-4" Elevation="2">
|
|
<MudStack Row AlignItems="AlignItems.Center" Class="mb-3">
|
|
<MudText Typo="Typo.h6">@cfg.StationId</MudText>
|
|
<MudChip T="string" Size="Size.Small"
|
|
Color="@(cfg.IsActive ? Color.Success : Color.Default)">
|
|
@(cfg.IsActive ? "Active" : "Inactive")
|
|
</MudChip>
|
|
<MudSpacer />
|
|
<MudIconButton Icon="@Icons.Material.Filled.Edit" Color="Color.Primary"
|
|
OnClick="OpenEditDialog" Disabled="State.IsSaving" />
|
|
<MudIconButton Icon="@Icons.Material.Filled.Delete" Color="Color.Error"
|
|
OnClick="OpenDeleteDialog" Disabled="State.IsSaving" />
|
|
</MudStack>
|
|
|
|
@if (!string.IsNullOrEmpty(cfg.ConfigName))
|
|
{
|
|
<MudText Typo="Typo.subtitle1" Class="mb-1">@cfg.ConfigName</MudText>
|
|
}
|
|
@if (!string.IsNullOrEmpty(cfg.Description))
|
|
{
|
|
<MudText Typo="Typo.body2" Color="Color.Tertiary" Class="mb-3">@cfg.Description</MudText>
|
|
}
|
|
|
|
<MudDivider Class="my-3" />
|
|
|
|
<MudText Typo="Typo.subtitle2" Class="mb-2">Search Area</MudText>
|
|
<MudGrid Spacing="2">
|
|
<MudItem xs="4"><MudText Typo="Typo.body2">X: <b>@cfg.X.ToString("F3")</b> m</MudText></MudItem>
|
|
<MudItem xs="4"><MudText Typo="Typo.body2">Y: <b>@cfg.Y.ToString("F3")</b> m</MudText></MudItem>
|
|
<MudItem xs="4"><MudText Typo="Typo.body2">Yaw: <b>@cfg.Yaw.ToString("F4")</b> rad</MudText></MudItem>
|
|
<MudItem xs="6"><MudText Typo="Typo.body2">Width: <b>@cfg.Width.ToString("F3")</b> m</MudText></MudItem>
|
|
<MudItem xs="6"><MudText Typo="Typo.body2">Length: <b>@cfg.Length.ToString("F3")</b> m</MudText></MudItem>
|
|
</MudGrid>
|
|
|
|
<MudDivider Class="my-3" />
|
|
|
|
<MudText Typo="Typo.subtitle2" Class="mb-2">Marker Entries (@cfg.MarkerEntries.Count)</MudText>
|
|
<MudPaper Style="max-height: calc(100vh - 460px); overflow-y: auto; padding-right: 4px;" Elevation="0">
|
|
@foreach (var entry in cfg.MarkerEntries.OrderBy(e => e.Priority))
|
|
{
|
|
<MudPaper Class="pa-3 mb-2" Outlined>
|
|
<MudGrid Spacing="1">
|
|
<MudItem xs="4"><MudText Typo="Typo.body2">Marker: <b>@entry.MarkerId</b></MudText></MudItem>
|
|
<MudItem xs="4"><MudText Typo="Typo.body2">Type: <b>@entry.Type</b></MudText></MudItem>
|
|
<MudItem xs="4"><MudText Typo="Typo.body2">Priority: <b>@entry.Priority</b></MudText></MudItem>
|
|
<MudItem xs="6"><MudText Typo="Typo.body2">Device: <b>@(entry.DeviceId ?? "-")</b></MudText></MudItem>
|
|
<MudItem xs="6"><MudText Typo="Typo.body2">Code: <b>@(entry.Code ?? "-")</b></MudText></MudItem>
|
|
</MudGrid>
|
|
@if (entry.ReferencePoints.Count > 0)
|
|
{
|
|
<MudText Typo="Typo.caption" Class="mt-1">
|
|
Reference Points: @string.Join(", ", entry.ReferencePoints.Select(p => $"({p.X:F3}, {p.Y:F3})"))
|
|
</MudText>
|
|
}
|
|
</MudPaper>
|
|
}
|
|
</MudPaper>
|
|
|
|
<MudDivider Class="my-3" />
|
|
<MudText Typo="Typo.caption" Color="Color.Tertiary">
|
|
Created: @cfg.CreatedAt.ToString("yyyy-MM-dd HH:mm") | Updated: @cfg.UpdatedAt.ToString("yyyy-MM-dd HH:mm")
|
|
</MudText>
|
|
</MudPaper>
|
|
}
|
|
else
|
|
{
|
|
<MudPaper Class="pa-8 d-flex align-center justify-center" Elevation="0" Style="min-height:300px">
|
|
<MudText Typo="Typo.body1" Color="Color.Tertiary">Select a dock station config to view details</MudText>
|
|
</MudPaper>
|
|
}
|
|
</MudItem>
|
|
</MudGrid>
|
|
</MudContainer>
|
|
|
|
<MudThemeProvider IsDarkMode />
|
|
<MudPopoverProvider />
|
|
<MudDialogProvider />
|
|
<MudSnackbarProvider />
|
|
|
|
@code {
|
|
protected override async Task OnInitializedAsync()
|
|
{
|
|
State.OnStateChanged += StateHasChanged;
|
|
await State.LoadConfigsAsync();
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
State.OnStateChanged -= StateHasChanged;
|
|
}
|
|
|
|
private async Task OnConfigSelected(DockStationConfigSummaryDto? config)
|
|
{
|
|
if (config is not null)
|
|
await State.SelectConfigAsync(config.Id);
|
|
}
|
|
|
|
private async Task OpenCreateDialog()
|
|
{
|
|
var dialog = await DialogService.ShowAsync<DockStationConfigDialog>(
|
|
"Create Dock Station Config",
|
|
new DialogParameters { ["Config"] = null },
|
|
new DialogOptions { MaxWidth = MaxWidth.Medium, FullWidth = true });
|
|
|
|
var result = await dialog.Result;
|
|
if (result is not null && !result.Canceled && result.Data is CreateDockStationConfigRequest request)
|
|
{
|
|
try
|
|
{
|
|
await State.CreateConfigAsync(request);
|
|
Snackbar.Add("Dock station config created.", Severity.Success);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Snackbar.Add($"Error: {ex.Message}", Severity.Error);
|
|
}
|
|
}
|
|
}
|
|
|
|
private async Task OpenEditDialog()
|
|
{
|
|
if (State.SelectedConfig is null) return;
|
|
|
|
var dialog = await DialogService.ShowAsync<DockStationConfigDialog>(
|
|
"Edit Dock Station Config",
|
|
new DialogParameters { ["Config"] = State.SelectedConfig },
|
|
new DialogOptions { MaxWidth = MaxWidth.Medium, FullWidth = true });
|
|
|
|
var result = await dialog.Result;
|
|
if (result is not null && !result.Canceled && result.Data is UpdateDockStationConfigRequest request)
|
|
{
|
|
try
|
|
{
|
|
await State.UpdateConfigAsync(State.SelectedConfig.Id, request);
|
|
Snackbar.Add("Dock station config updated.", Severity.Success);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Snackbar.Add($"Error: {ex.Message}", Severity.Error);
|
|
}
|
|
}
|
|
}
|
|
|
|
private async Task OpenDeleteDialog()
|
|
{
|
|
if (State.SelectedConfig is null) return;
|
|
|
|
var confirm = await DialogService.ShowMessageBoxAsync(
|
|
"Confirm Delete",
|
|
$"Are you sure you want to delete dock station config '{State.SelectedConfig.StationId}'?",
|
|
yesText: "Delete", cancelText: "Cancel");
|
|
|
|
if (confirm == true)
|
|
{
|
|
try
|
|
{
|
|
await State.DeleteConfigAsync(State.SelectedConfig.Id);
|
|
Snackbar.Add("Dock station config deleted.", Severity.Success);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Snackbar.Add($"Error: {ex.Message}", Severity.Error);
|
|
}
|
|
}
|
|
}
|
|
}
|