RobotApp/RobotApp.Client/Pages/Order/NodesPanel.razor
2025-12-21 16:32:06 +07:00

276 lines
14 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<MudPaper Class="pa-4 h-100 d-flex flex-column" Elevation="2">
<MudStack Row AlignItems="AlignItems.Center" Justify="Justify.SpaceBetween" Class="mb-4 flex-shrink-0">
<MudText Typo="Typo.h6">📍 Nodes</MudText>
<MudButton Variant="Variant.Filled"
Color="Color.Primary"
StartIcon="@Icons.Material.Filled.Add"
OnClick="AddNodeAsync">
Add Node
</MudButton>
</MudStack>
<div class="flex-grow-1" style="overflow:auto;">
<MudExpansionPanels MultiExpansion>
@foreach (var node in Order.Nodes)
{
<MudExpansionPanel @key="node.NodeId">
<TitleContent>
<div class="d-flex align-center justify-space-between w-100">
<MudText Typo="Typo.subtitle1" Class="fw-bold">@node.NodeId</MudText>
<div>
<MudIconButton Icon="@Icons.Material.Filled.Edit"
Color="Color.Primary"
Size="Size.Small"
OnClick="@(() => EditNodeAsync(node))"
StopPropagation />
<MudIconButton Icon="@Icons.Material.Filled.Delete"
Color="Color.Error"
Size="Size.Small"
OnClick="@(() => RemoveNodeAsync(node))"
StopPropagation />
</div>
</div>
</TitleContent>
<ChildContent>
<MudGrid Spacing="3">
<!-- Node ID -->
<MudItem xs="12">
<MudTextField Value="@node.NodeId"
ValueChanged="@((string v) => SetValue(() => node.NodeId = v))"
Immediate="true"
Label="Node ID" />
</MudItem>
<!-- Sequence -->
<MudItem xs="12">
<MudNumericField T="int"
Value="@node.SequenceId"
ValueChanged="@((int v) => SetValue(() => node.SequenceId = v))"
Immediate="true"
Label="Sequence ID" />
</MudItem>
<!-- Released -->
<MudItem xs="12">
<MudSwitch T="bool"
Checked="@node.Released"
CheckedChanged="@((bool v) => SetValue(() => node.Released = v))"
Label="Released" />
</MudItem>
<!-- Position -->
<MudItem xs="6">
<MudNumericField T="double"
Value="@node.NodePosition.X"
ValueChanged="@((double v) => SetValue(() => node.NodePosition.X = v))"
Immediate="true"
Label="X" />
</MudItem>
<MudItem xs="6">
<MudNumericField T="double"
Value="@node.NodePosition.Y"
ValueChanged="@((double v) => SetValue(() => node.NodePosition.Y = v))"
Immediate="true"
Label="Y" />
</MudItem>
<MudItem xs="12">
<MudTextField Value="@node.NodePosition.MapId"
ValueChanged="@((string v) => SetValue(() => node.NodePosition.MapId = v))"
Immediate="true"
Label="Map ID" />
</MudItem>
<MudItem xs="6">
<MudNumericField T="double"
Value="@node.NodePosition.Theta"
ValueChanged="@((double v) => SetValue(() => node.NodePosition.Theta = v))"
Immediate="true"
Label="Theta (rad)" />
</MudItem>
<MudItem xs="6">
<MudNumericField T="double"
Value="@node.NodePosition.AllowedDeviationXY"
ValueChanged="@((double v) => SetValue(() => node.NodePosition.AllowedDeviationXY = v))"
Immediate="true"
Label="Allowed Dev XY" />
</MudItem>
<MudItem xs="6">
<MudNumericField T="double"
Value="@node.NodePosition.AllowedDeviationTheta"
ValueChanged="@((double v) => SetValue(() => node.NodePosition.AllowedDeviationTheta = v))"
Immediate="true"
Label="Allowed Dev Theta" />
</MudItem>
<!-- Actions -->
<MudItem xs="12">
<MudDivider Class="my-4" />
<MudText Typo="Typo.subtitle1" Class="mb-3">Actions</MudText>
@foreach (var act in node.Actions ?? Array.Empty<VDA5050.InstantAction.Action>())
{
<MudPaper Class="pa-3 mb-3" Outlined>
<MudGrid Spacing="3">
<MudItem xs="12">
<MudSelect T="string"
Value="@act.ActionType"
ValueChanged="@((string v) => SetValue(() => act.ActionType = v))"
Dense
Label="Action Type">
@foreach (var at in Enum.GetValues<ActionType>())
{
<MudSelectItem Value="@at.ToString()">@at</MudSelectItem>
}
</MudSelect>
</MudItem>
<MudItem xs="12">
<MudSelect T="string"
Value="@act.BlockingType"
ValueChanged="@((string v) => SetValue(() => act.BlockingType = v))"
Label="Blocking Type">
<MudSelectItem Value="@("NONE")">NONE</MudSelectItem>
<MudSelectItem Value="@("SOFT")">SOFT</MudSelectItem>
<MudSelectItem Value="@("HARD")">HARD</MudSelectItem>
</MudSelect>
</MudItem>
<MudItem xs="12">
<MudTextField Value="@act.ActionId"
ValueChanged="@((string v) => SetValue(() => act.ActionId = v))"
Immediate="true"
Label="Action ID" />
</MudItem>
</MudGrid>
<MudText Typo="Typo.caption" Class="mt-3 mb-2">Action Parameters</MudText>
@foreach (var p in act.ActionParameters.Cast<UiActionParameter>())
{
<MudGrid Class="mt-1">
<MudItem xs="6">
<MudTextField Value="@p.Key"
ValueChanged="@((string v) => SetValue(() => p.Key = v))"
Immediate="true"
Label="Key" />
</MudItem>
<MudItem xs="6">
<MudTextField Value="@p.ValueString"
ValueChanged="@((string v) => SetValue(() => p.ValueString = v))"
Immediate="true"
Label="Value" />
</MudItem>
<MudItem xs="2">
<MudIconButton Icon="@Icons.Material.Filled.Delete"
Color="Color.Error"
OnClick="@(() => RemoveActionParameterAsync(act, p))" />
</MudItem>
</MudGrid>
}
<MudButton Size="Size.Small"
StartIcon="@Icons.Material.Filled.Add"
Class="mt-3"
OnClick="@(() => AddActionParameterAsync(act))">
Add Parameter
</MudButton>
<MudDivider Class="my-3" />
<MudButton Size="Size.Small"
Color="Color.Error"
Variant="Variant.Text"
StartIcon="@Icons.Material.Filled.Delete"
OnClick="@(() => RemoveActionAsync(node, act))">
Remove Action
</MudButton>
</MudPaper>
}
<MudButton Size="Size.Small"
StartIcon="@Icons.Material.Filled.Add"
OnClick="@(() => AddActionAsync(node))">
Add Action
</MudButton>
</MudItem>
</MudGrid>
</ChildContent>
</MudExpansionPanel>
}
</MudExpansionPanels>
</div>
</MudPaper>
@code {
[Parameter] public OrderMessage Order { get; set; } = default!;
[Parameter] public EventCallback OnAddNode { get; set; }
[Parameter] public EventCallback<Node> OnRemoveNode { get; set; }
[Parameter] public EventCallback<Node> OnEditNode { get; set; }
[Parameter] public EventCallback<Node> OnAddAction { get; set; }
[Parameter] public EventCallback<NodeActionWrapper> OnRemoveAction { get; set; }
[Parameter] public EventCallback<VDA5050.InstantAction.Action> OnAddActionParameter { get; set; }
[Parameter] public EventCallback<ActionParamWrapper> OnRemoveActionParameter { get; set; }
[Parameter] public EventCallback OnOrderChanged { get; set; }
// 🔥 helper realtime KHÔNG ambiguous
private async Task SetValue(System.Action setter)
{
setter();
await OnOrderChanged.InvokeAsync();
}
private async Task AddNodeAsync()
{
await OnAddNode.InvokeAsync();
await OnOrderChanged.InvokeAsync();
}
private async Task RemoveNodeAsync(Node node)
{
await OnRemoveNode.InvokeAsync(node);
await OnOrderChanged.InvokeAsync();
}
private async Task EditNodeAsync(Node node)
{
await OnEditNode.InvokeAsync(node);
await OnOrderChanged.InvokeAsync();
}
private async Task AddActionAsync(Node node)
{
await OnAddAction.InvokeAsync(node);
await OnOrderChanged.InvokeAsync();
}
private async Task RemoveActionAsync(Node node, VDA5050.InstantAction.Action action)
{
await OnRemoveAction.InvokeAsync(new NodeActionWrapper(node, action));
await OnOrderChanged.InvokeAsync();
}
private async Task AddActionParameterAsync(VDA5050.InstantAction.Action act)
{
await OnAddActionParameter.InvokeAsync(act);
await OnOrderChanged.InvokeAsync();
}
private async Task RemoveActionParameterAsync(VDA5050.InstantAction.Action act, ActionParameter param)
{
await OnRemoveActionParameter.InvokeAsync(new ActionParamWrapper(act, param));
await OnOrderChanged.InvokeAsync();
}
public record NodeActionWrapper(Node Node, VDA5050.InstantAction.Action Action);
public record ActionParamWrapper(VDA5050.InstantAction.Action Action, ActionParameter Parameter);
}