-
Notifications
You must be signed in to change notification settings - Fork 5
YouTube Import: Long-Running Task UX — Progress Tracking + Status Polling #130
Copy link
Copy link
Closed
Labels
go:needs-researchNeeds investigationNeeds investigationsquadSquad triage inbox — Lead will assign to a memberSquad triage inbox — Lead will assign to a membersquad:washAssigned to Wash (Backend Dev)Assigned to Wash (Backend Dev)
Description
Overview
Implement the client-side UX for tracking long-running video imports. The pattern is: submit → poll → display status → notify on completion.
Crew: Kaylee (UI) + Wash (API endpoints)
Depends on: #126 (data model), #128 (worker), #129 (UI pages)
Decision: Polling over SignalR
Why polling wins for this app:
- Blazor Hybrid on mobile: WebView pauses on backgrounding, killing SignalR connections
- Import pipeline takes 15-60 seconds — not a latency-sensitive operation
- Polling is simpler to implement, debug, and maintain
- Works identically on both MAUI (Blazor Hybrid) and web (Blazor Server)
Polling Behavior
On the Import page:
- Poll
GET /api/import?status=activeevery 5 seconds while page is visible - "Active" = Queued + FetchingTranscript + PolishingTranscript + ExtractingVocabulary
- Stop polling when no active imports remain
- Use
System.Threading.Timerin the Blazor component withIDisposablecleanup
On other pages (optional, phase 2):
- Poll every 30 seconds for a count of active imports
- Display badge on Import nav item if count > 0
- Lightweight:
GET /api/import/active-countreturns just an integer
On completion:
- Toast notification: "Video imported: {title}"
- Import row updates to show "Complete" with link to resource
- If the created resource has vocabulary, show word count: "22 words extracted"
On failure:
- Toast notification: "Import failed: {title}"
- Import row shows error message + "Retry" button
- Retry =
POST /api/import/{id}/retry→ resets status to Queued
API Endpoints (Wash)
GET /api/import — List imports (filterable by status)
GET /api/import/active-count — Count of non-terminal imports (for badge)
POST /api/import/{id}/retry — Reset failed import to Queued
Response shape:
{
"id": "abc-123",
"videoUrl": "https://youtube.com/watch?v=xyz",
"title": "Korean Street Food Tour",
"status": "ExtractingVocabulary",
"errorMessage": null,
"learningResourceId": null,
"channelName": "Korean Englishman",
"createdAt": "2026-07-22T10:30:00Z",
"updatedAt": "2026-07-22T10:30:45Z"
}Blazor Component Pattern
@implements IDisposable
private Timer? _pollTimer;
private List<VideoImportDto> _activeImports = new();
protected override void OnInitialized()
{
_pollTimer = new Timer(async _ =>
{
var imports = await Http.GetFromJsonAsync<List<VideoImportDto>>("/api/import?status=active");
if (imports != null)
{
// Check for newly completed imports → show toast
foreach (var completed in _activeImports
.Where(old => imports.Any(i => i.Id == old.Id && i.Status == "Complete")))
{
Toast.ShowSuccess($"Imported: {completed.Title}");
}
_activeImports = imports;
await InvokeAsync(StateHasChanged);
}
// Stop polling if nothing active
if (!_activeImports.Any())
_pollTimer?.Change(Timeout.Infinite, Timeout.Infinite);
}, null, TimeSpan.Zero, TimeSpan.FromSeconds(5));
}
public void Dispose() => _pollTimer?.Dispose();Tasks
- Create
VideoImportDtoin Contracts project - Add API endpoints: list imports, active count, retry
- Implement polling timer in Import.razor component
- Status display component (icon + label per status)
- Completion toast notifications
- Failure display with retry button
- Timer cleanup on component dispose
- Test: submit import → observe status changes → completion toast
- (Phase 2) Nav badge for active import count
Architecture Reference
See .squad/decisions/inbox/zoe-youtube-import-architecture.md — Section 3
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
go:needs-researchNeeds investigationNeeds investigationsquadSquad triage inbox — Lead will assign to a memberSquad triage inbox — Lead will assign to a membersquad:washAssigned to Wash (Backend Dev)Assigned to Wash (Backend Dev)