Browse Source

CmsKit - Initial commit of Admin Pages

pull/7871/head
enisn 6 years ago
parent
commit
167e3a8fd5
  1. 2007
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20210226112040_BlogPost_Author.Designer.cs
  2. 109
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20210226112040_BlogPost_Author.cs
  3. 29
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs
  4. 3
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/package.json
  5. 17
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Bundles/SlugifyScriptContributor.cs
  6. 72
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/CmsKitAdminWebModule.cs
  7. 81
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Menus/CmsKitAdminMenuContributor.cs
  8. 28
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Menus/CmsKitAdminMenus.cs
  9. 79
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/Create.cshtml
  10. 63
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/Create.cshtml.cs
  11. 33
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/Index.cshtml
  12. 7
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/Index.cshtml.cs
  13. 77
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/Update.cshtml
  14. 77
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/Update.cshtml.cs
  15. 212
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/create.js
  16. 68
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/index.js
  17. 180
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/update.js
  18. 23
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/CreateModal.cshtml
  19. 44
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/CreateModal.cshtml.cs
  20. 44
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/FeaturesModal.cshtml
  21. 77
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/FeaturesModal.cshtml.cs
  22. 38
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/Index.cshtml
  23. 7
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/Index.cshtml.cs
  24. 23
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/UpdateModal.cshtml
  25. 60
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/UpdateModal.cshtml.cs
  26. 47
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/createModal.js
  27. 85
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/index.js
  28. 30
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/updateModal.js
  29. 108
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Comments/Details.cshtml
  30. 33
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Comments/Details.cshtml.cs
  31. 71
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Comments/Index.cshtml
  32. 17
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Comments/Index.cshtml.cs
  33. 3
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Comments/details.css
  34. 146
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Comments/details.js
  35. 3
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Comments/index.css
  36. 158
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Comments/index.js
  37. 44
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Contents/Components/ContentEditor/ContentEditorViewComponent.cs
  38. 7
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Contents/Components/ContentEditor/Default.cshtml
  39. 80
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Contents/Components/ContentEditor/default.js
  40. 28
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Contents/Components/EntityContentEditor/ContentViewModel.cs
  41. 27
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Contents/Components/EntityContentEditor/Default.cshtml
  42. 65
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Contents/Components/EntityContentEditor/EntityContentEditorViewComponent.cs
  43. 34
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Contents/Components/EntityContentEditor/default.js
  44. 44
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Create.cshtml
  45. 47
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Create.cshtml.cs
  46. 40
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Index.cshtml
  47. 11
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Index.cshtml.cs
  48. 45
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Update.cshtml
  49. 62
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Update.cshtml.cs
  50. 72
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/create.js
  51. 81
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/index.js
  52. 65
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/update.js
  53. 22
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Tags/Components/TagEditor/Default.cshtml
  54. 49
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Tags/Components/TagEditor/TagEditorViewComponent.cs
  55. 26
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Tags/Components/TagEditor/default.js
  56. 23
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Tags/CreateModal.cshtml
  57. 58
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Tags/CreateModal.cshtml.cs
  58. 24
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Tags/EditModal.cshtml
  59. 54
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Tags/EditModal.cshtml.cs
  60. 38
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Tags/Index.cshtml
  61. 8
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Tags/Index.cshtml.cs
  62. 83
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Tags/Index.js
  63. 20
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKitAdminPageBase.cs
  64. 2
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Volo.CmsKit.Admin.Web.csproj

2007
modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20210226112040_BlogPost_Author.Designer.cs

File diff suppressed because it is too large

109
modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20210226112040_BlogPost_Author.cs

@ -0,0 +1,109 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
namespace Volo.CmsKit.Migrations
{
public partial class BlogPost_Author : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_CmsBlogPosts_CmsUsers_CreatorId",
table: "CmsBlogPosts");
migrationBuilder.DropForeignKey(
name: "FK_CmsBlogPosts_CmsUsers_DeleterId",
table: "CmsBlogPosts");
migrationBuilder.DropForeignKey(
name: "FK_CmsBlogPosts_CmsUsers_LastModifierId",
table: "CmsBlogPosts");
migrationBuilder.DropIndex(
name: "IX_CmsBlogPosts_CreatorId",
table: "CmsBlogPosts");
migrationBuilder.DropIndex(
name: "IX_CmsBlogPosts_DeleterId",
table: "CmsBlogPosts");
migrationBuilder.DropIndex(
name: "IX_CmsBlogPosts_LastModifierId",
table: "CmsBlogPosts");
migrationBuilder.AddColumn<Guid>(
name: "AuthorId",
table: "CmsBlogPosts",
type: "uniqueidentifier",
nullable: false,
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"));
migrationBuilder.CreateIndex(
name: "IX_CmsBlogPosts_AuthorId",
table: "CmsBlogPosts",
column: "AuthorId");
migrationBuilder.AddForeignKey(
name: "FK_CmsBlogPosts_CmsUsers_AuthorId",
table: "CmsBlogPosts",
column: "AuthorId",
principalTable: "CmsUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_CmsBlogPosts_CmsUsers_AuthorId",
table: "CmsBlogPosts");
migrationBuilder.DropIndex(
name: "IX_CmsBlogPosts_AuthorId",
table: "CmsBlogPosts");
migrationBuilder.DropColumn(
name: "AuthorId",
table: "CmsBlogPosts");
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.AddForeignKey(
name: "FK_CmsBlogPosts_CmsUsers_CreatorId",
table: "CmsBlogPosts",
column: "CreatorId",
principalTable: "CmsUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
migrationBuilder.AddForeignKey(
name: "FK_CmsBlogPosts_CmsUsers_DeleterId",
table: "CmsBlogPosts",
column: "DeleterId",
principalTable: "CmsUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
migrationBuilder.AddForeignKey(
name: "FK_CmsBlogPosts_CmsUsers_LastModifierId",
table: "CmsBlogPosts",
column: "LastModifierId",
principalTable: "CmsUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
}
}
}

29
modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs

@ -1257,6 +1257,9 @@ namespace Volo.CmsKit.Migrations
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<Guid>("AuthorId")
.HasColumnType("uniqueidentifier");
b.Property<Guid>("BlogId")
.HasColumnType("uniqueidentifier");
@ -1320,11 +1323,7 @@ namespace Volo.CmsKit.Migrations
b.HasKey("Id");
b.HasIndex("CreatorId");
b.HasIndex("DeleterId");
b.HasIndex("LastModifierId");
b.HasIndex("AuthorId");
b.HasIndex("Slug", "BlogId");
@ -1952,23 +1951,13 @@ namespace Volo.CmsKit.Migrations
modelBuilder.Entity("Volo.CmsKit.Blogs.BlogPost", b =>
{
b.HasOne("Volo.CmsKit.Users.CmsUser", "Creator")
.WithMany()
.HasForeignKey("CreatorId");
b.HasOne("Volo.CmsKit.Users.CmsUser", "Deleter")
b.HasOne("Volo.CmsKit.Users.CmsUser", "Author")
.WithMany()
.HasForeignKey("DeleterId");
b.HasOne("Volo.CmsKit.Users.CmsUser", "LastModifier")
.WithMany()
.HasForeignKey("LastModifierId");
b.Navigation("Creator");
b.Navigation("Deleter");
.HasForeignKey("AuthorId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("LastModifier");
b.Navigation("Author");
});
modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b =>

3
modules/cms-kit/host/Volo.CmsKit.Web.Unified/package.json

@ -7,6 +7,7 @@
"@abp/cms-kit": "4.2.1",
"@abp/tui-editor": "^4.2.1",
"tui-code-snippet": "1.5.2",
"@abp/uppy": "^4.2.1"
"@abp/uppy": "^4.2.1",
"slugify": "1.4.6"
}
}

17
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Bundles/SlugifyScriptContributor.cs

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
namespace Volo.CmsKit.Admin.Web.Bundles
{
public class SlugifyScriptContributor : BundleContributor
{
public override void ConfigureBundle(BundleConfigurationContext context)
{
context.Files.Add("/libs/slugify/slugify.js");
}
}
}

72
modules/cms-kit/src/Volo.CmsKit.Admin.Web/CmsKitAdminWebModule.cs

@ -7,6 +7,9 @@ using Volo.Abp.UI.Navigation;
using Volo.Abp.VirtualFileSystem;
using Volo.CmsKit.Localization;
using Volo.CmsKit.Web;
using Volo.CmsKit.Permissions;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.PageToolbars;
using Volo.Abp.Localization;
namespace Volo.CmsKit.Admin.Web
{
@ -46,10 +49,79 @@ namespace Volo.CmsKit.Admin.Web
options.FileSets.AddEmbedded<CmsKitAdminWebModule>("Volo.CmsKit.Admin.Web");
});
Configure<RazorPagesOptions>(options =>
{
options.Conventions.AuthorizeFolder("/CmsKit/Tags/", CmsKitAdminPermissions.Tags.Default);
options.Conventions.AuthorizeFolder("/CmsKit/Tags/CreateModal", CmsKitAdminPermissions.Tags.Create);
options.Conventions.AuthorizeFolder("/CmsKit/Tags/UpdateModal", CmsKitAdminPermissions.Tags.Update);
options.Conventions.AuthorizeFolder("/CmsKit/Pages", CmsKitAdminPermissions.Pages.Default);
options.Conventions.AuthorizeFolder("/CmsKit/Pages/Create", CmsKitAdminPermissions.Pages.Create);
options.Conventions.AuthorizeFolder("/CmsKit/Pages/Update", CmsKitAdminPermissions.Pages.Update);
options.Conventions.AuthorizeFolder("/CmsKit/Blogs", CmsKitAdminPermissions.Blogs.Default);
options.Conventions.AuthorizeFolder("/CmsKit/Blogs/Create", CmsKitAdminPermissions.Blogs.Create);
options.Conventions.AuthorizeFolder("/CmsKit/Blogs/Update", CmsKitAdminPermissions.Blogs.Update);
options.Conventions.AuthorizeFolder("/CmsKit/BlogPosts", CmsKitAdminPermissions.BlogPosts.Default);
options.Conventions.AuthorizeFolder("/CmsKit/BlogPosts/Create", CmsKitAdminPermissions.BlogPosts.Create);
options.Conventions.AuthorizeFolder("/CmsKit/BlogPosts/Update", CmsKitAdminPermissions.BlogPosts.Update);
options.Conventions.AuthorizeFolder("/CmsKit/Comments/", CmsKitAdminPermissions.Comments.Default);
options.Conventions.AuthorizeFolder("/CmsKit/Comments/Details", CmsKitAdminPermissions.Comments.Default);
});
Configure<RazorPagesOptions>(options =>
{
//Configure authorization.
});
Configure<AbpPageToolbarOptions>(options =>
{
options.Configure<Volo.CmsKit.Admin.Web.Pages.CmsKit.Tags.IndexModel>(
toolbar =>
{
toolbar.AddButton(
LocalizableString.Create<CmsKitResource>("New"),
icon: "plus",
name: "NewButton",
requiredPolicyName: CmsKitAdminPermissions.Tags.Create
);
}
);
options.Configure<Volo.CmsKit.Admin.Web.Pages.CmsKit.Pages.IndexModel>(
toolbar =>
{
toolbar.AddButton(
LocalizableString.Create<CmsKitResource>("New"),
icon: "plus",
name: "CreatePage",
requiredPolicyName: CmsKitAdminPermissions.Pages.Create
);
});
options.Configure<Volo.CmsKit.Admin.Web.Pages.CmsKit.Blogs.IndexModel>(
toolbar =>
{
toolbar.AddButton(
LocalizableString.Create<CmsKitResource>("New"),
icon: "plus",
name: "CreateBlog",
id: "CreateBlog",
requiredPolicyName: CmsKitAdminPermissions.Blogs.Create
);
});
options.Configure<Volo.CmsKit.Admin.Web.Pages.CmsKit.BlogPosts.IndexModel>(
toolbar =>
{
toolbar.AddButton(
LocalizableString.Create<CmsKitResource>("New"),
icon: "plus",
name: "CreateBlogPost",
id: "CreateBlogPost",
requiredPolicyName: CmsKitAdminPermissions.BlogPosts.Create
);
});
});
}
}
}

81
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Menus/CmsKitAdminMenuContributor.cs

@ -1,5 +1,9 @@
using System.Threading.Tasks;
using Volo.Abp.GlobalFeatures;
using Volo.Abp.UI.Navigation;
using Volo.CmsKit.GlobalFeatures;
using Volo.CmsKit.Localization;
using Volo.CmsKit.Permissions;
namespace Volo.CmsKit.Admin.Web.Menus
{
@ -13,11 +17,82 @@ namespace Volo.CmsKit.Admin.Web.Menus
}
}
private Task ConfigureMainMenuAsync(MenuConfigurationContext context)
private async Task ConfigureMainMenuAsync(MenuConfigurationContext context)
{
//Add main menu items.
await AddCmsMenuAsync(context);
}
private async Task AddCmsMenuAsync(MenuConfigurationContext context)
{
var l = context.GetLocalizer<CmsKitResource>();
var cmsMenu = context.Menu.FindMenuItem(CmsKitAdminMenus.GroupName);
cmsMenu ??= new ApplicationMenuItem(
CmsKitAdminMenus.GroupName,
l["Cms"],
icon: "far fa-newspaper");
if (GlobalFeatureManager.Instance.IsEnabled<CommentsFeature>())
{
if (await context.IsGrantedAsync(CmsKitAdminPermissions.Comments.Default))
{
cmsMenu.AddItem(new ApplicationMenuItem(
CmsKitAdminMenus.Comments.CommentsMenu,
l["Comments"].Value,
"/CmsKit/Comments"
)
);
}
}
if (GlobalFeatureManager.Instance.IsEnabled<TagsFeature>())
{
if (await context.IsGrantedAsync(CmsKitAdminPermissions.Tags.Default))
{
cmsMenu.AddItem(new ApplicationMenuItem(
CmsKitAdminMenus.Tags.TagsMenu,
l["Tags"].Value,
"/CmsKit/Tags"));
}
}
if (GlobalFeatureManager.Instance.IsEnabled<PagesFeature>())
{
if (await context.IsGrantedAsync(CmsKitAdminPermissions.Pages.Default))
{
cmsMenu.AddItem(new ApplicationMenuItem(
CmsKitAdminMenus.Pages.PagesMenu,
l["Pages"].Value,
"/CmsKit/Pages"));
}
}
if (GlobalFeatureManager.Instance.IsEnabled<BlogsFeature>())
{
if (await context.IsGrantedAsync(CmsKitAdminPermissions.Blogs.Default))
{
cmsMenu.AddItem(new ApplicationMenuItem(
CmsKitAdminMenus.Blogs.BlogsMenu,
l["Blogs"],
"/CmsKit/Blogs"
));
}
if (await context.IsGrantedAsync(CmsKitAdminPermissions.BlogPosts.Default))
{
cmsMenu.AddItem(new ApplicationMenuItem(
CmsKitAdminMenus.BlogPosts.BlogPostsMenu,
l["BlogPosts"],
"/CmsKit/BlogPosts"
));
}
}
return Task.CompletedTask;
if (cmsMenu.Items.Count > 0)
{
context.Menu.AddItem(cmsMenu);
}
}
}
}

28
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Menus/CmsKitAdminMenus.cs

@ -2,10 +2,32 @@
{
public class CmsKitAdminMenus
{
private const string Prefix = "CmsKit.Admin";
public const string GroupName = "Cms";
//Add your menu items here...
//public const string Home = Prefix + ".MyNewMenuItem";
public static class Comments
{
public const string CommentsMenu = GroupName + ".Comments";
}
public static class Tags
{
public const string TagsMenu = GroupName + ".Tags";
}
public static class Pages
{
public const string PagesMenu = GroupName + ".Pages";
}
public static class Blogs
{
public const string BlogsMenu = GroupName + ".Blogs";
}
public static class BlogPosts
{
public const string BlogPostsMenu = GroupName + ".BlogPosts";
}
}
}

79
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/Create.cshtml

@ -0,0 +1,79 @@
@page
@using Volo.CmsKit.Admin.Web.Pages.CmsKit.Contents.Components.EntityContentEditor
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Pages.Shared.Components.AbpPageToolbar
@using Volo.CmsKit.Admin.Web.Pages
@using Volo.CmsKit.Admin.Web.Menus
@using Volo.CmsKit.Admin.Web.Pages.CmsKit.BlogPosts
@using Volo.CmsKit.Admin.Web.Pages.CmsKit.Tags.Components.TagEditor
@using Volo.CmsKit.Blogs
@using Volo.Abp.AspNetCore.Mvc.UI.Packages.Uppy
@using Volo.CmsKit.Admin.Web.Bundles
@inherits CmsKitAdminPageBase
@model CreateModel
@{
PageLayout.Content.Title = L["BlogPosts"].Value;
PageLayout.Content.BreadCrumb.Add(L["Menu:CMS"].Value);
PageLayout.Content.MenuItemName = CmsKitAdminMenus.BlogPosts.BlogPostsMenu;
}
@section scripts {
<abp-script-bundle>
<abp-script type="typeof(UppyScriptContributor)" />
<abp-script src="/Pages/CmsKit/BlogPosts/create.js" />
<abp-script type="typeof(SlugifyScriptContributor)" />
</abp-script-bundle>
}
@section content_toolbar {
@await Component.InvokeAsync(typeof(AbpPageToolbarViewComponent), new { pageName = typeof(CreateModel).FullName })
}
<abp-card>
<abp-card-header title="@L["New"].Value"></abp-card-header>
<abp-card-body>
<div class="form-group">
<label>@L["CoverImage"]</label>
<input type="file" id="BlogPostCoverImage" class="form-control" />
</div>
<abp-dynamic-form abp-model="ViewModel" asp-page="/CmsKit/BlogPosts/Create" id="form-blog-post-create">
<div class="form-group">
<label asp-for="ViewModel.BlogId"></label>
<select asp-for="ViewModel.BlogId" id="BlogSelectionSelect" class="form-control"></select>
<span asp-validation-for="ViewModel.BlogId"></span>
</div>
<abp-input asp-for="ViewModel.Title" />
<abp-input asp-for="ViewModel.Slug" />
@await Component.InvokeAsync(typeof(EntityContentEditorViewComponent), new
{
entityType = BlogPostConsts.EntityType,
displaySubmitButton = false
})
<abp-form-content />
</abp-dynamic-form>
<div id="blog-post-tags-wrapper">
<hr />
@await Component.InvokeAsync(typeof(TagEditorViewComponent), new
{
entityType = BlogPostConsts.EntityType,
displaySubmitButton = false
})
</div>
</abp-card-body>
<abp-card-footer>
<abp-button button-type="Primary" type="submit" text="@L["Submit"].Value" id="button-blog-post-create" />
</abp-card-footer>
</abp-card>

63
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/Create.cshtml.cs

@ -0,0 +1,63 @@
using AutoMapper;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form;
using Volo.Abp.Validation;
using Volo.CmsKit.Admin.Blogs;
using Volo.CmsKit.Blogs;
namespace Volo.CmsKit.Admin.Web.Pages.CmsKit.BlogPosts
{
public class CreateModel : CmsKitAdminPageModel
{
protected IBlogPostAdminAppService BlogPostAdminAppService { get; }
[BindProperty]
public CreateBlogPostViewModel ViewModel { get; set; }
public CreateModel(
IBlogPostAdminAppService blogPostAdminAppService)
{
BlogPostAdminAppService = blogPostAdminAppService;
}
public async Task<IActionResult> OnPostAsync()
{
var dto = ObjectMapper.Map<CreateBlogPostViewModel, CreateBlogPostDto>(ViewModel);
var created = await BlogPostAdminAppService.CreateAsync(dto);
return new OkObjectResult(created);
}
[AutoMap(typeof(CreateBlogPostDto), ReverseMap = true)]
public class CreateBlogPostViewModel
{
[Required]
[DynamicFormIgnore]
public Guid BlogId { get; set; }
[Required]
[DynamicMaxLength(typeof(BlogPostConsts), nameof(BlogPostConsts.MaxTitleLength))]
[DynamicFormIgnore]
public string Title { get; set; }
[Required]
[DynamicStringLength(
typeof(BlogPostConsts),
nameof(BlogPostConsts.MaxSlugLength),
nameof(BlogPostConsts.MinSlugLength))]
[DynamicFormIgnore]
public string Slug { get; set; }
[DynamicMaxLength(typeof(BlogPostConsts), nameof(BlogPostConsts.MaxShortDescriptionLength))]
public string ShortDescription { get; set; }
}
}
}

33
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/Index.cshtml

@ -0,0 +1,33 @@
@page
@using Volo.CmsKit.Admin.Web.Pages.CmsKit.BlogPosts
@using Volo.CmsKit.Admin.Web.Pages
@using Volo.CmsKit.Admin.Web.Menus
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Pages.Shared.Components.AbpPageToolbar
@inherits CmsKitAdminPageBase
@model IndexModel
@{
PageLayout.Content.Title = L["BlogPosts"].Value;
PageLayout.Content.BreadCrumb.Add(L["Menu:CMS"].Value);
PageLayout.Content.MenuItemName = CmsKitAdminMenus.BlogPosts.BlogPostsMenu;
}
@section scripts {
<abp-script src="/Pages/CmsKit/BlogPosts/index.js" />
}
@section content_toolbar {
@await Component.InvokeAsync(typeof(AbpPageToolbarViewComponent), new { pageName = typeof(IndexModel).FullName })
}
<div id="CmsKitBlogPostsWrapper">
<abp-card>
<abp-card-body>
<abp-table striped-rows="true" id="BlogPostsTable" class="nowrap"></abp-table>
</abp-card-body>
</abp-card>
</div>

7
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/Index.cshtml.cs

@ -0,0 +1,7 @@
namespace Volo.CmsKit.Admin.Web.Pages.CmsKit.BlogPosts
{
public class IndexModel : CmsKitAdminPageModel
{
}
}

77
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/Update.cshtml

@ -0,0 +1,77 @@
@page "{Id}"
@using Volo.CmsKit.Blogs
@using Volo.CmsKit.Admin.Web.Pages
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Pages.Shared.Components.AbpPageToolbar
@using Volo.CmsKit.Admin.Web.Pages.CmsKit.Contents.Components.EntityContentEditor
@using Volo.CmsKit.Admin.Web.Menus
@using Volo.CmsKit.Admin.Web.Pages.CmsKit.BlogPosts
@using Volo.CmsKit.Admin.Web.Pages.CmsKit.Tags.Components.TagEditor
@using Volo.Abp.AspNetCore.Mvc.UI.Packages.Uppy
@using Volo.CmsKit.Admin.Web.Bundles
@inherits CmsKitAdminPageBase
@model UpdateModel
@{
PageLayout.Content.Title = L["BlogPosts"].Value;
PageLayout.Content.BreadCrumb.Add(L["Menu:CMS"].Value);
PageLayout.Content.MenuItemName = CmsKitAdminMenus.BlogPosts.BlogPostsMenu;
}
@section scripts {
<abp-script-bundle>
<abp-script type="typeof(UppyScriptContributor)" />
<abp-script src="/Pages/CmsKit/BlogPosts/update.js" />
<abp-script type="typeof(SlugifyScriptContributor)" />
</abp-script-bundle>
}
@section content_toolbar {
@await Component.InvokeAsync(typeof(AbpPageToolbarViewComponent), new { pageName = typeof(UpdateModel).FullName })
}
<abp-card>
<abp-card-header title="@L["Update"].Value"></abp-card-header>
<abp-card-body>
<div class="form-group">
<img height="120" src="/api/cms-kit-admin/blogs/blog-posts/@Model.Id/cover-image" />
<label>@L["CoverImage"]</label>
<input type="file" id="BlogPostCoverImage" class="form-control" />
</div>
<abp-dynamic-form abp-model="ViewModel" asp-page="/CmsKit/BlogPosts/Update" id="form-blog-post-update">
<abp-input asp-for="Id" />
<abp-input asp-for="ViewModel.Title" />
<abp-input asp-for="ViewModel.Slug" />
@await Component.InvokeAsync(typeof(EntityContentEditorViewComponent), new
{
entityType = BlogPostConsts.EntityType,
entityId = Model.Id.ToString(),
displaySubmitButton = false
})
<abp-form-content />
</abp-dynamic-form>
@if (Model.TagsFeature?.IsEnabled == true)
{
<hr />
@await Component.InvokeAsync(typeof(TagEditorViewComponent), new
{
entityType = BlogPostConsts.EntityType,
entityId = Model.Id.ToString(),
displaySubmitButton = false
})
}
</abp-card-body>
<abp-card-footer>
<abp-button button-type="Primary" type="submit" text="@L["Submit"].Value" id="button-blog-post-update" />
</abp-card-footer>
</abp-card>

77
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/Update.cshtml.cs

@ -0,0 +1,77 @@
using AutoMapper;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form;
using Volo.Abp.Validation;
using Volo.CmsKit.Admin.Blogs;
using Volo.CmsKit.Blogs;
namespace Volo.CmsKit.Admin.Web.Pages.CmsKit.BlogPosts
{
public class UpdateModel : CmsKitAdminPageModel
{
protected IBlogPostAdminAppService BlogPostAdminAppService { get; }
protected IBlogFeatureAppService BlogFeatureAppService { get; }
[BindProperty]
public virtual UpdateBlogPostViewModel ViewModel { get; set; }
[HiddenInput]
[BindProperty(SupportsGet = true)]
public virtual Guid Id { get; set; }
public virtual BlogFeatureDto TagsFeature { get; protected set; }
public UpdateModel(
IBlogPostAdminAppService blogPostAdminAppService,
IBlogFeatureAppService blogFeatureAppService)
{
BlogPostAdminAppService = blogPostAdminAppService;
BlogFeatureAppService = blogFeatureAppService;
}
public virtual async Task OnGetAsync()
{
var blogPost = await BlogPostAdminAppService.GetAsync(Id);
ViewModel = ObjectMapper.Map<BlogPostDto, UpdateBlogPostViewModel>(blogPost);
TagsFeature = await BlogFeatureAppService.GetOrDefaultAsync(blogPost.BlogId, GlobalFeatures.TagsFeature.Name);
}
public virtual async Task<IActionResult> OnPostAsync()
{
var dto = ObjectMapper.Map<UpdateBlogPostViewModel, UpdateBlogPostDto>(ViewModel);
await BlogPostAdminAppService.UpdateAsync(Id, dto);
return NoContent();
}
[AutoMap(typeof(BlogPostDto))]
[AutoMap(typeof(UpdateBlogPostDto), ReverseMap = true)]
public class UpdateBlogPostViewModel
{
[DynamicMaxLength(typeof(BlogPostConsts), nameof(BlogPostConsts.MaxTitleLength))]
[Required]
[DynamicFormIgnore]
public string Title { get; set; }
[DynamicStringLength(typeof(BlogPostConsts), nameof(BlogPostConsts.MaxSlugLength), nameof(BlogPostConsts.MinSlugLength))]
[Required]
[DisplayOrder(10000)]
[DynamicFormIgnore]
public string Slug { get; set; }
[DynamicMaxLength(typeof(BlogPostConsts), nameof(BlogPostConsts.MaxShortDescriptionLength))]
[DisplayOrder(10001)]
public string ShortDescription { get; set; }
}
}
}

212
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/create.js

@ -0,0 +1,212 @@
$(function () {
var l = abp.localization.getResource("CmsKit");
var $selectBlog = $('#BlogSelectionSelect');
var $formCreate = $('#form-blog-post-create');
var $title = $('#ViewModel_Title');
var $shortDescription = $('#ViewModel_ShortDescription');
var $url = $('#ViewModel_Slug');
var $buttonSubmit = $('#button-blog-post-create');
var $pageContentInput = $('#ViewModel_Value');
var $tagsInput = $('.tag-editor-form input[name=tags]');
var $fileInput = $('#BlogPostCoverImage');
var $tagsWrapper = $('#blog-post-tags-wrapper');
var UPPY_UPLOAD_ENDPOINT = "/api/cms-kit-admin/blogs/blog-posts/{0}/cover-image";
var UPPY_FILE_ID = "uppy-upload-file";
var isTagsEnabled = true;
$formCreate.data('validator').settings.ignore = ":hidden, [contenteditable='true']:not([name]), .tui-popup-wrapper";
function initSelectBlog() {
$selectBlog.data('autocompleteApiUrl', '/api/cms-kit-admin/blogs');
$selectBlog.data('autocompleteDisplayProperty', 'name');
$selectBlog.data('autocompleteValueProperty', 'id');
$selectBlog.data('autocompleteItemsProperty', 'items');
$selectBlog.data('autocompleteFilterParamName', 'filter');
abp.dom.initializers.initializeAutocompleteSelects($selectBlog);
}
initSelectBlog();
$formCreate.on('submit', function (e) {
e.preventDefault();
if ($formCreate.valid()) {
abp.ui.setBusy();
$formCreate.ajaxSubmit({
success: function (result) {
submitEntityContent(result.id);
},
error: function (result) {
abp.notify.error(result.responseJSON.error.message);
abp.ui.clearBusy();
}
});
}
});
$buttonSubmit.click(function (e) {
e.preventDefault();
$formCreate.submit();
});
function submitEntityContent(blogPostId) {
volo.cmsKit.admin.contents.contentAdmin
.create(
{
entityType: 'BlogPost',
entityId: blogPostId,
value: $pageContentInput.val()
})
.then(function (result) {
if (isTagsEnabled) {
submitEntityTags(blogPostId)
}
else {
submitCoverImage(blogPostId);
}
});
}
function submitEntityTags(blogPostId) {
var tags = $tagsInput.val().split(",");
volo.cmsKit.admin.tags.entityTagAdmin
.setEntityTags({
entityType: 'BlogPost',
entityId: blogPostId,
tags: tags
})
.then(function (result) {
submitCoverImage(blogPostId);
});
}
function getUppyHeaders() {
var headers = {};
headers[abp.security.antiForgery.tokenHeaderName] = abp.security.antiForgery.getToken();
return headers;
}
function submitCoverImage(blogPostId) {
var UPPY_OPTIONS = {
endpoint: UPPY_UPLOAD_ENDPOINT.replace("{0}", blogPostId),
formData: true,
fieldName: "file",
method: "post",
headers: getUppyHeaders()
};
var UPPY = Uppy.Core().use(Uppy.XHRUpload, UPPY_OPTIONS);
UPPY.reset();
var file = $fileInput[0].files[0];
if (file) {
UPPY.addFile({
id: UPPY_FILE_ID,
name: file.name, // file name
type: file.type, // file type
data: file, // file
});
UPPY.upload().then((result) => {
if (result.failed.length > 0) {
abp.message.error(l("UploadFailedMessage"));
} else {
finishSaving();
}
});
}
else {
finishSaving();
}
}
function finishSaving() {
abp.notify.success(l('SuccessfullySaved'));
abp.ui.clearBusy();
location.href = "/Admin/BlogPosts/";
}
var urlEdited = false;
var reflectedChange = false;
$url.on('change', function () {
reflectUrlChanges();
});
$title.on('keyup paste', function () {
reflectUrlChanges();
});
function reflectUrlChanges() {
var title = $title.val().toLocaleLowerCase();
if (urlEdited) {
title = $url.val();
}
var slugified = slugify(title, {
lower: true
});
if (slugified != $url.val()) {
reflectedChange = true;
$url.val(slugified);
reflectedChange = false;
}
}
$url.change(function () {
if (!reflectedChange) {
urlEdited = true;
}
});
var shorDescriptionEdited = false;
$pageContentInput.on('change', function () {
if (shorDescriptionEdited) {
return;
}
var htmlValue = $pageContentInput.val();
var plainValue = jQuery('<div>').html(htmlValue).text().replace(/\n/g, ' ').substring(0, 120);
$shortDescription.val(plainValue);
});
$shortDescription.on('change', function () {
shorDescriptionEdited = true;
});
$selectBlog.on('change', function () {
var blogId = $selectBlog.val();
volo.cmsKit.blogs.blogFeature
.getOrDefault(blogId, 'CmsKit.Tags')
.then(function (result) {
if (result) {
isTagsEnabled = result.isEnabled == true
if (isTagsEnabled === true) {
$tagsWrapper.removeClass('d-none');
}
else {
$tagsWrapper.addClass('d-none');
}
}
});
});
});

68
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/index.js

@ -0,0 +1,68 @@

$(function () {
var l = abp.localization.getResource("CmsKit");
var blogsService = volo.cmsKit.admin.blogs.blogPostAdmin;
var $blogPostWrapper = $('#CmsKitBlogPostsWrapper');
var dataTable = $("#BlogPostsTable").DataTable(abp.libs.datatables.normalizeConfiguration({
processing: true,
serverSide: true,
paging: true,
searching: false,
autoWidth: false,
scrollCollapse: true,
scrollX: true,
ordering: true,
order: [[1, "desc"]],
ajax: abp.libs.datatables.createAjax(blogsService.getList),
columnDefs: [
{
title: l("Details"),
targets: 0,
rowAction: {
items: [
{
text: l('Edit'),
visible: abp.auth.isGranted('CmsKit.Blogs.Update'),
action: function (data) {
location.href = "/CmsKit/BlogPosts/Update/" + data.record.id
}
},
{
text: l('Delete'),
visible: abp.auth.isGranted('CmsKit.Blogs.Delete'),
confirmMessage: function (data) {
return l("BlogPostDeletionConfirmationMessage", data.record.title)
},
action: function (data) {
blogsService
.delete(data.record.id)
.then(function () {
abp.notify.info(l("SuccessfullyDeleted"));
dataTable.ajax.reload();
});
}
}
]
}
},
{
title: l("Title"),
orderable: true,
data: "title"
},
{
title: l("Slug"),
orderable: true,
data: "slug"
}
]
}));
$('#AbpContentToolbar button[name=CreateBlogPost]').on('click', function (e) {
e.preventDefault();
window.location.href = "/CmsKit/BlogPosts/Create"
});
});

180
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/update.js

@ -0,0 +1,180 @@
$(function () {
var l = abp.localization.getResource("CmsKit");
var $selectBlog = $('#BlogSelectionSelect');
var $formUpdate = $('#form-blog-post-update');
var $title = $('#ViewModel_Title');
var $titleClone = $('#title-clone');
var $slug = $('#ViewModel_Slug');
var $buttonSubmit = $('#button-blog-post-update');
var $contentValueInput = $('#ViewModel_Value');
var $blogPostIdInput = $('#Id');
var $contentIdInput = $('#ViewModel_Id');
var $tagsInput = $('.tag-editor-form input[name=tags]');
var $fileInput = $('#BlogPostCoverImage');
var UPPY_UPLOAD_ENDPOINT = "/api/cms-kit-admin/blogs/blog-posts/{0}/cover-image";
var UPPY_FILE_ID = "uppy-upload-file";
$formUpdate.data('validator').settings.ignore = ":hidden, [contenteditable='true']:not([name]), .tui-popup-wrapper";
function initSelectBlog() {
$selectBlog.data('autocompleteApiUrl', '/api/cms-kit-admin/blogs/blogs');
$selectBlog.data('autocompleteDisplayProperty', 'name');
$selectBlog.data('autocompleteValueProperty', 'id');
$selectBlog.data('autocompleteItemsProperty', 'items');
$selectBlog.data('autocompleteFilterParamName', 'filter');
abp.dom.initializers.initializeAutocompleteSelects($selectBlog);
}
initSelectBlog();
$formUpdate.on('submit', function (e) {
e.preventDefault();
if ($formUpdate.valid()) {
abp.ui.setBusy();
$formUpdate.ajaxSubmit({
success: function (result) {
submitEntityContent();
},
error: function (result) {
abp.ui.clearBusy(); abp.notify.error(result.responseJSON.error.message);
}
});
}
});
$buttonSubmit.click(function (e) {
e.preventDefault();
$formUpdate.submit();
});
function submitEntityContent() {
var contentId = $contentIdInput.val();
var blogPostId = $blogPostIdInput.val();
var contentValue = $contentValueInput.val();
if (contentId) {
volo.cmsKit.admin.contents.contentAdmin
.update(contentId,
{
value: contentValue
})
.then(function (result) {
entityContentCallback(blogPostId);
});
}
else {
volo.cmsKit.admin.contents.contentAdmin
.create({
entityType: 'BlogPost',
entityId: blogPostId,
value: contentValue
})
.then(function (result) {
entityContentCallback(blogPostId);
});
}
}
function entityContentCallback(blogPostId) {
if ($tagsInput.val()) {
submitEntityTags(blogPostId);
}
else {
submitCoverImage(blogPostId);
}
}
function submitEntityTags(blogPostId) {
var tags = $tagsInput.val().split(",");
volo.cmsKit.admin.tags.entityTagAdmin
.setEntityTags({
entityType: 'BlogPost',
entityId: blogPostId,
tags: tags
})
.then(function (result) {
submitCoverImage(blogPostId);
});
}
function getUppyHeaders() {
var headers = {};
headers[abp.security.antiForgery.tokenHeaderName] = abp.security.antiForgery.getToken();
return headers;
}
function submitCoverImage(blogPostId) {
var UPPY_OPTIONS = {
endpoint: UPPY_UPLOAD_ENDPOINT.replace("{0}", blogPostId),
formData: true,
fieldName: "file",
method: "post",
headers: getUppyHeaders()
};
var UPPY = Uppy.Core().use(Uppy.XHRUpload, UPPY_OPTIONS);
UPPY.reset();
var file = $fileInput[0].files[0];
if (file) {
UPPY.addFile({
id: UPPY_FILE_ID,
name: file.name, // file name
type: file.type, // file type
data: file, // file
});
UPPY.upload().then((result) => {
if (result.failed.length > 0) {
abp.message.error(l("UploadFailedMessage"));
} else {
finishSaving();
}
});
}
else {
finishSaving();
}
}
function finishSaving(result) {
abp.notify.success(l('SuccessfullySaved'));
abp.ui.clearBusy();
location.href = "/Admin/BlogPosts/";
}
$titleClone.on('change paste keyup', function () {
$title.val($titleClone.val());
});
$slug.on('change', function () {
reflectUrlChanges();
});
function reflectUrlChanges() {
var title = $slug.val();
var slugified = slugify(title);
if (slugified != title) {
$slug.val(slugified, {
lower: true
});
}
}
});

23
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/CreateModal.cshtml

@ -0,0 +1,23 @@
@page
@using Volo.CmsKit.Admin.Web.Pages.CmsKit.Blogs
@using Volo.CmsKit.Admin.Web.Pages
@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal
@inherits CmsKitAdminPageBase
@model CreateModalModel
@{
Layout = null;
}
<abp-dynamic-form abp-model="ViewModel" asp-page="/CmsKit/Blogs/CreateModal">
<abp-modal>
<abp-modal-header title="@L["New"].Value"></abp-modal-header>
<abp-modal-body>
<abp-form-content />
</abp-modal-body>
<abp-modal-footer buttons="@(AbpModalButtons.Cancel | AbpModalButtons.Save)"></abp-modal-footer>
</abp-modal>
</abp-dynamic-form>

44
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/CreateModal.cshtml.cs

@ -0,0 +1,44 @@
using AutoMapper;
using Microsoft.AspNetCore.Mvc;
using System.ComponentModel.DataAnnotations;
using System.Threading.Tasks;
using Volo.Abp.Validation;
using Volo.CmsKit.Admin.Blogs;
using Volo.CmsKit.Blogs;
namespace Volo.CmsKit.Admin.Web.Pages.CmsKit.Blogs
{
public class CreateModalModel : CmsKitAdminPageModel
{
protected IBlogAdminAppService BlogAdminAppService { get; }
[BindProperty]
public CreateBlogViewModel ViewModel { get; set; }
public CreateModalModel(IBlogAdminAppService blogAdminAppService)
{
BlogAdminAppService = blogAdminAppService;
}
public async Task<IActionResult> OnPostAsync()
{
var dto = ObjectMapper.Map<CreateBlogViewModel, CreateBlogDto>(ViewModel);
await BlogAdminAppService.CreateAsync(dto);
return NoContent();
}
[AutoMap(typeof(BlogDto), ReverseMap = true)]
public class CreateBlogViewModel
{
[Required]
[DynamicMaxLength(typeof(BlogConsts), nameof(BlogConsts.MaxNameLength))]
public string Name { get; set; }
[DynamicMaxLength(typeof(BlogConsts), nameof(BlogConsts.MaxSlugLength))]
[Required]
public string Slug { get; set; }
}
}
}

44
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/FeaturesModal.cshtml

@ -0,0 +1,44 @@
@page
@using Volo.CmsKit.Admin.Web.Pages.CmsKit.Blogs
@using Volo.CmsKit.Admin.Web.Pages
@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal
@inherits CmsKitAdminPageBase
@model FeaturesModalModel
@{
Layout = null;
}
<form action="/CmsKit/Blogs/FeaturesModal">
<abp-modal>
<abp-modal-header title="@L["Features"].Value"></abp-modal-header>
<abp-modal-body>
<abp-input asp-for="BlogId"></abp-input>
@for (int i = 0; i < Model.Items.Count; i++)
{
<div class="form-group">
@if (Model.Items[i].IsAvailable)
{
<abp-input asp-for="Items[i].IsEnabled"
label="@L[Model.Items[i].FeatureName]" />
}
else
{
<div data-toggle="tooltip" title="@L["BlogFeatureNotAvailable"]">
<abp-input asp-for="Items[i].IsEnabled"
label="@L[Model.Items[i].FeatureName]"
disabled="true" />
</div>
}
<abp-input asp-for="Items[i].FeatureName" />
</div>
}
</abp-modal-body>
<abp-modal-footer buttons="@(AbpModalButtons.Close | AbpModalButtons.Save)"></abp-modal-footer>
</abp-modal>
</form>

77
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/FeaturesModal.cshtml.cs

@ -0,0 +1,77 @@
using AutoMapper;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.GlobalFeatures;
using Volo.CmsKit.Admin.Blogs;
using Volo.CmsKit.Admin.Web.Pages;
using Volo.CmsKit.Blogs;
namespace Volo.CmsKit.Admin.Web.Pages.CmsKit.Blogs
{
public class FeaturesModalModel : CmsKitAdminPageModel
{
[BindProperty(SupportsGet = true)]
[HiddenInput]
public Guid BlogId { get; set; }
[BindProperty]
public List<BlogFeatureViewModel> Items { get; set; }
protected IBlogFeatureAdminAppService BlogFeatureAdminAppService { get; }
public FeaturesModalModel(IBlogFeatureAdminAppService blogFeatureAdminAppService)
{
BlogFeatureAdminAppService = blogFeatureAdminAppService;
}
public async Task OnGetAsync()
{
var blogFeatureDtos = await BlogFeatureAdminAppService.GetListAsync(BlogId);
Items = ObjectMapper.Map<List<BlogFeatureDto>, List<BlogFeatureViewModel>>(blogFeatureDtos);
}
public async Task<IActionResult> OnPostAsync()
{
var dtos = ObjectMapper.Map<List<BlogFeatureViewModel>, List<BlogFeatureInputDto>>(Items);
foreach (var item in dtos)
{
await BlogFeatureAdminAppService.SetAsync(BlogId, item);
}
return NoContent();
}
[AutoMap(typeof(BlogFeatureDto), ReverseMap = true)]
[AutoMap(typeof(BlogFeatureInputDto), ReverseMap = true)]
public class BlogFeatureViewModel
{
private string featureName;
[HiddenInput]
public string FeatureName { get => featureName; set => SetFeatureName(value); }
public bool IsEnabled { get; set; }
public bool IsAvailable { get; private set; }
private void SetFeatureName(string value)
{
featureName = value;
IsAvailable = GlobalFeatureManager.Instance.Modules.CmsKit().GetFeatures().Any(a => a.FeatureName == FeatureName) ?
GlobalFeatureManager.Instance.IsEnabled(FeatureName) :
true;
if (!IsAvailable)
{
IsEnabled = false;
}
}
}
}
}

38
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/Index.cshtml

@ -0,0 +1,38 @@
@page
@using Volo.CmsKit.Admin.Web.Pages.CmsKit.Blogs
@using Volo.CmsKit.Admin.Web.Pages
@using Volo.CmsKit.Admin.Web.Menus
@using Volo.CmsKit.Admin.Web.Bundles
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Pages.Shared.Components.AbpPageToolbar
@inherits CmsKitAdminPageBase
@model IndexModel
@{
PageLayout.Content.Title = L["Blogs"].Value;
PageLayout.Content.BreadCrumb.Add(L["Menu:CMS"].Value);
PageLayout.Content.MenuItemName = CmsKitAdminMenus.Blogs.BlogsMenu;
}
@section scripts {
<abp-script-bundle>
<abp-script src="/Pages/CmsKit/Blogs/index.js" />
<abp-script src="/Pages/CmsKit/Blogs/createModal.js" />
<abp-script src="/Pages/CmsKit/Blogs/updateModal.js" />
<abp-script type="typeof(SlugifyScriptContributor)"/>
</abp-script-bundle>
}
@section content_toolbar {
@await Component.InvokeAsync(typeof(AbpPageToolbarViewComponent), new { pageName = typeof(IndexModel).FullName })
}
<div id="CmsKitBlogsWrapper">
<abp-card>
<abp-card-body>
<abp-table striped-rows="true" id="BlogsTable" class="nowrap"></abp-table>
</abp-card-body>
</abp-card>
</div>

7
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/Index.cshtml.cs

@ -0,0 +1,7 @@
namespace Volo.CmsKit.Admin.Web.Pages.CmsKit.Blogs
{
public class IndexModel : CmsKitAdminPageModel
{
}
}

23
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/UpdateModal.cshtml

@ -0,0 +1,23 @@
@page
@using Volo.CmsKit.Admin.Web.Pages
@using Volo.CmsKit.Admin.Web.Pages.CmsKit.Blogs
@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal
@inherits CmsKitAdminPageBase
@model UpdateModalModel
@{
Layout = null;
}
<abp-dynamic-form abp-model="ViewModel" asp-page="/CmsKit/Blogs/UpdateModal">
<abp-modal>
<abp-modal-header title="@L["Update"].Value"></abp-modal-header>
<abp-modal-body>
<abp-input asp-for="Id" />
<abp-form-content />
</abp-modal-body>
<abp-modal-footer buttons="@(AbpModalButtons.Cancel|AbpModalButtons.Save)"></abp-modal-footer>
</abp-modal>
</abp-dynamic-form>

60
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/UpdateModal.cshtml.cs

@ -0,0 +1,60 @@
using AutoMapper;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Validation;
using Volo.CmsKit.Admin.Blogs;
using Volo.CmsKit.Blogs;
namespace Volo.CmsKit.Admin.Web.Pages.CmsKit.Blogs
{
public class UpdateModalModel : CmsKitAdminPageModel
{
protected IBlogAdminAppService BlogAdminAppService { get; }
[HiddenInput]
[BindProperty(SupportsGet = true)]
public Guid Id { get; set; }
[BindProperty]
public UpdateBlogViewModel ViewModel { get; set; }
public UpdateModalModel(IBlogAdminAppService blogAdminAppService)
{
BlogAdminAppService = blogAdminAppService;
}
public async Task OnGetAsync()
{
var blog = await BlogAdminAppService.GetAsync(Id);
ViewModel = ObjectMapper.Map<BlogDto, UpdateBlogViewModel>(blog);
}
public async Task<IActionResult> OnPostAsync()
{
var dto = ObjectMapper.Map<UpdateBlogViewModel, UpdateBlogDto>(ViewModel);
await BlogAdminAppService.UpdateAsync(Id, dto);
return NoContent();
}
[AutoMap(typeof(BlogDto), ReverseMap = true)]
public class UpdateBlogViewModel
{
[Required]
[DynamicMaxLength(typeof(BlogConsts), nameof(BlogConsts.MaxNameLength))]
public string Name { get; set; }
[DynamicMaxLength(typeof(BlogConsts), nameof(BlogConsts.MaxSlugLength))]
[Required]
public string Slug { get; set; }
}
}
}

47
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/createModal.js

@ -0,0 +1,47 @@
var abp = abp || {};
$(function () {
abp.modals.createBlog = function () {
var initModal = function (publicApi, args) {
var $name = $('#ViewModel_Name');
var $slug = $('#ViewModel_Slug');
var urlEdited = false;
$name.on('change paste keyup', function () {
reflectUrlChanges();
});
$slug.on('change', function () {
reflectUrlChanges();
});
function reflectUrlChanges() {
var title = $name.val();
if (urlEdited) {
title = $slug.val();
}
var slugified = slugify(title, {
lower: true
});
if (slugified != $slug.val()) {
reflectedChange = true;
$slug.val(slugified);
reflectedChange = false;
}
}
$slug.change(function () {
urlEdited = true;
});
}
return {
initModal: initModal
};
};
});

85
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/index.js

@ -0,0 +1,85 @@

$(function () {
var l = abp.localization.getResource("CmsKit");
var createModal = new abp.ModalManager({ viewUrl: abp.appPath + "CmsKit/Blogs/CreateModal", modalClass: 'createBlog' });
var updateModal = new abp.ModalManager({ viewUrl: abp.appPath + "CmsKit/Blogs/UpdateModal", modalClass: 'updateBlog' });
var featuresModal = new abp.ModalManager(abp.appPath + "CmsKit/Blogs/FeaturesModal");
var blogsService = volo.cmsKit.admin.blogs.blogAdmin;
var dataTable = $("#BlogsTable").DataTable(abp.libs.datatables.normalizeConfiguration({
processing: true,
serverSide: true,
paging: true,
searching: false,
autoWidth: false,
scrollCollapse: true,
scrollX: true,
ordering: true,
order: [[1, "desc"]],
ajax: abp.libs.datatables.createAjax(blogsService.getList),
columnDefs: [
{
title: l("Details"),
targets: 0,
rowAction: {
items: [
{
text: l('Features'),
visible: abp.auth.isGranted('CmsKit.Blogs.Features'),
action: function (data) {
featuresModal.open({ blogId: data.record.id });
}
},
{
text: l('Edit'),
visible: abp.auth.isGranted('CmsKit.Blogs.Update'),
action: function (data) {
updateModal.open({ id: data.record.id });
}
},
{
text: l('Delete'),
visible: abp.auth.isGranted('CmsKit.Blogs.Delete'),
confirmMessage: function (data) {
return l("BlogDeletionConfirmationMessage", data.record.name)
},
action: function (data) {
blogsService
.delete(data.record.id)
.then(function () {
abp.notify.info(l("SuccessfullyDeleted"));
dataTable.ajax.reload();
});
}
}
]
}
},
{
title: l("Name"),
orderable: true,
data: "name"
},
{
title: l("Slug"),
orderable: true,
data: "slug"
}
]
}));
$('#AbpContentToolbar button[name=CreateBlog]').on('click', function (e) {
e.preventDefault();
createModal.open();
});
createModal.onResult(function () {
dataTable.ajax.reload();
});
updateModal.onResult(function () {
dataTable.ajax.reload();
});
});

30
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/updateModal.js

@ -0,0 +1,30 @@
var abp = abp || {};
$(function () {
abp.modals.updateBlog = function () {
var initModal = function (publicApi, args) {
debugger;
var $slug = $('#ViewModel_Slug');
$slug.on('change', function () {
reflectUrlChanges();
});
function reflectUrlChanges() {
var title = $slug.val();
var slugified = slugify(title);
if (slugified != title) {
$slug.val(slugified, {
lower: true
});
}
}
}
return {
initModal: initModal
};
};
});

108
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Comments/Details.cshtml

@ -0,0 +1,108 @@
@page "{id}"
@using System.Globalization
@using Microsoft.AspNetCore.Mvc.Localization
@using Volo.Abp.AspNetCore.Mvc.UI.Layout
@using Volo.CmsKit.Admin.Web.Pages.CmsKit.Comments
@using Volo.CmsKit.Admin.Web.Menus
@using Volo.CmsKit.Localization
@inject IPageLayout PageLayout
@inject IHtmlLocalizer<CmsKitResource> L
@model DetailsModel
@{
PageLayout.Content.Title = L["Details"].Value;
PageLayout.Content.BreadCrumb.Add(L["Menu:CMS"].Value);
PageLayout.Content.BreadCrumb.Add(L["Comments"].Value);
PageLayout.Content.MenuItemName = CmsKitAdminMenus.Comments.CommentsMenu;
}
@section styles{
<abp-style-bundle>
<abp-style src="/Pages/CmsKit/Comments/details.css" />
</abp-style-bundle>
}
@section scripts {
<abp-script-bundle>
<abp-script src="/Pages/CmsKit/Comments/details.js" />
</abp-script-bundle>
}
<div id="CmsKitCommentsWrapper">
<abp-card>
<abp-card-body>
<abp-row>
<abp-column>
<abp-table>
<tr>
<td width="10%"><b>@L["EntityType"]</b>:</td>
<td>@Model.CommentWithAuthorDto.EntityType</td>
</tr>
<tr>
<td><b>@L["EntityId"]</b>:</td>
<td>@Model.CommentWithAuthorDto.EntityId</td>
</tr>
<tr>
<td><b>@L["CreationTime"]</b>:</td>
<td>@Model.CommentWithAuthorDto.CreationTime.ToString(CultureInfo.CurrentUICulture)</td>
</tr>
<tr>
<td><b>@L["Username"]</b>:</td>
<td>@Model.CommentWithAuthorDto.Author.Name</td>
</tr>
@if (Model.CommentWithAuthorDto.RepliedCommentId.HasValue)
{
<tr>
<td><b>@L["ReplyTo"]</b>:</td>
<td><a href="/CmsKit/Comments/Details/@Model.CommentWithAuthorDto.RepliedCommentId">@Model.CommentWithAuthorDto.RepliedCommentId</a></td>
</tr>
}
<tr>
<td class="align-text-top"><b>@L["Text"]</b>:</td>
<td>@Model.CommentWithAuthorDto.Text</td>
</tr>
</abp-table>
</abp-column>
</abp-row>
</abp-card-body>
</abp-card>
<abp-card>
<abp-card-body>
<abp-row>
<abp-column>
<form id="CmsKitCommentsFilterForm" method="post">
<abp-row>
<input type="hidden" name="@nameof(Model.CommentWithAuthorDto.RepliedCommentId)" value="@Model.CommentWithAuthorDto.Id"/>
<abp-column size-lg="_6" size-md="_12" class="input-group input-daterange">
<abp-column size="_6" style="padding-left: 0">
<abp-input asp-for="@Model.CreationStartDate" label="@L["StartDate"].Value" type="text"/>
</abp-column>
<abp-column size="_6" style="padding-right: 0">
<abp-input asp-for="@Model.CreationEndDate" label="@L["EndDate"].Value" type="text"/>
</abp-column>
</abp-column>
<abp-column size-lg="_4" size-md="_12">
<abp-input asp-for="@Model.Author" label="@L["Username"].Value" type="text"/>
</abp-column>
<abp-column size-lg="_2" size-md="_12">
<abp-button class="mt-md-4" size="Block" button-type="Primary" type="submit">
<i class="fa fa-search" aria-hidden="true"></i>
</abp-button>
</abp-column>
</abp-row>
</form>
</abp-column>
</abp-row>
</abp-card-body>
</abp-card>
<h3>@L["RepliesToThisComment"]</h3>
<abp-table striped-rows="true" id="CommentsTable" class="nowrap"></abp-table>
</div>

33
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Comments/Details.cshtml.cs

@ -0,0 +1,33 @@
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Volo.CmsKit.Admin.Comments;
namespace Volo.CmsKit.Admin.Web.Pages.CmsKit.Comments
{
public class DetailsModel : CmsKitAdminPageModel
{
[BindProperty(SupportsGet = true)]
public Guid Id { get; set; }
public string Author { get; set; }
public DateTime? CreationStartDate { get; set; }
public DateTime? CreationEndDate { get; set; }
public CommentWithAuthorDto CommentWithAuthorDto { get; protected set; }
protected readonly ICommentAdminAppService CommentAdminAppService;
public DetailsModel(ICommentAdminAppService commentAdminAppService)
{
CommentAdminAppService = commentAdminAppService;
}
public async Task OnGetAsync()
{
CommentWithAuthorDto = await CommentAdminAppService.GetAsync(Id);
}
}
}

71
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Comments/Index.cshtml

@ -0,0 +1,71 @@
@page
@using Microsoft.AspNetCore.Mvc.Localization
@using Volo.Abp.AspNetCore.Mvc.UI.Layout
@using Volo.CmsKit.Admin.Web.Pages.CmsKit.Comments
@using Volo.CmsKit.Admin.Web.Menus
@using Volo.CmsKit.Localization
@inject IPageLayout PageLayout
@inject IHtmlLocalizer<CmsKitResource> L
@model IndexModel
@{
PageLayout.Content.Title = L["Comments"].Value;
PageLayout.Content.BreadCrumb.Add(L["Menu:CMS"].Value);
PageLayout.Content.MenuItemName = CmsKitAdminMenus.Comments.CommentsMenu;
var defaultStartDate = DateTime.Now.AddDays(-7).Date.ToShortDateString();
}
@section styles{
<abp-style-bundle>
<abp-style src="/Pages/CmsKit/Comments/index.css" />
</abp-style-bundle>
}
@section scripts {
<abp-script-bundle>
<abp-script src="/Pages/CmsKit/Comments/index.js" />
</abp-script-bundle>
}
<div id="CmsKitCommentsWrapper">
<abp-card>
<abp-card-body>
<abp-row>
<abp-column>
<form id="CmsKitCommentsFilterForm" method="post">
<abp-row>
<abp-column size-lg="_4" size-md="_12" class="input-group input-daterange">
<abp-column size="_6" style="padding-left: 0">
<abp-input asp-for="@Model.CreationStartDate" label="@L["StartDate"].Value" value="@defaultStartDate" type="text" />
</abp-column>
<abp-column size="_6" style="padding-right: 0">
<abp-input asp-for="@Model.CreationEndDate" label="@L["EndDate"].Value" type="text" />
</abp-column>
</abp-column>
<abp-column size-lg="_2" size-md="_6">
<abp-input asp-for="@Model.EntityType" label="@L["EntityType"].Value" type="text"/>
</abp-column>
<abp-column size-lg="_2" size-md="_6">
<abp-input asp-for="@Model.EntityId" label="@L["EntityId"].Value" type="text"/>
</abp-column>
<abp-column size-lg="_2" size-md="_12">
<abp-input asp-for="@Model.Author" label="@L["Username"].Value" type="text"/>
</abp-column>
<abp-column size-lg="_2" size-md="_12">
<abp-button class="mt-md-4" size="Block" button-type="Primary" type="submit">
<i class="fa fa-search" aria-hidden="true"></i>
</abp-button>
</abp-column>
</abp-row>
</form>
</abp-column>
</abp-row>
</abp-card-body>
</abp-card>
<abp-table striped-rows="true" id="CommentsTable" class="nowrap"></abp-table>
</div>

17
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Comments/Index.cshtml.cs

@ -0,0 +1,17 @@
using System;
namespace Volo.CmsKit.Admin.Web.Pages.CmsKit.Comments
{
public class IndexModel : CmsKitAdminPageModel
{
public string EntityType { get; set; }
public string EntityId { get; set; }
public string Author { get; set; }
public DateTime? CreationStartDate { get; set; }
public DateTime? CreationEndDate { get; set; }
}
}

3
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Comments/details.css

@ -0,0 +1,3 @@
.datatableCell{
cursor: pointer;
}

146
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Comments/details.js

@ -0,0 +1,146 @@
$(function (){
var l = abp.localization.getResource("CmsKit");
var commentsService = volo.cmsKit.admin.comments.commentAdmin;
var detailsModal = new abp.ModalManager(abp.appPath + "CmsKit/Comments/DetailsModal");
$(".input-daterange")
.datepicker({
todayBtn: "linked",
autoclose: true,
language: abp.localization.currentCulture.cultureName,
})
.on("hide", function (e) {
e.stopPropagation();
});
var filterForm = $('#CmsKitCommentsFilterForm');
var getFilter = function () {
var filterObj = filterForm.serializeFormToObject();
var startDate = luxon.DateTime.fromFormat(
filterObj.creationStartDate,
abp.localization.currentCulture.dateTimeFormat.shortDatePattern,
{ locale: abp.localization.currentCulture.cultureName }
);
if (!startDate.invalid) {
filterObj.creationStartDate = startDate.toFormat("yyyy-MM-dd");
}
var endDate = luxon.DateTime.fromFormat(
filterObj.creationEndDate,
abp.localization.currentCulture.dateTimeFormat.shortDatePattern,
{ locale: abp.localization.currentCulture.cultureName }
);
if (!endDate.invalid) {
filterObj.creationEndDate = endDate.toFormat("yyyy-MM-dd");
}
return filterObj;
};
var _dataTable = $('#CommentsTable').DataTable(abp.libs.datatables.normalizeConfiguration({
processing: true,
serverSide: true,
paging: true,
scrollX: true,
searching: false,
scrollCollapse: true,
ajax: abp.libs.datatables.createAjax(commentsService.getList, getFilter),
columnDefs: [
{
width: "10%",
title: l("Actions"),
targets: 0,
orderable: false,
rowAction: {
items: [
{
text: l('Details'),
action: function (data) {
window.location = abp.appPath + 'CmsKit/Comments/Details/' + data.record.id;
}
},
{
text: l('Delete'),
visible: abp.auth.isGranted('CmsKit.Comments.Delete'),
confirmMessage: function (data) {
return l("CommentDeletionConfirmationMessage")
},
action: function (data) {
commentsService
.delete(data.record.id)
.then(function () {
abp.notify.info(l("SuccessfullyDeleted"));
_dataTable.ajax.reload();
});
}
}
]
}
},
{
width: "10%",
title: l("Username"),
orderable: false,
data: "author.userName",
render: function (data) {
if (data !== null) {
return GetFilterableDatatableContent('#Author', data);
}
return "";
}
},
{
title: l("Text"),
data: "text",
orderable: false,
render: function (data) {
data = data || "";
var maxChars = 64;
if (data.length > maxChars) {
return (
'<span data-toggle="tooltip" title="' +
data +
'">' +
data.substring(0, maxChars) +
"..." +
"</span>"
);
} else {
return data;
}
}
},
{
width: "15%",
title: l("CreationTime"),
data: "creationTime",
orderable: true,
dataFormat: "datetime"
}
]
}));
function GetFilterableDatatableContent(filterSelector, data){
return '<span class="datatableCell" data-field="'+ filterSelector +'" data-val="'+ data +'">' + data + '</span>';
}
$(document).on('click', '.datatableCell', function () {
var inputSelector = $(this).attr('data-field');
var value = $(this).attr('data-val');
$(inputSelector).val(value);
_dataTable.ajax.reload();
});
filterForm.submit(function (e){
e.preventDefault();
_dataTable.ajax.reload();
});
});

3
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Comments/index.css

@ -0,0 +1,3 @@
.datatableCell{
cursor: pointer;
}

158
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Comments/index.js

@ -0,0 +1,158 @@
$(function (){
var l = abp.localization.getResource("CmsKit");
var commentsService = volo.cmsKit.admin.comments.commentAdmin;
var detailsModal = new abp.ModalManager(abp.appPath + "CmsKit/Comments/DetailsModal");
$(".input-daterange")
.datepicker({
todayBtn: "linked",
autoclose: true,
language: abp.localization.currentCulture.cultureName,
})
.on("hide", function (e) {
e.stopPropagation();
});
var filterForm = $('#CmsKitCommentsFilterForm');
var getFilter = function () {
var filterObj = filterForm.serializeFormToObject();
var startDate = luxon.DateTime.fromFormat(
filterObj.creationStartDate,
abp.localization.currentCulture.dateTimeFormat.shortDatePattern,
{ locale: abp.localization.currentCulture.cultureName }
);
if (!startDate.invalid) {
filterObj.creationStartDate = startDate.toFormat("yyyy-MM-dd");
}
var endDate = luxon.DateTime.fromFormat(
filterObj.creationEndDate,
abp.localization.currentCulture.dateTimeFormat.shortDatePattern,
{ locale: abp.localization.currentCulture.cultureName }
);
if (!endDate.invalid) {
filterObj.creationEndDate = endDate.toFormat("yyyy-MM-dd");
}
return filterObj;
};
var _dataTable = $('#CommentsTable').DataTable(abp.libs.datatables.normalizeConfiguration({
processing: true,
serverSide: true,
paging: true,
scrollX: true,
searching: false,
scrollCollapse: true,
ajax: abp.libs.datatables.createAjax(commentsService.getList, getFilter),
columnDefs: [
{
width: "10%",
title: l("Actions"),
targets: 0,
orderable: false,
rowAction: {
items: [
{
text: l('Details'),
action: function (data) {
window.location = abp.appPath + 'CmsKit/Comments/Details/' + data.record.id;
}
},
{
text: l('Delete'),
visible: abp.auth.isGranted('CmsKit.Comments.Delete'),
confirmMessage: function (data) {
return l("CommentDeletionConfirmationMessage")
},
action: function (data) {
commentsService
.delete(data.record.id)
.then(function () {
abp.notify.info(l("SuccessfullyDeleted"));
_dataTable.ajax.reload();
});
}
}
]
}
},
{
width: "10%",
title: l("Username"),
orderable: false,
data: "author.userName",
render: function (data) {
if (data !== null) {
return GetFilterableDatatableContent('#Author', data);
}
return "";
}
},
{
width: "15%",
title: l("EntityType"),
orderable: false,
data: "entityType",
render: function (data) {
if (data !== null) {
return GetFilterableDatatableContent('#EntityType', data);
}
return "";
}
},
{
title: l("Text"),
data: "text",
orderable: false,
render: function (data) {
data = data || "";
var maxChars = 64;
if (data.length > maxChars) {
return (
'<span data-toggle="tooltip" title="' +
data +
'">' +
data.substring(0, maxChars) +
"..." +
"</span>"
);
} else {
return data;
}
}
},
{
width: "15%",
title: l("CreationTime"),
data: "creationTime",
orderable: true,
dataFormat: "datetime"
}
]
}));
function GetFilterableDatatableContent(filterSelector, data){
return '<span class="datatableCell" data-field="'+ filterSelector +'" data-val="'+ data +'">' + data + '</span>';
}
$(document).on('click', '.datatableCell', function () {
var inputSelector = $(this).attr('data-field');
var value = $(this).attr('data-val');
$(inputSelector).val(value);
_dataTable.ajax.reload();
});
filterForm.submit(function (e){
e.preventDefault();
_dataTable.ajax.reload();
});
});

44
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Contents/Components/ContentEditor/ContentEditorViewComponent.cs

@ -0,0 +1,44 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using System.Threading.Tasks;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.Packages.TuiEditor;
using Volo.Abp.AspNetCore.Mvc.UI.Packages.Uppy;
using Volo.Abp.AspNetCore.Mvc.UI.Widgets;
namespace Volo.CmsKit.Admin.Web.Pages.CmsKit.Contents.Components.ContentEditor
{
[Widget(
StyleTypes = new[]
{
typeof(TuiEditorStyleContributor)
},
ScriptTypes = new[]
{
typeof(TuiEditorScriptContributor),
typeof(UppyScriptContributor)
},
ScriptFiles = new[]
{
"/Pages/CmsKit/Contents/Components/ContentEditor/default.js"
})]
public class ContentEditorViewComponent : AbpViewComponent
{
public async Task<IViewComponentResult> InvokeAsync(string inputId)
{
return View(
"~/Pages/CmsKit/Contents/Components/ContentEditor/Default.cshtml",
new ContentEditorViewModel(inputId));
}
public class ContentEditorViewModel
{
public ContentEditorViewModel(string inputId)
{
InputId = inputId;
}
public string InputId { get; set; }
}
}
}

7
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Contents/Components/ContentEditor/Default.cshtml

@ -0,0 +1,7 @@
@using System.Globalization
@using Volo.CmsKit.Admin.Web.Pages.CmsKit.Contents.Components.ContentEditor
@model ContentEditorViewComponent.ContentEditorViewModel
<div class="content-editor" id="@Model.InputId-container" data-input-id="@Model.InputId" data-language="@(CultureInfo.CurrentUICulture.TwoLetterISOLanguageName)">
</div>

80
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Contents/Components/ContentEditor/default.js

@ -0,0 +1,80 @@
$(function () {
var fileUploadUri = "/api/cms-kit-admin/media";
var fileUriPrefix = "/api/cms-kit/media/";
var editorDataKey = "tuiEditor";
initAllEditors();
function initAllEditors() {
$('.content-editor').each(function (i, item) {
initEditor(item);
});
}
function initEditor(element) {
var $editorContainer = $(element);
var inputName = $editorContainer.data('input-id');
var $editorInput = $('#' + inputName);
var initialValue = $editorInput.val();
var editor = $editorContainer.tuiEditor({
usageStatistics: false,
useCommandShortcut: true,
initialValue: initialValue,
previewStyle: 'tab',
height: "25em",
minHeight: "25em",
initialEditType: initialValue ? 'wysiwyg' : 'markdown',
language: $editorContainer.data("language"),
hooks: {
addImageBlobHook: uploadFile,
},
events: {
change: function (_val) {
$editorInput.val(editor.getHtml());
$editorInput.trigger("change");
}
}
}).data(editorDataKey);
}
function getUppyHeaders() {
var headers = {};
headers[abp.security.antiForgery.tokenHeaderName] = abp.security.antiForgery.getToken();
return headers;
}
function uploadFile(blob, callback, source) {
var UPPY_OPTIONS = {
endpoint: fileUploadUri,
formData: true,
fieldName: "file",
method: "post",
headers: getUppyHeaders()
};
var UPPY = Uppy.Core().use(Uppy.XHRUpload, UPPY_OPTIONS);
UPPY.reset();
UPPY.addFile({
id: "content-file",
name: blob.name,
type: blob.type,
data: blob,
});
UPPY.upload().then((result) => {
if (result.failed.length > 0) {
abp.message.error("File upload failed");
} else {
var mediaDto = result.successful[0].response.body;
var fileUrl = (fileUriPrefix + mediaDto.id);
callback(fileUrl, mediaDto.name);
}
});
}
});

28
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Contents/Components/EntityContentEditor/ContentViewModel.cs

@ -0,0 +1,28 @@
using Microsoft.AspNetCore.Mvc;
using System;
namespace Volo.CmsKit.Admin.Web.Pages.CmsKit.Contents.Components.EntityContentEditor
{
public class ContentViewModel
{
public ContentViewModel(string entityType, string entityId, string value = null, Guid? id = null)
{
EntityType = entityType;
EntityId = entityId;
Value = value;
Id = id;
}
[HiddenInput]
public string EntityType { get; set; }
[HiddenInput]
public string EntityId { get; set; }
[HiddenInput]
public string Value { get; set; }
[HiddenInput]
public Guid? Id { get; set; }
}
}

27
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Contents/Components/EntityContentEditor/Default.cshtml

@ -0,0 +1,27 @@
@using Volo.CmsKit.Admin.Web.Pages.CmsKit.Contents.Components.EntityContentEditor
@using Volo.CmsKit.Admin.Web.Pages.CmsKit.Contents.Components.ContentEditor
@using Volo.CmsKit.Localization
@using Microsoft.Extensions.Localization
@model EntityContentEditorViewComponent.EntityContentEditorViewModel
@inject IStringLocalizer<CmsKitResource> L
@if (Model.DisplaySubmitButton)
{
<abp-dynamic-form abp-model="ViewModel" class="form-entity-content-editor">
<abp-form-content />
<abp-button button-type="Primary" type="submit" text="@L["Submit"]" />
</abp-dynamic-form>
}
else
{
<abp-input asp-for="ViewModel.Id" />
<abp-input asp-for="ViewModel.EntityId" />
<abp-input asp-for="ViewModel.EntityType" />
<abp-input asp-for="ViewModel.Value" />
}
@await Component.InvokeAsync(typeof(ContentEditorViewComponent), new { inputId = Html.IdFor(m => m.ViewModel.Value) })

65
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Contents/Components/EntityContentEditor/EntityContentEditorViewComponent.cs

@ -0,0 +1,65 @@
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form;
using Volo.Abp.AspNetCore.Mvc.UI.Widgets;
using Volo.Abp.Domain.Entities;
using Volo.CmsKit.Admin.Contents;
namespace Volo.CmsKit.Admin.Web.Pages.CmsKit.Contents.Components.EntityContentEditor
{
[Widget(
ScriptFiles = new[]
{
"/Pages/CmsKit/Contents/Components/EntityContentEditor/default.js"
})]
public class EntityContentEditorViewComponent : AbpViewComponent
{
private readonly IContentAdminAppService contentAdminAppService;
public EntityContentEditorViewComponent(IContentAdminAppService contentAdminAppService)
{
this.contentAdminAppService = contentAdminAppService;
}
public async Task<IViewComponentResult> InvokeAsync(string entityType, string entityId, bool displaySubmitButton = true)
{
var viewModel = new ContentViewModel(entityType, entityId);
try
{
if (entityId != null)
{
var content = await contentAdminAppService.GetAsync(entityType, entityId);
viewModel.Value = content.Value;
viewModel.Id = content.Id;
}
}
catch (EntityNotFoundException)
{
// Initialize editor even content doesn't exist.
}
return View(
"~/Pages/CmsKit/Contents/Components/EntityContentEditor/Default.cshtml",
new EntityContentEditorViewModel(viewModel, displaySubmitButton));
}
public class EntityContentEditorViewModel
{
public ContentViewModel ViewModel { get; set; }
public bool DisplaySubmitButton { get; set; }
public EntityContentEditorViewModel(ContentViewModel viewModel, bool displaySubmitButton)
{
ViewModel = viewModel;
DisplaySubmitButton = displaySubmitButton;
}
}
}
}

34
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Contents/Components/EntityContentEditor/default.js

@ -0,0 +1,34 @@
$(function () {
$entityContentEditors = $('.form-entity-content-editor');
var contentAdminService = volo.cmsKit.admin.contents.contentAdmin;
$entityContentEditors.on('submit', function (e, obj) {
e.preventDefault();
var $form = $(e.currentTarget);
if ($form.valid()) {
var data = form.serializeFormToObject().viewModel;
abp.ui.setBusy(e);
if (data.id) {
contentAdminService
.update(data.id, data)
.then(function (result) {
abp.ui.clearBusy();
});
}
else {
contentAdminService
.create(data)
.then(function (result) {
abp.ui.clearBusy();
});
}
}
})
})

44
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Create.cshtml

@ -0,0 +1,44 @@
@page
@using Volo.CmsKit.Admin.Web.Pages.CmsKit.Contents.Components.EntityContentEditor
@using Volo.CmsKit.Admin.Web.Pages
@using Volo.CmsKit.Admin.Web.Menus
@using Volo.CmsKit.Admin.Web.Pages.CmsKit.Pages
@inherits CmsKitAdminPageBase
@model CreateModel
@{
PageLayout.Content.Title = L["Pages"].Value;
PageLayout.Content.BreadCrumb.Add(L["Menu:CMS"].Value);
PageLayout.Content.MenuItemName = CmsKitAdminMenus.Pages.PagesMenu;
}
@section scripts {
<abp-script-bundle>
<abp-script src="/Pages/CmsKit/Pages/create.js" />
<abp-script type="typeof(SlugifyScriptContributor)" />
</abp-script-bundle>
}
<abp-card>
<abp-card-header title="@L["New"].Value"></abp-card-header>
<abp-card-body>
<abp-dynamic-form abp-model="ViewModel" asp-page="/CmsKit/Pages/Create" id="form-page-create">
<abp-form-content />
<abp-input asp-for="ViewModel.Slug" title="@L["PageSlugInformation"]" data-toggle="tooltip"/>
</abp-dynamic-form>
@await Component.InvokeAsync(typeof(EntityContentEditorViewComponent), new
{
entityType = "Page",
displaySubmitButton = false
})
</abp-card-body>
<abp-card-footer>
<abp-button button-type="Primary" type="submit" text="@L["Submit"].Value" id="button-page-create" />
</abp-card-footer>
</abp-card>

47
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Create.cshtml.cs

@ -0,0 +1,47 @@
using AutoMapper;
using Microsoft.AspNetCore.Mvc;
using System.ComponentModel.DataAnnotations;
using System.Threading.Tasks;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form;
using Volo.Abp.Validation;
using Volo.CmsKit.Admin.Pages;
using Volo.CmsKit.Admin.Web.Pages;
using Volo.CmsKit.Pages;
namespace Volo.CmsKit.Admin.Web.Pages.CmsKit.Pages
{
public class CreateModel : CmsKitAdminPageModel
{
protected readonly IPageAdminAppService pageAdminAppService;
[BindProperty]
public CreatePageViewModel ViewModel { get; set; }
public CreateModel(IPageAdminAppService pageAdminAppService)
{
this.pageAdminAppService = pageAdminAppService;
}
public async Task<IActionResult> OnPostAsync()
{
var createInput = ObjectMapper.Map<CreatePageViewModel, CreatePageInputDto>(ViewModel);
var created = await pageAdminAppService.CreateAsync(createInput);
return new OkObjectResult(created);
}
[AutoMap(typeof(CreatePageInputDto), ReverseMap = true)]
public class CreatePageViewModel
{
[DynamicMaxLength(typeof(PageConsts), nameof(PageConsts.MaxTitleLength))]
[Required]
public string Title { get; set; }
[DynamicMaxLength(typeof(PageConsts), nameof(PageConsts.MaxSlugLength))]
[Required]
[DynamicFormIgnore]
public string Slug { get; set; }
}
}
}

40
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Index.cshtml

@ -0,0 +1,40 @@
@page
@using Volo.Abp.AspNetCore.Mvc.UI.Layout
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Pages.Shared.Components.AbpPageToolbar
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Pages.Shared.Components.AbpPageSearchBox
@using Volo.CmsKit.Admin.Web.Pages
@using Volo.CmsKit.Admin.Web.Menus
@using Volo.CmsKit.Admin.Web.Pages.CmsKit.Pages
@inherits CmsKitAdminPageBase
@model IndexModel
@{
PageLayout.Content.Title = L["Pages"].Value;
PageLayout.Content.BreadCrumb.Add(L["Menu:CMS"].Value);
PageLayout.Content.MenuItemName = CmsKitAdminMenus.Pages.PagesMenu;
}
@section scripts {
<abp-script src="/Pages/CmsKit/Pages/index.js"/>
}
@section content_toolbar {
@await Component.InvokeAsync(typeof(AbpPageToolbarViewComponent), new {pageName = typeof(IndexModel).FullName})
}
<div id="CmsKitPagesWrapper">
<abp-card>
<abp-card-body>
<abp-row>
<abp-column>
@await Component.InvokeAsync(typeof(AbpPageSearchBoxViewComponent))
</abp-column>
</abp-row>
</abp-card-body>
</abp-card>
<abp-table striped-rows="true" id="PagesTable" class="nowrap"></abp-table>
</div>

11
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Index.cshtml.cs

@ -0,0 +1,11 @@

namespace Volo.CmsKit.Admin.Web.Pages.CmsKit.Pages
{
public class IndexModel : CmsKitAdminPageModel
{
public void OnGet()
{
}
}
}

45
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Update.cshtml

@ -0,0 +1,45 @@
@page "{Id}"
@using Volo.CmsKit.Admin.Web.Pages.CmsKit.Contents.Components.EntityContentEditor
@using Volo.CmsKit.Admin.Web.Menus
@using Volo.CmsKit.Admin.Web.Pages.CmsKit.Pages
@using Volo.CmsKit.Admin.Web.Pages
@inherits CmsKitAdminPageBase
@model UpdateModel
@{
PageLayout.Content.Title = L["Pages"].Value;
PageLayout.Content.BreadCrumb.Add(L["Menu:CMS"].Value);
PageLayout.Content.MenuItemName = CmsKitAdminMenus.Pages.PagesMenu;
}
@section scripts {
<abp-script src="/Pages/CmsKit/Pages/update.js" />
}
<abp-card>
<abp-card-header title="@L["Update"].Value"></abp-card-header>
<abp-card-body>
<abp-dynamic-form abp-model="ViewModel" asp-page="/CmsKit/Pages/Update" id="form-page-update">
<abp-input asp-for="Id" />
<abp-form-content />
<abp-input asp-for="ViewModel.Slug" title="@L["PageSlugInformation"]" data-toggle="tooltip" />
</abp-dynamic-form>
@await Component.InvokeAsync(typeof(EntityContentEditorViewComponent), new
{
entityType = "Page",
entityId = Model.Id.ToString(),
displaySubmitButton = false
})
</abp-card-body>
<abp-card-footer>
<abp-button button-type="Primary" type="submit" text="@L["Submit"].Value" id="button-page-update" />
</abp-card-footer>
</abp-card>

62
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Update.cshtml.cs

@ -0,0 +1,62 @@
using AutoMapper;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form;
using Volo.Abp.Validation;
using Volo.CmsKit.Admin.Pages;
using Volo.CmsKit.Pages;
namespace Volo.CmsKit.Admin.Web.Pages.CmsKit.Pages
{
public class UpdateModel : CmsKitAdminPageModel
{
[BindProperty(SupportsGet = true)]
[HiddenInput]
public Guid Id { get; set; }
[BindProperty]
public UpdatePageViewModel ViewModel { get; set; }
protected readonly IPageAdminAppService pageAdminAppService;
public UpdateModel(IPageAdminAppService pageAdminAppService)
{
this.pageAdminAppService = pageAdminAppService;
}
public async Task OnGetAsync()
{
var dto = await pageAdminAppService.GetAsync(Id);
ViewModel = ObjectMapper.Map<PageDto, UpdatePageViewModel>(dto);
}
public async Task<IActionResult> OnPostAsync()
{
var updateInput = ObjectMapper.Map<UpdatePageViewModel, UpdatePageInputDto>(ViewModel);
await pageAdminAppService.UpdateAsync(Id, updateInput);
return NoContent();
}
[AutoMap(typeof(PageDto))]
[AutoMap(typeof(UpdatePageInputDto), ReverseMap = true)]
public class UpdatePageViewModel
{
[DynamicMaxLength(typeof(PageConsts), nameof(PageConsts.MaxTitleLength))]
[Required]
public string Title { get; set; }
[DynamicMaxLength(typeof(PageConsts), nameof(PageConsts.MaxSlugLength))]
[Required]
[DynamicFormIgnore]
public string Slug { get; set; }
}
}
}

72
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/create.js

@ -0,0 +1,72 @@
$(function () {
var l = abp.localization.getResource("CmsKit");
var $formCreate = $('#form-page-create');
var $title = $('#ViewModel_Title');
var $slug = $('#ViewModel_Slug');
var $buttonSubmit = $('#button-page-create');
var $pageContentInput = $('#ViewModel_Value');
$formCreate.on('submit', function (e) {
e.preventDefault();
if ($formCreate.valid()) {
abp.ui.setBusy();
$formCreate.ajaxSubmit({
success: function (result) {
submitEntityContent(result.id);
}
});
}
});
$buttonSubmit.click(function (e) {
e.preventDefault();
$formCreate.submit();
});
function submitEntityContent(pageId) {
volo.cmsKit.admin.contents.contentAdmin
.create(
{
entityType: 'Page',
entityId: pageId,
value: $pageContentInput.val()
})
.then(function (result) {
finishSaving();
});
}
function finishSaving() {
abp.notify.success(l('SuccessfullySaved'));
abp.ui.clearBusy();
location.href = "/CmsKit/Pages/";
}
var slugEdited = false;
$title.on('change paste keyup', function () {
var title = $title.val();
if (slugEdited) {
title = $slug.val();
}
var slugified = slugify(title, {
lower: true
});
if (slugified != $slug.val()) {
reflectedChange = true;
$slug.val(slugified);
reflectedChange = false;
}
});
$slug.change(function () {
slugEdited = true;
});
});

81
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/index.js

@ -0,0 +1,81 @@
$(function (){
var l = abp.localization.getResource("CmsKit");
var pagesService = volo.cmsKit.admin.pages.pageAdmin;
var getFilter = function () {
return {
filter: $('#CmsKitPagesWrapper input.page-search-filter-text').val()
};
};
var _dataTable = $("#PagesTable").DataTable(abp.libs.datatables.normalizeConfiguration({
processing: true,
serverSide: true,
paging: true,
searching: false,
autoWidth: false,
scrollCollapse: true,
scrollX: true,
ordering: true,
order: [[3, "desc"]],
ajax: abp.libs.datatables.createAjax(pagesService.getList, getFilter),
columnDefs: [
{
title: l("Details"),
targets: 0,
rowAction: {
items: [
{
text: l('Edit'),
visible: abp.auth.isGranted('CmsKit.Pages.Update'),
action: function (data) {
location.href = '/CmsKit/Pages/Update/' + data.record.id;
}
},
{
text: l('Delete'),
visible: abp.auth.isGranted('CmsKit.Pages.Delete'),
confirmMessage: function (data) {
return l("PageDeletionConfirmationMessage")
},
action: function (data) {
pagesService
.delete(data.record.id)
.then(function () {
abp.notify.info(l("SuccessfullyDeleted"));
_dataTable.ajax.reload();
});
}
}
]
}
},
{
title: l("Title"),
orderable: true,
data: "title"
},
{
title: l("Slug"),
orderable: true,
data: "slug"
},
{
title: l("CreationTime"),
orderable: true,
data: 'creationTime'
}
]
}));
$('#CmsKitPagesWrapper form.page-search-form').submit(function (e) {
e.preventDefault();
_dataTable.ajax.reload();
});
$('#AbpContentToolbar button[name=CreatePage]').on('click', function (e) {
e.preventDefault();
window.location.href = "/CmsKit/Pages/Create"
});
});

65
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/update.js

@ -0,0 +1,65 @@
$(function () {
var l = abp.localization.getResource("CmsKit");
var $formUpdate = $('#form-page-update');
var $buttonSubmit = $('#button-page-update');
var $pageContentInput = $('#ViewModel_Value');
var $pageIdInput = $('#Id');
var $contentIdInput = $('#ViewModel_Id');
$formUpdate.on('submit', function (e) {
e.preventDefault();
if ($formUpdate.valid()) {
abp.ui.setBusy();
$formUpdate.ajaxSubmit({
success: function (result) {
submitEntityContent();
}
});
}
});
$buttonSubmit.click(function (e) {
e.preventDefault();
$formUpdate.submit();
});
function submitEntityContent() {
var contentId = $contentIdInput.val();
var pageId = $pageIdInput.val();
var contentValue = $pageContentInput.val();
if (contentId) {
volo.cmsKit.admin.contents.contentAdmin
.update(contentId,
{
value: contentValue
})
.then(function (result) {
finishSaving(result);
});
}
else {
volo.cmsKit.admin.contents.contentAdmin
.create({
entityType: 'Page',
entityId: pageId,
value: contentValue
})
.then(function (result) {
finishSaving(result);
});
}
}
function finishSaving(result) {
abp.notify.success(l('SuccessfullySaved'));
abp.ui.clearBusy();
location.href = "/CmsKit/Pages/";
}
});

22
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Tags/Components/TagEditor/Default.cshtml

@ -0,0 +1,22 @@
@model TagEditorViewComponent.TagEditorViewModel
@using Volo.CmsKit.Admin.Web.Pages.CmsKit.Tags.Components.TagEditor
@using Volo.CmsKit.Localization
@using Microsoft.Extensions.Localization
@inject IStringLocalizer<CmsKitResource> L
<form class="tag-editor-form" data-entity-id="@Model.EntityId" data-entity-type="@Model.EntityType">
<div class="form-group">
<label>@L["Tags"]</label>
<input name="tags" value="@string.Join(',', Model.Tags.Select(s => s.Name))" class="form-control"/>
</div>
@if (Model.DisplaySubmitButton)
{
<abp-form-row>
<abp-button type="submit" text="@L["Submit"]" />
</abp-form-row>
}
</form>

49
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Tags/Components/TagEditor/TagEditorViewComponent.cs

@ -0,0 +1,49 @@
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.Widgets;
using Volo.CmsKit.Tags;
namespace Volo.CmsKit.Admin.Web.Pages.CmsKit.Tags.Components.TagEditor
{
[Widget(
ScriptFiles = new[]
{
"/Pages/CmsKit/Tags/Components/TagEditor/default.js"
})]
public class TagEditorViewComponent : AbpViewComponent
{
protected ITagAppService TagAppService { get; }
public TagEditorViewComponent(ITagAppService tagAppService)
{
TagAppService = tagAppService;
}
public async Task<IViewComponentResult> InvokeAsync(string entityType, string entityId, bool displaySubmitButton = true)
{
var tags =
entityId.IsNullOrWhiteSpace() ?
new List<TagDto>() :
await TagAppService.GetAllRelatedTagsAsync(entityType, entityId);
return View("~/Pages/CmsKit/Tags/Components/TagEditor/Default.cshtml", new TagEditorViewModel
{
EntityId = entityId,
EntityType = entityType,
Tags = tags,
DisplaySubmitButton = displaySubmitButton
});
}
public class TagEditorViewModel
{
public string EntityType { get; set; }
public string EntityId { get; set; }
public List<TagDto> Tags { get; set; }
public bool DisplaySubmitButton { get; set; }
}
}
}

26
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Tags/Components/TagEditor/default.js

@ -0,0 +1,26 @@
$(function () {
var $tagEditorForms = $('.tag-editor-form');
$tagEditorForms.on('submit', function (e) {
e.preventDefault();
var $form = $(e.currentTarget);
if ($form.valid()) {
abp.ui.setBusy();
var entityId = $form.data('entity-id');
var entityType = $form.data('entity-type');
var tags = $form.find('input').val().split(",");
volo.cmsKit.admin.tags.entityTagAdmin
.setEntityTags({
entityId: entityId,
entityType: entityType,
tags: tags
})
}
})
})

23
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Tags/CreateModal.cshtml

@ -0,0 +1,23 @@
@page
@using Microsoft.AspNetCore.Mvc.Localization
@using Volo.CmsKit.Admin.Web.Pages.CmsKit.Tags
@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal
@using Volo.CmsKit.Localization
@inject IHtmlLocalizer<CmsKitResource> L
@model CreateModalModel
@{
Layout = null;
}
<abp-dynamic-form abp-model="ViewModel" asp-page="/CmsKit/Tags/CreateModal">
<abp-modal>
<abp-modal-header title="@L["New"].Value"></abp-modal-header>
<abp-modal-body>
<abp-form-content/>
</abp-modal-body>
<abp-modal-footer buttons="@(AbpModalButtons.Cancel | AbpModalButtons.Save)"></abp-modal-footer>
</abp-modal>
</abp-dynamic-form>

58
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Tags/CreateModal.cshtml.cs

@ -0,0 +1,58 @@
using AutoMapper;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form;
using Volo.Abp.Validation;
using Volo.CmsKit.Admin.Tags;
using Volo.CmsKit.Tags;
namespace Volo.CmsKit.Admin.Web.Pages.CmsKit.Tags
{
public class CreateModalModel : CmsKitAdminPageModel
{
protected ITagAdminAppService TagAdminAppService { get; }
[BindProperty]
public TagCreateViewModel ViewModel { get; set; }
public List<SelectListItem> TagDefinitions { get; set; }
public CreateModalModel(ITagAdminAppService tagAdminAppService)
{
TagAdminAppService = tagAdminAppService;
}
public async Task OnGetAsync()
{
var definitions = await TagAdminAppService.GetTagDefinitionsAsync();
TagDefinitions = definitions.Select(s => new SelectListItem(s.DisplayName, s.EntityType)).ToList();
}
public async Task<IActionResult> OnPostAsync()
{
var tagCreateDto = ObjectMapper.Map<TagCreateViewModel, TagCreateDto>(ViewModel);
await TagAdminAppService.CreateAsync(tagCreateDto);
return NoContent();
}
[AutoMap(typeof(TagCreateDto), ReverseMap = true)]
public class TagCreateViewModel
{
[DynamicMaxLength(typeof(TagConsts), nameof(TagConsts.MaxEntityTypeLength))]
[Required]
[SelectItems(nameof(TagDefinitions))]
public string EntityType { get; set; }
[DynamicMaxLength(typeof(TagConsts), nameof(TagConsts.MaxNameLength))]
[Required]
public string Name { get; set; }
}
}
}

24
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Tags/EditModal.cshtml

@ -0,0 +1,24 @@
@page
@using Microsoft.AspNetCore.Mvc.Localization
@using Volo.CmsKit.Admin.Web.Pages
@using Volo.CmsKit.Admin.Web.Pages.CmsKit.Tags
@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal
@using Volo.CmsKit.Localization
@inject IHtmlLocalizer<CmsKitResource> L
@model EditModalModel
@{
Layout = null;
}
<abp-dynamic-form abp-model="ViewModel" asp-page="/CmsKit/Tags/EditModal">
<abp-modal>
<abp-modal-header title="@L["Update"].Value"></abp-modal-header>
<abp-modal-body>
<abp-input asp-for="Id" />
<abp-form-content />
</abp-modal-body>
<abp-modal-footer buttons="@(AbpModalButtons.Cancel|AbpModalButtons.Save)"></abp-modal-footer>
</abp-modal>
</abp-dynamic-form>

54
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Tags/EditModal.cshtml.cs

@ -0,0 +1,54 @@
using AutoMapper;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Validation;
using Volo.CmsKit.Admin.Tags;
using Volo.CmsKit.Tags;
namespace Volo.CmsKit.Admin.Web.Pages.CmsKit.Tags
{
public class EditModalModel : CmsKitAdminPageModel
{
protected ITagAdminAppService TagAdminAppService { get; }
[HiddenInput]
[BindProperty(SupportsGet = true)]
public Guid Id { get; set; }
[BindProperty]
public TagEditViewModel ViewModel { get; set; }
public EditModalModel(ITagAdminAppService tagAdminAppService)
{
this.TagAdminAppService = tagAdminAppService;
}
public async Task OnGetAsync()
{
var dto = await TagAdminAppService.GetAsync(Id);
ViewModel = ObjectMapper.Map<TagDto, TagEditViewModel>(dto);
}
public async Task<IActionResult> OnPostAsync()
{
var tagDto = ObjectMapper.Map<TagEditViewModel, TagUpdateDto>(ViewModel);
await TagAdminAppService.UpdateAsync(Id, tagDto);
return NoContent();
}
[AutoMap(typeof(TagDto))]
[AutoMap(typeof(TagUpdateDto), ReverseMap = true)]
public class TagEditViewModel
{
[Required]
[DynamicMaxLength(typeof(TagConsts), nameof(TagConsts.MaxNameLength))]
public string Name { get; set; }
}
}
}

38
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Tags/Index.cshtml

@ -0,0 +1,38 @@
@page
@using Volo.CmsKit.Admin.Web.Pages
@using Volo.CmsKit.Admin.Web.Pages.CmsKit.Tags
@using Volo.CmsKit.Admin.Web.Menus
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Pages.Shared.Components.AbpPageToolbar
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Pages.Shared.Components.AbpPageSearchBox
@inherits CmsKitAdminPageBase
@model IndexModel
@{
PageLayout.Content.Title = L["Tags"].Value;
PageLayout.Content.BreadCrumb.Add(L["Menu:CMS"].Value);
PageLayout.Content.MenuItemName = CmsKitAdminMenus.Tags.TagsMenu;
}
@section scripts {
<abp-script src="/Pages/CmsKit/Tags/Index.js" />
}
@section content_toolbar {
@await Component.InvokeAsync(typeof(AbpPageToolbarViewComponent), new { pageName = typeof(IndexModel).FullName })
}
<div id="CmsKitTagsWrapper">
<abp-card>
<abp-card-body>
<abp-row>
<abp-column>
@await Component.InvokeAsync(typeof(AbpPageSearchBoxViewComponent))
</abp-column>
</abp-row>
</abp-card-body>
</abp-card>
<abp-table striped-rows="true" id="TagsTable"></abp-table>
</div>

8
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Tags/Index.cshtml.cs

@ -0,0 +1,8 @@
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages;
namespace Volo.CmsKit.Admin.Web.Pages.CmsKit.Tags
{
public class IndexModel : CmsKitAdminPageModel
{
}
}

83
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Tags/Index.js

@ -0,0 +1,83 @@
$(function () {
var l = abp.localization.getResource("CmsKit");
var createModal = new abp.ModalManager(abp.appPath + "CmsKit/Tags/CreateModal");
var updateModal = new abp.ModalManager(abp.appPath + "CmsKit/Tags/EditModal");
var service = volo.cmsKit.admin.tags.tagAdmin;
var getFilter = function () {
return {
filter: $('#CmsKitTagsWrapper input.page-search-filter-text').val()
};
};
let dataTable = $("#TagsTable").DataTable(abp.libs.datatables.normalizeConfiguration({
processing: true,
serverSide: true,
paging: true,
searching: false,
autoWidth: false,
scrollCollapse: true,
scrollX: true,
ordering: false,
ajax: abp.libs.datatables.createAjax(service.getList, getFilter),
columnDefs: [
{
title: l("Actions"),
rowAction: {
items: [
{
text: l("Edit"),
visible: abp.auth.isGranted('CmsKit.Tags.Update'),
action: function (data) {
updateModal.open({ id: data.record.id });
}
},
{
text: l("Delete"),
visible: abp.auth.isGranted('CmsKit.Tags.Delete'),
confirmMessage: function (data) {
return l("TagDeletionConfirmationMessage", data.record.name)
},
action: function (data) {
service
.delete(data.record.id)
.then(function () {
abp.notify.info(l("SuccessfullyDeleted"));
dataTable.ajax.reload(null, false);
});
}
}
]
}
},
{
title: l("EntityType"),
data: "entityType"
},
{
title: l("Name"),
data: "name"
}
]
}));
$('#CmsKitTagsWrapper form.page-search-form').on('submit', function (e) {
e.preventDefault();
dataTable.ajax.reload();
});
$('#AbpContentToolbar button[name=NewButton]').on('click', function (e) {
e.preventDefault();
createModal.open();
});
createModal.onResult(function () {
dataTable.ajax.reload();
});
updateModal.onResult(function () {
dataTable.ajax.reload();
});
});

20
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKitAdminPageBase.cs

@ -0,0 +1,20 @@
using Microsoft.AspNetCore.Mvc.Razor.Internal;
using Microsoft.Extensions.Localization;
using System.Threading.Tasks;
using Volo.Abp.AspNetCore.Mvc.UI.Layout;
using Volo.CmsKit.Localization;
namespace Volo.CmsKit.Admin.Web.Pages
{
public class CmsKitAdminPageBase : Microsoft.AspNetCore.Mvc.RazorPages.Page
{
[RazorInject] public IStringLocalizer<CmsKitResource> L { get; set; }
[RazorInject] public IPageLayout PageLayout { get; set; }
public override Task ExecuteAsync()
{
return Task.CompletedTask; // Will be overriden by razor pages. (.cshtml)
}
}
}

2
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Volo.CmsKit.Admin.Web.csproj

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk.Web">
<Import Project="..\..\..\..\common.props" />
<Import Project="..\..\..\..\configureawait.props" />

Loading…
Cancel
Save