Implemented the dashboard layout refinement.
This commit is contained in:
parent
d872289e6f
commit
76fde1b74b
@ -406,7 +406,7 @@ public sealed class ProjectService(
|
||||
|
||||
var projectBooks = await books.ListByProjectAsync(projectId);
|
||||
var metrics = await projects.GetDashboardMetricsAsync(projectId);
|
||||
var recentActivity = await projectActivity.ListRecentForProjectAsync(projectId, 10);
|
||||
var recentActivity = await projectActivity.ListRecentForProjectAsync(projectId, 5);
|
||||
var dashboardWarnings = await warnings.ListDashboardUnresolvedAsync(projectId, 5);
|
||||
var attentionThreads = await projects.ListDashboardAttentionThreadsAsync(projectId, 5);
|
||||
var writingPlans = await writingSchedule.GetWritingPlanSummariesByUserAsync(userId, projectId);
|
||||
|
||||
@ -86,7 +86,84 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="mb-4" aria-label="Dashboard attention">
|
||||
<section class="mb-4" aria-label="Books">
|
||||
<div class="d-flex align-items-center justify-content-between gap-3 flex-wrap mb-3">
|
||||
<h2 class="h4 mb-0">Books <help-icon key="projects.books" /></h2>
|
||||
<a class="btn btn-primary btn-sm" asp-controller="Books" asp-action="Create" asp-route-projectId="@Model.Project.ProjectID">Add book</a>
|
||||
</div>
|
||||
|
||||
@if (!Model.Books.Any())
|
||||
{
|
||||
<div class="empty-panel">
|
||||
<h2>No books yet</h2>
|
||||
<p class="muted mb-0">Add the first book to begin shaping this series.</p>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="row g-4">
|
||||
@foreach (var book in Model.Books)
|
||||
{
|
||||
<div class="col-12 col-md-6 col-lg-4">
|
||||
<article class="card h-100 overflow-hidden">
|
||||
<div class="row g-0 h-100">
|
||||
<div class="col-4 d-flex align-items-center justify-content-center" style="aspect-ratio:2 / 3; background:var(--plotline-soft);">
|
||||
<img src="@book.CoverThumbnailPath"
|
||||
alt="Cover for @book.BookTitle"
|
||||
class="img-fluid"
|
||||
style="max-width:100%; max-height:100%; object-fit:contain;" />
|
||||
</div>
|
||||
<div class="col-8">
|
||||
<div class="card-body h-100 d-flex flex-column">
|
||||
<div class="d-flex align-items-start justify-content-between gap-2 mb-2">
|
||||
<div>
|
||||
<p class="eyebrow mb-1">Book @book.BookNumber</p>
|
||||
<h3 class="h5 mb-1">
|
||||
<a asp-controller="Books" asp-action="Details" asp-route-id="@book.BookID">@book.BookTitle</a>
|
||||
</h3>
|
||||
@if (!string.IsNullOrWhiteSpace(book.Subtitle))
|
||||
{
|
||||
<p class="muted mb-0">@book.Subtitle</p>
|
||||
}
|
||||
</div>
|
||||
<span class="status-pill">@book.Status</span>
|
||||
</div>
|
||||
|
||||
<p class="mb-2">@book.WordCountLabel</p>
|
||||
@if (book.ProgressPercentage.HasValue)
|
||||
{
|
||||
var progressValue = Math.Round(book.ProgressPercentage.Value);
|
||||
<div class="progress mb-3" role="progressbar" aria-label="Book progress" aria-valuenow="@progressValue" aria-valuemin="0" aria-valuemax="100" style="height:8px;">
|
||||
<div class="progress-bar" style="width:@progressValue%"></div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="d-flex gap-3 flex-wrap small text-muted mb-3">
|
||||
<span>@book.ChapterCount.ToString("N0") chapters</span>
|
||||
<span>@book.SceneCount.ToString("N0") scenes</span>
|
||||
<span>Modified @book.UpdatedDate.ToString("dd MMM yyyy")</span>
|
||||
</div>
|
||||
|
||||
<div class="button-row mt-auto">
|
||||
<a class="btn btn-primary btn-sm" asp-controller="Books" asp-action="Details" asp-route-id="@book.BookID">Open Book</a>
|
||||
<a class="btn btn-outline-secondary btn-sm" asp-controller="Books" asp-action="Edit" asp-route-id="@book.BookID">Edit Book</a>
|
||||
<form asp-controller="Books" asp-action="Archive" method="post" class="archive-button-form" data-confirm-message="Archive this book? This will hide it from active lists and timelines, but the data will be kept and can be restored later.">
|
||||
<input type="hidden" name="id" value="@book.BookID" />
|
||||
<input type="hidden" name="projectId" value="@Model.Project.ProjectID" />
|
||||
<button class="btn btn-outline-danger btn-sm" type="submit">Archive</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</section>
|
||||
|
||||
<section aria-label="Dashboard attention">
|
||||
<div class="row g-4">
|
||||
<div class="col-12 col-xl-7">
|
||||
<article class="card h-100">
|
||||
@ -220,80 +297,3 @@
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section aria-label="Books">
|
||||
<div class="d-flex align-items-center justify-content-between gap-3 flex-wrap mb-3">
|
||||
<h2 class="h4 mb-0">Books <help-icon key="projects.books" /></h2>
|
||||
<a class="btn btn-primary btn-sm" asp-controller="Books" asp-action="Create" asp-route-projectId="@Model.Project.ProjectID">Add book</a>
|
||||
</div>
|
||||
|
||||
@if (!Model.Books.Any())
|
||||
{
|
||||
<div class="empty-panel">
|
||||
<h2>No books yet</h2>
|
||||
<p class="muted mb-0">Add the first book to begin shaping this series.</p>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="row g-4">
|
||||
@foreach (var book in Model.Books)
|
||||
{
|
||||
<div class="col-12 col-md-6 col-lg-4">
|
||||
<article class="card h-100 overflow-hidden">
|
||||
<div class="row g-0 h-100">
|
||||
<div class="col-4 d-flex align-items-center justify-content-center" style="aspect-ratio:2 / 3; background:var(--plotline-soft);">
|
||||
<img src="@book.CoverThumbnailPath"
|
||||
alt="Cover for @book.BookTitle"
|
||||
class="img-fluid"
|
||||
style="max-width:100%; max-height:100%; object-fit:contain;" />
|
||||
</div>
|
||||
<div class="col-8">
|
||||
<div class="card-body h-100 d-flex flex-column">
|
||||
<div class="d-flex align-items-start justify-content-between gap-2 mb-2">
|
||||
<div>
|
||||
<p class="eyebrow mb-1">Book @book.BookNumber</p>
|
||||
<h3 class="h5 mb-1">
|
||||
<a asp-controller="Books" asp-action="Details" asp-route-id="@book.BookID">@book.BookTitle</a>
|
||||
</h3>
|
||||
@if (!string.IsNullOrWhiteSpace(book.Subtitle))
|
||||
{
|
||||
<p class="muted mb-0">@book.Subtitle</p>
|
||||
}
|
||||
</div>
|
||||
<span class="status-pill">@book.Status</span>
|
||||
</div>
|
||||
|
||||
<p class="mb-2">@book.WordCountLabel</p>
|
||||
@if (book.ProgressPercentage.HasValue)
|
||||
{
|
||||
var progressValue = Math.Round(book.ProgressPercentage.Value);
|
||||
<div class="progress mb-3" role="progressbar" aria-label="Book progress" aria-valuenow="@progressValue" aria-valuemin="0" aria-valuemax="100" style="height:8px;">
|
||||
<div class="progress-bar" style="width:@progressValue%"></div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="d-flex gap-3 flex-wrap small text-muted mb-3">
|
||||
<span>@book.ChapterCount.ToString("N0") chapters</span>
|
||||
<span>@book.SceneCount.ToString("N0") scenes</span>
|
||||
<span>Modified @book.UpdatedDate.ToString("dd MMM yyyy")</span>
|
||||
</div>
|
||||
|
||||
<div class="button-row mt-auto">
|
||||
<a class="btn btn-primary btn-sm" asp-controller="Books" asp-action="Details" asp-route-id="@book.BookID">Open Book</a>
|
||||
<a class="btn btn-outline-secondary btn-sm" asp-controller="Books" asp-action="Edit" asp-route-id="@book.BookID">Edit Book</a>
|
||||
<form asp-controller="Books" asp-action="Archive" method="post" class="archive-button-form" data-confirm-message="Archive this book? This will hide it from active lists and timelines, but the data will be kept and can be restored later.">
|
||||
<input type="hidden" name="id" value="@book.BookID" />
|
||||
<input type="hidden" name="projectId" value="@Model.Project.ProjectID" />
|
||||
<button class="btn btn-outline-danger btn-sm" type="submit">Archive</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</section>
|
||||
|
||||
BIN
PlotLine/wwwroot/uploads/books/21/cover-standard.webp
Normal file
BIN
PlotLine/wwwroot/uploads/books/21/cover-standard.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 65 KiB |
BIN
PlotLine/wwwroot/uploads/books/21/cover-thumb.webp
Normal file
BIN
PlotLine/wwwroot/uploads/books/21/cover-thumb.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 33 KiB |
Loading…
x
Reference in New Issue
Block a user