DEEP-41 Minor UI tweaks

This commit is contained in:
Andrey Shabarshov 2023-08-19 10:14:17 +01:00
parent b9f9c6fca3
commit d8783e2959
5 changed files with 69 additions and 38 deletions

View File

@ -19,20 +19,23 @@
<MudCard Class="card mb-3"> <MudCard Class="card mb-3">
<MudCardHeader> <MudCardHeader>
<CardHeaderAvatar>
<MudAvatar Color="MudBlazor.Color.Secondary">@Model?.Name[..1].ToUpper()</MudAvatar>
</CardHeaderAvatar>
<CardHeaderContent> <CardHeaderContent>
<MudText Typo="Typo.h6">@Model?.Name</MudText> <MudText Typo="Typo.body1">@Model?.Name</MudText>
</CardHeaderContent> </CardHeaderContent>
<CardHeaderActions> <CardHeaderActions>
<MudSwitch @bind-Checked="IsEnabled"> @Model?.IsEnabled</MudSwitch> <MudSwitch @bind-Checked="IsEnabled"> @(IsEnabled ? "On" : "Off")</MudSwitch>
</CardHeaderActions> </CardHeaderActions>
</MudCardHeader> </MudCardHeader>
<MudCardContent> <MudCardContent>
<MudText>Current state: @_prediction.PredictedLabel</MudText> <MudText Class="@TextStyle">Current state: @_prediction.PredictedLabel</MudText>
<MudText>@_updated.ToString("HH:mm:ss")</MudText> <MudText Class="@TextStyle">@_updated.ToString("HH:mm:ss")</MudText>
</MudCardContent> </MudCardContent>
</MudCard> </MudCard>
@code{ @code{
[Parameter] [Parameter]
public TrainedModelDefinition? Model { get; set; } public TrainedModelDefinition? Model { get; set; }
@ -41,6 +44,8 @@
private IMLProcessor? _mlProcessor; private IMLProcessor? _mlProcessor;
private DateTime _updated = DateTime.MinValue; private DateTime _updated = DateTime.MinValue;
private string TextStyle => IsEnabled ? "mud-secondary-text" : "";
protected override async Task OnAfterRenderAsync(bool firstRender) protected override async Task OnAfterRenderAsync(bool firstRender)
{ {
if (!firstRender || Model?.Id == null) if (!firstRender || Model?.Id == null)
@ -66,6 +71,7 @@
} }
Model.IsEnabled = value; Model.IsEnabled = value;
InvokeAsync(SaveIsEnabled); InvokeAsync(SaveIsEnabled);
InvokeAsync(StateHasChanged);
} }
} }

View File

@ -44,12 +44,17 @@
await base.OnInitializedAsync(); await base.OnInitializedAsync();
} }
//protected override async Task OnAfterRenderAsync(bool firstRender) private bool _rendered = false;
//{
// if (firstRender) protected override async Task OnAfterRenderAsync(bool firstRender)
// await UpdateChart(); {
// base.OnAfterRender(firstRender); if (firstRender)
//} {
_rendered = true;
await UpdateChart();
}
base.OnAfterRender(firstRender);
}
protected override async Task OnParametersSetAsync() protected override async Task OnParametersSetAsync()
{ {
@ -73,9 +78,9 @@
return; return;
//await InvokeAsync(StateHasChanged); //await InvokeAsync(StateHasChanged);
if (_currentData.Series.Count > 0) if (_currentData.Series.Count > 0 && _rendered)
{ {
await _chart.UpdateSeriesAsync(); await InvokeAsync( async () => await _chart.UpdateSeriesAsync() );
await _chart.UpdateOptionsAsync(true, true, true); await _chart.UpdateOptionsAsync(true, true, true);
} }
await InvokeAsync(StateHasChanged); await InvokeAsync(StateHasChanged);

View File

@ -5,32 +5,33 @@
@inject ITrainedModelStorageService TrainedModelService @inject ITrainedModelStorageService TrainedModelService
<PageTitle>Index</PageTitle> <PageTitle>DeepTrace</PageTitle>
<h1>Hello, world!</h1> <h1>Dashboard</h1>
Welcome to your new app.
@if (_trainedModels != null) @if (_trainedModels != null)
{ {
@foreach(TrainedModelDefinition model in _trainedModels) @foreach(TrainedModelDefinition model in _trainedModels)
{ {
<ModelCard Model="@model"/> <ModelCard Model="@model"/>
}
} }
} else else
{ {
<MudText>Nothing to display</MudText> <MudText>Nothing to display. Train AI models first!</MudText>
} }
@code{ @code
private List<TrainedModelDefinition> _trainedModels = new();
protected override async Task OnInitializedAsync()
{ {
private List<TrainedModelDefinition> _trainedModels = new();
protected override async Task OnInitializedAsync()
{
base.OnInitialized(); base.OnInitialized();
_trainedModels = await TrainedModelService.Load(); _trainedModels = await TrainedModelService.Load();
} }
} }

View File

@ -9,6 +9,7 @@
@using PrometheusAPI; @using PrometheusAPI;
@using System.Text; @using System.Text;
@using System.Globalization; @using System.Globalization;
@using System.Collections.Concurrent;
@inject PrometheusClient Prometheus @inject PrometheusClient Prometheus
@inject IDialogService DialogService @inject IDialogService DialogService
@ -271,13 +272,17 @@
var startDate = MinDate ?? (DateTime.UtcNow - TimeSpan.FromDays(30)); var startDate = MinDate ?? (DateTime.UtcNow - TimeSpan.FromDays(30));
var endDate = MaxDate ?? DateTime.UtcNow; var endDate = MaxDate ?? DateTime.UtcNow;
var reported = new ConcurrentDictionary<string, bool>();
await UpdateDisplayData(startDate, endDate); await UpdateDisplayData(startDate, endDate, reported);
await InvokeAsync(StateHasChanged); await InvokeAsync(StateHasChanged);
} }
private async Task UpdateDisplayData(DateTime startDate, DateTime endDate) private async Task UpdateDisplayData(
DateTime startDate,
DateTime endDate,
ConcurrentDictionary<string, bool> reported
)
{ {
// use automatic step value to always request 500 elements // use automatic step value to always request 500 elements
@ -306,20 +311,26 @@
{ {
if (res.Status != StatusType.Success) if (res.Status != StatusType.Success)
{ {
await ShowError(res.Error ?? "Error"); var msg = res.Error ?? "Error";
if ( reported.TryAdd(msg, true))
await ShowError(msg);
return; return;
} }
if (res.ResultType != ResultTypeType.Matrix) if (res.ResultType != ResultTypeType.Matrix)
{ {
await ShowError($"Got {res.ResultType}, but Matrix expected for {def.Query}"); var msg = $"Got {res.ResultType}, but Matrix expected for {def.Query}";
if (reported.TryAdd(msg, true))
await ShowError(msg);
return; return;
} }
var m = res.AsMatrix().Result; var m = res.AsMatrix().Result;
if (m == null || m.Length != 1) if (m == null || m.Length != 1)
{ {
await ShowError($"No data returned for {def.Query}"); var msg = $"No data returned for {def.Query}";
if (reported.TryAdd(msg, true))
await ShowError(msg);
return; return;
} }
@ -391,8 +402,13 @@
if(element is IntervalDefinition interval) if(element is IntervalDefinition interval)
{ {
_nameBackUp = interval.Name; _nameBackUp = interval.Name;
var reported = new ConcurrentDictionary<string, bool>();
InvokeAsync( async () =>
{
await UpdateDisplayData(interval.From, interval.To, reported);
await InvokeAsync(StateHasChanged);
});
} }
} }
private void ResetItemToOriginalValues(object element) private void ResetItemToOriginalValues(object element)
@ -414,10 +430,10 @@
return; return;
var previousIntervals = _modelForm!.CurrentModel.IntervalDefinitionList; var previousIntervals = _modelForm!.CurrentModel.IntervalDefinitionList;
var reported = new ConcurrentDictionary<string, bool>();
foreach(var currentInterval in previousIntervals) foreach(var currentInterval in previousIntervals)
{ {
await UpdateDisplayData(currentInterval.From,currentInterval.To); await UpdateDisplayData(currentInterval.From,currentInterval.To, reported);
currentInterval.Data = DisplayData!.Series; currentInterval.Data = DisplayData!.Series;
} }
await ModelService.Store(_modelForm!.CurrentModel); await ModelService.Store(_modelForm!.CurrentModel);

View File

@ -16,6 +16,9 @@
</MudAppBar> </MudAppBar>
<MudDrawer @bind-Open="_drawerOpen" ClipMode="DrawerClipMode.Always" Elevation="2"> <MudDrawer @bind-Open="_drawerOpen" ClipMode="DrawerClipMode.Always" Elevation="2">
<NavMenu /> <NavMenu />
<div class="d-flex justify-left align-end mud-height-full">
<MudSwitch @bind-Checked="@IsDarkMode" Color="MudBlazor.Color.Primary" Class="ma-4" T="bool" Label="Dark Mode" />
</div>
</MudDrawer> </MudDrawer>
<MudMainContent> <MudMainContent>
<CascadingValue Value="@IsDarkMode"> <CascadingValue Value="@IsDarkMode">