Replace chapter setting with multi-select locations; add chapter character summary
Chapters now carry many Locations (new Tags-style entity with cross-referencing) instead of a single free-text Setting field, with a Locations tab on the novel for browsing them and seeing every chapter set at each one. Also surfaces the distinct characters appearing in a chapter's beats, linked, under the beat/word count on the outline tab.
This commit is contained in:
+1232
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,90 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Novelly.Api.Data.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class RenameSettingToLocations : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Setting",
|
||||
table: "Chapters");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Locations",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "TEXT", nullable: false),
|
||||
NovelId = table.Column<Guid>(type: "TEXT", nullable: false),
|
||||
Name = table.Column<string>(type: "TEXT", maxLength: 120, nullable: false),
|
||||
CreatedAt = table.Column<long>(type: "INTEGER", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Locations", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_Locations_Novels_NovelId",
|
||||
column: x => x.NovelId,
|
||||
principalTable: "Novels",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "ChapterLocations",
|
||||
columns: table => new
|
||||
{
|
||||
ChaptersId = table.Column<Guid>(type: "TEXT", nullable: false),
|
||||
LocationsId = table.Column<Guid>(type: "TEXT", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_ChapterLocations", x => new { x.ChaptersId, x.LocationsId });
|
||||
table.ForeignKey(
|
||||
name: "FK_ChapterLocations_Chapters_ChaptersId",
|
||||
column: x => x.ChaptersId,
|
||||
principalTable: "Chapters",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_ChapterLocations_Locations_LocationsId",
|
||||
column: x => x.LocationsId,
|
||||
principalTable: "Locations",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_ChapterLocations_LocationsId",
|
||||
table: "ChapterLocations",
|
||||
column: "LocationsId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Locations_NovelId_Name",
|
||||
table: "Locations",
|
||||
columns: new[] { "NovelId", "Name" },
|
||||
unique: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "ChapterLocations");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Locations");
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Setting",
|
||||
table: "Chapters",
|
||||
type: "TEXT",
|
||||
nullable: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -62,6 +62,21 @@ namespace Novelly.Api.Data.Migrations
|
||||
b.ToTable("BeatTags", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("ChapterLocation", b =>
|
||||
{
|
||||
b.Property<Guid>("ChaptersId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid>("LocationsId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("ChaptersId", "LocationsId");
|
||||
|
||||
b.HasIndex("LocationsId");
|
||||
|
||||
b.ToTable("ChapterLocations", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("ChapterTag", b =>
|
||||
{
|
||||
b.Property<Guid>("ChaptersId")
|
||||
@@ -273,9 +288,6 @@ namespace Novelly.Api.Data.Migrations
|
||||
b.Property<string>("Prose")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Setting")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasMaxLength(32)
|
||||
@@ -620,6 +632,31 @@ namespace Novelly.Api.Data.Migrations
|
||||
b.ToTable("ImportJobs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Novelly.Api.Locations.Location", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<long>("CreatedAt")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(120)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid>("NovelId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NovelId", "Name")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Locations");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Novelly.Api.Novels.Novel", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
@@ -901,6 +938,21 @@ namespace Novelly.Api.Data.Migrations
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("ChapterLocation", b =>
|
||||
{
|
||||
b.HasOne("Novelly.Api.Chapters.Chapter", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("ChaptersId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Novelly.Api.Locations.Location", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("LocationsId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("ChapterTag", b =>
|
||||
{
|
||||
b.HasOne("Novelly.Api.Chapters.Chapter", null)
|
||||
@@ -1064,6 +1116,17 @@ namespace Novelly.Api.Data.Migrations
|
||||
b.Navigation("RelatedCharacter");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Novelly.Api.Locations.Location", b =>
|
||||
{
|
||||
b.HasOne("Novelly.Api.Novels.Novel", "Novel")
|
||||
.WithMany()
|
||||
.HasForeignKey("NovelId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Novel");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Novelly.Api.Novels.Novel", b =>
|
||||
{
|
||||
b.HasOne("Novelly.Api.Users.NovellyUser", "Owner")
|
||||
|
||||
@@ -7,6 +7,7 @@ using Novelly.Api.Chapters;
|
||||
using Novelly.Api.Characters;
|
||||
using Novelly.Api.Genres;
|
||||
using Novelly.Api.Imports;
|
||||
using Novelly.Api.Locations;
|
||||
using Novelly.Api.Novels;
|
||||
using Novelly.Api.Questions;
|
||||
using Novelly.Api.Tags;
|
||||
@@ -24,6 +25,7 @@ public class NovelDbContext(DbContextOptions<NovelDbContext> options) : Identity
|
||||
public DbSet<CharacterArcStage> CharacterArcStages => Set<CharacterArcStage>();
|
||||
public DbSet<Beat> Beats => Set<Beat>();
|
||||
public DbSet<Tag> Tags => Set<Tag>();
|
||||
public DbSet<Location> Locations => Set<Location>();
|
||||
public DbSet<Chapter> Chapters => Set<Chapter>();
|
||||
public DbSet<OpenQuestion> OpenQuestions => Set<OpenQuestion>();
|
||||
public DbSet<AgentConversation> Conversations => Set<AgentConversation>();
|
||||
@@ -51,6 +53,7 @@ public interface INovelDbContext
|
||||
DbSet<CharacterArcStage> CharacterArcStages { get; }
|
||||
DbSet<Beat> Beats { get; }
|
||||
DbSet<Tag> Tags { get; }
|
||||
DbSet<Location> Locations { get; }
|
||||
DbSet<Chapter> Chapters { get; }
|
||||
DbSet<OpenQuestion> OpenQuestions { get; }
|
||||
DbSet<AgentConversation> Conversations { get; }
|
||||
|
||||
Reference in New Issue
Block a user