277 lines
14 KiB
Plaintext
277 lines
14 KiB
Plaintext
<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);
|
||
}
|