fix(tickets): Import broadcastet TaskUpdated fuer neue Tasks

ImportTickets sendete nur ListUpdated. Die UI liest das als Aenderung der
Listen-Metadaten und patcht nur bestehende Zeilen, also tauchten die
importierten Tasks erst nach Schliessen und Neuoeffnen der Liste auf.
TicketImportResult liefert jetzt die angelegten Task-Ids, der Hub
broadcastet pro Id ein TaskUpdated - derselbe Pfad, den jeder andere
out-of-band Creator nutzt.
This commit is contained in:
mika kuns
2026-09-10 15:39:58 +02:00
parent 3d09323ee1
commit 1770b67713
3 changed files with 20 additions and 6 deletions
+5
View File
@@ -1394,6 +1394,11 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub
try
{
var result = await _ticketImport.ImportAsync(listId, Context.ConnectionAborted);
// ListUpdated allein reicht nicht: die UI liest das als "Listen-Metadaten geaendert"
// und patcht nur bestehende Zeilen. Neue Tasks tauchen nur ueber TaskUpdated auf, wie
// bei jedem anderen out-of-band Creator (add_task und Co.).
foreach (var taskId in result.CreatedTaskIds)
await _broadcaster.TaskUpdated(taskId);
await _broadcaster.ListUpdated(listId);
return new TicketImportResultDto(result.Examined, result.Created);
}
@@ -6,7 +6,7 @@ using TaskStatus = ClaudeDo.Data.Models.TaskStatus;
namespace ClaudeDo.Worker.Tickets;
public sealed record TicketImportResult(int Examined, int Created);
public sealed record TicketImportResult(int Examined, int Created, IReadOnlyList<string> CreatedTaskIds);
/// <summary>
/// Holt das Board des verknüpften Ticket-Projekts und legt für jedes offene, dem Token-Inhaber
@@ -61,16 +61,17 @@ public sealed class TicketImportService
var knownSet = known.ToHashSet(StringComparer.OrdinalIgnoreCase);
var repo = new TaskRepository(ctx);
var created = 0;
var created = new List<string>();
foreach (var ticket in mine)
{
var reference = $"bandel:{ticket.Id}";
if (!knownSet.Add(reference)) continue;
var taskId = Guid.NewGuid().ToString();
await repo.AddAsync(new TaskEntity
{
Id = Guid.NewGuid().ToString(),
Id = taskId,
ListId = listId,
Title = ticket.Title,
Description = BuildDescription(ticket),
@@ -79,14 +80,14 @@ public sealed class TicketImportService
TicketRef = reference,
CreatedBy = "ticketsystem",
}, ct);
created++;
created.Add(taskId);
}
_logger.LogInformation(
"Ticket-Import für Liste {list_id}: {examined} geprüft, {created} neue Tasks",
listId, board.Count, created);
listId, board.Count, created.Count);
return new TicketImportResult(board.Count, created);
return new TicketImportResult(board.Count, created.Count, created);
}
/// <summary>
@@ -43,6 +43,14 @@ public sealed class TicketImportServiceTests : IDisposable
.ToListAsync();
Assert.Equal(["bandel:1", "bandel:3"], refs.Order());
// Ohne die Ids kann der Hub kein TaskUpdated broadcasten und die offene Liste
// zeigt die neuen Tasks erst nach Schließen/Öffnen.
var createdIds = await ctx.Tasks
.Where(t => t.CreatedBy == "ticketsystem")
.Select(t => t.Id)
.ToListAsync();
Assert.Equal(createdIds.Order(), result.CreatedTaskIds.Order());
var created = await ctx.Tasks.Where(t => t.TicketRef == "bandel:1").SingleAsync();
Assert.Equal("Fix X", created.Title);
Assert.Equal(TaskStatus.Idle, created.Status);