RobotNet/RobotNet.WebApp/Maps/Components/Setting/MapSettingAction.razor
2025-10-15 15:15:53 +07:00

391 lines
16 KiB
Plaintext

@inject IHttpClientFactory HttpClientFactory
@inject ISnackbar Snackbar
@inject IDialogService Dialog
<div class="d-flex flex-row w-100 h-100 overflow-hidden position-relative">
<div class="actions-list">
<MudGrid Class="m-2" Justify="Justify.FlexStart" Style="width: 93%">
@foreach (var action in Actions)
{
<MudItem Class="p-0 w-100">
<MudButton Class="m-1" Variant="Variant.Filled" Color="Color.Info" OnClick="(() => ActionSelectedChanged(action))" Style="text-transform:none">
@action.Name
</MudButton>
</MudItem>
}
</MudGrid>
</div>
<MudDivider Vertical="true" Style="height: 100%; border: 1px solid gray; opacity: 0.7" />
<div class="d-flex flex-grow-1 flex-row">
<div class="d-flex flex-grow-1 m-2 flex-column">
<MudText Typo="Typo.h5">Action: @ActionSelected?.Name</MudText>
<div class="d-flex flex-column m-2">
<MudTextField Class="my-2" T="string" @bind-Value="@VDAActionSelected.ActionId" @bind-Value:after="PreviewAction" Variant="Variant.Outlined" Label="Action Id" Immediate />
<div class="d-flex flex-row my-2">
<MudTextField Class="me-1" T="string" @bind-Value="@VDAActionSelected.ActionType" @bind-Value:after="PreviewAction" Variant="Variant.Outlined" Label="Action Type" Immediate />
<MudSelect Class="ms-1" T="string" @bind-Value="@VDAActionSelected.BlockingType" @bind-Value:after="PreviewAction" Label="Blocking Type" AnchorOrigin="Origin.BottomLeft" Variant="Variant.Outlined">
<MudSelectItem Value="@BlockingType.NONE.ToString()" />
<MudSelectItem Value="@BlockingType.SOFT.ToString()" />
<MudSelectItem Value="@BlockingType.HARD.ToString()" />
</MudSelect>
</div>
<MudTextField Class="my-2" T="string" @bind-Value="@VDAActionSelected.ActionDescription" @bind-Value:after="PreviewAction" Variant="Variant.Outlined" Label="Action Description" Lines="3" MaxLines="3" Immediate />
<div class="d-flex flex-row my-2">
<div class="d-flex flex-column w-50 me-1">
<MudTextField T="string" Label="Key" Variant="Variant.Outlined" @bind-Value=ActionParameter.Key />
<MudTextField T="string" Label="Value" Variant="Variant.Outlined" @bind-Value=ActionParameter.Value />
</div>
<div class="d-flex flex-grow-1 justify-content-left ms-3 align-items-center">
<div>
<MudButton Variant="Variant.Filled" Color="Color.Primary" OnClick="AddParamterClick" Disabled="@(ActionSelected == null)">Add Parameter</MudButton>
</div>
</div>
</div>
<div class="flex-grow-1 my-2 position-relative">
<MudDataGrid T="ActionParameter" Items="@VDAActionSelected.ActionParameters" EditMode="@DataGridEditMode.Cell" ReadOnly="false" Outlined="true"
CommittedItemChanges="@CommittedItemChanges"
Bordered="true" Dense="true" EditTrigger="DataGridEditTrigger.OnRowClick" Elevation="0" FixedHeader="true" Height="41vh">
<ColGroup>
<col style="width: 30px" />
<col style="width: 35%" />
<col style="width: 35%" />
<col />
</ColGroup>
<Columns>
<PropertyColumn Property="x => (Array.IndexOf(VDAActionSelected.ActionParameters, x) + 1)" Title="Nr" Editable="false" Required="false" />
<PropertyColumn Property="x => x.Key" Editable="true" Title="Key" />
<PropertyColumn Property="x => x.Value" Editable="true" Title="Value" />
<TemplateColumn Editable="false">
<CellTemplate>
<div class="d-flex justify-content-end">
<MudIconButton Size="@Size.Small" Icon="@Icons.Material.Outlined.Delete" Color="Color.Secondary" Variant="Variant.Filled" OnClick="(() => DeleteParameter(context.Item))" />
</div>
</CellTemplate>
</TemplateColumn>
</Columns>
</MudDataGrid>
</div>
</div>
</div>
<div class="actions-preview">
<MudPaper Outlined="true" Height="100%" Class="p-2" Style="border: 1px solid black; border-radius: 20px">
<div>
@ActionSelected?.Content
</div>
</MudPaper>
</div>
</div>
<MudOverlay Visible="OverlayVisible" DarkBackground="true" Absolute="true">
<MudProgressCircular Color="Color.Secondary" Indeterminate="true" />
</MudOverlay>
</div>
<MudDialog @bind-Visible="@CreateActionVisible" DefaultFocus="DefaultFocus.FirstChild">
<TitleContent>
<MudText Typo="Typo.h5">Create Action</MudText>
</TitleContent>
<DialogContent>
<MudTextField @bind-Value="ActionCreateModel.Name" T="string" Label="Name" Variant="Variant.Outlined" Required="true" RequiredError="Name is Required!" Validation="@(new Func<string, IEnumerable<string>>(MapEditorHelper.NameValidation))" />
</DialogContent>
<DialogActions>
<MudButton Color="Color.Default" Variant="Variant.Filled" OnClick="(() => CreateActionVisible = false)">Cancel</MudButton>
<MudButton Color="Color.Primary" Variant="Variant.Filled" OnClick="CreateAction" Disabled="string.IsNullOrEmpty(ActionCreateModel.Name)">Create</MudButton>
</DialogActions>
</MudDialog>
@code {
[Parameter, EditorRequired]
public Guid Id { get; set; }
private bool CreateActionVisible = false;
private ActionCreateModel ActionCreateModel = new();
private List<ActionDto> Actions = [];
private ActionDto? ActionSelected = null;
private readonly ActionModel VDAActionSelected = new();
private readonly ActionModel VDAActionSelectedReset = new();
private bool OverlayVisible;
private ActionParameter ActionParameter = new();
private HttpClient Http = default!;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await base.OnAfterRenderAsync(firstRender);
if (!firstRender) return;
Http = HttpClientFactory.CreateClient("MapManagerAPI");
await LoadAction();
StateHasChanged();
}
private async Task LoadAction()
{
OverlayVisible = true;
Actions.Clear();
var result = await Http.GetFromJsonAsync<IEnumerable<ActionDto>>($"api/Actions/{Id}");
if (result is not null && result.Any())
{
Actions.AddRange(result);
ActionSelectedChanged(Actions.First());
}
OverlayVisible = false;
StateHasChanged();
}
private async Task CreateAction()
{
var nameInvalid = MapEditorHelper.NameValidation(ActionCreateModel.Name);
if (nameInvalid.Any())
{
Snackbar.Add(string.Join(';', nameInvalid), Severity.Error);
return;
}
var actionDefault = new ActionModel()
{
ActionId = Guid.NewGuid().ToString(),
ActionType = ActionCreateModel.Name,
ActionDescription = "",
BlockingType = BlockingType.NONE.ToString(),
ActionParameters = [],
};
ActionCreateModel.Content = JsonSerializer.Serialize(actionDefault, JsonOptionExtends.Write);
var result = await (await Http.PostAsJsonAsync<ActionCreateModel>("api/Actions", ActionCreateModel)).Content.ReadFromJsonAsync<MessageResult<ActionDto>>();
if (result == null)
{
Snackbar.Add("Lỗi giao tiếp với hệ thống", Severity.Error);
return;
}
else if (!result.IsSuccess)
{
Snackbar.Add(result.Message, Severity.Error);
return;
}
else if (result.Data is null)
{
Snackbar.Add("Không có dữ liệu trả về", Severity.Error);
return;
}
Actions.Add(result.Data);
if (Actions.Any()) ActionSelectedChanged(Actions.First());
else ActionSelected = new();
Snackbar.Add("Tạo Action thành công", Severity.Success);
CreateActionVisible = false;
StateHasChanged();
}
public async Task DeleteAction()
{
if (ActionSelected is null) return;
var parameters = new DialogParameters<ConfirmDialog>
{
{ x => x.Content, $"Bạn có chắc chắn muốn xóa Action {ActionSelected.Name} đi không?" },
{ x => x.ConfirmText, "Delete" },
{ x => x.Color, Color.Secondary }
};
var ConfirmDelete = await Dialog.ShowAsync<ConfirmDialog>("Xoá Action", parameters);
var result = await ConfirmDelete.Result;
if (result is not null && result.Data is not null && bool.TryParse(result.Data.ToString(), out bool data) && data)
{
var deletResult = await Http.DeleteFromJsonAsync<MessageResult>($"api/Actions/{ActionSelected.Id}");
if (deletResult == null)
{
Snackbar.Add("Lỗi giao tiếp với hệ thống", Severity.Error);
return;
}
else if (!deletResult.IsSuccess)
{
Snackbar.Add(deletResult.Message, Severity.Error);
return;
}
var action = Actions.FirstOrDefault(action => action.Id == ActionSelected.Id);
if (action is not null) Actions.Remove(action);
if (Actions.Any()) ActionSelectedChanged(Actions.First());
else
{
ActionSelected = null;
ActionModel actionNew = new();
SetActionSelectedDto(actionNew);
SetActionSelectedResetDto(actionNew);
}
Snackbar.Add("Xóa Action thành công", Severity.Success);
StateHasChanged();
}
}
private void ActionSelectedChanged(ActionDto action)
{
if (ActionSelected != action)
{
ActionSelected = action;
var vdaAction = JsonSerializer.Deserialize<ActionModel>(ActionSelected.Content, JsonOptionExtends.Read);
if (vdaAction is not null)
{
SetActionSelectedDto(vdaAction);
SetActionSelectedResetDto(vdaAction);
}
StateHasChanged();
}
}
public void ShowCreateAction()
{
ActionCreateModel.MapId = Id;
ActionCreateModel.Content = "";
CreateActionVisible = true;
StateHasChanged();
}
public void Reset()
{
if (ActionSelected is null) return;
SetActionSelectedDto(VDAActionSelectedReset);
PreviewAction();
StateHasChanged();
}
public async Task Save()
{
if (ActionSelected is null) return;
if (!ValidateUpdateData(VDAActionSelectedReset, VDAActionSelected))
{
Snackbar.Add("Không có sự thay đổi", Severity.Warning);
return;
}
ActionSelected.Content = JsonSerializer.Serialize(VDAActionSelected, JsonOptionExtends.Write);
var result = await (await Http.PutAsJsonAsync<ActionDto>("api/Actions", ActionSelected)).Content.ReadFromJsonAsync<MessageResult>();
if (result == null)
{
Snackbar.Add("Lỗi giao tiếp với hệ thống", Severity.Error);
return;
}
else if (!result.IsSuccess)
{
Snackbar.Add(result.Message, Severity.Error);
return;
}
SetActionSelectedResetDto(VDAActionSelected);
Snackbar.Add("Cập nhật thành công", Severity.Success);
StateHasChanged();
}
private void PreviewAction()
{
if (ActionSelected is null) return;
ActionSelected.Content = JsonSerializer.Serialize(VDAActionSelected, JsonOptionExtends.Write);
StateHasChanged();
}
private void SetActionSelectedDto(ActionModel dto)
{
VDAActionSelected.ActionId = dto.ActionId;
VDAActionSelected.ActionType = dto.ActionType;
VDAActionSelected.ActionDescription = dto.ActionDescription;
VDAActionSelected.BlockingType = dto.BlockingType;
List<ActionParameter> actionParameters = [];
foreach (var param in dto.ActionParameters)
{
actionParameters.Add(new() { Value = param.Value, Key = param.Key });
}
VDAActionSelected.ActionParameters = [..actionParameters];
}
private void SetActionSelectedResetDto(ActionModel dto)
{
VDAActionSelectedReset.ActionId = dto.ActionId;
VDAActionSelectedReset.ActionType = dto.ActionType;
VDAActionSelectedReset.ActionDescription = dto.ActionDescription;
VDAActionSelectedReset.BlockingType = dto.BlockingType;
List<ActionParameter> actionParameters = [];
foreach (var param in dto.ActionParameters)
{
actionParameters.Add(new() { Value = param.Value, Key = param.Key });
}
VDAActionSelectedReset.ActionParameters = [.. actionParameters];
}
private bool ValidateUpdateData(ActionModel old, ActionModel update)
{
if (old.ActionId != update.ActionId) return true;
if (old.ActionType != update.ActionType) return true;
if (old.ActionDescription != update.ActionDescription) return true;
if (old.BlockingType != update.BlockingType) return true;
if (old.ActionParameters.Length != update.ActionParameters.Length) return true;
foreach (var param in old.ActionParameters)
{
if (!update.ActionParameters.Any(a => a.Key == param.Key && a.Value == param.Value)) return true;
}
return false;
}
private void AddParamterClick()
{
if (ActionSelected is null) return;
if (string.IsNullOrEmpty(ActionParameter.Key))
{
Snackbar.Add("Key không được để trống", Severity.Warning);
return;
}
if (string.IsNullOrEmpty(ActionParameter.Value))
{
Snackbar.Add("Value không được để trống", Severity.Warning);
return;
}
List<ActionParameter> parameters = [];
if (VDAActionSelected.ActionParameters is not null && VDAActionSelected.ActionParameters.Any()) parameters.AddRange(VDAActionSelected.ActionParameters.ToList());
parameters.Add(new()
{
Key = ActionParameter.Key,
Value = ActionParameter.Value
});
VDAActionSelected.ActionParameters = [.. parameters];
PreviewAction();
ActionParameter.Key = string.Empty;
ActionParameter.Value = string.Empty;
StateHasChanged();
}
private void CommittedItemChanges(ActionParameter item)
{
PreviewAction();
StateHasChanged();
}
private async Task DeleteParameter(ActionParameter item)
{
var parameters = new DialogParameters<ConfirmDialog>
{
{ x => x.Content, "Bạn có chắc chắn muốn xóa paramter đi không?" },
{ x => x.ConfirmText, "Delete" },
{ x => x.Color, Color.Secondary }
};
var ConfirmDelete = await Dialog.ShowAsync<ConfirmDialog>("Xoá Paramter", parameters);
var result = await ConfirmDelete.Result;
if (result is not null && result.Data is not null && bool.TryParse(result.Data.ToString(), out bool data) && data)
{
List<ActionParameter> actionParameters = [];
if (VDAActionSelected.ActionParameters is not null && VDAActionSelected.ActionParameters.Any()) actionParameters.AddRange(VDAActionSelected.ActionParameters.ToList());
if (actionParameters.Any()) actionParameters.Remove(item);
VDAActionSelected.ActionParameters = [.. actionParameters];
PreviewAction();
StateHasChanged();
}
}
}