Add genre feature; extract ConfirmModal for reusable confirm dialogs

Genres seed on boot, are editable per project, and gate agent config
errors more gracefully. ConfirmModal replaces ad-hoc confirm prompts
across chapters, tags, and characters pages.
This commit is contained in:
James Wampler
2026-08-15 11:25:13 -07:00
parent ffb476a81a
commit 27c287b9c8
27 changed files with 1428 additions and 80 deletions
+9
View File
@@ -4,6 +4,7 @@ using Novelly.Api.Agent;
using Novelly.Api.Beats;
using Novelly.Api.Chapters;
using Novelly.Api.Characters;
using Novelly.Api.Genres;
using Novelly.Api.Imports;
using Novelly.Api.Projects;
using Novelly.Api.Questions;
@@ -30,6 +31,7 @@ public class NovelDbContext(DbContextOptions<NovelDbContext> options)
public DbSet<AgentConversation> Conversations => Set<AgentConversation>();
public DbSet<AgentMessage> AgentMessages => Set<AgentMessage>();
public DbSet<ImportJob> ImportJobs => Set<ImportJob>();
public DbSet<Genre> Genres => Set<Genre>();
Task<int> INovelDbContext.SaveChangesAsync(CancellationToken cancellationToken) =>
base.SaveChangesAsync(cancellationToken);
@@ -150,6 +152,13 @@ public class NovelDbContext(DbContextOptions<NovelDbContext> options)
entity.HasIndex(m => new { m.ConversationId, m.Sequence }).IsUnique();
});
builder.Entity<Genre>(entity =>
{
entity.Property(g => g.Name).IsRequired().HasMaxLength(100);
entity.HasIndex(g => g.Name).IsUnique();
entity.HasData(SeededGenres.All);
});
builder.Entity<ImportJob>(entity =>
{
entity.Property(j => j.SourceRoot).IsRequired().HasMaxLength(1000);