110 lines
4.3 KiB
Plaintext
110 lines
4.3 KiB
Plaintext
@model StoryIntelligenceSavedRunsViewModel
|
|
@{
|
|
ViewData["Title"] = "Saved Story Intelligence Runs";
|
|
}
|
|
|
|
<div class="page-heading compact">
|
|
<div>
|
|
<p class="eyebrow">Admin utility</p>
|
|
<h1>Saved Story Intelligence Runs</h1>
|
|
<p class="lead-text">Audit records saved from the admin chapter-to-scene dry-run pipeline.</p>
|
|
</div>
|
|
</div>
|
|
|
|
<nav class="mb-3" aria-label="Breadcrumb">
|
|
<a asp-controller="Projects" asp-action="Index">Projects</a>
|
|
<span class="muted"> / </span>
|
|
<a asp-action="Index">Admin</a>
|
|
<span class="muted"> / Saved Story Intelligence Runs</span>
|
|
</nav>
|
|
|
|
@if (TempData["AdminMessage"] is string message)
|
|
{
|
|
<div class="alert alert-success">@message</div>
|
|
}
|
|
|
|
<section class="edit-panel">
|
|
<div class="button-row mb-3">
|
|
<a class="btn btn-primary" asp-action="ChapterStoryIntelligenceTest">Run pipeline test</a>
|
|
<a class="btn btn-outline-primary" asp-action="StoryIntelligenceExistingChapter">Queue from existing chapter</a>
|
|
<a class="btn btn-outline-secondary" asp-action="StoryIntelligenceDiagnostics">Diagnostics</a>
|
|
</div>
|
|
|
|
@if (Model.Runs.Count == 0)
|
|
{
|
|
<p class="mb-0">No Story Intelligence runs have been saved yet.</p>
|
|
}
|
|
else
|
|
{
|
|
<div class="table-responsive">
|
|
<table class="table align-middle">
|
|
<thead>
|
|
<tr>
|
|
<th>Run ID</th>
|
|
<th>Created</th>
|
|
<th>Project / Book</th>
|
|
<th>Status</th>
|
|
<th>Source</th>
|
|
<th>Failure stage</th>
|
|
<th>Scenes</th>
|
|
<th>Tokens</th>
|
|
<th>Cost</th>
|
|
<th>Duration</th>
|
|
<th>Validation</th>
|
|
<th></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@foreach (var run in Model.Runs)
|
|
{
|
|
<tr>
|
|
<td>@run.StoryIntelligenceRunID.ToString("N0")</td>
|
|
<td>@run.CreatedUtc.ToString("yyyy-MM-dd HH:mm") UTC</td>
|
|
<td>
|
|
<div>@DisplayName(run.ProjectTitle, run.ProjectID, "Project")</div>
|
|
<div class="muted">@DisplayName(run.BookTitle, run.BookID, "Book")</div>
|
|
</td>
|
|
<td>@run.Status</td>
|
|
<td>@Display(run.SourceType)</td>
|
|
<td>@Display(run.FailureStage)</td>
|
|
<td>@run.SceneCount.ToString("N0")</td>
|
|
<td>@Display(run.TotalTokens)</td>
|
|
<td>@DisplayCost(run.EstimatedCostGBP, "GBP") / @DisplayCost(run.EstimatedCostUSD, "USD")</td>
|
|
<td>@DisplayDuration(run.TotalDurationMs)</td>
|
|
<td>@run.ValidationErrorsCount.ToString("N0") error(s), @run.ValidationWarningsCount.ToString("N0") warning(s)</td>
|
|
<td><a class="btn btn-outline-primary btn-sm" asp-action="StoryIntelligenceRunDetails" asp-route-id="@run.StoryIntelligenceRunID">Open</a></td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
}
|
|
</section>
|
|
|
|
@functions {
|
|
private static string Display(object? value) => value switch
|
|
{
|
|
null => "None",
|
|
string text when string.IsNullOrWhiteSpace(text) => "None",
|
|
int number => number.ToString("N0"),
|
|
_ => value.ToString() ?? "None"
|
|
};
|
|
|
|
private static string DisplayDuration(long? milliseconds)
|
|
=> milliseconds.HasValue
|
|
? TimeSpan.FromMilliseconds(milliseconds.Value).TotalSeconds < 1
|
|
? $"{milliseconds.Value:N0} ms"
|
|
: $"{TimeSpan.FromMilliseconds(milliseconds.Value).TotalSeconds:0.00} sec"
|
|
: "None";
|
|
|
|
private static string DisplayCost(decimal? value, string currency)
|
|
=> value.HasValue ? $"{value.Value:0.000000} {currency}" : "None";
|
|
|
|
private static string DisplayName(string? title, int? id, string label)
|
|
=> !string.IsNullOrWhiteSpace(title)
|
|
? title
|
|
: id.HasValue
|
|
? $"{label} {id.Value:N0}"
|
|
: "None";
|
|
}
|