Skip to content

Commit

Permalink
Merge pull request #747 from EdiWang/page-css-refact
Browse files Browse the repository at this point in the history
Page css refact
  • Loading branch information
EdiWang authored Sep 4, 2023
2 parents 1ec04b2 + cac48d0 commit af54fb7
Show file tree
Hide file tree
Showing 20 changed files with 139 additions and 84 deletions.
21 changes: 21 additions & 0 deletions src/Moonglade.Core/DeleteStyleSheetCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
namespace Moonglade.Core;

public record DeleteStyleSheetCommand(Guid Id) : IRequest;

public class DeleteStyleSheetCommandHandler : IRequestHandler<DeleteStyleSheetCommand>
{
private readonly IRepository<StyleSheetEntity> _repo;

public DeleteStyleSheetCommandHandler(IRepository<StyleSheetEntity> repo) => _repo = repo;

public async Task Handle(DeleteStyleSheetCommand request, CancellationToken cancellationToken)
{
var styleSheet = await _repo.GetAsync(request.Id, cancellationToken);
if (styleSheet is null)
{
throw new InvalidOperationException($"StyleSheetEntity with Id '{request.Id}' not found.");
}

await _repo.DeleteAsync(styleSheet, cancellationToken);
}
}
16 changes: 16 additions & 0 deletions src/Moonglade.Core/GetStyleSheetQuery.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
namespace Moonglade.Core;

public record GetStyleSheetQuery(Guid Id) : IRequest<StyleSheetEntity>;

public class GetStyleSheetQueryHandler : IRequestHandler<GetStyleSheetQuery, StyleSheetEntity>
{
private readonly IRepository<StyleSheetEntity> _repo;

public GetStyleSheetQueryHandler(IRepository<StyleSheetEntity> repo) => _repo = repo;

public async Task<StyleSheetEntity> Handle(GetStyleSheetQuery request, CancellationToken cancellationToken)
{
var result = await _repo.GetAsync(request.Id, cancellationToken);
return result;
}
}
4 changes: 2 additions & 2 deletions src/Moonglade.Core/PageFeature/BlogPage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ public class BlogPage
public string Slug { get; set; }
public string MetaDescription { get; set; }
public string RawHtmlContent { get; set; }
public string CssContent { get; set; }
public string CssId { get; set; }
public bool HideSidebar { get; set; }
public bool IsPublished { get; set; }
public DateTime CreateTimeUtc { get; set; }
Expand All @@ -25,7 +25,7 @@ public BlogPage(PageEntity entity)
Id = entity.Id;
Title = entity.Title.Trim();
CreateTimeUtc = entity.CreateTimeUtc;
CssContent = entity.CssContent;
CssId = entity.CssId;
RawHtmlContent = entity.HtmlContent;
HideSidebar = entity.HideSidebar;
Slug = entity.Slug.Trim().ToLower();
Expand Down
22 changes: 18 additions & 4 deletions src/Moonglade.Core/PageFeature/CreatePageCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,36 @@ public record CreatePageCommand(EditPageRequest Payload) : IRequest<Guid>;
public class CreatePageCommandHandler : IRequestHandler<CreatePageCommand, Guid>
{
private readonly IRepository<PageEntity> _repo;
public CreatePageCommandHandler(IRepository<PageEntity> repo) => _repo = repo;
private readonly IMediator _mediator;

public CreatePageCommandHandler(IRepository<PageEntity> repo, IMediator mediator)
{
_repo = repo;
_mediator = mediator;
}

public async Task<Guid> Handle(CreatePageCommand request, CancellationToken ct)
{
var slug = request.Payload.Slug.ToLower().Trim();

Guid? cssId = null;
if (!string.IsNullOrWhiteSpace(request.Payload.CssContent))
{
cssId = await _mediator.Send(new SaveStyleSheetCommand(Guid.NewGuid(), slug, request.Payload.CssContent), ct);
}

var uid = Guid.NewGuid();
var page = new PageEntity
{
Id = uid,
Title = request.Payload.Title.Trim(),
Slug = request.Payload.Slug.ToLower().Trim(),
Slug = slug,
MetaDescription = request.Payload.MetaDescription,
CreateTimeUtc = DateTime.UtcNow,
HtmlContent = request.Payload.RawHtmlContent,
CssContent = request.Payload.CssContent,
HideSidebar = request.Payload.HideSidebar,
IsPublished = request.Payload.IsPublished
IsPublished = request.Payload.IsPublished,
CssId = cssId.ToString()
};

await _repo.AddAsync(page, ct);
Expand Down
23 changes: 21 additions & 2 deletions src/Moonglade.Core/PageFeature/DeletePageCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,27 @@ public record DeletePageCommand(Guid Id) : IRequest;
public class DeletePageCommandHandler : IRequestHandler<DeletePageCommand>
{
private readonly IRepository<PageEntity> _repo;
public DeletePageCommandHandler(IRepository<PageEntity> repo) => _repo = repo;
private readonly IMediator _mediator;

public DeletePageCommandHandler(IRepository<PageEntity> repo, IMediator mediator)
{
_repo = repo;
_mediator = mediator;
}

public async Task Handle(DeletePageCommand request, CancellationToken ct)
{
var page = await _repo.GetAsync(request.Id, ct);
if (page is null)
{
throw new InvalidOperationException($"PageEntity with Id '{request.Id}' not found.");
}

if (page.CssId != null)
{
await _mediator.Send(new DeleteStyleSheetCommand(new(page.CssId)), ct);
}

public async Task Handle(DeletePageCommand request, CancellationToken ct) =>
await _repo.DeleteAsync(request.Id, ct);
}
}
19 changes: 16 additions & 3 deletions src/Moonglade.Core/PageFeature/UpdatePageCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,13 @@ public record UpdatePageCommand(Guid Id, EditPageRequest Payload) : IRequest<Gui
public class UpdatePageCommandHandler : IRequestHandler<UpdatePageCommand, Guid>
{
private readonly IRepository<PageEntity> _repo;
private readonly IMediator _mediator;

public UpdatePageCommandHandler(IRepository<PageEntity> repo) => _repo = repo;
public UpdatePageCommandHandler(IRepository<PageEntity> repo, IMediator mediator)
{
_repo = repo;
_mediator = mediator;
}

public async Task<Guid> Handle(UpdatePageCommand request, CancellationToken ct)
{
Expand All @@ -17,14 +22,22 @@ public async Task<Guid> Handle(UpdatePageCommand request, CancellationToken ct)
throw new InvalidOperationException($"PageEntity with Id '{guid}' not found.");
}

var slug = request.Payload.Slug.ToLower().Trim();

Guid? cssId = null;
if (!string.IsNullOrWhiteSpace(request.Payload.CssContent))
{
cssId = await _mediator.Send(new SaveStyleSheetCommand(page.Id, slug, request.Payload.CssContent), ct);
}

page.Title = payload.Title.Trim();
page.Slug = payload.Slug.ToLower().Trim();
page.Slug = slug;
page.MetaDescription = payload.MetaDescription;
page.HtmlContent = payload.RawHtmlContent;
page.CssContent = payload.CssContent;
page.HideSidebar = payload.HideSidebar;
page.UpdateTimeUtc = DateTime.UtcNow;
page.IsPublished = payload.IsPublished;
page.CssId = cssId.ToString();

await _repo.UpdateAsync(page, ct);

Expand Down
10 changes: 5 additions & 5 deletions src/Moonglade.Core/SaveStyleSheetCommand.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
using System.Security.Cryptography;
using Moonglade.Data.Spec;

namespace Moonglade.Core;

public record SaveStyleSheetCommand(string Slug, string CssContent) : IRequest<Guid>;
public record SaveStyleSheetCommand(Guid Id, string Slug, string CssContent) : IRequest<Guid>;

public class SaveStyleSheetCommandHandler : IRequestHandler<SaveStyleSheetCommand, Guid>
{
Expand All @@ -17,13 +16,13 @@ public async Task<Guid> Handle(SaveStyleSheetCommand request, CancellationToken
var css = request.CssContent.Trim();
var hash = CalculateHash($"{slug}_{css}");

var entity = await _repo.GetAsync(new StyleSheetByFriendlyNameSpec(slug), cancellationToken);
var entity = await _repo.GetAsync(request.Id, cancellationToken);
if (entity is null)
{
entity = new()
{
Id = Guid.NewGuid(),
FriendlyName = slug,
Id = request.Id,
FriendlyName = $"page_{slug}",
CssContent = css,
Hash = hash,
LastModifiedTimeUtc = DateTime.UtcNow
Expand All @@ -33,6 +32,7 @@ public async Task<Guid> Handle(SaveStyleSheetCommand request, CancellationToken
}
else
{
entity.FriendlyName = $"page_{slug}";
entity.CssContent = css;
entity.Hash = hash;
entity.LastModifiedTimeUtc = DateTime.UtcNow;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public void Configure(EntityTypeBuilder<PageEntity> builder)
builder.Property(e => e.Id).ValueGeneratedNever();
builder.Property(e => e.Title).HasMaxLength(128);
builder.Property(e => e.Slug).HasMaxLength(128);
builder.Property(e => e.CssId).HasMaxLength(64);
builder.Property(e => e.MetaDescription).HasMaxLength(256);
builder.Property(e => e.CreateTimeUtc).HasColumnType("datetime");
builder.Property(e => e.UpdateTimeUtc).HasColumnType("datetime");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public void Configure(EntityTypeBuilder<PageEntity> builder)
builder.Property(e => e.Id).ValueGeneratedNever();
builder.Property(e => e.Title).HasMaxLength(128);
builder.Property(e => e.Slug).HasMaxLength(128);
builder.Property(e => e.CssId).HasMaxLength(64);
builder.Property(e => e.MetaDescription).HasMaxLength(256);
builder.Property(e => e.CreateTimeUtc).HasColumnType("timestamp");
builder.Property(e => e.UpdateTimeUtc).HasColumnType("timestamp");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public void Configure(EntityTypeBuilder<PageEntity> builder)
builder.Property(e => e.Id).ValueGeneratedNever();
builder.Property(e => e.Title).HasMaxLength(128);
builder.Property(e => e.Slug).HasMaxLength(128);
builder.Property(e => e.CssId).HasMaxLength(64);
builder.Property(e => e.MetaDescription).HasMaxLength(256);
builder.Property(e => e.CreateTimeUtc).HasColumnType("datetime");
builder.Property(e => e.UpdateTimeUtc).HasColumnType("datetime");
Expand Down
2 changes: 1 addition & 1 deletion src/Moonglade.Data/Entities/PageEntity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ public class PageEntity
public string Slug { get; set; }
public string MetaDescription { get; set; }
public string HtmlContent { get; set; }
public string CssContent { get; set; }
public string CssId { get; set; }
public bool HideSidebar { get; set; }
public bool IsPublished { get; set; }
public DateTime CreateTimeUtc { get; set; }
Expand Down
2 changes: 1 addition & 1 deletion src/Moonglade.Data/Exporting/ExportPageDataCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public Task<ExportResult> Handle(ExportPageDataCommand request, CancellationToke
p.Slug,
p.MetaDescription,
p.HtmlContent,
p.CssContent,
p.CssId,
p.HideSidebar,
p.IsPublished,
p.CreateTimeUtc,
Expand Down
11 changes: 0 additions & 11 deletions src/Moonglade.Data/Spec/StyleSheetSpec.cs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@

namespace Moonglade.Theme;

public record GetStyleSheetQuery(int Id) : IRequest<string>;
public class GetStyleSheetQueryHandler : IRequestHandler<GetStyleSheetQuery, string>
public record GetSiteThemeStyleSheetQuery(int Id) : IRequest<string>;
public class GetStyleSheetQueryHandler : IRequestHandler<GetSiteThemeStyleSheetQuery, string>
{
private readonly IRepository<BlogThemeEntity> _repo;

public GetStyleSheetQueryHandler(IRepository<BlogThemeEntity> repo) => _repo = repo;

public async Task<string> Handle(GetStyleSheetQuery request, CancellationToken ct)
public async Task<string> Handle(GetSiteThemeStyleSheetQuery request, CancellationToken ct)
{
var theme = await _repo.GetAsync(request.Id, ct);
if (null == theme) return null;
Expand Down
2 changes: 1 addition & 1 deletion src/Moonglade.Web/Controllers/ThemeController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public async Task<IActionResult> Css()
await _mediator.Send(new UpdateConfigurationCommand(kvp.Key, kvp.Value));
}
var data = await _mediator.Send(new GetStyleSheetQuery(_blogConfig.GeneralSettings.ThemeId));
var data = await _mediator.Send(new GetSiteThemeStyleSheetQuery(_blogConfig.GeneralSettings.ThemeId));
return data;
});

Expand Down
33 changes: 18 additions & 15 deletions src/Moonglade.Web/Middleware/StyleSheetMiddleware.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using System.Net;
using System.Text.RegularExpressions;
using System.Web;
using System.Web;
using NUglify;

namespace Moonglade.Web.Middleware;
Expand All @@ -13,14 +11,14 @@ public class StyleSheetMiddleware

public StyleSheetMiddleware(RequestDelegate next) => _next = next;

public async Task Invoke(HttpContext context, IBlogConfig blogConfig)
public async Task Invoke(HttpContext context, IBlogConfig blogConfig, IMediator mediator)
{
if (!context.Request.Path.ToString().ToLower().EndsWith(".css"))
{
await _next(context);
return;
}

if (context.Request.Path == Options.DefaultPath)
{
if (!blogConfig.CustomStyleSheetSettings.EnableCustomCss)
Expand All @@ -36,21 +34,26 @@ public async Task Invoke(HttpContext context, IBlogConfig blogConfig)
{
// Get query string value
var qs = HttpUtility.ParseQueryString(context.Request.QueryString.Value!);
string slug = qs["slug"];
var id = qs["id"];

if (!string.IsNullOrWhiteSpace(slug))
if (!string.IsNullOrWhiteSpace(id))
{
slug = slug.ToLower();

var slugRegex = "^(?!-)([a-zA-Z0-9-]){1,128}$";
if (!Regex.IsMatch(slug, slugRegex, RegexOptions.Compiled, TimeSpan.FromSeconds(1)))
if (!Guid.TryParse(id, out var guid))
{
context.Response.StatusCode = StatusCodes.Status404NotFound;
}

// TODO: Output blog page css
// Need a server side cache
// Need pattern validation
else
{
var css = await mediator.Send(new GetStyleSheetQuery(guid));
if (css == null)
{
context.Response.StatusCode = StatusCodes.Status404NotFound;
return;
}

// TODO: May need a server side cache
await WriteStyleSheet(context, css.CssContent);
}
}
else
{
Expand Down
9 changes: 8 additions & 1 deletion src/Moonglade.Web/Pages/Admin/EditPage.cshtml.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Microsoft.AspNetCore.Mvc.RazorPages;
using Moonglade.Core.PageFeature;
using Moonglade.Data.Entities;

namespace Moonglade.Web.Pages.Admin;

Expand All @@ -24,14 +25,20 @@ public async Task<IActionResult> OnGetAsync(Guid? id)
var page = await _mediator.Send(new GetPageByIdQuery(id.Value));
if (page is null) return NotFound();

StyleSheetEntity css = null;
if (!string.IsNullOrWhiteSpace(page.CssId))
{
css = await _mediator.Send(new GetStyleSheetQuery(Guid.Parse(page.CssId)));
}

PageId = page.Id;

EditPageRequest = new()
{
Title = page.Title,
Slug = page.Slug,
MetaDescription = page.MetaDescription,
CssContent = page.CssContent,
CssContent = css?.CssContent,
RawHtmlContent = page.RawHtmlContent,
HideSidebar = page.HideSidebar,
IsPublished = page.IsPublished
Expand Down
Loading

0 comments on commit af54fb7

Please sign in to comment.