mirror of https://github.com/abpframework/abp.git
54 changed files with 2435 additions and 290 deletions
File diff suppressed because it is too large
@ -0,0 +1,106 @@ |
|||||
|
using System; |
||||
|
using Microsoft.EntityFrameworkCore.Migrations; |
||||
|
|
||||
|
namespace Volo.CmsKit.Migrations |
||||
|
{ |
||||
|
public partial class UrlSlugToSlug : Migration |
||||
|
{ |
||||
|
protected override void Up(MigrationBuilder migrationBuilder) |
||||
|
{ |
||||
|
migrationBuilder.CreateTable( |
||||
|
name: "CmsBlogPosts", |
||||
|
columns: table => new |
||||
|
{ |
||||
|
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false), |
||||
|
BlogId = table.Column<Guid>(type: "uniqueidentifier", nullable: false), |
||||
|
Title = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false), |
||||
|
Slug = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false), |
||||
|
ShortDescription = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true), |
||||
|
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), |
||||
|
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true), |
||||
|
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true), |
||||
|
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false), |
||||
|
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), |
||||
|
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true), |
||||
|
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), |
||||
|
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false), |
||||
|
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), |
||||
|
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true) |
||||
|
}, |
||||
|
constraints: table => |
||||
|
{ |
||||
|
table.PrimaryKey("PK_CmsBlogPosts", x => x.Id); |
||||
|
table.ForeignKey( |
||||
|
name: "FK_CmsBlogPosts_CmsUsers_CreatorId", |
||||
|
column: x => x.CreatorId, |
||||
|
principalTable: "CmsUsers", |
||||
|
principalColumn: "Id", |
||||
|
onDelete: ReferentialAction.Restrict); |
||||
|
table.ForeignKey( |
||||
|
name: "FK_CmsBlogPosts_CmsUsers_DeleterId", |
||||
|
column: x => x.DeleterId, |
||||
|
principalTable: "CmsUsers", |
||||
|
principalColumn: "Id", |
||||
|
onDelete: ReferentialAction.Restrict); |
||||
|
table.ForeignKey( |
||||
|
name: "FK_CmsBlogPosts_CmsUsers_LastModifierId", |
||||
|
column: x => x.LastModifierId, |
||||
|
principalTable: "CmsUsers", |
||||
|
principalColumn: "Id", |
||||
|
onDelete: ReferentialAction.Restrict); |
||||
|
}); |
||||
|
|
||||
|
migrationBuilder.CreateTable( |
||||
|
name: "CmsBlogs", |
||||
|
columns: table => new |
||||
|
{ |
||||
|
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false), |
||||
|
Name = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false), |
||||
|
Slug = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false), |
||||
|
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), |
||||
|
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true), |
||||
|
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true), |
||||
|
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false), |
||||
|
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), |
||||
|
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true), |
||||
|
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), |
||||
|
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false), |
||||
|
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), |
||||
|
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true) |
||||
|
}, |
||||
|
constraints: table => |
||||
|
{ |
||||
|
table.PrimaryKey("PK_CmsBlogs", x => x.Id); |
||||
|
}); |
||||
|
|
||||
|
migrationBuilder.CreateIndex( |
||||
|
name: "IX_CmsBlogPosts_CreatorId", |
||||
|
table: "CmsBlogPosts", |
||||
|
column: "CreatorId"); |
||||
|
|
||||
|
migrationBuilder.CreateIndex( |
||||
|
name: "IX_CmsBlogPosts_DeleterId", |
||||
|
table: "CmsBlogPosts", |
||||
|
column: "DeleterId"); |
||||
|
|
||||
|
migrationBuilder.CreateIndex( |
||||
|
name: "IX_CmsBlogPosts_LastModifierId", |
||||
|
table: "CmsBlogPosts", |
||||
|
column: "LastModifierId"); |
||||
|
|
||||
|
migrationBuilder.CreateIndex( |
||||
|
name: "IX_CmsBlogPosts_Slug_BlogId", |
||||
|
table: "CmsBlogPosts", |
||||
|
columns: new[] { "Slug", "BlogId" }); |
||||
|
} |
||||
|
|
||||
|
protected override void Down(MigrationBuilder migrationBuilder) |
||||
|
{ |
||||
|
migrationBuilder.DropTable( |
||||
|
name: "CmsBlogPosts"); |
||||
|
|
||||
|
migrationBuilder.DropTable( |
||||
|
name: "CmsBlogs"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
using Volo.Abp.Application.Dtos; |
||||
|
|
||||
|
namespace Volo.CmsKit.Admin.Blogs |
||||
|
{ |
||||
|
public class BlogGetListInput : PagedAndSortedResultRequestDto |
||||
|
{ |
||||
|
public string Filter { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,31 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp; |
||||
|
|
||||
|
namespace Volo.CmsKit.Blogs |
||||
|
{ |
||||
|
public class BlogPostSlugAlreadyExistException : BusinessException |
||||
|
{ |
||||
|
internal BlogPostSlugAlreadyExistException(string code = null, string message = null, string details = null, Exception innerException = null, Microsoft.Extensions.Logging.LogLevel logLevel = Microsoft.Extensions.Logging.LogLevel.Warning) : base(code, message, details, innerException, logLevel) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
internal BlogPostSlugAlreadyExistException(System.Runtime.Serialization.SerializationInfo serializationInfo, System.Runtime.Serialization.StreamingContext context) : base(serializationInfo, context) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public BlogPostSlugAlreadyExistException(Guid blogId, string slug) |
||||
|
{ |
||||
|
Slug = slug; |
||||
|
BlogId = blogId; |
||||
|
|
||||
|
Code = CmsKitErrorCodes.Blogs.SlugAlreadyExist; |
||||
|
|
||||
|
WithData(nameof(Slug), Slug); |
||||
|
WithData(nameof(BlogId), BlogId); |
||||
|
} |
||||
|
|
||||
|
public string Slug { get; } |
||||
|
|
||||
|
public Guid BlogId { get; } |
||||
|
} |
||||
|
} |
||||
@ -1,31 +0,0 @@ |
|||||
using System; |
|
||||
using Volo.Abp; |
|
||||
|
|
||||
namespace Volo.CmsKit.Blogs |
|
||||
{ |
|
||||
public class BlogPostUrlSlugAlreadyExistException : BusinessException |
|
||||
{ |
|
||||
internal BlogPostUrlSlugAlreadyExistException(string code = null, string message = null, string details = null, Exception innerException = null, Microsoft.Extensions.Logging.LogLevel logLevel = Microsoft.Extensions.Logging.LogLevel.Warning) : base(code, message, details, innerException, logLevel) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
internal BlogPostUrlSlugAlreadyExistException(System.Runtime.Serialization.SerializationInfo serializationInfo, System.Runtime.Serialization.StreamingContext context) : base(serializationInfo, context) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public BlogPostUrlSlugAlreadyExistException(Guid blogId, string urlSlug) |
|
||||
{ |
|
||||
UrlSlug = urlSlug; |
|
||||
BlogId = blogId; |
|
||||
|
|
||||
Code = CmsKitErrorCodes.Blogs.UrlSlugAlreadyExist; |
|
||||
|
|
||||
WithData(nameof(UrlSlug), UrlSlug); |
|
||||
WithData(nameof(BlogId), BlogId); |
|
||||
} |
|
||||
|
|
||||
public string UrlSlug { get; } |
|
||||
|
|
||||
public Guid BlogId { get; } |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,15 @@ |
|||||
|
using Slugify; |
||||
|
using Unidecode.NET; |
||||
|
|
||||
|
namespace Volo.CmsKit.Blogs.Extensions |
||||
|
{ |
||||
|
public static class SlugExtensions |
||||
|
{ |
||||
|
public static string NormalizeSlug(this string value) |
||||
|
{ |
||||
|
var slugHelper = new SlugHelper(); |
||||
|
|
||||
|
return slugHelper.GenerateSlug(value?.Unidecode()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,30 +0,0 @@ |
|||||
using System.Text.RegularExpressions; |
|
||||
using Unidecode.NET; |
|
||||
|
|
||||
namespace Volo.CmsKit.Blogs.Extensions |
|
||||
{ |
|
||||
public static class UrlSlugExtensions |
|
||||
{ |
|
||||
public static string NormalizeAsUrlSlug(this string value) |
|
||||
{ |
|
||||
value = value.ToLowerInvariant(); |
|
||||
|
|
||||
// Unidecode for non-latin characters
|
|
||||
value = value.Unidecode(); |
|
||||
|
|
||||
// Replace spaces
|
|
||||
value = Regex.Replace(value, @"\s", "-", RegexOptions.Compiled); |
|
||||
|
|
||||
// Remove invalid chars
|
|
||||
value = Regex.Replace(value, @"[^a-z0-9\s-_]", "", RegexOptions.Compiled); |
|
||||
|
|
||||
// Trim dashes & dots
|
|
||||
value = value.Trim('-', '_', '.'); |
|
||||
|
|
||||
// Replace double occurences of - or _
|
|
||||
value = Regex.Replace(value, @"([-_]){2,}", "$1", RegexOptions.Compiled); |
|
||||
|
|
||||
return value; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,34 @@ |
|||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Microsoft.AspNetCore.Mvc.ActionConstraints; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.CmsKit.Public.Pages; |
||||
|
|
||||
|
namespace Volo.CmsKit.Public.Web.Controllers |
||||
|
{ |
||||
|
public class PageController : CmsKitPublicControllerBase |
||||
|
{ |
||||
|
protected IPageAppService PageAppService { get; } |
||||
|
|
||||
|
public PageController(IPageAppService pageAppService) |
||||
|
{ |
||||
|
PageAppService = pageAppService; |
||||
|
} |
||||
|
|
||||
|
[HttpGet("/{*url}", Order = int.MaxValue)] |
||||
|
public async Task<IActionResult> IndexAsync(string url) |
||||
|
{ |
||||
|
var page = await PageAppService.FindByUrlAsync(url); |
||||
|
|
||||
|
if (page == null) |
||||
|
{ |
||||
|
return NotFound(); |
||||
|
} |
||||
|
|
||||
|
return View("~/Views/Page/Index.cshtml", page); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,13 +0,0 @@ |
|||||
@page "{*pageUrl}" |
|
||||
@using Microsoft.AspNetCore.Mvc.Localization |
|
||||
@using Volo.CmsKit.Localization |
|
||||
@using Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.Pages |
|
||||
@model Volo.CmsKit.Public.Web.Pages.CmsKit.Pages.IndexModel |
|
||||
@inject IHtmlLocalizer<CmsKitResource> L |
|
||||
|
|
||||
@await Component.InvokeAsync(typeof(DefaultPageViewComponent), |
|
||||
new |
|
||||
{ |
|
||||
pageId = Model.Page.Id, |
|
||||
title = Model.Page.Title |
|
||||
}) |
|
||||
@ -1,34 +0,0 @@ |
|||||
using System.Threading.Tasks; |
|
||||
using Microsoft.AspNetCore.Mvc; |
|
||||
using Volo.CmsKit.Public.Pages; |
|
||||
using Volo.CmsKit.Web.Pages; |
|
||||
|
|
||||
namespace Volo.CmsKit.Public.Web.Pages.CmsKit.Pages |
|
||||
{ |
|
||||
public class IndexModel : CommonPageModel |
|
||||
{ |
|
||||
[BindProperty(SupportsGet = true)] |
|
||||
public string PageUrl { get; set; } |
|
||||
|
|
||||
protected readonly IPageAppService PageAppService; |
|
||||
|
|
||||
public PageDto Page; |
|
||||
|
|
||||
public IndexModel(IPageAppService pageAppService) |
|
||||
{ |
|
||||
PageAppService = pageAppService; |
|
||||
} |
|
||||
|
|
||||
public async Task<IActionResult> OnGetAsync() |
|
||||
{ |
|
||||
Page = await PageAppService.FindByUrlAsync(PageUrl); |
|
||||
|
|
||||
if (Page == null) |
|
||||
{ |
|
||||
return NotFound(); |
|
||||
} |
|
||||
|
|
||||
return Page(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,9 @@ |
|||||
|
@model Volo.CmsKit.Public.Pages.PageDto |
||||
|
|
||||
|
@using Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.Pages |
||||
|
|
||||
|
@await Component.InvokeAsync(typeof(DefaultPageViewComponent), new |
||||
|
{ |
||||
|
pageId = Model.Id, |
||||
|
title = Model.Title |
||||
|
}) |
||||
Loading…
Reference in new issue