First cut of admin dashboard
Add web log details to common model
This commit is contained in:
parent
39e0d5ec8b
commit
8f94d7ddfe
13
src/MyWebLog.Data/Extensions/CategoryExtensions.cs
Normal file
13
src/MyWebLog.Data/Extensions/CategoryExtensions.cs
Normal file
|
@ -0,0 +1,13 @@
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace MyWebLog.Data;
|
||||
|
||||
public static class CategoryEtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Count all categories
|
||||
/// </summary>
|
||||
/// <returns>A count of all categories</returns>
|
||||
public static async Task<int> CountAll(this DbSet<Category> db) =>
|
||||
await db.CountAsync().ConfigureAwait(false);
|
||||
}
|
|
@ -4,11 +4,26 @@ namespace MyWebLog.Data;
|
|||
|
||||
public static class PageExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Count the number of pages
|
||||
/// </summary>
|
||||
/// <returns>The number of pages</returns>
|
||||
public static async Task<int> CountAll(this DbSet<Page> db) =>
|
||||
await db.CountAsync().ConfigureAwait(false);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve a page by its ID (non-tracked)
|
||||
/// </summary>
|
||||
/// <param name="id">The ID of the page to retrieve</param>
|
||||
/// <returns>The requested page (or null if it is not found)</returns>
|
||||
public static async Task<Page?> FindById(this DbSet<Page> db, string id) =>
|
||||
await db.FirstOrDefaultAsync(p => p.Id == id).ConfigureAwait(false);
|
||||
await db.SingleOrDefaultAsync(p => p.Id == id).ConfigureAwait(false);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve a page by its permalink (non-tracked)
|
||||
/// </summary>
|
||||
/// <param name="permalink">The permalink</param>
|
||||
/// <returns>The requested page (or null if it is not found)</returns>
|
||||
public static async Task<Page?> FindByPermalink(this DbSet<Page> db, string permalink) =>
|
||||
await db.SingleOrDefaultAsync(p => p.Permalink == permalink).ConfigureAwait(false);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,22 @@ namespace MyWebLog.Data;
|
|||
|
||||
public static class PostExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Count the posts in the given status
|
||||
/// </summary>
|
||||
/// <param name="status">The status for which posts should be counted</param>
|
||||
/// <returns>A count of the posts in the given status</returns>
|
||||
public static async Task<int> CountByStatus(this DbSet<Post> db, PostStatus status) =>
|
||||
await db.CountAsync(p => p.Status == status).ConfigureAwait(false);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve a post by its permalink (non-tracked)
|
||||
/// </summary>
|
||||
/// <param name="permalink">The possible post permalink</param>
|
||||
/// <returns>The post matching the permalink, or null if none is found</returns>
|
||||
public static async Task<Post?> FindByPermalink(this DbSet<Post> db, string permalink) =>
|
||||
await db.SingleOrDefaultAsync(p => p.Id == permalink).ConfigureAwait(false);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve a page of published posts (non-tracked)
|
||||
/// </summary>
|
||||
|
|
|
@ -12,8 +12,12 @@ public class AdminController : MyWebLogController
|
|||
public AdminController(WebLogDbContext db) : base(db) { }
|
||||
|
||||
[HttpGet("")]
|
||||
public IActionResult Index()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
public async Task<IActionResult> Index() =>
|
||||
View(new DashboardModel(WebLog)
|
||||
{
|
||||
Posts = await Db.Posts.CountByStatus(PostStatus.Published),
|
||||
Drafts = await Db.Posts.CountByStatus(PostStatus.Draft),
|
||||
Pages = await Db.Pages.CountAll(),
|
||||
Categories = await Db.Categories.CountAll()
|
||||
});
|
||||
}
|
||||
|
|
30
src/MyWebLog/Features/Admin/DashboardModel.cs
Normal file
30
src/MyWebLog/Features/Admin/DashboardModel.cs
Normal file
|
@ -0,0 +1,30 @@
|
|||
namespace MyWebLog.Features.Admin;
|
||||
|
||||
/// <summary>
|
||||
/// The model used to display the dashboard
|
||||
/// </summary>
|
||||
public class DashboardModel : MyWebLogModel
|
||||
{
|
||||
/// <summary>
|
||||
/// The number of published posts
|
||||
/// </summary>
|
||||
public int Posts { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// The number of post drafts
|
||||
/// </summary>
|
||||
public int Drafts { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// The number of pages
|
||||
/// </summary>
|
||||
public int Pages { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// The number of categories
|
||||
/// </summary>
|
||||
public int Categories { get; set; } = 0;
|
||||
|
||||
/// <inheritdoc />
|
||||
public DashboardModel(WebLogDetails webLog) : base(webLog) { }
|
||||
}
|
|
@ -1,5 +1,35 @@
|
|||
@{
|
||||
@model DashboardModel
|
||||
@{
|
||||
Layout = "_AdminLayout";
|
||||
ViewBag.Title = Resources.Dashboard;
|
||||
}
|
||||
<p>You're logged on!</p>
|
||||
<article class="container">
|
||||
<div class="row">
|
||||
<section class="col col-sm-4">
|
||||
<h3>@Resources.Posts</h3>
|
||||
<p>@string.Format(Resources.ThereAreXPublishedPostsAndYDrafts, Model.Posts, Model.Drafts)</p>
|
||||
<p>
|
||||
<a asp-action="All" asp-controller="Post" class="btn btn-secondary me-2">View All</a>
|
||||
<a asp-action="Edit" asp-controller="Post" asp-route-id="new" class="btn btn-primary">Write a New Post</a>
|
||||
</p>
|
||||
</section>
|
||||
<section class="col col-sm-4">
|
||||
<h3>@Resources.Pages</h3>
|
||||
<p>@string.Format(Resources.ThereAreXPages, Model.Pages)</p>
|
||||
<p>
|
||||
<a asp-action="All" asp-controller="Page" class="btn btn-secondary me-2">View All</a>
|
||||
<a asp-action="Edit" asp-controller="Page" asp-route-id="new" class="btn btn-primary">Create a New Page</a>
|
||||
</p>
|
||||
</section>
|
||||
<section class="col col-sm-4">
|
||||
<h3>@Resources.Categories</h3>
|
||||
<p>@string.Format(Resources.ThereAreXCategories, Model.Categories)</p>
|
||||
<p>
|
||||
<a asp-action="All" asp-controller="Category" class="btn btn-secondary me-2">View All</a>
|
||||
<a asp-action="Edit" asp-controller="Category" asp-route-id="new" class="btn btn-secondary">
|
||||
Add a New Category
|
||||
</a>
|
||||
</p>
|
||||
</section>
|
||||
</div>
|
||||
</article>
|
||||
|
|
29
src/MyWebLog/Features/Categories/CategoryController.cs
Normal file
29
src/MyWebLog/Features/Categories/CategoryController.cs
Normal file
|
@ -0,0 +1,29 @@
|
|||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace MyWebLog.Features.Categories;
|
||||
|
||||
/// <summary>
|
||||
/// Handle routes for categories
|
||||
/// </summary>
|
||||
[Route("/category")]
|
||||
[Authorize]
|
||||
public class CategoryController : MyWebLogController
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public CategoryController(WebLogDbContext db) : base(db) { }
|
||||
|
||||
[HttpGet("all")]
|
||||
public async Task<IActionResult> All()
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
[HttpGet("{id}/edit")]
|
||||
public async Task<IActionResult> Edit(string id)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
29
src/MyWebLog/Features/Pages/PageController.cs
Normal file
29
src/MyWebLog/Features/Pages/PageController.cs
Normal file
|
@ -0,0 +1,29 @@
|
|||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace MyWebLog.Features.Pages;
|
||||
|
||||
/// <summary>
|
||||
/// Handle routes for pages
|
||||
/// </summary>
|
||||
[Route("/page")]
|
||||
[Authorize]
|
||||
public class PageController : MyWebLogController
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public PageController(WebLogDbContext db) : base(db) { }
|
||||
|
||||
[HttpGet("all")]
|
||||
public async Task<IActionResult> All()
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
[HttpGet("{id}/edit")]
|
||||
public async Task<IActionResult> Edit(string id)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
22
src/MyWebLog/Features/Pages/SinglePageModel.cs
Normal file
22
src/MyWebLog/Features/Pages/SinglePageModel.cs
Normal file
|
@ -0,0 +1,22 @@
|
|||
namespace MyWebLog.Features.Pages;
|
||||
|
||||
/// <summary>
|
||||
/// The model used to render a single page
|
||||
/// </summary>
|
||||
public class SinglePageModel : MyWebLogModel
|
||||
{
|
||||
/// <summary>
|
||||
/// The page to be rendered
|
||||
/// </summary>
|
||||
public Page Page { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="page">The page to be rendered</param>
|
||||
/// <param name="webLog">The details for the web log</param>
|
||||
public SinglePageModel(Page page, WebLogDetails webLog) : base(webLog)
|
||||
{
|
||||
Page = page;
|
||||
}
|
||||
}
|
22
src/MyWebLog/Features/Posts/MultiplePostModel.cs
Normal file
22
src/MyWebLog/Features/Posts/MultiplePostModel.cs
Normal file
|
@ -0,0 +1,22 @@
|
|||
namespace MyWebLog.Features.Posts;
|
||||
|
||||
/// <summary>
|
||||
/// The model used to render multiple posts
|
||||
/// </summary>
|
||||
public class MultiplePostModel : MyWebLogModel
|
||||
{
|
||||
/// <summary>
|
||||
/// The posts to be rendered
|
||||
/// </summary>
|
||||
public IEnumerable<Post> Posts { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="posts">The posts to be rendered</param>
|
||||
/// <param name="webLog">The details for the web log</param>
|
||||
public MultiplePostModel(IEnumerable<Post> posts, WebLogDetails webLog) : base(webLog)
|
||||
{
|
||||
Posts = posts;
|
||||
}
|
||||
}
|
|
@ -1,25 +1,68 @@
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using MyWebLog.Features.Pages;
|
||||
|
||||
namespace MyWebLog.Features.Posts;
|
||||
|
||||
/// <summary>
|
||||
/// Handle post-related requests
|
||||
/// </summary>
|
||||
[Route("/post")]
|
||||
[Authorize]
|
||||
public class PostController : MyWebLogController
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public PostController(WebLogDbContext db) : base(db) { }
|
||||
|
||||
[HttpGet("~/")]
|
||||
[AllowAnonymous]
|
||||
public async Task<IActionResult> Index()
|
||||
{
|
||||
var webLog = WebLogCache.Get(HttpContext);
|
||||
if (webLog.DefaultPage == "posts")
|
||||
if (WebLog.DefaultPage == "posts") return await PageOfPosts(1);
|
||||
|
||||
var page = await Db.Pages.FindById(WebLog.DefaultPage);
|
||||
return page is null ? NotFound() : ThemedView("SinglePage", new SinglePageModel(page, WebLog));
|
||||
}
|
||||
|
||||
[HttpGet("~/page/{pageNbr:int}")]
|
||||
[AllowAnonymous]
|
||||
public async Task<IActionResult> PageOfPosts(int pageNbr) =>
|
||||
ThemedView("Index",
|
||||
new MultiplePostModel(await Db.Posts.FindPageOfPublishedPosts(pageNbr, WebLog.PostsPerPage), WebLog));
|
||||
|
||||
[HttpGet("~/{*permalink}")]
|
||||
public async Task<IActionResult> CatchAll(string permalink)
|
||||
{
|
||||
Console.Write($"Got permalink |{permalink}|");
|
||||
var post = await Db.Posts.FindByPermalink(permalink);
|
||||
if (post != null)
|
||||
{
|
||||
var posts = await Db.Posts.FindPageOfPublishedPosts(1, webLog.PostsPerPage);
|
||||
return ThemedView("Index", posts);
|
||||
// TODO: return via single-post action
|
||||
}
|
||||
var page = await Db.Pages.FindById(webLog.DefaultPage);
|
||||
return page is null ? NotFound() : ThemedView("SinglePage", page);
|
||||
|
||||
var page = await Db.Pages.FindByPermalink(permalink);
|
||||
if (page != null)
|
||||
{
|
||||
return ThemedView("SinglePage", new SinglePageModel(page, WebLog));
|
||||
}
|
||||
|
||||
// TOOD: search prior permalinks for posts and pages
|
||||
|
||||
await Task.CompletedTask;
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
[HttpGet("all")]
|
||||
public async Task<IActionResult> All()
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
[HttpGet("{id}/edit")]
|
||||
public async Task<IActionResult> Edit(string id)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,11 +9,16 @@ public abstract class MyWebLogController : Controller
|
|||
/// </summary>
|
||||
protected WebLogDbContext Db { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// The details for the current web log
|
||||
/// </summary>
|
||||
protected WebLogDetails WebLog => WebLogCache.Get(HttpContext);
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="db">The data context to use to fulfil this request</param>
|
||||
protected MyWebLogController(WebLogDbContext db)
|
||||
protected MyWebLogController(WebLogDbContext db) : base()
|
||||
{
|
||||
Db = db;
|
||||
}
|
||||
|
|
21
src/MyWebLog/Features/Shared/MyWebLogModel.cs
Normal file
21
src/MyWebLog/Features/Shared/MyWebLogModel.cs
Normal file
|
@ -0,0 +1,21 @@
|
|||
namespace MyWebLog.Features.Shared;
|
||||
|
||||
/// <summary>
|
||||
/// Base model class for myWebLog views
|
||||
/// </summary>
|
||||
public class MyWebLogModel
|
||||
{
|
||||
/// <summary>
|
||||
/// The details for the web log
|
||||
/// </summary>
|
||||
public WebLogDetails WebLog { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="webLog">The details for the web log</param>
|
||||
protected MyWebLogModel(WebLogDetails webLog)
|
||||
{
|
||||
WebLog = webLog;
|
||||
}
|
||||
}
|
|
@ -1,12 +1,9 @@
|
|||
@inject IHttpContextAccessor ctxAcc
|
||||
@{
|
||||
var details = WebLogCache.Get(ctxAcc.HttpContext!);
|
||||
}
|
||||
@model MyWebLogModel
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<title>@ViewBag.Title « @Resources.Admin « @details.Name</title>
|
||||
<title>@ViewBag.Title « @Resources.Admin « @Model.WebLog.Name</title>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"
|
||||
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="~/css/admin.css">
|
||||
|
@ -15,7 +12,7 @@
|
|||
<header>
|
||||
<nav class="navbar navbar-dark bg-dark navbar-expand-md justify-content-start px-2">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="~/">@details.Name</a>
|
||||
<a class="navbar-brand" href="~/">@Model.WebLog.Name</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarText"
|
||||
aria-controls="navbarText" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
|
|
|
@ -5,7 +5,7 @@ namespace MyWebLog.Features.Users;
|
|||
/// <summary>
|
||||
/// The model to use to allow a user to log on
|
||||
/// </summary>
|
||||
public class LogOnModel
|
||||
public class LogOnModel : MyWebLogModel
|
||||
{
|
||||
/// <summary>
|
||||
/// The user's e-mail address
|
||||
|
@ -21,4 +21,10 @@ public class LogOnModel
|
|||
[Required(AllowEmptyStrings = false)]
|
||||
[Display(ResourceType = typeof(Resources), Name = "Password")]
|
||||
public string Password { get; set; } = "";
|
||||
|
||||
[Obsolete("Only used for model binding; use the WebLogDetails constructor")]
|
||||
public LogOnModel() : base(new()) { }
|
||||
|
||||
/// <inheritdoc />
|
||||
public LogOnModel(WebLogDetails webLog) : base(webLog) { }
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ public class UserController : MyWebLogController
|
|||
|
||||
[HttpGet("log-on")]
|
||||
public IActionResult LogOn() =>
|
||||
View(new LogOnModel());
|
||||
View(new LogOnModel(WebLog));
|
||||
|
||||
[HttpPost("log-on")]
|
||||
public async Task<IActionResult> DoLogOn(LogOnModel model)
|
||||
|
|
54
src/MyWebLog/Properties/Resources.Designer.cs
generated
54
src/MyWebLog/Properties/Resources.Designer.cs
generated
|
@ -69,6 +69,15 @@ namespace MyWebLog.Properties {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Categories.
|
||||
/// </summary>
|
||||
public static string Categories {
|
||||
get {
|
||||
return ResourceManager.GetString("Categories", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Dashboard.
|
||||
/// </summary>
|
||||
|
@ -105,6 +114,15 @@ namespace MyWebLog.Properties {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Pages.
|
||||
/// </summary>
|
||||
public static string Pages {
|
||||
get {
|
||||
return ResourceManager.GetString("Pages", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Password.
|
||||
/// </summary>
|
||||
|
@ -113,5 +131,41 @@ namespace MyWebLog.Properties {
|
|||
return ResourceManager.GetString("Password", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Posts.
|
||||
/// </summary>
|
||||
public static string Posts {
|
||||
get {
|
||||
return ResourceManager.GetString("Posts", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to There are {0} categories.
|
||||
/// </summary>
|
||||
public static string ThereAreXCategories {
|
||||
get {
|
||||
return ResourceManager.GetString("ThereAreXCategories", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to There are {0} pages.
|
||||
/// </summary>
|
||||
public static string ThereAreXPages {
|
||||
get {
|
||||
return ResourceManager.GetString("ThereAreXPages", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to There are {0} published posts and {1} drafts.
|
||||
/// </summary>
|
||||
public static string ThereAreXPublishedPostsAndYDrafts {
|
||||
get {
|
||||
return ResourceManager.GetString("ThereAreXPublishedPostsAndYDrafts", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -120,6 +120,9 @@
|
|||
<data name="Admin" xml:space="preserve">
|
||||
<value>Admin</value>
|
||||
</data>
|
||||
<data name="Categories" xml:space="preserve">
|
||||
<value>Categories</value>
|
||||
</data>
|
||||
<data name="Dashboard" xml:space="preserve">
|
||||
<value>Dashboard</value>
|
||||
</data>
|
||||
|
@ -132,7 +135,22 @@
|
|||
<data name="LogOn" xml:space="preserve">
|
||||
<value>Log On</value>
|
||||
</data>
|
||||
<data name="Pages" xml:space="preserve">
|
||||
<value>Pages</value>
|
||||
</data>
|
||||
<data name="Password" xml:space="preserve">
|
||||
<value>Password</value>
|
||||
</data>
|
||||
<data name="Posts" xml:space="preserve">
|
||||
<value>Posts</value>
|
||||
</data>
|
||||
<data name="ThereAreXCategories" xml:space="preserve">
|
||||
<value>There are {0} categories</value>
|
||||
</data>
|
||||
<data name="ThereAreXPages" xml:space="preserve">
|
||||
<value>There are {0} pages</value>
|
||||
</data>
|
||||
<data name="ThereAreXPublishedPostsAndYDrafts" xml:space="preserve">
|
||||
<value>There are {0} published posts and {1} drafts</value>
|
||||
</data>
|
||||
</root>
|
|
@ -1,19 +1,16 @@
|
|||
@inject IHttpContextAccessor ctxAcc
|
||||
@{
|
||||
var details = WebLogCache.Get(ctxAcc.HttpContext!);
|
||||
}
|
||||
@model MyWebLogModel
|
||||
<header>
|
||||
<nav class="navbar navbar-light bg-light navbar-expand-md justify-content-start px-2">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="~/">@details.Name</a>
|
||||
<a class="navbar-brand" href="~/">@Model.WebLog.Name</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarText"
|
||||
aria-controls="navbarText" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarText">
|
||||
@if (details.Subtitle is not null)
|
||||
@if (Model.WebLog.Subtitle is not null)
|
||||
{
|
||||
<span class="navbar-text">@details.Subtitle</span>
|
||||
<span class="navbar-text">@Model.WebLog.Subtitle</span>
|
||||
}
|
||||
@* TODO: list pages for current web log *@
|
||||
@await Html.PartialAsync("_LogOnOffPartial")
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
@inject IHttpContextAccessor ctxAcc
|
||||
@{
|
||||
var details = WebLogCache.Get(ctxAcc.HttpContext!);
|
||||
}
|
||||
@model MyWebLogModel
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
|
@ -9,9 +6,9 @@
|
|||
<meta name="generator" content="myWebLog 2">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"
|
||||
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="~/css/@details.ThemePath/style.css">
|
||||
<link rel="stylesheet" href="~/css/@Model.WebLog.ThemePath/style.css">
|
||||
@await RenderSectionAsync("Style", false)
|
||||
<title>@ViewBag.Title « @details.Name</title>
|
||||
<title>@ViewBag.Title « @Model.WebLog.Name</title>
|
||||
</head>
|
||||
<body>
|
||||
@if (IsSectionDefined("Header"))
|
||||
|
@ -20,7 +17,7 @@
|
|||
}
|
||||
else
|
||||
{
|
||||
@await Html.PartialAsync("_DefaultHeader")
|
||||
@await Html.PartialAsync("_DefaultHeader", Model)
|
||||
}
|
||||
<main>
|
||||
@RenderBody()
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
@model Page
|
||||
@using MyWebLog.Features.Pages
|
||||
@model SinglePageModel
|
||||
@{
|
||||
Layout = "_Layout";
|
||||
ViewBag.Title = Model.Title;
|
||||
ViewBag.Title = Model.Page.Title;
|
||||
}
|
||||
<h2>@Model.Title</h2>
|
||||
<h2>@Model.Page.Title</h2>
|
||||
<article>
|
||||
@Html.Raw(Model.Text)
|
||||
@Html.Raw(Model.Page.Text)
|
||||
</article>
|
||||
|
|
Loading…
Reference in New Issue
Block a user