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:
@@ -2,6 +2,7 @@ using Microsoft.EntityFrameworkCore;
|
||||
using Novelly.Api.Common;
|
||||
using Novelly.Api.Common.Validation;
|
||||
using Novelly.Api.Data;
|
||||
using Novelly.Api.Locations;
|
||||
using Novelly.Api.Tags;
|
||||
using Novelly.Api.Users;
|
||||
|
||||
@@ -11,6 +12,7 @@ public class ChapterService(
|
||||
INovelDbContext db,
|
||||
NovelAccessService access,
|
||||
TagService tags,
|
||||
LocationService locations,
|
||||
ILogger<ChapterService> logger,
|
||||
IModelValidator<CreateChapterRequest> createValidator,
|
||||
IModelValidator<UpdateChapterRequest> updateValidator)
|
||||
@@ -26,6 +28,7 @@ public class ChapterService(
|
||||
return await db.Chapters
|
||||
.Include(c => c.Beats)
|
||||
.Include(c => c.Tags)
|
||||
.Include(c => c.Locations)
|
||||
.Where(c => c.NovelId == novelId)
|
||||
.OrderBy(c => c.Number)
|
||||
.ToListAsync(ct);
|
||||
@@ -69,7 +72,6 @@ public class ChapterService(
|
||||
Title = request.Title,
|
||||
Number = request.Number ?? await NextChapterNumberAsync(novelId, ct),
|
||||
Summary = request.Summary,
|
||||
Setting = request.Setting,
|
||||
Notes = request.Notes,
|
||||
Status = request.Status,
|
||||
TargetWordCount = request.TargetWordCount,
|
||||
@@ -82,6 +84,11 @@ public class ChapterService(
|
||||
chapter.Tags = await tags.ResolveAsync(novelId, names, ct);
|
||||
}
|
||||
|
||||
if (request.Locations is { } locationNames)
|
||||
{
|
||||
chapter.Locations = await locations.ResolveAsync(novelId, locationNames, ct);
|
||||
}
|
||||
|
||||
db.Chapters.Add(chapter);
|
||||
await db.SaveChangesAsync(ct);
|
||||
|
||||
@@ -107,7 +114,6 @@ public class ChapterService(
|
||||
chapter.Title = Patch.Apply(chapter.Title, request.Title) ?? chapter.Title;
|
||||
chapter.Number = request.Number ?? chapter.Number;
|
||||
chapter.Summary = Patch.Apply(chapter.Summary, request.Summary);
|
||||
chapter.Setting = Patch.Apply(chapter.Setting, request.Setting);
|
||||
chapter.Notes = Patch.Apply(chapter.Notes, request.Notes);
|
||||
chapter.Status = request.Status ?? chapter.Status;
|
||||
chapter.TargetWordCount = request.TargetWordCount ?? chapter.TargetWordCount;
|
||||
@@ -125,6 +131,11 @@ public class ChapterService(
|
||||
chapter.Tags = await tags.ResolveAsync(chapter.NovelId, names, ct);
|
||||
}
|
||||
|
||||
if (request.Locations is { } locationNames)
|
||||
{
|
||||
chapter.Locations = await locations.ResolveAsync(chapter.NovelId, locationNames, ct);
|
||||
}
|
||||
|
||||
await db.SaveChangesAsync(ct);
|
||||
return (await FindAsync(id, ct))!;
|
||||
}
|
||||
@@ -169,6 +180,7 @@ public class ChapterService(
|
||||
.Include(c => c.Beats).ThenInclude(b => b.Characters)
|
||||
.Include(c => c.Beats).ThenInclude(b => b.Tags)
|
||||
.Include(c => c.Tags)
|
||||
.Include(c => c.Locations)
|
||||
.FirstOrDefaultAsync(c => c.Id == id, ct);
|
||||
|
||||
if (chapter is null)
|
||||
|
||||
Reference in New Issue
Block a user