feat(hub): add RunTicketImportNow and ticket fallback list endpoints
This commit is contained in:
@@ -222,7 +222,7 @@ public sealed record LaunchSpec(
|
|||||||
// action -- confirms with a count, then cancels each one before closing the pane.
|
// action -- confirms with a count, then cancels each one before closing the pane.
|
||||||
public record HandlerOpenTaskDto(string Id, string Title);
|
public record HandlerOpenTaskDto(string Id, string Title);
|
||||||
|
|
||||||
public record TicketSettingsDto(string? ApiBaseUrl, bool TokenSet);
|
public record TicketSettingsDto(string? ApiBaseUrl, bool TokenSet, string? FallbackListId = null);
|
||||||
public record TicketConnectionDto(bool Ok, string? UserName, IReadOnlyList<string> Scopes, string? Error);
|
public record TicketConnectionDto(bool Ok, string? UserName, IReadOnlyList<string> Scopes, string? Error);
|
||||||
public record TicketProjectDto(int Id, string Title, string DepartmentName);
|
public record TicketProjectDto(int Id, string Title, string DepartmentName);
|
||||||
public record TicketImportResultDto(int Examined, int Created);
|
public record TicketImportResultDto(int Examined, int Created);
|
||||||
|
|||||||
@@ -1028,11 +1028,15 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub
|
|||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> RunDailyPrepNow()
|
public Task<bool> RunDailyPrepNow() => RunPrimeNowAsync(ClaudeDo.Data.Models.PrimeActionKind.FillMyDay);
|
||||||
|
|
||||||
|
/// <summary>The "Tickets + plan day" button: ticket import, then FillMyDay, through the same Prime gate.</summary>
|
||||||
|
public Task<bool> RunTicketImportNow() => RunPrimeNowAsync(ClaudeDo.Data.Models.PrimeActionKind.ImportTickets);
|
||||||
|
|
||||||
|
// A button means its own kind no matter how the schedules are configured — hence a synthetic schedule.
|
||||||
|
private async Task<bool> RunPrimeNowAsync(ClaudeDo.Data.Models.PrimeActionKind kind)
|
||||||
{
|
{
|
||||||
var schedule = new PrimeScheduleDto(
|
var schedule = new PrimeScheduleDto(Guid.Empty, 0, TimeSpan.Zero, true, null, null, kind);
|
||||||
Guid.Empty, 0, TimeSpan.Zero, true, null, null,
|
|
||||||
ClaudeDo.Data.Models.PrimeActionKind.FillMyDay);
|
|
||||||
var firedAt = DateTimeOffset.Now;
|
var firedAt = DateTimeOffset.Now;
|
||||||
var outcome = await _primeRunner.FireAsync(schedule, Context.ConnectionAborted);
|
var outcome = await _primeRunner.FireAsync(schedule, Context.ConnectionAborted);
|
||||||
await _broadcaster.PrimeFired(Guid.Empty, outcome.Success, outcome.Message, firedAt);
|
await _broadcaster.PrimeFired(Guid.Empty, outcome.Success, outcome.Message, firedAt);
|
||||||
@@ -1363,8 +1367,19 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub
|
|||||||
|
|
||||||
// Liefert die EFFEKTIVE Base-URL (inkl. ergänztem Schema), nicht den rohen Feldwert: sonst
|
// Liefert die EFFEKTIVE Base-URL (inkl. ergänztem Schema), nicht den rohen Feldwert: sonst
|
||||||
// sieht der Nutzer im Tab weiter "host.local", während der Client "http://host.local" ruft.
|
// sieht der Nutzer im Tab weiter "host.local", während der Client "http://host.local" ruft.
|
||||||
public TicketSettingsDto GetTicketSettings()
|
public async Task<TicketSettingsDto> GetTicketSettings()
|
||||||
=> new(_ticketConfig.BaseUrl, _ticketConfig.Token is not null);
|
{
|
||||||
|
using var ctx = _dbFactory.CreateDbContext();
|
||||||
|
var settings = await new AppSettingsRepository(ctx).GetAsync(Context.ConnectionAborted);
|
||||||
|
return new TicketSettingsDto(_ticketConfig.BaseUrl, _ticketConfig.Token is not null, settings.TicketFallbackListId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Sets the list that import_ticket uses when Claude passes no list; null clears it.</summary>
|
||||||
|
public async Task SetTicketFallbackList(string? listId)
|
||||||
|
{
|
||||||
|
using var ctx = _dbFactory.CreateDbContext();
|
||||||
|
await new AppSettingsRepository(ctx).SetTicketFallbackListIdAsync(listId, Context.ConnectionAborted);
|
||||||
|
}
|
||||||
|
|
||||||
public void SetTicketApiBaseUrl(string? baseUrl)
|
public void SetTicketApiBaseUrl(string? baseUrl)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
using ClaudeDo.Worker;
|
||||||
|
using ClaudeDo.Worker.Config;
|
||||||
|
using ClaudeDo.Worker.Hub;
|
||||||
|
using ClaudeDo.Worker.Tests.Infrastructure;
|
||||||
|
using ClaudeDo.Worker.Tickets;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace ClaudeDo.Worker.Tests.Hub;
|
||||||
|
|
||||||
|
public sealed class TicketFallbackHubTests : IDisposable
|
||||||
|
{
|
||||||
|
private readonly DbFixture _db = new();
|
||||||
|
private readonly string _patDir = Path.Combine(Path.GetTempPath(), "cdo-hubpat-" + Guid.NewGuid().ToString("N"));
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_db.Dispose();
|
||||||
|
try { Directory.Delete(_patDir, recursive: true); } catch { /* best effort */ }
|
||||||
|
}
|
||||||
|
|
||||||
|
private WorkerHub CreateHub()
|
||||||
|
{
|
||||||
|
var ticketConfig = new TicketSystemConfig(
|
||||||
|
new WorkerConfig(), new TicketPatStore(new DpapiTokenStore(Path.Combine(_patDir, "ticket.pat"))));
|
||||||
|
var hub = new WorkerHub(
|
||||||
|
null!, null!, null!, null!, new HubBroadcaster(new CapturingHubContext()), _db.CreateFactory(),
|
||||||
|
null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!,
|
||||||
|
null!, new ClaudeDo.Worker.Online.OnlineInboxConfig(), new ClaudeDo.Worker.OnlineRefreshTokenStore(new DpapiTokenStore("unused.token")),
|
||||||
|
new ClaudeDo.Worker.Runner.PendingQuestionRegistry(), null!,
|
||||||
|
ticketConfig: ticketConfig);
|
||||||
|
hub.Clients = new FakeHubCallerClients(new RecordingClientProxy());
|
||||||
|
hub.Context = new FakeHubCallerContext();
|
||||||
|
return hub;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Fallback_list_set_through_the_hub_comes_back_in_the_ticket_settings()
|
||||||
|
{
|
||||||
|
var hub = CreateHub();
|
||||||
|
|
||||||
|
await hub.SetTicketFallbackList("l-fallback");
|
||||||
|
var dto = await hub.GetTicketSettings();
|
||||||
|
|
||||||
|
Assert.Equal("l-fallback", dto.FallbackListId);
|
||||||
|
Assert.False(dto.TokenSet);
|
||||||
|
|
||||||
|
await hub.SetTicketFallbackList(null);
|
||||||
|
Assert.Null((await hub.GetTicketSettings()).FallbackListId);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user