RobotNet/RobotNet.WebApp/Scripts/Components/Dashboards/Missions.razor
2025-10-15 15:15:53 +07:00

260 lines
8.1 KiB
Plaintext

@implements IDisposable
@using Microsoft.AspNetCore.SignalR.Client
@using RobotNet.WebApp.Scripts.Models
@inject IHttpClientFactory httpFactory
@inject IDialogService DialogService
<div class="flex-grow-1 h-100 position-relative overflow-hidden">
<div @ref="divRef" class="w-100 h-100 position-absolute top-0 start-0 overflow-hidden">
<MudTable Style="margin: 10px;" Items="scriptMissions" Height="@TableHeight" FixedHeader Virtualize Hover Elevation="6">
<ToolBarContent>
<div @ref="toolbarRef" class="w-100 d-flex flex-row">
<h3>Danh sách Script Missions</h3>
<MudSpacer />
</div>
</ToolBarContent>
<ColGroup>
<col style="width:60px;" />
<col />
<col />
<col style="width:60px;" />
<col style="width:60px;" />
</ColGroup>
<HeaderContent>
<MudTh>STT</MudTh>
<MudTh>Tên</MudTh>
<MudTh>Parameters</MudTh>
<MudTh>Script</MudTh>
</HeaderContent>
<RowTemplate>
<MudTd>@context.Index</MudTd>
<MudTd DataLabel="Tên">@context.Name</MudTd>
<MudTd DataLabel="Parameters">
<span>
@if (context.Parameters?.Any() == true)
{
<MudIconButton Icon="@Icons.Material.Filled.Info" Color="Color.Primary" Size="Size.Small"
OnClick="@(() => ShowParametersDialog(context))" />
}
else
{
<span>Không có</span>
}
</span>
</MudTd>
<MudTd DataLabel="Script">
<span>
<MudIconButton Icon="@Icons.Material.Filled.Visibility" Color="Color.Primary" Size="Size.Small"
OnClick="@(() => ShowCodeDialog(context.Code))" />
</span>
</MudTd>
<MudTd>
<span>
<MudIconButton Icon="@Icons.Material.Filled.PlayArrow" Color="Color.Success" Size="Size.Small"
Disabled="@CallDisabled" OnClick="@(() => ShowInstantiateMissionDialog(context))" />
</span>
</MudTd>
</RowTemplate>
</MudTable>
</div>
</div>
<MudDialog @bind-Visible="_parametersDialogOpen">
<DialogContent>
<h6>Thông tin Parameters</h6>
@if (_selectedParameters != null)
{
<MudTable Items="_selectedParameters" Style="min-width: 400px;">
<HeaderContent>
<MudTh>Tên</MudTh>
<MudTh>Kiểu</MudTh>
<MudTh>Default</MudTh>
</HeaderContent>
<RowTemplate>
<MudTd>@context.Name</MudTd>
<MudTd>@context.Type</MudTd>
<MudTd>@context.Default</MudTd>
</RowTemplate>
</MudTable>
}
</DialogContent>
<DialogActions>
<MudButton OnClick="CloseParametersDialog">Đóng</MudButton>
</DialogActions>
</MudDialog>
<MudDialog @bind-Visible="_codeDialogOpen" Style="min-width: 900px;">
<DialogContent>
<h6>Mã Script đầy đủ</h6>
<MudPaper Class="pa-2" Style="overflow-x:auto;">
<pre style="white-space:pre-wrap;word-break:break-all;">@_selectedCode</pre>
</MudPaper>
</DialogContent>
<DialogActions>
<MudButton OnClick="CloseCodeDialog">Đóng</MudButton>
</DialogActions>
</MudDialog>
@code {
[CascadingParameter]
private ProcessorHubClient ProcessorHub { get; set; } = null!;
private string TableHeight = "0px";
private ElementReference divRef;
private ElementReference toolbarRef;
private HttpClient http = default!;
private List<ScriptMissionModel> scriptMissions = [];
// Dialog state
private bool _parametersDialogOpen = false;
private IEnumerable<ScriptValueModel>? _selectedParameters;
private bool _codeDialogOpen = false;
private string? _selectedCode;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await base.OnAfterRenderAsync(firstRender);
if (firstRender)
{
var rect = await divRef.MudGetBoundingClientRectAsync();
var toolbarRect = await toolbarRef.MudGetBoundingClientRectAsync();
TableHeight = $"{rect.Height - 25 - Math.Max(toolbarRect.Height, 64)}px";
StateHasChanged();
}
}
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
http = httpFactory.CreateClient("ScriptManagerAPI");
await ReloadData();
if (ProcessorHub.IsConnected)
{
OnProcessorStateChanged(await ProcessorHub.GetState());
}
ProcessorHub.StateChanged += OnProcessorStateChanged;
ProcessorHub.ConnectionStateChanged += OnConnectionStateChanged;
}
private void OnConnectionStateChanged(HubConnectionState state)
{
if (state == HubConnectionState.Connected)
{
_ = InvokeAsync(async Task () =>
{
OnProcessorStateChanged(await ProcessorHub.GetState());
});
}
}
private bool isRebuild = false;
private bool CallDisabled = true;
private void OnProcessorStateChanged(ProcessorState state)
{
if (state == ProcessorState.Building)
{
isRebuild = true;
}
else if (state == ProcessorState.Ready)
{
if (isRebuild)
{
isRebuild = false;
_ = InvokeAsync(async Task () =>
{
await ReloadData();
});
}
}
if (CallDisabled)
{
if (state == ProcessorState.Running)
{
CallDisabled = false;
StateHasChanged();
}
}
else
{
if (state != ProcessorState.Running)
{
CallDisabled = true;
StateHasChanged();
}
}
}
private async Task ReloadData()
{
scriptMissions.Clear();
var missions = await http.GetFromJsonAsync<List<ScriptMissionDto>>("/api/ScriptMissions") ?? [];
foreach (var item in missions.Select((value, index) => (value, index)))
{
scriptMissions.Add(new ScriptMissionModel(item.index + 1, item.value));
}
StateHasChanged();
}
private void ShowParametersDialog(ScriptMissionModel model)
{
_selectedParameters = model.Parameters;
_parametersDialogOpen = true;
StateHasChanged();
}
private void CloseParametersDialog()
{
_parametersDialogOpen = false;
_selectedParameters = null;
StateHasChanged();
}
private void ShowCodeDialog(string code)
{
_selectedCode = code;
_codeDialogOpen = true;
StateHasChanged();
}
private void CloseCodeDialog()
{
_codeDialogOpen = false;
_selectedCode = null;
StateHasChanged();
}
private async Task ShowInstantiateMissionDialog(ScriptMissionModel model)
{
if (CallDisabled) return;
foreach (var parameter in model.Parameters)
{
parameter.Reset();
}
;
var parameters = new DialogParameters<InstantiateMissionDialog>()
{
{x => x.Model, model},
};
var dialog = await DialogService.ShowAsync<InstantiateMissionDialog>("Instantiate new mission", parameters);
var resultDialog = await dialog.Result;
}
public void Dispose()
{
ProcessorHub.StateChanged -= OnProcessorStateChanged;
ProcessorHub.ConnectionStateChanged -= OnConnectionStateChanged;
}
}