Browse Source

Merge branch 'salihozkara/blogImprovements' into salihozkara/abpUnited

pull/19876/head
Salih 3 years ago
parent
commit
d06d397095
  1. 2
      modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Members/MemberAppService.cs
  2. 14
      modules/blogging/src/Volo.Blogging.Web/BloggingUrlOptions.cs
  3. 30
      modules/blogging/src/Volo.Blogging.Web/BloggingWebModule.cs
  4. 27
      modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/BloggingPageModel.cs
  5. 10
      modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Index.cshtml.cs
  6. 6
      modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Members/Index.cshtml
  7. 2
      modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Members/Index.cshtml.cs
  8. 0
      modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Members/Index.css
  9. 0
      modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Members/Index.js
  10. 18
      modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Detail.cshtml
  11. 10
      modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Detail.cshtml.cs
  12. 23
      modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Edit.cshtml.cs
  13. 37
      modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Index.cshtml
  14. 10
      modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Index.cshtml.cs
  15. 19
      modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/New.cshtml.cs

2
modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Members/MemberAppService.cs

@ -17,7 +17,7 @@ public class MemberAppService : BloggingAppServiceBase, IMemberAppService
public virtual async Task<BlogUserDto> FindAsync(string username) public virtual async Task<BlogUserDto> FindAsync(string username)
{ {
var user = await _userRepository.FindAsync(x => x.UserName == username); var user = await _userRepository.FindAsync(x => x.UserName == username && x.IsActive);
if (user == null) if (user == null)
{ {

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. /// Used to specify ignore paths if the route prefix is null or empty.
/// </summary> /// </summary>
public List<string> IgnoredPaths { get; } = new (); public List<string> IgnoredPaths { get; } = new ();
public SingleBlogModeOptions SingleBlogMode { get; } = new ();
private string GetFormattedRoutePrefix() private string GetFormattedRoutePrefix()
{ {
@ -31,4 +34,15 @@ namespace Volo.Blogging
return _routePrefix.EnsureEndsWith('/').EnsureStartsWith('/'); 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; }
}
} }

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

@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Mvc.RazorPages; using System;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
@ -79,7 +80,7 @@ namespace Volo.Blogging
options.IgnoredPaths.AddRange(new[] options.IgnoredPaths.AddRange(new[]
{ {
"error", "ApplicationConfigurationScript", "ServiceProxyScript", "Languages/Switch", "error", "ApplicationConfigurationScript", "ServiceProxyScript", "Languages/Switch",
"ApplicationLocalizationScript" "ApplicationLocalizationScript", "members"
}); });
}); });
@ -91,11 +92,26 @@ namespace Volo.Blogging
var routePrefix = urlOptions.RoutePrefix; var routePrefix = urlOptions.RoutePrefix;
options.Conventions.AddPageRoute("/Blogs/Posts/Index", routePrefix + "{blogShortName:blogNameConstraint}"); if (urlOptions.SingleBlogMode.Enable)
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/Index", routePrefix);
options.Conventions.AddPageRoute("/Blogs/Posts/New", routePrefix + "{blogShortName}/posts/new"); options.Conventions.AddPageRoute("/Blogs/Posts/Detail", routePrefix + "{postUrl}");
options.Conventions.AddPageRoute("/Members/Index", routePrefix + "members/{userName}"); options.Conventions.AddPageRoute("/Blogs/Posts/Edit", routePrefix + "posts/{postId}/edit");
options.Conventions.AddPageRoute("/Blogs/Posts/New", routePrefix + "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}");
}); });
Configure<DynamicJavaScriptProxyOptions>(options => Configure<DynamicJavaScriptProxyOptions>(options =>

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

6
modules/blogging/src/Volo.Blogging.Web/Pages/Members/Index.cshtml → modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Members/Index.cshtml

@ -5,7 +5,7 @@
@using Volo.Abp.Users @using Volo.Abp.Users
@using Volo.Blogging.Areas.Blog.Helpers.TagHelpers @using Volo.Blogging.Areas.Blog.Helpers.TagHelpers
@using Volo.Blogging.Localization @using Volo.Blogging.Localization
@model Volo.Blogging.Pages.Members.IndexModel @model Volo.Blogging.Pages.Blogs.Members.IndexModel
@inject IStringLocalizer<BloggingResource> L @inject IStringLocalizer<BloggingResource> L
@inject ICurrentUser CurrentUser @inject ICurrentUser CurrentUser
@{ @{
@ -13,11 +13,11 @@
} }
@section scripts { @section scripts {
<abp-script src="/Pages/Members/Index.js" /> <abp-script src="/Pages/Blogs/Members/Index.js" />
} }
@section styles { @section styles {
<abp-style src="/Pages/Members/Index.css"/> <abp-style src="/Pages/Blogs/Members/Index.css"/>
} }
<main> <main>

2
modules/blogging/src/Volo.Blogging.Web/Pages/Members/Index.cshtml.cs → modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Members/Index.cshtml.cs

@ -8,7 +8,7 @@ using Volo.Blogging.Blogs;
using Volo.Blogging.Members; using Volo.Blogging.Members;
using Volo.Blogging.Posts; using Volo.Blogging.Posts;
namespace Volo.Blogging.Pages.Members; namespace Volo.Blogging.Pages.Blogs.Members;
public class IndexModel : AbpPageModel public class IndexModel : AbpPageModel
{ {

0
modules/blogging/src/Volo.Blogging.Web/Pages/Members/Index.css → modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Members/Index.css

0
modules/blogging/src/Volo.Blogging.Web/Pages/Members/Index.js → modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Members/Index.js

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

@ -67,7 +67,7 @@
<div class="col-auto pe-1"> <div class="col-auto pe-1">
@if (Model.Post.Writer != null) @if (Model.Post.Writer != null)
{ {
<a href="/Members/@Model.Post.Writer.UserName" aria-label="Go to user profile"> <a href="@Url.Page("/Blogs/Members/Index", new {userName = Model.Post.Writer.UserName})" aria-label="Go to user profile">
<img gravatar-email="@Model.Post.Writer.Email" default-image="Identicon" class="article-avatar" alt="User Avatar"/> <img gravatar-email="@Model.Post.Writer.Email" default-image="Identicon" class="article-avatar" alt="User Avatar"/>
</a> </a>
} }
@ -76,7 +76,7 @@
@if (Model.Post.Writer != null) @if (Model.Post.Writer != null)
{ {
<h5 class="mt-2 mb-1"> <h5 class="mt-2 mb-1">
<a href="/Members/@Model.Post.Writer.UserName"> <a href="@Url.Page("/Blogs/Members/Index", new {userName = Model.Post.Writer.UserName})">
@(Model.Post.Writer.UserName) @(Model.Post.Writer.UserName)
</a> </a>
<span>@BloggingPageHelper.GetLocalizedTimeAgoText(Model.Post.CreationTime)</span> <span>@BloggingPageHelper.GetLocalizedTimeAgoText(Model.Post.CreationTime)</span>
@ -141,7 +141,7 @@
<div class="col-auto pe-2"> <div class="col-auto pe-2">
@if (Model.Post.Writer != null) @if (Model.Post.Writer != null)
{ {
<a href="/Members/@Model.Post.Writer.UserName" aria-label="Go to user profile"> <a href="@Url.Page("/Blogs/Members/Index", new {userName = Model.Post.Writer.UserName})" aria-label="Go to user profile">
<img gravatar-email="@Model.Post.Writer.Email" default-image="Identicon" class="article-avatar rounded-circle" alt="User Avatar"/> <img gravatar-email="@Model.Post.Writer.Email" default-image="Identicon" class="article-avatar rounded-circle" alt="User Avatar"/>
</a> </a>
} }
@ -151,7 +151,7 @@
{ {
<h5 class="mt-2 mb-1"> <h5 class="mt-2 mb-1">
<a href="/Members/@Model.Post.Writer.UserName"> <a href="@Url.Page("/Blogs/Members/Index", new {userName = Model.Post.Writer.UserName})">
@if (Model.Post.Writer.Name != null && Model.Post.Writer.Surname != null) @if (Model.Post.Writer.Name != null && Model.Post.Writer.Surname != null)
{ {
<p class="fw-bold pt-2 fs-5">@Model.Post.Writer.Name @Model.Post.Writer.Surname</p> <p class="fw-bold pt-2 fs-5">@Model.Post.Writer.Name @Model.Post.Writer.Surname</p>
@ -172,7 +172,7 @@
@if (CurrentUser.Id.HasValue && CurrentUser.Id.Value == Model.Post.Writer?.Id) @if (CurrentUser.Id.HasValue && CurrentUser.Id.Value == Model.Post.Writer?.Id)
{ {
<a class="fw-lighter" href="/Members/@Model.Post.Writer?.UserName#edit-profile">@L["EditProfile"] <i class="fas fa-edit"></i></a> <a class="fw-lighter" href="@(Url.Page("/Blogs/Members/Index", new {userName = Model.Post.Writer.UserName}))#edit-profile">@L["EditProfile"] <i class="fas fa-edit"></i></a>
} }
</div> </div>
@if (Model.LatestPosts.Count > 1) @if (Model.LatestPosts.Count > 1)
@ -194,14 +194,14 @@
{ {
<div class="row"> <div class="row">
<div class="col-auto pe-1"> <div class="col-auto pe-1">
<a href="/Members/@post.Writer.UserName" aria-label="Go to user profile"> <a href="@Url.Page("/Blogs/Members/Index", new {userName = Model.Post.Writer.UserName})" aria-label="Go to user profile">
<img gravatar-email="@post.Writer.Email" default-image="Identicon" class="last-post-image" alt="User Avatar"/> <img gravatar-email="@post.Writer.Email" default-image="Identicon" class="last-post-image" alt="User Avatar"/>
</a> </a>
</div> </div>
<div class="col"> <div class="col">
<h5 class="last-post-name"> <h5 class="last-post-name">
<a href="/Members/@post.Writer!.UserName"> <a href="@Url.Page("/Blogs/Members/Index", new {userName = Model.Post.Writer.UserName})">
@(post.Writer!.UserName) @(post.Writer!.UserName)
</a> </a>
</h5> </h5>
@ -456,13 +456,13 @@ else
var post = Model.PostsList[index]; var post = Model.PostsList[index];
<div class="post-item"> <div class="post-item">
<div class="post-type-cont"> <div class="post-type-cont">
<a href="/members/@Model.Post.Writer.UserName" class="text-decoration-none"> <a href="@Url.Page("/Blogs/Members/Index", new {userName = Model.Post.Writer.UserName})" class="text-decoration-none">
<img gravatar-email="@Model.Post.Writer.Email" default-image="Identicon" class="post-member-img rounded-circle d-block"/> <img gravatar-email="@Model.Post.Writer.Email" default-image="Identicon" class="post-member-img rounded-circle d-block"/>
</a> </a>
</div> </div>
<div class="post-detail-cont"> <div class="post-detail-cont">
<div class="post-info fs-12 mb-2"> <div class="post-info fs-12 mb-2">
<a href="/members/@Model.Post.Writer.UserName" class="text-decoration-none"> <a href="@Url.Page("/Blogs/Members/Index", new {userName = Model.Post.Writer.UserName})" class="text-decoration-none">
<span class="text-dark dot">@Model.Post.Writer.UserName</span> <span class="text-dark dot">@Model.Post.Writer.UserName</span>
</a> </a>
<span class="text-dark-200">@post.CreationTime.ToString("MMMM yyyy")</span> <span class="text-dark-200">@post.CreationTime.ToString("MMMM yyyy")</span>

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

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

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

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

@ -6,6 +6,7 @@
@inject IAuthorizationService Authorization @inject IAuthorizationService Authorization
@model Volo.Blogging.Pages.Blog.Posts.IndexModel @model Volo.Blogging.Pages.Blog.Posts.IndexModel
@using Microsoft.Extensions.Localization @using Microsoft.Extensions.Localization
@using Microsoft.Extensions.Options
@using Volo.Blogging.Localization @using Volo.Blogging.Localization
@using Volo.Blogging.Pages.Blog @using Volo.Blogging.Pages.Blog
@using IndexModel = Volo.Blogging.Pages.Blog.Posts.IndexModel @using IndexModel = Volo.Blogging.Pages.Blog.Posts.IndexModel
@ -13,6 +14,7 @@
@inject BloggingPageHelper BloggingPageHelper @inject BloggingPageHelper BloggingPageHelper
@{ @{
ViewBag.Title = "Read All Blog Posts"; ViewBag.Title = "Read All Blog Posts";
var blogShortNameRouteParam = Model.BlogOptions.SingleBlogMode.Enable ? null : Model.BlogShortName;
} }
@section scripts { @section scripts {
<abp-script-bundle name="@typeof(IndexModel).FullName"> <abp-script-bundle name="@typeof(IndexModel).FullName">
@ -27,7 +29,6 @@
<abp-style src="/Pages/Blogs/Shared/Styles/blog.css" /> <abp-style src="/Pages/Blogs/Shared/Styles/blog.css" />
</abp-style-bundle> </abp-style-bundle>
} }
<div class="vs-blog blah"> <div class="vs-blog blah">
<div class="container"> <div class="container">
<div class="pb-3"> <div class="pb-3">
@ -39,18 +40,18 @@
var post = Model.Posts[index]; var post = Model.Posts[index];
<div class="hero-articles"> <div class="hero-articles">
<div class="img-container"> <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"> <img src="@post.CoverImage" class="hero-article-img" alt="@post.Title cover image">
</a> </a>
</div> </div>
<div class="hero-content pt-3"> <div class="hero-content pt-3">
<h2> <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> </h2>
<p class="article-sum"> <p class="article-sum">
@Html.Raw(BloggingPageHelper.GetShortContent(post.Content)) @Html.Raw(BloggingPageHelper.GetShortContent(post.Content))
</p> </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> </div>
@if (post.Writer != null) @if (post.Writer != null)
@ -60,13 +61,13 @@
<div class="user-card"> <div class="user-card">
<div class="row"> <div class="row">
<div class="col-auto pe-1"> <div class="col-auto pe-1">
<a href="/Members/@post.Writer.UserName"> <a href="@Url.Page("/Blogs/Members/Index", new {userName = post.Writer.UserName})">
<img gravatar-email="@post.Writer.Email" default-image="Identicon" class="article-avatar" alt="@post.Writer.UserName avatar" /> <img gravatar-email="@post.Writer.Email" default-image="Identicon" class="article-avatar" alt="@post.Writer.UserName avatar" />
</a> </a>
</div> </div>
<div class="col ps-1"> <div class="col ps-1">
<h5 class="mt-2 mb-1"> <h5 class="mt-2 mb-1">
<a href="/Members/@post.Writer.UserName"> <a href="@Url.Page("/Blogs/Members/Index", new {userName = post.Writer.UserName})">
@post.Writer.UserName @post.Writer.UserName
</a> </a>
<span>@BloggingPageHelper.GetLocalizedTimeAgoText(post.CreationTime)</span> <span>@BloggingPageHelper.GetLocalizedTimeAgoText(post.CreationTime)</span>
@ -84,7 +85,7 @@
<p class="tags"> <p class="tags">
@foreach (var tag in post.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> </p>
@ -97,7 +98,7 @@
@if (await Authorization.IsGrantedAsync(BloggingPermissions.Posts.Create)) @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"> <div class="list-group">
@ -109,14 +110,14 @@
<div class="row align-middle"> <div class="row align-middle">
<div class="col-4"> <div class="col-4">
<div class="img-container"> <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"> <img src="@post.CoverImage" class="box-article-img" alt="@post.Title cover image">
</a> </a>
</div> </div>
</div> </div>
<div class="col-8 ps-0"> <div class="col-8 ps-0">
<h3 class="font-125"> <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> </h3>
@if (post.Writer != null) @if (post.Writer != null)
@ -127,7 +128,7 @@
@if (post.Writer != null) @if (post.Writer != null)
{ {
<h5 class="mt-2 mb-1"> <h5 class="mt-2 mb-1">
<a href="/Members/@post.Writer.UserName"> <a href="@Url.Page("/Blogs/Members/Index", new {userName = post.Writer.UserName})">
@post.Writer.UserName @post.Writer.UserName
</a> </a>
<span>@BloggingPageHelper.GetLocalizedTimeAgoText(post.CreationTime)</span> <span>@BloggingPageHelper.GetLocalizedTimeAgoText(post.CreationTime)</span>
@ -169,19 +170,19 @@
<div class="row"> <div class="row">
<div class="col-md-4"> <div class="col-md-4">
<div class="img-container"> <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"> <img src="@post.CoverImage" class="box-article-img" alt="@post.Title cover image">
</a> </a>
</div> </div>
</div> </div>
<div class="col"> <div class="col">
<h3> <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> </h3>
<p> <p>
@Html.Raw(BloggingPageHelper.GetShortContent(post.Content)) @Html.Raw(BloggingPageHelper.GetShortContent(post.Content))
</p> </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) @if (post.Writer != null)
{ {
@ -190,13 +191,13 @@
<div class="user-card"> <div class="user-card">
<div class="row"> <div class="row">
<div class="col-auto pe-1"> <div class="col-auto pe-1">
<a href="/Members/@post.Writer.UserName"> <a href="@Url.Page("/Blogs/Members/Index", new {userName = post.Writer.UserName})">
<img gravatar-email="@post.Writer.Email" default-image="Identicon" class="article-avatar" alt="@post.Writer.UserName avatar" /> <img gravatar-email="@post.Writer.Email" default-image="Identicon" class="article-avatar" alt="@post.Writer.UserName avatar" />
</a> </a>
</div> </div>
<div class="col ps-1"> <div class="col ps-1">
<h5 class="mt-2 mb-1"> <h5 class="mt-2 mb-1">
<a href="/Members/@post.Writer.UserName"> <a href="@Url.Page("/Blogs/Members/Index", new {userName = post.Writer.UserName})">
@post.Writer.UserName @post.Writer.UserName
</a> </a>
<span>@BloggingPageHelper.GetLocalizedTimeAgoText(post.CreationTime)</span> <span>@BloggingPageHelper.GetLocalizedTimeAgoText(post.CreationTime)</span>
@ -213,7 +214,7 @@
<p class="tags"> <p class="tags">
@foreach (var tag in post.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> </p>
</div> </div>
@ -234,7 +235,7 @@
<div class="tags"> <div class="tags">
@foreach (var popularTag in Model.PopularTags) @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>
</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.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; using Volo.Abp.AspNetCore.Mvc.UI.RazorPages;
using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Entities;
using Volo.Blogging.Blogs; using Volo.Blogging.Blogs;
@ -18,6 +19,7 @@ namespace Volo.Blogging.Pages.Blog.Posts
private readonly IPostAppService _postAppService; private readonly IPostAppService _postAppService;
private readonly IBlogAppService _blogAppService; private readonly IBlogAppService _blogAppService;
private readonly ITagAppService _tagAppService; private readonly ITagAppService _tagAppService;
public BloggingUrlOptions BlogOptions { get; }
[BindProperty(SupportsGet = true)] [BindProperty(SupportsGet = true)]
public string BlogShortName { get; set; } public string BlogShortName { get; set; }
@ -31,11 +33,12 @@ namespace Volo.Blogging.Pages.Blog.Posts
public IReadOnlyList<TagDto> PopularTags { get; set; } 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; _postAppService = postAppService;
_blogAppService = blogAppService; _blogAppService = blogAppService;
_tagAppService = tagAppService; _tagAppService = tagAppService;
BlogOptions = blogOptions.Value;
} }
public virtual async Task<ActionResult> OnGetAsync() public virtual async Task<ActionResult> OnGetAsync()
@ -47,7 +50,8 @@ namespace Volo.Blogging.Pages.Blog.Posts
try try
{ {
Blog = await _blogAppService.GetByShortNameAsync(BlogShortName); Blog = await GetBlogAsync(_blogAppService, BlogOptions, BlogShortName);
BlogShortName = Blog.ShortName;
} }
catch (EntityNotFoundException) catch (EntityNotFoundException)
{ {
@ -59,5 +63,7 @@ namespace Volo.Blogging.Pages.Blog.Posts
return Page(); return Page();
} }
} }
} }

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

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

Loading…
Cancel
Save