Add GitHub-style activity contribution graph
Record create/update/delete events across novel content (chapters, beats, characters, arc stages, tags, locations, questions) into an append-only ActivityEvent log, aggregate by UTC day, and surface as a heatmap on the novels list and each novel's dashboard. Backfills history from existing CreatedAt timestamps on first boot after the migration.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Novelly.Api.Activity;
|
||||
using Novelly.Api.Common;
|
||||
using Novelly.Api.Common.Validation;
|
||||
using Novelly.Api.Data;
|
||||
@@ -13,6 +14,7 @@ public class ChapterService(
|
||||
NovelAccessService access,
|
||||
TagService tags,
|
||||
LocationService locations,
|
||||
ActivityLog activity,
|
||||
ILogger<ChapterService> logger,
|
||||
IModelValidator<CreateChapterRequest> createValidator,
|
||||
IModelValidator<UpdateChapterRequest> updateValidator)
|
||||
@@ -90,6 +92,7 @@ public class ChapterService(
|
||||
}
|
||||
|
||||
db.Chapters.Add(chapter);
|
||||
activity.Record(novelId, ActivityEntityKind.Chapter, ActivityAction.Created, chapter.Id, chapter.WordCount);
|
||||
await db.SaveChangesAsync(ct);
|
||||
|
||||
return (await FindAsync(chapter.Id, ct))!;
|
||||
@@ -118,6 +121,8 @@ public class ChapterService(
|
||||
chapter.Status = request.Status ?? chapter.Status;
|
||||
chapter.TargetWordCount = request.TargetWordCount ?? chapter.TargetWordCount;
|
||||
|
||||
var wordCountBeforeEdit = chapter.WordCount;
|
||||
|
||||
if (request.Prose is not null)
|
||||
{
|
||||
chapter.Prose = Patch.Apply(chapter.Prose, request.Prose);
|
||||
@@ -136,6 +141,7 @@ public class ChapterService(
|
||||
chapter.Locations = await locations.ResolveAsync(chapter.NovelId, locationNames, ct);
|
||||
}
|
||||
|
||||
activity.Record(chapter.NovelId, ActivityEntityKind.Chapter, ActivityAction.Updated, chapter.Id, chapter.WordCount - wordCountBeforeEdit);
|
||||
await db.SaveChangesAsync(ct);
|
||||
return (await FindAsync(id, ct))!;
|
||||
}
|
||||
@@ -155,6 +161,7 @@ public class ChapterService(
|
||||
await access.RequireAsync(chapter.NovelId, NovelPermission.DeleteContent, ct);
|
||||
|
||||
db.Chapters.Remove(chapter);
|
||||
activity.Record(chapter.NovelId, ActivityEntityKind.Chapter, ActivityAction.Deleted, chapter.Id, -chapter.WordCount);
|
||||
await db.SaveChangesAsync(ct);
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user