Add dev hook for basic location review rebuild
This commit is contained in:
parent
1cf0174466
commit
66e28b7f0e
@ -1,5 +1,7 @@
|
|||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
using PlotLine.Data;
|
||||||
using PlotLine.Models;
|
using PlotLine.Models;
|
||||||
using PlotLine.Services;
|
using PlotLine.Services;
|
||||||
using PlotLine.ViewModels;
|
using PlotLine.ViewModels;
|
||||||
@ -23,8 +25,17 @@ public sealed class AdminController(
|
|||||||
IStoryIntelligenceImportCommitService storyIntelligenceImportCommit,
|
IStoryIntelligenceImportCommitService storyIntelligenceImportCommit,
|
||||||
INameIntelligenceService nameIntelligence,
|
INameIntelligenceService nameIntelligence,
|
||||||
IIllustrationLibraryService illustrationLibrary,
|
IIllustrationLibraryService illustrationLibrary,
|
||||||
|
IProjectRepository projects,
|
||||||
|
IBookRepository books,
|
||||||
|
IOnboardingBuildRepository onboardingBuilds,
|
||||||
|
ICoreImportBasicLocationService coreImportBasicLocations,
|
||||||
|
IWebHostEnvironment environment,
|
||||||
ILogger<AdminController> logger) : Controller
|
ILogger<AdminController> logger) : Controller
|
||||||
{
|
{
|
||||||
|
private static readonly Guid DiscoveryBasicLocationReviewPreviewId = Guid.Parse("50760000-3068-4000-8000-000000005076");
|
||||||
|
private const int DiscoveryProjectId = 3068;
|
||||||
|
private const int DiscoveryBookId = 5076;
|
||||||
|
|
||||||
[HttpGet("")]
|
[HttpGet("")]
|
||||||
[HttpGet("index")]
|
[HttpGet("index")]
|
||||||
public async Task<IActionResult> Index()
|
public async Task<IActionResult> Index()
|
||||||
@ -41,6 +52,110 @@ public sealed class AdminController(
|
|||||||
return View();
|
return View();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet("development/core-basic-location-review/discovery")]
|
||||||
|
public async Task<IActionResult> DevelopmentDiscoveryBasicLocationReview(bool reset = true)
|
||||||
|
{
|
||||||
|
if (!environment.IsDevelopment())
|
||||||
|
{
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentUser.UserId is not int userId)
|
||||||
|
{
|
||||||
|
return Forbid();
|
||||||
|
}
|
||||||
|
|
||||||
|
var project = await projects.GetAsync(DiscoveryProjectId);
|
||||||
|
var book = await books.GetAsync(DiscoveryBookId);
|
||||||
|
if (project is null || book is null || book.ProjectID != DiscoveryProjectId)
|
||||||
|
{
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
var sceneSources = await onboardingBuilds.ListSceneManuscriptSourcesByBookAsync(DiscoveryBookId);
|
||||||
|
if (sceneSources.Count == 0)
|
||||||
|
{
|
||||||
|
TempData["AdminError"] = "Book 5076 has no canonical scene source text to prepare.";
|
||||||
|
return RedirectToAction(nameof(Index));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reset)
|
||||||
|
{
|
||||||
|
await coreImportBasicLocations.ResetAndPrepareAsync(userId, DiscoveryBasicLocationReviewPreviewId, DiscoveryProjectId, DiscoveryBookId, null, sceneSources);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await coreImportBasicLocations.EnsurePreparedAsync(userId, DiscoveryBasicLocationReviewPreviewId, DiscoveryProjectId, DiscoveryBookId, null, sceneSources);
|
||||||
|
}
|
||||||
|
|
||||||
|
var model = await coreImportBasicLocations.GetReviewAsync(
|
||||||
|
userId,
|
||||||
|
DiscoveryBasicLocationReviewPreviewId,
|
||||||
|
"Discovery retained Book 5076",
|
||||||
|
project.ProjectName,
|
||||||
|
book.BookDisplayTitle);
|
||||||
|
if (model is null)
|
||||||
|
{
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
return View("~/Views/Onboarding/ScanLocations.cshtml", new CoreImportBasicLocationReviewViewModel
|
||||||
|
{
|
||||||
|
PreviewID = model.PreviewID,
|
||||||
|
ReviewID = model.ReviewID,
|
||||||
|
Status = model.Status,
|
||||||
|
DocumentTitle = model.DocumentTitle,
|
||||||
|
SelectedProjectName = model.SelectedProjectName,
|
||||||
|
SelectedBookTitle = model.SelectedBookTitle,
|
||||||
|
FormController = "Admin",
|
||||||
|
FormAction = nameof(SaveDevelopmentDiscoveryBasicLocationReview),
|
||||||
|
ContinueButtonText = "Save selected locations",
|
||||||
|
RawObservationCount = model.RawObservationCount,
|
||||||
|
CandidateCount = model.CandidateCount,
|
||||||
|
Candidates = model.Candidates,
|
||||||
|
ExistingLocationOptions = model.ExistingLocationOptions
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("development/core-basic-location-review/discovery")]
|
||||||
|
[RequestFormLimits(ValueCountLimit = 20000, KeyLengthLimit = 4096, ValueLengthLimit = 1024 * 1024)]
|
||||||
|
[ValidateAntiForgeryToken]
|
||||||
|
public async Task<IActionResult> SaveDevelopmentDiscoveryBasicLocationReview(CoreImportBasicLocationReviewForm form, string intent = "save")
|
||||||
|
{
|
||||||
|
if (!environment.IsDevelopment())
|
||||||
|
{
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentUser.UserId is not int userId)
|
||||||
|
{
|
||||||
|
return Forbid();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (form.PreviewID != DiscoveryBasicLocationReviewPreviewId)
|
||||||
|
{
|
||||||
|
return BadRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.Equals(intent, "skip", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
await coreImportBasicLocations.SkipAsync(userId, form.PreviewID);
|
||||||
|
TempData["AdminMessage"] = "Development basic location review skipped for Book 5076.";
|
||||||
|
return RedirectToAction(nameof(Index));
|
||||||
|
}
|
||||||
|
|
||||||
|
await coreImportBasicLocations.SaveDecisionsAsync(userId, form);
|
||||||
|
if (string.Equals(intent, "continue", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
await coreImportBasicLocations.CompleteAsync(userId, form.PreviewID);
|
||||||
|
TempData["AdminMessage"] = "Development basic location review materialised selected locations for Book 5076.";
|
||||||
|
return RedirectToAction(nameof(Index));
|
||||||
|
}
|
||||||
|
|
||||||
|
TempData["OnboardingReviewMessage"] = "Development location review choices saved.";
|
||||||
|
return RedirectToAction(nameof(DevelopmentDiscoveryBasicLocationReview), new { reset = false });
|
||||||
|
}
|
||||||
|
|
||||||
[HttpPost("name-intelligence/validate")]
|
[HttpPost("name-intelligence/validate")]
|
||||||
[ValidateAntiForgeryToken]
|
[ValidateAntiForgeryToken]
|
||||||
public async Task<IActionResult> ValidateNameIntelligence(CancellationToken cancellationToken)
|
public async Task<IActionResult> ValidateNameIntelligence(CancellationToken cancellationToken)
|
||||||
|
|||||||
@ -7,6 +7,7 @@ namespace PlotLine.Data;
|
|||||||
public interface ICoreImportBasicLocationReviewRepository
|
public interface ICoreImportBasicLocationReviewRepository
|
||||||
{
|
{
|
||||||
Task<CoreImportBasicLocationReview?> GetByPreviewAsync(int userId, Guid previewId);
|
Task<CoreImportBasicLocationReview?> GetByPreviewAsync(int userId, Guid previewId);
|
||||||
|
Task ResetByPreviewAsync(int userId, Guid previewId);
|
||||||
Task<CoreImportBasicLocationReview> CreateAsync(int userId, Guid previewId, int projectId, int bookId, int? buildId);
|
Task<CoreImportBasicLocationReview> CreateAsync(int userId, Guid previewId, int projectId, int bookId, int? buildId);
|
||||||
Task<CoreImportBasicLocationCandidate> SaveCandidateAsync(int reviewId, CoreImportBasicLocationCandidate candidate);
|
Task<CoreImportBasicLocationCandidate> SaveCandidateAsync(int reviewId, CoreImportBasicLocationCandidate candidate);
|
||||||
Task DeleteEvidenceAsync(int candidateId);
|
Task DeleteEvidenceAsync(int candidateId);
|
||||||
@ -30,6 +31,15 @@ public sealed class CoreImportBasicLocationReviewRepository(ISqlConnectionFactor
|
|||||||
commandType: CommandType.StoredProcedure);
|
commandType: CommandType.StoredProcedure);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task ResetByPreviewAsync(int userId, Guid previewId)
|
||||||
|
{
|
||||||
|
using var connection = connectionFactory.CreateConnection();
|
||||||
|
await connection.ExecuteAsync(
|
||||||
|
"dbo.CoreImportBasicLocationReview_ResetByPreview",
|
||||||
|
new { UserID = userId, PreviewID = previewId },
|
||||||
|
commandType: CommandType.StoredProcedure);
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<CoreImportBasicLocationReview> CreateAsync(int userId, Guid previewId, int projectId, int bookId, int? buildId)
|
public async Task<CoreImportBasicLocationReview> CreateAsync(int userId, Guid previewId, int projectId, int bookId, int? buildId)
|
||||||
{
|
{
|
||||||
using var connection = connectionFactory.CreateConnection();
|
using var connection = connectionFactory.CreateConnection();
|
||||||
|
|||||||
@ -8,6 +8,7 @@ namespace PlotLine.Services;
|
|||||||
public interface ICoreImportBasicLocationService
|
public interface ICoreImportBasicLocationService
|
||||||
{
|
{
|
||||||
Task<CoreImportBasicLocationReview?> EnsurePreparedAsync(int userId, Guid previewId, int projectId, int bookId, int? buildId, IReadOnlyList<SceneManuscriptSourceRecord> sceneSources);
|
Task<CoreImportBasicLocationReview?> EnsurePreparedAsync(int userId, Guid previewId, int projectId, int bookId, int? buildId, IReadOnlyList<SceneManuscriptSourceRecord> sceneSources);
|
||||||
|
Task<CoreImportBasicLocationReview?> ResetAndPrepareAsync(int userId, Guid previewId, int projectId, int bookId, int? buildId, IReadOnlyList<SceneManuscriptSourceRecord> sceneSources);
|
||||||
Task<CoreImportBasicLocationReviewViewModel?> GetReviewAsync(int userId, Guid previewId, string documentTitle, string projectName, string bookTitle);
|
Task<CoreImportBasicLocationReviewViewModel?> GetReviewAsync(int userId, Guid previewId, string documentTitle, string projectName, string bookTitle);
|
||||||
Task<bool> IsCompleteAsync(int userId, Guid previewId);
|
Task<bool> IsCompleteAsync(int userId, Guid previewId);
|
||||||
Task SaveDecisionsAsync(int userId, CoreImportBasicLocationReviewForm form);
|
Task SaveDecisionsAsync(int userId, CoreImportBasicLocationReviewForm form);
|
||||||
@ -57,6 +58,18 @@ public sealed class CoreImportBasicLocationService(
|
|||||||
return await reviews.GetByPreviewAsync(userId, previewId);
|
return await reviews.GetByPreviewAsync(userId, previewId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<CoreImportBasicLocationReview?> ResetAndPrepareAsync(
|
||||||
|
int userId,
|
||||||
|
Guid previewId,
|
||||||
|
int projectId,
|
||||||
|
int bookId,
|
||||||
|
int? buildId,
|
||||||
|
IReadOnlyList<SceneManuscriptSourceRecord> sceneSources)
|
||||||
|
{
|
||||||
|
await reviews.ResetByPreviewAsync(userId, previewId);
|
||||||
|
return await EnsurePreparedAsync(userId, previewId, projectId, bookId, buildId, sceneSources);
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<CoreImportBasicLocationReviewViewModel?> GetReviewAsync(int userId, Guid previewId, string documentTitle, string projectName, string bookTitle)
|
public async Task<CoreImportBasicLocationReviewViewModel?> GetReviewAsync(int userId, Guid previewId, string documentTitle, string projectName, string bookTitle)
|
||||||
{
|
{
|
||||||
var review = await reviews.GetByPreviewAsync(userId, previewId);
|
var review = await reviews.GetByPreviewAsync(userId, previewId);
|
||||||
|
|||||||
@ -0,0 +1,17 @@
|
|||||||
|
SET ANSI_NULLS ON;
|
||||||
|
GO
|
||||||
|
SET QUOTED_IDENTIFIER ON;
|
||||||
|
GO
|
||||||
|
|
||||||
|
CREATE OR ALTER PROCEDURE dbo.CoreImportBasicLocationReview_ResetByPreview
|
||||||
|
@UserID int,
|
||||||
|
@PreviewID uniqueidentifier
|
||||||
|
AS
|
||||||
|
BEGIN
|
||||||
|
SET NOCOUNT ON;
|
||||||
|
|
||||||
|
DELETE dbo.CoreImportBasicLocationReviews
|
||||||
|
WHERE UserID = @UserID
|
||||||
|
AND PreviewID = @PreviewID;
|
||||||
|
END;
|
||||||
|
GO
|
||||||
@ -956,6 +956,9 @@ public sealed class CoreImportBasicLocationReviewViewModel
|
|||||||
public string DocumentTitle { get; init; } = "Word manuscript";
|
public string DocumentTitle { get; init; } = "Word manuscript";
|
||||||
public string SelectedProjectName { get; init; } = string.Empty;
|
public string SelectedProjectName { get; init; } = string.Empty;
|
||||||
public string SelectedBookTitle { get; init; } = string.Empty;
|
public string SelectedBookTitle { get; init; } = string.Empty;
|
||||||
|
public string FormController { get; init; } = "Onboarding";
|
||||||
|
public string FormAction { get; init; } = "SaveBasicLocations";
|
||||||
|
public string ContinueButtonText { get; init; } = "Save locations and review characters";
|
||||||
public int RawObservationCount { get; init; }
|
public int RawObservationCount { get; init; }
|
||||||
public int CandidateCount { get; init; }
|
public int CandidateCount { get; init; }
|
||||||
public IReadOnlyList<CoreImportBasicLocationCandidateViewModel> Candidates { get; init; } = [];
|
public IReadOnlyList<CoreImportBasicLocationCandidateViewModel> Candidates { get; init; } = [];
|
||||||
|
|||||||
@ -31,7 +31,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form asp-controller="Onboarding" asp-action="SaveBasicLocations" method="post">
|
<form asp-controller="@Model.FormController" asp-action="@Model.FormAction" method="post">
|
||||||
@Html.AntiForgeryToken()
|
@Html.AntiForgeryToken()
|
||||||
<input type="hidden" name="PreviewID" value="@Model.PreviewID" />
|
<input type="hidden" name="PreviewID" value="@Model.PreviewID" />
|
||||||
|
|
||||||
@ -122,7 +122,7 @@
|
|||||||
<div class="form-actions">
|
<div class="form-actions">
|
||||||
<button class="btn btn-secondary" type="submit" name="intent" value="save">Save choices</button>
|
<button class="btn btn-secondary" type="submit" name="intent" value="save">Save choices</button>
|
||||||
<button class="btn btn-outline-secondary" type="submit" name="intent" value="skip">Skip locations</button>
|
<button class="btn btn-outline-secondary" type="submit" name="intent" value="skip">Skip locations</button>
|
||||||
<button class="btn btn-primary" type="submit" name="intent" value="continue">Save locations and review characters</button>
|
<button class="btn btn-primary" type="submit" name="intent" value="continue">@Model.ContinueButtonText</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user