diff --git a/PlotLine/Data/WordCompanionRepository.cs b/PlotLine/Data/WordCompanionRepository.cs index 5a78dd7..603ddb9 100644 --- a/PlotLine/Data/WordCompanionRepository.cs +++ b/PlotLine/Data/WordCompanionRepository.cs @@ -36,9 +36,23 @@ public sealed class WordCompanionRepository(ISqlConnectionFactory connectionFact { using var connection = connectionFactory.CreateConnection(); var rows = await connection.QueryAsync( - "dbo.WordCompanion_Book_ListByProject", + """ + SELECT b.BookID AS BookId, + b.BookTitle AS Title, + b.Subtitle, + b.SortOrder + FROM dbo.Books b + INNER JOIN dbo.ProjectUserAccess pua ON pua.ProjectID = b.ProjectID + INNER JOIN dbo.Projects p ON p.ProjectID = b.ProjectID + WHERE b.ProjectID = @ProjectID + AND pua.UserID = @UserID + AND pua.IsActive = 1 + AND p.IsArchived = 0 + AND b.IsArchived = 0 + ORDER BY b.SortOrder, b.BookNumber, b.BookTitle, b.BookID; + """, new { ProjectID = projectId, UserID = userId }, - commandType: CommandType.StoredProcedure); + commandType: CommandType.Text); return rows.ToList(); } diff --git a/PlotLine/Models/WordCompanionApiModels.cs b/PlotLine/Models/WordCompanionApiModels.cs index 316544e..b52cab6 100644 --- a/PlotLine/Models/WordCompanionApiModels.cs +++ b/PlotLine/Models/WordCompanionApiModels.cs @@ -15,6 +15,7 @@ public sealed class WordCompanionBookDto { public int BookId { get; set; } public string Title { get; set; } = string.Empty; + public string? Subtitle { get; set; } public int SortOrder { get; set; } } diff --git a/PlotLine/wwwroot/js/word-companion-host.js b/PlotLine/wwwroot/js/word-companion-host.js index b89a9ca..f6737ff 100644 --- a/PlotLine/wwwroot/js/word-companion-host.js +++ b/PlotLine/wwwroot/js/word-companion-host.js @@ -917,6 +917,12 @@ select.disabled = rows.length === 0; }; + const bookDisplayTitle = (book) => { + const title = String(book?.title || "").trim(); + const subtitle = String(book?.subtitle || "").trim(); + return subtitle ? `${title}: ${subtitle}` : title; + }; + const selectedProject = () => { const projectId = Number.parseInt(projectSelect?.value || "", 10); return projects.find((project) => project.projectId === projectId) || null; @@ -935,7 +941,7 @@ summaryProject.textContent = project?.title || "(Not connected)"; } if (summaryBook) { - summaryBook.textContent = book?.title || "(Not connected)"; + summaryBook.textContent = book ? bookDisplayTitle(book) : "(Not connected)"; } if (syncNote) { syncNote.textContent = book ? "" : "Select a PlotDirector book before refreshing."; @@ -2203,7 +2209,7 @@ } const chapterTitle = normalizeWhitespace(detectedChapterTitle); - const confirmed = await confirmCreateChapter(chapterTitle, book.title || "selected book"); + const confirmed = await confirmCreateChapter(chapterTitle, bookDisplayTitle(book) || "selected book"); if (!confirmed) { return; } @@ -2649,7 +2655,7 @@ projectId: project?.projectId, projectTitle: project?.title, bookId: book?.bookId, - bookTitle: book?.title, + bookTitle: book ? bookDisplayTitle(book) : undefined, detectedChapter: detectedChapterTitle, detectedScene: detectedSceneTitle, requestChapter: requestChapterTitle, @@ -2725,7 +2731,7 @@ projectId: project?.projectId, projectTitle: project?.title, bookId: book?.bookId, - bookTitle: book?.title, + bookTitle: book ? bookDisplayTitle(book) : undefined, detectedChapter: detectedChapterTitle, detectedScene: detectedSceneTitle, requestChapter: requestChapterTitle, @@ -3098,7 +3104,10 @@ return; } - addOptions(bookSelect, "Choose a book", books, "bookId", "title"); + addOptions(bookSelect, "Choose a book", books.map((book) => ({ + ...book, + displayTitle: bookDisplayTitle(book) + })), "bookId", "displayTitle"); const validBook = books.find((book) => book.bookId === preferredBookId); if (validBook && bookSelect) { bookSelect.value = String(validBook.bookId);