2026-06-01 20:47:20 +01:00

138 lines
5.5 KiB
Plaintext

@model ImportIndexViewModel
@{
ViewData["Title"] = "JSON Import";
var preview = Model.Preview;
}
<div class="page-heading compact">
<div>
<p class="eyebrow">Tools</p>
<h1>JSON Import</h1>
<p class="lead-text">Paste or upload a Phase 1A package, preview it, then import a new project when validation passes.</p>
</div>
<a class="btn btn-outline-secondary" asp-controller="Projects" asp-action="Index">Back to projects</a>
</div>
@if (!string.IsNullOrWhiteSpace(Model.StatusMessage))
{
<div class="alert alert-warning">@Model.StatusMessage</div>
}
<section class="edit-panel import-panel">
<form asp-action="Preview" method="post" enctype="multipart/form-data">
<div class="row g-3">
<div class="col-12">
<label asp-for="JsonFile" class="form-label">Upload JSON file</label>
<input asp-for="JsonFile" class="form-control" type="file" accept=".json,application/json" />
<div class="form-text">Uploading a file replaces the pasted text for this preview.</div>
</div>
<div class="col-12">
<label asp-for="JsonText" class="form-label">JSON package</label>
<textarea asp-for="JsonText" class="form-control import-json-input" rows="22" spellcheck="false"></textarea>
</div>
</div>
<div class="button-row mt-3">
<button class="btn btn-primary" type="submit">Validate and preview</button>
<button class="btn btn-outline-secondary" type="button" data-copy-sample>Use sample JSON</button>
</div>
</form>
</section>
@if (preview is not null)
{
<section class="list-section import-preview-section mt-3">
<div class="import-preview-heading">
<div>
<p class="eyebrow">Preview</p>
<h2>@(preview.Package?.Project.Title ?? "Import package")</h2>
</div>
<div class="import-counts">
<span><strong>@preview.BookCount</strong> books</span>
<span><strong>@preview.ChapterCount</strong> chapters</span>
<span><strong>@preview.SceneCount</strong> scenes</span>
</div>
</div>
@if (preview.Validation.Errors.Any())
{
<div class="alert alert-warning">
<strong>Validation needs attention</strong>
<ul class="mb-0 mt-2">
@foreach (var error in preview.Validation.Errors)
{
<li>@error</li>
}
</ul>
</div>
}
@if (preview.Validation.Warnings.Any())
{
<div class="alert alert-info">
<strong>Import notes</strong>
<ul class="mb-0 mt-2">
@foreach (var warning in preview.Validation.Warnings)
{
<li>@warning</li>
}
</ul>
</div>
}
@if (preview.Package is not null)
{
<div class="import-tree">
@foreach (var book in preview.Package.Books.OrderBy(x => x.SeriesOrder))
{
<article class="import-tree-book">
<h3>Book @book.SeriesOrder: @(string.IsNullOrWhiteSpace(book.Subtitle) ? book.Title : $"{book.Title}: {book.Subtitle}")</h3>
@foreach (var chapter in book.Chapters.OrderBy(x => x.Order))
{
<div class="import-tree-chapter">
<strong>Chapter @chapter.ChapterNumber: @chapter.Title</strong>
<ul>
@foreach (var scene in chapter.Scenes.OrderBy(x => x.Order))
{
<li>Scene @scene.SceneNumber: @scene.Title</li>
}
</ul>
</div>
}
</article>
}
</div>
<form asp-action="Import" method="post" class="import-confirm-form mt-3">
<input asp-for="JsonText" type="hidden" />
@if (preview.HasDuplicateProjectTitle)
{
<div class="form-check import-duplicate-confirm">
<input asp-for="AllowDuplicateProjectTitle" class="form-check-input" />
<label asp-for="AllowDuplicateProjectTitle" class="form-check-label">
Import anyway and create another project with this same title.
</label>
</div>
}
<button class="btn btn-primary mt-3" type="submit" disabled="@(!Model.CanImport)">Import project</button>
</form>
}
</section>
}
<script type="application/json" id="importSampleJson">@Html.Raw(System.Text.Json.JsonSerializer.Serialize(ImportIndexViewModel.SampleJson))</script>
@section Scripts {
<script>
(() => {
const button = document.querySelector("[data-copy-sample]");
const textarea = document.querySelector("#JsonText");
const sample = document.querySelector("#importSampleJson");
if (!button || !textarea || !sample) return;
button.addEventListener("click", () => {
textarea.value = JSON.parse(sample.textContent);
textarea.focus();
});
})();
</script>
}