Add ChapterKind for front/back matter chapters
Chapters can now be marked FrontMatter/Body/BackMatter. Number stays the manuscript sort key for every chapter; the author-facing display number is now computed per-request as the chapter's ordinal among Body chapters only, so a foreword or afterword no longer shifts the numbering of the rest of the book. Surfaced through the API, agent toolset, and import toolset.
This commit is contained in:
@@ -12,7 +12,12 @@ public static class ChapterEndpoints
|
||||
.AddEndpointFilter<ValidationEndpointFilter>();
|
||||
|
||||
novelScoped.MapGet("/", async (Guid novelId, ChapterService service, CancellationToken ct) =>
|
||||
Results.Ok((await service.ListAsync(novelId, ct)).Select(c => c.ToSummaryResponse())))
|
||||
{
|
||||
var chapters = await service.ListAsync(novelId, ct);
|
||||
var displayNumbers = ChapterNumbering.DisplayNumbers(chapters);
|
||||
return Results.Ok(chapters.Select(c =>
|
||||
c.ToSummaryResponse(displayNumbers.TryGetValue(c.Id, out var n) ? n : null)));
|
||||
})
|
||||
.WithSummary("List a novel's chapters in manuscript order.");
|
||||
|
||||
novelScoped.MapPost("/", async (
|
||||
@@ -24,7 +29,8 @@ public static class ChapterEndpoints
|
||||
return Results.NotFound();
|
||||
}
|
||||
|
||||
var created = chapter.ToResponse();
|
||||
var displayNumber = await service.DisplayNumberAsync(chapter, ct);
|
||||
var created = chapter.ToResponse(displayNumber);
|
||||
return Results.Created($"/api/chapters/{created.Id}", created);
|
||||
})
|
||||
.WithSummary("Add a chapter.");
|
||||
@@ -34,12 +40,30 @@ public static class ChapterEndpoints
|
||||
.AddEndpointFilter<ValidationEndpointFilter>();
|
||||
|
||||
chapters.MapGet("/{id:guid}", async (Guid id, ChapterService service, CancellationToken ct) =>
|
||||
(await service.GetAsync(id, ct))?.ToResponse().ToApiResult())
|
||||
{
|
||||
var chapter = await service.GetAsync(id, ct);
|
||||
if (chapter is null)
|
||||
{
|
||||
return Results.NotFound();
|
||||
}
|
||||
|
||||
var displayNumber = await service.DisplayNumberAsync(chapter, ct);
|
||||
return chapter.ToResponse(displayNumber).ToApiResult();
|
||||
})
|
||||
.WithSummary("Read a chapter with its beats and prose.");
|
||||
|
||||
chapters.MapPatch("/{id:guid}", async (
|
||||
Guid id, UpdateChapterRequest request, ChapterService service, CancellationToken ct) =>
|
||||
(await service.UpdateAsync(id, request, ct))?.ToResponse().ToApiResult())
|
||||
{
|
||||
var chapter = await service.UpdateAsync(id, request, ct);
|
||||
if (chapter is null)
|
||||
{
|
||||
return Results.NotFound();
|
||||
}
|
||||
|
||||
var displayNumber = await service.DisplayNumberAsync(chapter, ct);
|
||||
return chapter.ToResponse(displayNumber).ToApiResult();
|
||||
})
|
||||
.WithSummary("Update a chapter.");
|
||||
|
||||
chapters.MapDelete("/{id:guid}", async (Guid id, ChapterService service, CancellationToken ct) =>
|
||||
|
||||
Reference in New Issue
Block a user