@page "/robot-config" @rendermode InteractiveWebAssemblyNoPrerender @attribute [Authorize] @inject HttpClient Http @inject ISnackbar Snackbar @using System.Net.Http.Json @using RobotApp.Common.Shares.Dtos Robot Configuration
@switch (SelectedType) { case RobotConfigType.VDA5050: @RenderList(VdaConfigs, SelectVda, v => v.ConfigName, v => v.IsActive) break; case RobotConfigType.Safety: @RenderList(SafetyConfigs, SelectSafety, s => s.ConfigName, s => s.IsActive) break; case RobotConfigType.Simulation: @RenderList(SimulationConfigs, SelectSimulation, s => s.ConfigName, s => s.IsActive) break; case RobotConfigType.PLC: @RenderList(PlcConfigs, SelectPlc, p => p.ConfigName, p => p.IsActive) break; case RobotConfigType.Core: @RenderList(CoreConfigs, SelectCore, c => c.ConfigName, c => c.IsActive) break; default:
No configs.
break; }
@if (!HasSelection) {
Select a config from the list or click Add to create one.
} else { @switch (SelectedType) { case RobotConfigType.VDA5050: break; case RobotConfigType.Safety: break; case RobotConfigType.Simulation: break; case RobotConfigType.PLC: break; case RobotConfigType.Core: break; } }
@if (IsLoading) {
Loading…
} @if (IsAddingNew) { } @if (ShowDeleteConfirm) { }
@code { private List VdaConfigs { get; set; } = new(); private List SafetyConfigs { get; set; } = new(); private List SimulationConfigs { get; set; } = new(); private List PlcConfigs { get; set; } = new(); private List CoreConfigs { get; set; } = new(); private RobotVDA5050ConfigDto? SelectedVda { get; set; } private RobotSafetyConfigDto? SelectedSafety { get; set; } private RobotSimulationConfigDto? SelectedSimulation { get; set; } private RobotPlcConfigDto? SelectedPlc { get; set; } private RobotConfigDto? SelectedCore { get; set; } private CreateRobotVDA5050ConfigDto CreateVda = new(); private CreateRobotConfigDto CreateSafety = new(); private CreateRobotSafetyConfigDto CreateSimulation = new(); private CreateRobotSimulationConfigDto CreatePlc = new(); private CreateRobotPlcConfigDto CreateCore = new(); private RobotConfigType SelectedType = RobotConfigType.VDA5050; private int SelectedIndex = -1; private bool HasSelection => SelectedIndex >= 0; private bool IsLoading = false; private bool IsAddingNew = false; private bool ShowDeleteConfirm = false; private Guid? DeletePendingId; private string DeletePendingName = string.Empty; private class AddFormModel { public string ConfigName { get; set; } = string.Empty; public string Description { get; set; } = string.Empty; } private AddFormModel addForm = new(); private string SelectedTemplateIdString = string.Empty; private IEnumerable<(Guid Id, string Name, bool Active)> GetTemplatesForSelectedType() { return SelectedType switch { RobotConfigType.VDA5050 => VdaConfigs.Select(x => (x.Id, x.ConfigName ?? string.Empty, x.IsActive)), RobotConfigType.Safety => SafetyConfigs.Select(x => (x.Id, x.ConfigName ?? string.Empty, x.IsActive)), RobotConfigType.Simulation => SimulationConfigs.Select(x => (x.Id, x.ConfigName ?? string.Empty, x.IsActive)), RobotConfigType.PLC => PlcConfigs.Select(x => (x.Id, x.ConfigName ?? string.Empty, x.IsActive)), RobotConfigType.Core => CoreConfigs.Select(x => (x.Id, x.ConfigName ?? string.Empty, x.IsActive)), _ => [], }; } protected override async Task OnAfterRenderAsync(bool firstRender) { await base.OnAfterRenderAsync(firstRender); if (!firstRender) return; await LoadForTypeAsync(SelectedType); } private async Task OnTypeChanged(ChangeEventArgs e) { if (e?.Value is null) return; if (!Enum.TryParse(e.Value.ToString(), out var newType)) return; if (newType == SelectedType) return; SelectedType = newType; await LoadForTypeAsync(newType); } private async Task LoadForTypeAsync(RobotConfigType type) { IsLoading = true; StateHasChanged(); try { switch (type) { case RobotConfigType.VDA5050: await LoadVDA5050Configs(); break; case RobotConfigType.Safety: await LoadRobotSafetyConfigs(); break; case RobotConfigType.Simulation: await LoadRobotSimulationConfigs(); break; case RobotConfigType.PLC: await LoadRobotPlcConfigs(); break; case RobotConfigType.Core: await LoadRobotConfigs(); break; } } finally { IsLoading = false; StateHasChanged(); } } RenderFragment RenderList(List list, Action onSelect, Func nameSelector, Func? isActiveSelector = null) where T : class { return builder => { if (list is null || !list.Any()) { builder.OpenElement(0, "div"); builder.AddAttribute(1, "class", "p-2 text-muted"); builder.AddContent(2, "No configs found."); builder.CloseElement(); return; } builder.OpenElement(3, "ul"); builder.AddAttribute(4, "class", "list-group list-group-flush"); for (int i = 0; i < list.Count; i++) { var item = list[i]; var idx = i; builder.OpenElement(10 + i * 6, "li"); builder.AddAttribute(11 + i * 6, "class", $"list-group-item {(SelectedIndex == idx ? "active" : "")}"); builder.AddAttribute(12 + i * 6, "style", "cursor:pointer;padding:0.75rem 1rem;"); builder.AddAttribute(13 + i * 6, "onclick", EventCallback.Factory.Create(this, () => onSelect(idx))); string name; try { name = nameSelector(item) ?? "Unnamed"; } catch { name = "Unnamed"; } builder.AddContent(14 + i * 6, name); bool isActive = false; if (isActiveSelector is not null) { try { isActive = isActiveSelector(item); } catch { isActive = false; } } if (isActive) { builder.OpenElement(15 + i * 6, "span"); builder.AddAttribute(16 + i * 6, "class", "badge bg-success ms-2 float-end"); builder.AddContent(17 + i * 6, "Active"); builder.CloseElement(); } builder.CloseElement(); } builder.CloseElement(); }; } private Action SelectVda => idx => { SelectedIndex = idx; SelectedVda = idx >= 0 && idx < VdaConfigs.Count ? VdaConfigs[idx] with { } : null; StateHasChanged(); }; private Action SelectSafety => idx => { SelectedIndex = idx; SelectedSafety = idx >= 0 && idx < SafetyConfigs.Count ? SafetyConfigs[idx] with { } : null; StateHasChanged(); }; private Action SelectSimulation => idx => { SelectedIndex = idx; SelectedSimulation = idx >= 0 && idx < SimulationConfigs.Count ? SimulationConfigs[idx] with { } : null; StateHasChanged(); }; private Action SelectPlc => idx => { SelectedIndex = idx; SelectedPlc = idx >= 0 && idx < PlcConfigs.Count ? PlcConfigs[idx] with { } : null; StateHasChanged(); }; private Action SelectCore => idx => { SelectedIndex = idx; SelectedCore = idx >= 0 && idx < CoreConfigs.Count ? CoreConfigs[idx] with { } : null; StateHasChanged(); }; private void OpenAddConfig() { addForm = new AddFormModel(); var model = GetTemplatesForSelectedType(); var modelActive = model.Where(x => x.Active).ToList(); SelectedTemplateIdString = modelActive.Count > 0 ? modelActive.First().Id.ToString() : model.Any() ? model.First().Id.ToString() : string.Empty; IsAddingNew = true; } private void CloseAddDialog() { IsAddingNew = false; } private void DeleteConfig() { var tuple = SelectedType switch { RobotConfigType.VDA5050 => (Id: SelectedVda?.Id, Name: SelectedVda?.ConfigName), RobotConfigType.Safety => (Id: SelectedSafety?.Id, Name: SelectedSafety?.ConfigName), RobotConfigType.Simulation => (Id: SelectedSimulation?.Id, Name: SelectedSimulation?.ConfigName), RobotConfigType.PLC => (Id: SelectedPlc?.Id, Name: SelectedPlc?.ConfigName), RobotConfigType.Core => (Id: SelectedCore?.Id, Name: SelectedCore?.ConfigName), _ => (Id: (Guid?)null, Name: (string?)null) }; if (tuple.Id is null || tuple.Id == Guid.Empty) { Snackbar.Add("No config selected to delete.", Severity.Warning); return; } DeletePendingId = tuple.Id; DeletePendingName = tuple.Name ?? string.Empty; ShowDeleteConfirm = true; } private void CancelDelete() { ShowDeleteConfirm = false; DeletePendingId = null; DeletePendingName = string.Empty; } }