fix: wire import chapter ingestion, live task polling, a11y labels, notification user targeting
- NewBookImporter now takes *Store instead of raw *minio.Client (same package access) - Runner Dependencies gains ChapterIngester interface; storeImportedChapters no-op removed - store.IngestChapters is now actually called after PDF/EPUB extraction - BookImport and ChapterIngester wired in runner main.go - CreateImportTask interface gains initiatorUserID param; threaded through store/asynq/handler - domain.ImportTask gains InitiatorUserID field; parseImportTask populates it - Runner notifies initiator (falls back to 'admin' when empty) - UI: import task list polls every 3s while any task is pending/running - UI: label[for] + input[id] fix for a11y warnings in admin import page
This commit is contained in:
@@ -44,6 +44,11 @@ type Notifier interface {
|
||||
CreateNotification(ctx context.Context, userID, title, message, link string) error
|
||||
}
|
||||
|
||||
// ChapterIngester persists imported chapters for a book.
|
||||
type ChapterIngester interface {
|
||||
IngestChapters(ctx context.Context, slug string, chapters []bookstore.Chapter) error
|
||||
}
|
||||
|
||||
// Config tunes the runner behaviour.
|
||||
type Config struct {
|
||||
// WorkerID uniquely identifies this runner instance in PocketBase records.
|
||||
@@ -110,6 +115,8 @@ type Dependencies struct {
|
||||
CoverStore bookstore.CoverStore
|
||||
// BookImport handles PDF/EPUB file parsing and chapter extraction.
|
||||
BookImport bookstore.BookImporter
|
||||
// ChapterIngester persists extracted chapters into MinIO/PocketBase.
|
||||
ChapterIngester ChapterIngester
|
||||
// Notifier creates notifications for users.
|
||||
Notifier Notifier
|
||||
// SearchIndex indexes books in Meilisearch after scraping.
|
||||
@@ -712,9 +719,12 @@ func (r *Runner) runImportTask(ctx context.Context, task domain.ImportTask, obje
|
||||
})
|
||||
}
|
||||
|
||||
// For now, we'll call a simple store method - in production this would
|
||||
// go through BookWriter or a dedicated method
|
||||
if err := r.storeImportedChapters(ctx, task.Slug, domainChapters); err != nil {
|
||||
// Store chapters via ChapterIngester
|
||||
if r.deps.ChapterIngester == nil {
|
||||
fail("chapter ingester not configured")
|
||||
return
|
||||
}
|
||||
if err := r.deps.ChapterIngester.IngestChapters(ctx, task.Slug, domainChapters); err != nil {
|
||||
fail(fmt.Sprintf("store chapters: %v", err))
|
||||
return
|
||||
}
|
||||
@@ -729,27 +739,15 @@ func (r *Runner) runImportTask(ctx context.Context, task domain.ImportTask, obje
|
||||
log.Error("runner: FinishImportTask failed", "err", err)
|
||||
}
|
||||
|
||||
// Create notification for admin
|
||||
// Create notification for the user who initiated the import
|
||||
if r.deps.Notifier != nil {
|
||||
msg := fmt.Sprintf("Import completed: %d chapters from %s", len(chapters), task.Title)
|
||||
_ = r.deps.Notifier.CreateNotification(ctx, "admin", "Import Complete", msg, "/admin/import")
|
||||
targetUser := task.InitiatorUserID
|
||||
if targetUser == "" {
|
||||
targetUser = "admin"
|
||||
}
|
||||
_ = r.deps.Notifier.CreateNotification(ctx, targetUser, "Import Complete", msg, "/admin/import")
|
||||
}
|
||||
|
||||
log.Info("runner: import task finished", "chapters", len(chapters))
|
||||
}
|
||||
|
||||
// storeImportedChapters stores imported chapters in MinIO (similar to scraped chapters).
|
||||
func (r *Runner) storeImportedChapters(ctx context.Context, slug string, chapters []bookstore.Chapter) error {
|
||||
for _, ch := range chapters {
|
||||
_ = fmt.Sprintf("# Chapter %d\n\n%s", ch.Number, ch.Content)
|
||||
if ch.Title != "" {
|
||||
_ = fmt.Sprintf("# %s\n\n%s", ch.Title, ch.Content)
|
||||
}
|
||||
_ = fmt.Sprintf("books/%s/chapters/%d.md", slug, ch.Number)
|
||||
// Use MinIO client directly since we have access to it via BookWriter/Store
|
||||
// In a real implementation, this would be abstracted through BookWriter
|
||||
r.deps.Log.Info("runner: stored chapter", "slug", slug, "chapter", ch.Number)
|
||||
}
|
||||
// TODO: Actually store via BookWriter or direct MinIO call
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user