Browse Source

Add SingleBlogModeOptions

pull/19418/head
Salih 3 years ago
parent
commit
86a6c198a6
  1. 14
      modules/blogging/src/Volo.Blogging.Web/BloggingUrlOptions.cs
  2. 24
      modules/blogging/src/Volo.Blogging.Web/BloggingWebModule.cs
  3. 27
      modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/BloggingPageModel.cs
  4. 10
      modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Index.cshtml.cs
  5. 10
      modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Detail.cshtml.cs
  6. 23
      modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Edit.cshtml.cs
  7. 27
      modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Index.cshtml
  8. 10
      modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Index.cshtml.cs
  9. 19
      modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/New.cshtml.cs

14
modules/blogging/src/Volo.Blogging.Web/BloggingUrlOptions.cs

@ -20,6 +20,9 @@ namespace Volo.Blogging
/// Used to specify ignore paths if the route prefix is null or empty.
/// </summary>
public List<string> IgnoredPaths { get; } = new ();
public SingleBlogModeOptions SingleBlogMode { get; } = new ();
private string GetFormattedRoutePrefix()
{
@ -31,4 +34,15 @@ namespace Volo.Blogging
return _routePrefix.EnsureEndsWith('/').EnsureStartsWith('/');
}
}
public class SingleBlogModeOptions
{
/// <summary>
/// Determines whether to enable single blog mode by removing the blog name from the routing.
/// When enabled, only a single blog is allowed within the module.
/// </summary>
public bool Enable { get; set; }
public string BlogName { get; set; }
}
}

24
modules/blogging/src/Volo.Blogging.Web/BloggingWebModule.cs

@ -92,15 +92,25 @@ namespace Volo.Blogging
var routePrefix = urlOptions.RoutePrefix;
if (!routePrefix.IsNullOrWhiteSpace())
if (urlOptions.SingleBlogMode.Enable)
{
options.Conventions.AddPageRoute("/Blogs/Index", routePrefix);
options.Conventions.AddPageRoute("/Blogs/Posts/Index", routePrefix);
options.Conventions.AddPageRoute("/Blogs/Posts/Detail", routePrefix + "{postUrl}");
options.Conventions.AddPageRoute("/Blogs/Posts/Edit", routePrefix + "posts/{postId}/edit");
options.Conventions.AddPageRoute("/Blogs/Posts/New", routePrefix + "posts/new");
}
options.Conventions.AddPageRoute("/Blogs/Posts/Index", routePrefix + "{blogShortName:blogNameConstraint}");
options.Conventions.AddPageRoute("/Blogs/Posts/Detail", routePrefix + "{blogShortName:blogNameConstraint}/{postUrl}");
options.Conventions.AddPageRoute("/Blogs/Posts/Edit", routePrefix + "{blogShortName}/posts/{postId}/edit");
options.Conventions.AddPageRoute("/Blogs/Posts/New", routePrefix + "{blogShortName}/posts/new");
else
{
if (!routePrefix.IsNullOrWhiteSpace())
{
options.Conventions.AddPageRoute("/Blogs/Index", routePrefix);
}
options.Conventions.AddPageRoute("/Blogs/Posts/Index", routePrefix + "{blogShortName:blogNameConstraint}");
options.Conventions.AddPageRoute("/Blogs/Posts/Detail", routePrefix + "{blogShortName:blogNameConstraint}/{postUrl}");
options.Conventions.AddPageRoute("/Blogs/Posts/Edit", routePrefix + "{blogShortName}/posts/{postId}/edit");
options.Conventions.AddPageRoute("/Blogs/Posts/New", routePrefix + "{blogShortName}/posts/new");
}
options.Conventions.AddPageRoute("/Blogs/Members/Index", routePrefix + "members/{userName}");
});

27
modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/BloggingPageModel.cs

@ -1,4 +1,8 @@
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages;
using System;
using System.Threading.Tasks;
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages;
using Volo.Blogging.Blogs;
using Volo.Blogging.Blogs.Dtos;
namespace Volo.Blogging.Pages.Blog
{
@ -8,5 +12,26 @@ namespace Volo.Blogging.Pages.Blog
{
ObjectMapperContext = typeof(BloggingWebModule);
}
protected async Task<BlogDto> GetBlogAsync(IBlogAppService blogAppService, BloggingUrlOptions blogOptions, string blogShortName)
{
if (!blogOptions.SingleBlogMode.Enable)
{
return await blogAppService.GetByShortNameAsync(blogShortName);
}
if (!blogOptions.SingleBlogMode.BlogName.IsNullOrEmpty())
{
return await blogAppService.GetByShortNameAsync(blogOptions.SingleBlogMode.BlogName);
}
var blogs = await blogAppService.GetListAsync();
if (blogs.Items.Count == 1)
{
return blogs.Items[0];
}
return await blogAppService.GetByShortNameAsync(blogOptions.SingleBlogMode.BlogName);
}
}
}

10
modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Index.cshtml.cs

@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages;
using Volo.Blogging.Blogs;
using Volo.Blogging.Blogs.Dtos;
@ -10,16 +11,23 @@ namespace Volo.Blogging.Pages.Blog
public class IndexModel : AbpPageModel
{
private readonly IBlogAppService _blogAppService;
private readonly BloggingUrlOptions _blogOptions;
public IReadOnlyList<BlogDto> Blogs { get; private set; }
public IndexModel(IBlogAppService blogAppService)
public IndexModel(IBlogAppService blogAppService, IOptions<BloggingUrlOptions> blogOptions)
{
_blogAppService = blogAppService;
_blogOptions = blogOptions.Value;
}
public virtual async Task<IActionResult> OnGetAsync()
{
if (_blogOptions.SingleBlogMode.Enable)
{
return RedirectToPage("./Posts/Index");
}
var result = await _blogAppService.GetListAsync();
if (result.Items.Count == 1)

10
modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Detail.cshtml.cs

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Threading.Tasks;
using System.Web;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages;
using Volo.Blogging.Blogs;
using Volo.Blogging.Blogs.Dtos;
@ -19,6 +20,7 @@ namespace Volo.Blogging.Pages.Blog.Posts
private readonly IPostAppService _postAppService;
private readonly IBlogAppService _blogAppService;
private readonly ICommentAppService _commentAppService;
private readonly BloggingUrlOptions _blogOptions;
[BindProperty(SupportsGet = true)]
public string BlogShortName { get; set; }
@ -47,11 +49,12 @@ namespace Volo.Blogging.Pages.Blog.Posts
[BindProperty(SupportsGet = true)]
public string TagName { get; set; }
public DetailModel(IPostAppService postAppService, IBlogAppService blogAppService, ICommentAppService commentAppService)
public DetailModel(IPostAppService postAppService, IBlogAppService blogAppService, ICommentAppService commentAppService, IOptions<BloggingUrlOptions> blogOptions)
{
_postAppService = postAppService;
_blogAppService = blogAppService;
_commentAppService = commentAppService;
_blogOptions = blogOptions.Value;
}
public virtual async Task<IActionResult> OnGetAsync()
@ -60,6 +63,11 @@ namespace Volo.Blogging.Pages.Blog.Posts
{
return NotFound();
}
if (_blogOptions.SingleBlogMode.Enable)
{
BlogShortName = _blogOptions.SingleBlogMode.BlogName;
}
await GetData();

23
modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Edit.cshtml.cs

@ -1,10 +1,12 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Validation;
@ -19,6 +21,7 @@ namespace Volo.Blogging.Pages.Blog.Posts
private readonly IPostAppService _postAppService;
private readonly IBlogAppService _blogAppService;
private readonly IAuthorizationService _authorization;
private readonly BloggingUrlOptions _blogOptions;
[BindProperty(SupportsGet = true)]
public string BlogShortName { get; set; }
@ -29,11 +32,12 @@ namespace Volo.Blogging.Pages.Blog.Posts
[BindProperty]
public EditPostViewModel Post { get; set; }
public EditModel(IPostAppService postAppService, IBlogAppService blogAppService, IAuthorizationService authorization)
public EditModel(IPostAppService postAppService, IBlogAppService blogAppService, IAuthorizationService authorization, IOptions<BloggingUrlOptions> blogOptions)
{
_postAppService = postAppService;
_blogAppService = blogAppService;
_authorization = authorization;
_blogOptions = blogOptions.Value;
}
public virtual async Task<ActionResult> OnGetAsync()
@ -42,6 +46,12 @@ namespace Volo.Blogging.Pages.Blog.Posts
{
return Redirect("/");
}
if (_blogOptions.SingleBlogMode.Enable)
{
BlogShortName = _blogOptions.SingleBlogMode.BlogName;
}
if (BlogNameControlHelper.IsProhibitedFileFormatName(BlogShortName))
{
return NotFound();
@ -73,7 +83,16 @@ namespace Volo.Blogging.Pages.Blog.Posts
var editedPost = await _postAppService.UpdateAsync(Post.Id, post);
var blog = await _blogAppService.GetAsync(editedPost.BlogId);
return RedirectToPage("/Blogs/Posts/Detail", new { blogShortName = blog.ShortName, postUrl = editedPost.Url });
Dictionary<string, object> routeValues = new()
{
{ nameof(DetailModel.PostUrl), editedPost.Url }
};
if (!_blogOptions.SingleBlogMode.Enable)
{
routeValues.Add(nameof(DetailModel.BlogShortName), blog.ShortName);
}
return RedirectToPage("/Blogs/Posts/Detail", routeValues);
}
}

27
modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Index.cshtml

@ -6,6 +6,7 @@
@inject IAuthorizationService Authorization
@model Volo.Blogging.Pages.Blog.Posts.IndexModel
@using Microsoft.Extensions.Localization
@using Microsoft.Extensions.Options
@using Volo.Blogging.Localization
@using Volo.Blogging.Pages.Blog
@using IndexModel = Volo.Blogging.Pages.Blog.Posts.IndexModel
@ -13,6 +14,7 @@
@inject BloggingPageHelper BloggingPageHelper
@{
ViewBag.Title = "Read All Blog Posts";
var blogShortNameRouteParam = Model.BlogOptions.SingleBlogMode.Enable ? null : Model.BlogShortName;
}
@section scripts {
<abp-script-bundle name="@typeof(IndexModel).FullName">
@ -27,7 +29,6 @@
<abp-style src="/Pages/Blogs/Shared/Styles/blog.css" />
</abp-style-bundle>
}
<div class="vs-blog blah">
<div class="container">
<div class="pb-3">
@ -39,18 +40,18 @@
var post = Model.Posts[index];
<div class="hero-articles">
<div class="img-container">
<a asp-page="./Detail" asp-route-postUrl="@post.Url" asp-route-blogShortName="@Model.BlogShortName">
<a asp-page="./Detail" asp-route-postUrl="@post.Url" asp-route-blogShortName="@blogShortNameRouteParam">
<img src="@post.CoverImage" class="hero-article-img" alt="@post.Title cover image">
</a>
</div>
<div class="hero-content pt-3">
<h2>
<a asp-page="./Detail" asp-route-postUrl="@post.Url" asp-route-blogShortName="@Model.BlogShortName">@post.Title</a>
<a asp-page="./Detail" asp-route-postUrl="@post.Url" asp-route-blogShortName="@blogShortNameRouteParam">@post.Title</a>
</h2>
<p class="article-sum">
@Html.Raw(BloggingPageHelper.GetShortContent(post.Content))
</p>
<a asp-page="./Detail" asp-route-postUrl="@post.Url" asp-route-blogShortName="@Model.BlogShortName" class="read-more-btn">@L["ContinueReading"] &#8594;</a>
<a asp-page="./Detail" asp-route-postUrl="@post.Url" asp-route-blogShortName="@blogShortNameRouteParam" class="read-more-btn">@L["ContinueReading"] &#8594;</a>
</div>
@if (post.Writer != null)
@ -84,7 +85,7 @@
<p class="tags">
@foreach (var tag in post.Tags)
{
<a asp-page="/Blogs/Posts/Index" asp-route-blogShortName="@Model.BlogShortName" asp-route-tagName="@tag.Name" class="tag">@tag.Name</a>
<a asp-page="/Blogs/Posts/Index" asp-route-blogShortName="@blogShortNameRouteParam" asp-route-tagName="@tag.Name" class="tag">@tag.Name</a>
}
</p>
@ -97,7 +98,7 @@
@if (await Authorization.IsGrantedAsync(BloggingPermissions.Posts.Create))
{
<a class="btn btn-primary btn-rounded mb-3 active " asp-page="./New" asp-route-blogShortName="@Model.BlogShortName">@L["CreateANewPost"]</a>
<a class="btn btn-primary btn-rounded mb-3 active " asp-page="./New" asp-route-blogShortName="@blogShortNameRouteParam">@L["CreateANewPost"]</a>
}
<div class="list-group">
@ -109,14 +110,14 @@
<div class="row align-middle">
<div class="col-4">
<div class="img-container">
<a asp-page="./Detail" asp-route-postUrl="@post.Url" asp-route-blogShortName="@Model.BlogShortName">
<a asp-page="./Detail" asp-route-postUrl="@post.Url" asp-route-blogShortName="@blogShortNameRouteParam">
<img src="@post.CoverImage" class="box-article-img" alt="@post.Title cover image">
</a>
</div>
</div>
<div class="col-8 ps-0">
<h3 class="font-125">
<a asp-page="./Detail" asp-route-postUrl="@post.Url" asp-route-blogShortName="@Model.BlogShortName">@post.Title</a>
<a asp-page="./Detail" asp-route-postUrl="@post.Url" asp-route-blogShortName="@blogShortNameRouteParam">@post.Title</a>
</h3>
@if (post.Writer != null)
@ -169,19 +170,19 @@
<div class="row">
<div class="col-md-4">
<div class="img-container">
<a asp-page="./Detail" asp-route-postUrl="@post.Url" asp-route-blogShortName="@Model.BlogShortName">
<a asp-page="./Detail" asp-route-postUrl="@post.Url" asp-route-blogShortName="@blogShortNameRouteParam">
<img src="@post.CoverImage" class="box-article-img" alt="@post.Title cover image">
</a>
</div>
</div>
<div class="col">
<h3>
<a asp-page="./Detail" asp-route-postUrl="@post.Url" asp-route-blogShortName="@Model.BlogShortName">@post.Title</a>
<a asp-page="./Detail" asp-route-postUrl="@post.Url" asp-route-blogShortName="@blogShortNameRouteParam">@post.Title</a>
</h3>
<p>
@Html.Raw(BloggingPageHelper.GetShortContent(post.Content))
</p>
<a asp-page="./Detail" asp-route-postUrl="@post.Url" asp-route-blogShortName="@Model.BlogShortName" class="read-more-btn">@L["ContinueReading"] &#8594;</a>
<a asp-page="./Detail" asp-route-postUrl="@post.Url" asp-route-blogShortName="@blogShortNameRouteParam" class="read-more-btn">@L["ContinueReading"] &#8594;</a>
@if (post.Writer != null)
{
@ -213,7 +214,7 @@
<p class="tags">
@foreach (var tag in post.Tags)
{
<a asp-page="/Blogs/Posts/Index" asp-route-blogShortName="@Model.BlogShortName" asp-route-tagName="@tag.Name" class="tag">@tag.Name</a>
<a asp-page="/Blogs/Posts/Index" asp-route-blogShortName="@blogShortNameRouteParam" asp-route-tagName="@tag.Name" class="tag">@tag.Name</a>
}
</p>
</div>
@ -234,7 +235,7 @@
<div class="tags">
@foreach (var popularTag in Model.PopularTags)
{
<a class="tag" asp-page="/Blogs/Posts/Index" asp-route-blogShortName="@Model.BlogShortName" asp-route-tagName="@popularTag.Name">@popularTag.Name <small>(@popularTag.UsageCount)</small></a>
<a class="tag" asp-page="/Blogs/Posts/Index" asp-route-blogShortName="@blogShortNameRouteParam" asp-route-tagName="@popularTag.Name">@popularTag.Name <small>(@popularTag.UsageCount)</small></a>
}
</div>
</div>

10
modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Index.cshtml.cs

@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages;
using Volo.Abp.Domain.Entities;
using Volo.Blogging.Blogs;
@ -18,6 +19,7 @@ namespace Volo.Blogging.Pages.Blog.Posts
private readonly IPostAppService _postAppService;
private readonly IBlogAppService _blogAppService;
private readonly ITagAppService _tagAppService;
public BloggingUrlOptions BlogOptions { get; }
[BindProperty(SupportsGet = true)]
public string BlogShortName { get; set; }
@ -31,11 +33,12 @@ namespace Volo.Blogging.Pages.Blog.Posts
public IReadOnlyList<TagDto> PopularTags { get; set; }
public IndexModel(IPostAppService postAppService, IBlogAppService blogAppService, ITagAppService tagAppService)
public IndexModel(IPostAppService postAppService, IBlogAppService blogAppService, ITagAppService tagAppService, IOptions<BloggingUrlOptions> blogOptions)
{
_postAppService = postAppService;
_blogAppService = blogAppService;
_tagAppService = tagAppService;
BlogOptions = blogOptions.Value;
}
public virtual async Task<ActionResult> OnGetAsync()
@ -47,7 +50,8 @@ namespace Volo.Blogging.Pages.Blog.Posts
try
{
Blog = await _blogAppService.GetByShortNameAsync(BlogShortName);
Blog = await GetBlogAsync(_blogAppService, BlogOptions, BlogShortName);
BlogShortName = Blog.ShortName;
}
catch (EntityNotFoundException)
{
@ -59,5 +63,7 @@ namespace Volo.Blogging.Pages.Blog.Posts
return Page();
}
}
}

19
modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/New.cshtml.cs

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Net;
using System.Threading.Tasks;
@ -48,7 +49,9 @@ namespace Volo.Blogging.Pages.Blog.Posts
return NotFound();
}
Blog = await _blogAppService.GetByShortNameAsync(BlogShortName);
Blog = await GetBlogAsync(_blogAppService, _blogOptions, BlogShortName);
BlogShortName = Blog.ShortName;
Post = new CreatePostViewModel
{
BlogId = Blog.Id
@ -70,9 +73,17 @@ namespace Volo.Blogging.Pages.Blog.Posts
var postWithDetailsDto = await _postAppService.CreateAsync(ObjectMapper.Map<CreatePostViewModel, CreatePostDto>(Post));
//TODO: Try Url.Page(...)
var urlPrefix = _blogOptions.RoutePrefix;
return Redirect(Url.Content($"~{urlPrefix}{WebUtility.UrlEncode(blog.ShortName)}/{WebUtility.UrlEncode(postWithDetailsDto.Url)}"));
Dictionary<string, object> routeValues = new()
{
{ nameof(DetailModel.PostUrl), postWithDetailsDto.Url }
};
if (!_blogOptions.SingleBlogMode.Enable)
{
routeValues.Add(nameof(DetailModel.BlogShortName), blog.ShortName);
}
return RedirectToPage("/Blogs/Posts/Detail", routeValues);
}
public class CreatePostViewModel

Loading…
Cancel
Save