feat(ui): Settings-Tab fuer die Ticketsystem-Anbindung
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
using ClaudeDo.Ui.Localization;
|
||||
using ClaudeDo.Ui.Services;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
|
||||
namespace ClaudeDo.Ui.ViewModels.Modals.Settings;
|
||||
|
||||
public sealed partial class TicketSettingsTabViewModel : ViewModelBase
|
||||
{
|
||||
private readonly IWorkerClient _worker;
|
||||
|
||||
[ObservableProperty] private string _apiBaseUrl = "";
|
||||
[ObservableProperty] private string _token = "";
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedFor(nameof(TokenPlaceholder))]
|
||||
private bool _tokenSet;
|
||||
[ObservableProperty] private bool _isBusy;
|
||||
[ObservableProperty] private string _statusMessage = "";
|
||||
|
||||
// Never shows the stored token — TicketSettingsDto only ever carries the bool.
|
||||
public string TokenPlaceholder => TokenSet ? Loc.T("settings.tickets.tokenSet") : "";
|
||||
|
||||
public TicketSettingsTabViewModel(IWorkerClient worker) => _worker = worker;
|
||||
|
||||
public async Task LoadAsync()
|
||||
{
|
||||
var dto = await _worker.GetTicketSettingsAsync();
|
||||
if (dto is null)
|
||||
{
|
||||
StatusMessage = Loc.T("vm.tickets.workerOffline");
|
||||
return;
|
||||
}
|
||||
ApiBaseUrl = dto.ApiBaseUrl ?? "";
|
||||
TokenSet = dto.TokenSet;
|
||||
}
|
||||
|
||||
public async Task SaveAsync()
|
||||
{
|
||||
await _worker.SetTicketApiBaseUrlAsync(ApiBaseUrl);
|
||||
if (!string.IsNullOrWhiteSpace(Token))
|
||||
{
|
||||
await _worker.SetTicketTokenAsync(Token);
|
||||
Token = "";
|
||||
TokenSet = true;
|
||||
}
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task TestConnection()
|
||||
{
|
||||
IsBusy = true;
|
||||
StatusMessage = "";
|
||||
try
|
||||
{
|
||||
await SaveAsync();
|
||||
var result = await _worker.TestTicketConnectionAsync();
|
||||
if (result is null || !result.Ok)
|
||||
{
|
||||
StatusMessage = result?.Error ?? Loc.T("vm.tickets.workerOffline");
|
||||
return;
|
||||
}
|
||||
|
||||
var missing = RequiredScopes.Where(s => !result.Scopes.Contains(s)).ToList();
|
||||
StatusMessage = missing.Count == 0
|
||||
? Loc.T("vm.tickets.connectionOk", result.UserName!)
|
||||
: Loc.T("vm.tickets.connectionMissingScopes", result.UserName!, string.Join(", ", missing));
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsBusy = false;
|
||||
}
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task ClearToken()
|
||||
{
|
||||
await _worker.ClearTicketTokenAsync();
|
||||
Token = "";
|
||||
TokenSet = false;
|
||||
StatusMessage = Loc.T("vm.tickets.tokenCleared");
|
||||
}
|
||||
|
||||
// Ohne diese drei Scopes scheitert entweder der Import oder die Statusrueckmeldung —
|
||||
// der mit Abstand haeufigste Konfigurationsfehler, deshalb wird er beim Testen benannt
|
||||
// statt nur geloggt.
|
||||
private static readonly string[] RequiredScopes =
|
||||
[
|
||||
"pat:projects:read",
|
||||
"pat:board:read",
|
||||
"pat:tickets:write",
|
||||
];
|
||||
}
|
||||
Reference in New Issue
Block a user