feat(app): add host, docker, and health check view models
This commit is contained in:
1 parent
2648a9a0a6
commit
419316efef
5 files changed
+229
No files matched your search
@@ -0,0 +1,30 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Vantage.Core.Models;
|
||||
|
||||
namespace Vantage.App.ViewModels;
|
||||
|
||||
public partial class DockerContainerViewModel : ViewModelBase
|
||||
{
|
||||
[ObservableProperty] private DockerContainer container;
|
||||
|
||||
public DockerContainerViewModel(DockerContainer container)
|
||||
{
|
||||
this.container = container;
|
||||
}
|
||||
|
||||
public string Id => Container.Id;
|
||||
public string Name => Container.Name;
|
||||
public string Image => Container.Image;
|
||||
public string StatusText => Container.StatusText;
|
||||
public bool IsRunning => Container.IsRunning;
|
||||
public ContainerState State => Container.State;
|
||||
|
||||
partial void OnContainerChanged(DockerContainer value)
|
||||
{
|
||||
OnPropertyChanged(nameof(Name));
|
||||
OnPropertyChanged(nameof(Image));
|
||||
OnPropertyChanged(nameof(StatusText));
|
||||
OnPropertyChanged(nameof(IsRunning));
|
||||
OnPropertyChanged(nameof(State));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Vantage.Core.Docker;
|
||||
using Vantage.Core.Models;
|
||||
|
||||
namespace Vantage.App.ViewModels;
|
||||
|
||||
public partial class DockerViewModel : ViewModelBase
|
||||
{
|
||||
private readonly IDockerProvider dockerProvider;
|
||||
|
||||
[ObservableProperty] private bool isBusy;
|
||||
[ObservableProperty] private string? lastError;
|
||||
[ObservableProperty] private DockerContainerViewModel? selectedContainer;
|
||||
|
||||
public DockerViewModel(IDockerProvider dockerProvider)
|
||||
{
|
||||
this.dockerProvider = dockerProvider;
|
||||
}
|
||||
|
||||
public ObservableCollection<DockerContainerViewModel> Containers { get; } = new();
|
||||
|
||||
public HostConfig? Host { get; private set; }
|
||||
|
||||
public void SetHost(HostConfig? host)
|
||||
{
|
||||
Host = host;
|
||||
Containers.Clear();
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
public async Task RefreshAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
if (Host is null)
|
||||
return;
|
||||
|
||||
IsBusy = true;
|
||||
LastError = null;
|
||||
try
|
||||
{
|
||||
var containers = await dockerProvider.ListContainersAsync(Host, cancellationToken).ConfigureAwait(false);
|
||||
Containers.Clear();
|
||||
foreach (var container in containers)
|
||||
Containers.Add(new DockerContainerViewModel(container));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LastError = ex.Message;
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsBusy = false;
|
||||
}
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private Task StartAsync(DockerContainerViewModel? container) => ExecuteAsync(DockerAction.Start, container);
|
||||
|
||||
[RelayCommand]
|
||||
private Task StopAsync(DockerContainerViewModel? container) => ExecuteAsync(DockerAction.Stop, container);
|
||||
|
||||
[RelayCommand]
|
||||
private Task RestartAsync(DockerContainerViewModel? container) => ExecuteAsync(DockerAction.Restart, container);
|
||||
|
||||
private async Task ExecuteAsync(DockerAction action, DockerContainerViewModel? container)
|
||||
{
|
||||
if (Host is null || container is null)
|
||||
return;
|
||||
|
||||
IsBusy = true;
|
||||
LastError = null;
|
||||
try
|
||||
{
|
||||
await dockerProvider.ExecuteAsync(Host, action, container.Id, CancellationToken.None).ConfigureAwait(false);
|
||||
await RefreshAsync(CancellationToken.None).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LastError = ex.Message;
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsBusy = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using System.Globalization;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Vantage.Core.Health;
|
||||
using Vantage.Core.Models;
|
||||
|
||||
namespace Vantage.App.ViewModels;
|
||||
|
||||
public partial class HealthCheckViewModel : ViewModelBase
|
||||
{
|
||||
private readonly IHealthChecker checker;
|
||||
|
||||
[ObservableProperty] private HealthStatus status = HealthStatus.Unknown;
|
||||
[ObservableProperty] private string statusText = "Not checked";
|
||||
[ObservableProperty] private string latencyText = "-";
|
||||
[ObservableProperty] private string lastCheckedText = "never";
|
||||
|
||||
public HealthCheckViewModel(HealthCheckConfig config, IHealthChecker checker)
|
||||
{
|
||||
Config = config;
|
||||
this.checker = checker;
|
||||
}
|
||||
|
||||
public HealthCheckConfig Config { get; }
|
||||
|
||||
public string Name => string.IsNullOrWhiteSpace(Config.Name) ? Config.Target : Config.Name;
|
||||
public string Target => Config.Target;
|
||||
public string KindText => Config.Kind.ToString().ToUpperInvariant();
|
||||
|
||||
[RelayCommand]
|
||||
public async Task RunAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var checkResult = await checker.CheckAsync(Config, cancellationToken).ConfigureAwait(false);
|
||||
Status = checkResult.Status;
|
||||
StatusText = checkResult.Status + (string.IsNullOrEmpty(checkResult.Message) ? "" : $" - {checkResult.Message}");
|
||||
LatencyText = checkResult.LatencyMs is { } ms
|
||||
? ms.ToString("0", CultureInfo.InvariantCulture) + " ms"
|
||||
: "-";
|
||||
LastCheckedText = checkResult.CheckedAt.ToLocalTime().ToString("HH:mm:ss", CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Vantage.Core.Metrics;
|
||||
using Vantage.Core.Models;
|
||||
|
||||
namespace Vantage.App.ViewModels;
|
||||
|
||||
public partial class HostViewModel : ViewModelBase
|
||||
{
|
||||
private readonly MetricsHistory cpuHistory;
|
||||
private readonly MetricsHistory memoryHistory;
|
||||
|
||||
[ObservableProperty] private double cpuUsagePercent;
|
||||
[ObservableProperty] private double memoryUsedPercent;
|
||||
[ObservableProperty] private double diskUsedPercent;
|
||||
[ObservableProperty] private string memoryText = "-";
|
||||
[ObservableProperty] private string diskText = "-";
|
||||
[ObservableProperty] private string loadText = "-";
|
||||
[ObservableProperty] private string uptimeText = "-";
|
||||
[ObservableProperty] private string statusText = "Not polled yet";
|
||||
[ObservableProperty] private bool isOnline;
|
||||
[ObservableProperty] private string? lastError;
|
||||
|
||||
public HostViewModel(HostConfig config, int historyLength)
|
||||
{
|
||||
Config = config;
|
||||
cpuHistory = new MetricsHistory(historyLength);
|
||||
memoryHistory = new MetricsHistory(historyLength);
|
||||
}
|
||||
|
||||
public HostConfig Config { get; }
|
||||
|
||||
public string Name => string.IsNullOrWhiteSpace(Config.Name) ? Config.Address : Config.Name;
|
||||
public string Endpoint => $"{Config.Username}@{Config.Address}:{Config.Port}";
|
||||
|
||||
public IReadOnlyList<double> CpuPoints => cpuHistory.Snapshot();
|
||||
public IReadOnlyList<double> MemoryPoints => memoryHistory.Snapshot();
|
||||
|
||||
public void ApplyMetrics(HostMetrics metrics)
|
||||
{
|
||||
CpuUsagePercent = metrics.CpuUsagePercent;
|
||||
MemoryUsedPercent = metrics.MemoryUsedPercent;
|
||||
DiskUsedPercent = metrics.DiskUsedPercent;
|
||||
MemoryText = ValueFormatting.BytesPair(metrics.MemoryUsedBytes, metrics.MemoryTotalBytes);
|
||||
DiskText = ValueFormatting.BytesPair(metrics.DiskUsedBytes, metrics.DiskTotalBytes);
|
||||
LoadText = $"{metrics.Load1:0.00} {metrics.Load5:0.00} {metrics.Load15:0.00}";
|
||||
UptimeText = ValueFormatting.Uptime(metrics.Uptime);
|
||||
|
||||
cpuHistory.Add(metrics.CpuUsagePercent);
|
||||
memoryHistory.Add(metrics.MemoryUsedPercent);
|
||||
OnPropertyChanged(nameof(CpuPoints));
|
||||
OnPropertyChanged(nameof(MemoryPoints));
|
||||
|
||||
IsOnline = true;
|
||||
LastError = null;
|
||||
StatusText = "Online";
|
||||
}
|
||||
|
||||
public void ApplyError(string message)
|
||||
{
|
||||
IsOnline = false;
|
||||
LastError = message;
|
||||
StatusText = "Unreachable";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace Vantage.App.ViewModels;
|
||||
|
||||
public abstract class ViewModelBase : ObservableObject
|
||||
{
|
||||
}
|
||||
Reference in new issue
Block a user