feat: Implement Authentik group synchronization and add confirmation dialogs for service management
This commit is contained in:
@@ -2,6 +2,7 @@ using System.Collections.ObjectModel;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using OTSSignsOrchestrator.Core.Models.DTOs;
|
||||
using OTSSignsOrchestrator.Core.Models.Entities;
|
||||
using OTSSignsOrchestrator.Core.Services;
|
||||
using OTSSignsOrchestrator.Desktop.Models;
|
||||
@@ -49,7 +50,15 @@ public partial class InstanceDetailsViewModel : ObservableObject
|
||||
[ObservableProperty] private bool _isPendingSetup;
|
||||
[ObservableProperty] private string _initClientId = string.Empty;
|
||||
[ObservableProperty] private string _initClientSecret = string.Empty;
|
||||
// ── Services (for restart) ─────────────────────────────────────────────────────
|
||||
[ObservableProperty] private ObservableCollection<ServiceInfo> _stackServices = new();
|
||||
[ObservableProperty] private bool _isLoadingServices;
|
||||
|
||||
/// <summary>
|
||||
/// Callback the View wires up to show a confirmation dialog.
|
||||
/// Parameters: (title, message) → returns true if the user confirmed.
|
||||
/// </summary>
|
||||
public Func<string, string, Task<bool>>? ConfirmAsync { get; set; }
|
||||
// Cached instance — needed by InitializeCommand to reload after setup
|
||||
private LiveStackItem? _currentInstance;
|
||||
public InstanceDetailsViewModel(IServiceProvider services)
|
||||
@@ -111,6 +120,9 @@ public partial class InstanceDetailsViewModel : ObservableObject
|
||||
InitClientId = string.Empty;
|
||||
InitClientSecret = string.Empty;
|
||||
}
|
||||
|
||||
// ── Load stack services ───────────────────────────────────────
|
||||
await LoadServicesAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -213,6 +225,64 @@ public partial class InstanceDetailsViewModel : ObservableObject
|
||||
// Rotation
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
|
||||
[RelayCommand]
|
||||
private async Task RestartServiceAsync(ServiceInfo? service)
|
||||
{
|
||||
if (service is null || _currentInstance is null) return;
|
||||
|
||||
if (ConfirmAsync is not null)
|
||||
{
|
||||
var confirmed = await ConfirmAsync(
|
||||
"Restart Service",
|
||||
$"Are you sure you want to restart '{service.Name}'?\n\nThis will force-update the service, causing its tasks to be recreated.");
|
||||
if (!confirmed) return;
|
||||
}
|
||||
|
||||
IsBusy = true;
|
||||
StatusMessage = $"Restarting service '{service.Name}'...";
|
||||
try
|
||||
{
|
||||
var dockerCli = _services.GetRequiredService<SshDockerCliService>();
|
||||
var ok = await dockerCli.ForceUpdateServiceAsync(service.Name);
|
||||
StatusMessage = ok
|
||||
? $"Service '{service.Name}' restarted successfully."
|
||||
: $"Failed to restart service '{service.Name}'.";
|
||||
|
||||
// Refresh service list to show updated replica status
|
||||
await LoadServicesAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
StatusMessage = $"Error restarting service: {ex.Message}";
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsBusy = false;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task LoadServicesAsync()
|
||||
{
|
||||
if (_currentInstance is null) return;
|
||||
|
||||
IsLoadingServices = true;
|
||||
try
|
||||
{
|
||||
var dockerCli = _services.GetRequiredService<SshDockerCliService>();
|
||||
dockerCli.SetHost(_currentInstance.Host);
|
||||
var services = await dockerCli.InspectStackServicesAsync(_currentInstance.StackName);
|
||||
StackServices = new ObservableCollection<ServiceInfo>(services);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
StatusMessage = $"Error loading services: {ex.Message}";
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsLoadingServices = false;
|
||||
}
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task RotateAdminPasswordAsync()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user