Add character aliases/identity links, move-beats, keyboard help overlay
- Characters can carry aliases and be linked as the same underlying person (canonical SameCharacterAsId, optional reveal chapter/note), surfaced through the API, MCP tools, agent toolset, and web UI. - Characters page redesigned as a filterable/sortable table (name+ aliases, role, importance, occupation, tags) instead of a sidebar list, to stay usable as the cast grows. - Beats can be moved between chapters (BeatService.MoveAsync + MCP/ agent tool + endpoint). - Add a keyboard-shortcuts help overlay (HelpButton/HelpOverlayContext) wired into the project layout. - CLAUDE.md: require every frontend component to carry a unique id attribute; apply it to CharacterMultiSelect and MarkdownEditor.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
using Novelly.Api.Beats;
|
||||
using Novelly.Api.Chapters;
|
||||
using Novelly.Api.Projects;
|
||||
using Novelly.Api.Tags;
|
||||
|
||||
@@ -38,6 +39,16 @@ public class Character
|
||||
|
||||
public string? Notes { get; set; }
|
||||
|
||||
public List<string> Aliases { get; set; } = [];
|
||||
|
||||
public Guid? SameCharacterAsId { get; set; }
|
||||
public Character? SameCharacterAs { get; set; }
|
||||
public List<Character> OtherIdentities { get; set; } = [];
|
||||
|
||||
public Guid? RevealedInChapterId { get; set; }
|
||||
public Chapter? RevealedInChapter { get; set; }
|
||||
public string? IdentityNote { get; set; }
|
||||
|
||||
public DateTimeOffset CreatedAt { get; set; } = DateTimeOffset.UtcNow;
|
||||
public DateTimeOffset UpdatedAt { get; set; } = DateTimeOffset.UtcNow;
|
||||
|
||||
@@ -72,12 +83,19 @@ public class CharacterEntityTypeConfiguration : IEntityTypeConfiguration<Charact
|
||||
entity.Property(c => c.Role).HasConversion<string>().HasMaxLength(32);
|
||||
entity.Property(c => c.Importance).HasConversion<string>().HasMaxLength(32);
|
||||
entity.HasIndex(c => c.ProjectId);
|
||||
entity.HasIndex(c => c.SameCharacterAsId);
|
||||
|
||||
entity.HasMany(c => c.Relationships).WithOne(r => r.Character!)
|
||||
.HasForeignKey(r => r.CharacterId).OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
entity.HasMany(c => c.ArcStages).WithOne(s => s.Character!)
|
||||
.HasForeignKey(s => s.CharacterId).OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
entity.HasOne(c => c.SameCharacterAs).WithMany(c => c.OtherIdentities)
|
||||
.HasForeignKey(c => c.SameCharacterAsId).OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
entity.HasOne(c => c.RevealedInChapter).WithMany()
|
||||
.HasForeignKey(c => c.RevealedInChapterId).OnDelete(DeleteBehavior.SetNull);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user