diff --git a/FictionArchive.Service.NovelService/GraphQL/Mutation.cs b/FictionArchive.Service.NovelService/GraphQL/Mutation.cs index af7724f..cea85b8 100644 --- a/FictionArchive.Service.NovelService/GraphQL/Mutation.cs +++ b/FictionArchive.Service.NovelService/GraphQL/Mutation.cs @@ -7,6 +7,7 @@ using FictionArchive.Service.NovelService.Services; using FictionArchive.Service.NovelService.Services.SourceAdapters; using FictionArchive.Service.Shared.Services.EventBus; using HotChocolate.Authorization; +using HotChocolate.Types; using Microsoft.EntityFrameworkCore; namespace FictionArchive.Service.NovelService.GraphQL; @@ -26,4 +27,12 @@ public class Mutation { return await service.QueueChapterPull(novelId, chapterNumber); } + + [Error] + [Authorize] + public async Task DeleteNovel(uint novelId, NovelUpdateService service) + { + await service.DeleteNovel(novelId); + return true; + } } \ No newline at end of file diff --git a/FictionArchive.Service.NovelService/Services/NovelUpdateService.cs b/FictionArchive.Service.NovelService/Services/NovelUpdateService.cs index c9819da..ae5c917 100644 --- a/FictionArchive.Service.NovelService/Services/NovelUpdateService.cs +++ b/FictionArchive.Service.NovelService/Services/NovelUpdateService.cs @@ -379,12 +379,23 @@ public class NovelUpdateService var chapter = novel.Chapters.Where(chapter => chapter.Order == chapterNumber).FirstOrDefault(); var adapter = _sourceAdapters.FirstOrDefault(adapter => adapter.SourceDescriptor.Key == novel.Source.Key); var rawChapter = await adapter.GetRawChapter(chapter.Url); - var localizationText = new LocalizationText() + + // If we already have the raw for this, overwrite it for now. Revisions will come later. + var localizationText = chapter.Body.Texts.FirstOrDefault(text => text.Language == novel.RawLanguage); + if (localizationText == null) { - Text = rawChapter.Text, - Language = novel.RawLanguage - }; - chapter.Body.Texts.Add(localizationText); + localizationText = new LocalizationText() + { + Text = rawChapter.Text, + Language = novel.RawLanguage + }; + chapter.Body.Texts.Add(localizationText); + } + else + { + localizationText.Text = rawChapter.Text; + } + chapter.Images = rawChapter.ImageData.Select(img => new Image() { OriginalPath = img.Url @@ -477,4 +488,49 @@ public class NovelUpdateService await _eventBus.Publish(chapterPullEvent); return chapterPullEvent; } + + public async Task DeleteNovel(uint novelId) + { + var novel = await _dbContext.Novels + .Include(n => n.CoverImage) + .Include(n => n.Name).ThenInclude(k => k.Texts) + .Include(n => n.Description).ThenInclude(k => k.Texts) + .Include(n => n.Chapters).ThenInclude(c => c.Images) + .Include(n => n.Chapters).ThenInclude(c => c.Name).ThenInclude(k => k.Texts) + .Include(n => n.Chapters).ThenInclude(c => c.Body).ThenInclude(k => k.Texts) + .FirstOrDefaultAsync(n => n.Id == novelId); + + if (novel == null) + throw new KeyNotFoundException($"Novel with ID '{novelId}' not found"); + + // Collect all LocalizationKey IDs for cleanup + var locKeyIds = new List { novel.Name.Id, novel.Description.Id }; + locKeyIds.AddRange(novel.Chapters.Select(c => c.Name.Id)); + locKeyIds.AddRange(novel.Chapters.Select(c => c.Body.Id)); + + // 1. Remove LocalizationRequests referencing these keys + var locRequests = await _dbContext.LocalizationRequests + .Where(r => locKeyIds.Contains(r.KeyRequestedForTranslation.Id)) + .ToListAsync(); + _dbContext.LocalizationRequests.RemoveRange(locRequests); + + // 2. Remove LocalizationTexts (NO ACTION FK - won't cascade) + _dbContext.RemoveRange(novel.Name.Texts); + _dbContext.RemoveRange(novel.Description.Texts); + foreach (var chapter in novel.Chapters) + { + _dbContext.RemoveRange(chapter.Name.Texts); + _dbContext.RemoveRange(chapter.Body.Texts); + } + + // 3. Remove Images (NO ACTION FK - won't cascade) + if (novel.CoverImage != null) + _dbContext.Images.Remove(novel.CoverImage); + foreach (var chapter in novel.Chapters) + _dbContext.Images.RemoveRange(chapter.Images); + + // 4. Remove novel - cascades: chapters, localization keys, tag mappings + _dbContext.Novels.Remove(novel); + await _dbContext.SaveChangesAsync(); + } } diff --git a/fictionarchive-web-astro/src/lib/components/NovelDetailPage.svelte b/fictionarchive-web-astro/src/lib/components/NovelDetailPage.svelte index b7ed57d..e85aae3 100644 --- a/fictionarchive-web-astro/src/lib/components/NovelDetailPage.svelte +++ b/fictionarchive-web-astro/src/lib/components/NovelDetailPage.svelte @@ -32,7 +32,7 @@