Browse Source

Merge pull request #7871 from abpframework/cms-kit/admin-pages

Cms Kit - Admin Pages
pull/7895/head
İlkay İlknur 5 years ago
committed by GitHub
parent
commit
554650c907
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  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. 21
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/wwwroot/libs/slugify/LICENSE
  6. 90
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/wwwroot/libs/slugify/README.md
  7. 40
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/wwwroot/libs/slugify/package.json
  8. 23
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/wwwroot/libs/slugify/slugify.d.ts
  9. 66
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/wwwroot/libs/slugify/slugify.js
  10. 5
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/yarn.lock
  11. 17
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Bundles/SlugifyScriptContributor.cs
  12. 87
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/CmsKitAdminWebModule.cs
  13. 95
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Menus/CmsKitAdminMenuContributor.cs
  14. 28
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Menus/CmsKitAdminMenus.cs
  15. 79
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/Create.cshtml
  16. 63
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/Create.cshtml.cs
  17. 33
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/Index.cshtml
  18. 7
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/Index.cshtml.cs
  19. 77
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/Update.cshtml
  20. 77
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/Update.cshtml.cs
  21. 212
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/create.js
  22. 68
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/index.js
  23. 180
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/update.js
  24. 23
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/CreateModal.cshtml
  25. 44
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/CreateModal.cshtml.cs
  26. 44
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/FeaturesModal.cshtml
  27. 77
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/FeaturesModal.cshtml.cs
  28. 38
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/Index.cshtml
  29. 7
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/Index.cshtml.cs
  30. 23
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/UpdateModal.cshtml
  31. 61
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/UpdateModal.cshtml.cs
  32. 47
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/createModal.js
  33. 85
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/index.js
  34. 30
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/updateModal.js
  35. 108
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Comments/Details.cshtml
  36. 33
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Comments/Details.cshtml.cs
  37. 71
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Comments/Index.cshtml
  38. 17
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Comments/Index.cshtml.cs
  39. 3
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Comments/details.css
  40. 146
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Comments/details.js
  41. 3
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Comments/index.css
  42. 158
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Comments/index.js
  43. 44
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Contents/Components/ContentEditor/ContentEditorViewComponent.cs
  44. 7
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Contents/Components/ContentEditor/Default.cshtml
  45. 80
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Contents/Components/ContentEditor/default.js
  46. 28
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Contents/Components/EntityContentEditor/ContentViewModel.cs
  47. 27
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Contents/Components/EntityContentEditor/Default.cshtml
  48. 65
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Contents/Components/EntityContentEditor/EntityContentEditorViewComponent.cs
  49. 34
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Contents/Components/EntityContentEditor/default.js
  50. 45
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Create.cshtml
  51. 47
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Create.cshtml.cs
  52. 40
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Index.cshtml
  53. 11
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Index.cshtml.cs
  54. 45
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Update.cshtml
  55. 62
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Update.cshtml.cs
  56. 72
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/create.js
  57. 81
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/index.js
  58. 65
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/update.js
  59. 22
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Tags/Components/TagEditor/Default.cshtml
  60. 49
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Tags/Components/TagEditor/TagEditorViewComponent.cs
  61. 26
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Tags/Components/TagEditor/default.js
  62. 23
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Tags/CreateModal.cshtml
  63. 58
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Tags/CreateModal.cshtml.cs
  64. 24
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Tags/EditModal.cshtml
  65. 54
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Tags/EditModal.cshtml.cs
  66. 38
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Tags/Index.cshtml
  67. 8
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Tags/Index.cshtml.cs
  68. 83
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Tags/Index.js
  69. 4
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/_ViewImports.cshtml
  70. 20
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKitAdminPageBase.cs
  71. 2
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Volo.CmsKit.Admin.Web.csproj
  72. 69
      modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/en.json
  73. 71
      modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/tr.json
  74. 4
      modules/cms-kit/src/Volo.CmsKit.Public.Web/CmsKitPublicWebModule.cs
  75. 5
      modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/BlogPost.cshtml
  76. 2
      modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/BlogPost.cshtml.cs
  77. 5
      modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/Index.cshtml
  78. 2
      modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/Index.cshtml.cs
  79. 2
      modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Pages/Index.cshtml
  80. 2
      modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Pages/Index.cshtml.cs
  81. 0
      modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/_ViewImports.cshtml

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"
}
}

21
modules/cms-kit/host/Volo.CmsKit.Web.Unified/wwwroot/libs/slugify/LICENSE

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) Simeon Velichkov <simeonvelichkov@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

90
modules/cms-kit/host/Volo.CmsKit.Web.Unified/wwwroot/libs/slugify/README.md

@ -0,0 +1,90 @@
# slugify
[![npm-version]][npm] [![travis-ci]][travis] [![coveralls-status]][coveralls]
```js
var slugify = require('slugify')
slugify('some string') // some-string
// if you prefer something other than '-' as separator
slugify('some string', '_') // some_string
```
- Vanilla ES5 JavaScript
- No dependencies
- Coerces foreign symbols to their English equivalent (check out the [charMap][charmap] for more details)
- Works in the browser (window.slugify) and AMD/CommonJS-flavored module loaders
## Options
```js
slugify('some string', {
replacement: '-', // replace spaces with replacement character, defaults to `-`
remove: undefined, // remove characters that match regex, defaults to `undefined`
lower: false, // convert to lower case, defaults to `false`
strict: false, // strip special characters except replacement, defaults to `false`
locale: 'vi' // language code of the locale to use
})
```
## Remove
For example, to remove `*+~.()'"!:@` from the result slug, you can use `slugify('..', {remove: /[*+~.()'"!:@]/g})`.
## Locales
The main `charmap.json` file contains all known characters and their transliteration. All new characters should be added there first. In case you stumble upon a character already set in `charmap.json`, but not transliterated correctly according to your language, then you have to add those characters in `locales.json` to override the already existing transliteration in `charmap.json`, but for your locale only.
You can get the correct language code of your language from [here](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes).
## Extend
Out of the box `slugify` comes with support for a handful of Unicode symbols. For example the `☢` (radioactive) symbol is not defined in the [`charMap`][charmap] and therefore it will be stripped by default:
```js
slugify('unicode ♥ is ☢') // unicode-love-is
```
However you can extend the supported symbols, or override the existing ones with your own:
```js
slugify.extend({'☢': 'radioactive'})
slugify('unicode ♥ is ☢') // unicode-love-is-radioactive
```
Keep in mind that the `extend` method extends/overrides the default `charMap` for the entire process. In case you need a fresh instance of the slugify's `charMap` object you have to clean up the module cache first:
```js
delete require.cache[require.resolve('slugify')]
var slugify = require('slugify')
```
## Contribute
1. Add chars to `charmap.json`
2. Run tests `npm test`
3. The tests will build the charmap in `index.js` and will sort the `charmap.json`
4. Commit **all** modified files
---
> This module was originally a vanilla javascript port of [node-slug][node-slug].<br>
> Note that the original [slug][slug] module has been ported to vanilla javascript too.<br>
> One major difference between the two modules is that `slugify` does not depend on the external [unicode][unicode] module.
[npm-version]: https://img.shields.io/npm/v/slugify.svg?style=flat-square (NPM Package Version)
[travis-ci]: https://img.shields.io/travis/simov/slugify/master.svg?style=flat-square (Build Status - Travis CI)
[coveralls-status]: https://img.shields.io/coveralls/simov/slugify.svg?style=flat-square (Test Coverage - Coveralls)
[npm]: https://www.npmjs.com/package/slugify
[travis]: https://travis-ci.org/simov/slugify
[coveralls]: https://coveralls.io/r/simov/slugify?branch=master
[node-slug]: https://github.com/dodo/node-slug
[slug]: https://www.npmjs.com/package/slug
[unicode]: https://www.npmjs.com/package/unicode
[index]: https://github.com/simov/slugify/blob/master/index.js
[charmap]: https://github.com/simov/slugify/blob/master/config/charmap.json

40
modules/cms-kit/host/Volo.CmsKit.Web.Unified/wwwroot/libs/slugify/package.json

@ -0,0 +1,40 @@
{
"name": "slugify",
"version": "1.4.6",
"description": "Slugifies a String",
"keywords": [
"slugify",
"slug",
"url",
"urlify"
],
"license": "MIT",
"homepage": "https://github.com/simov/slugify",
"author": "Simeon Velichkov <simeonvelichkov@gmail.com> (https://simov.github.io)",
"repository": {
"type": "git",
"url": "https://github.com/simov/slugify.git"
},
"devDependencies": {
"coveralls": "^3.1.0",
"mocha": "^7.2.0",
"nyc": "^15.1.0"
},
"main": "./slugify.js",
"files": [
"LICENSE",
"README.md",
"slugify.d.ts",
"slugify.js"
],
"types": "slugify.d.ts",
"scripts": {
"build": "node bin/build",
"test:ci": "npx mocha --recursive",
"test:cov": "npx nyc --reporter=lcov --reporter=text-summary mocha -- --recursive",
"test": "npm run build && npm run test:ci"
},
"engines": {
"node": ">=8.0.0"
}
}

23
modules/cms-kit/host/Volo.CmsKit.Web.Unified/wwwroot/libs/slugify/slugify.d.ts

@ -0,0 +1,23 @@
declare module slugify {
type ExtendArgs = {
[key: string]: any;
}
export function extend (args: ExtendArgs): void;
}
declare function slugify(
string: string,
options?:
| {
replacement?: string;
remove?: RegExp;
lower?: boolean;
strict?: boolean;
locale?: string;
}
| string,
): string;
export default slugify;

66
modules/cms-kit/host/Volo.CmsKit.Web.Unified/wwwroot/libs/slugify/slugify.js

File diff suppressed because one or more lines are too long

5
modules/cms-kit/host/Volo.CmsKit.Web.Unified/yarn.lock

@ -3032,6 +3032,11 @@ signal-exit@^3.0.0:
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=
slugify@1.4.6:
version "1.4.6"
resolved "https://registry.yarnpkg.com/slugify/-/slugify-1.4.6.tgz#ef288d920a47fb01c2be56b3487b6722f5e34ace"
integrity sha512-ZdJIgv9gdrYwhXqxsH9pv7nXxjUEyQ6nqhngRxoAAOlmMGA28FDq5O4/5US4G2/Nod7d1ovNcgURQJ7kHq50KQ==
snapdragon-node@^2.0.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b"

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");
}
}
}

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

@ -7,6 +7,10 @@ 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;
using Volo.Abp.AutoMapper;
namespace Volo.CmsKit.Admin.Web
{
@ -46,9 +50,90 @@ namespace Volo.CmsKit.Admin.Web
options.FileSets.AddEmbedded<CmsKitAdminWebModule>("Volo.CmsKit.Admin.Web");
});
context.Services.AddAutoMapperObjectMapper<CmsKitAdminWebModule>();
Configure<AbpAutoMapperOptions>(options => { options.AddMaps<CmsKitAdminWebModule>(validate: true); });
Configure<RazorPagesOptions>(options =>
{
//Configure authorization.
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 =>
{
options.Conventions.AddPageRoute("/CmsKit/Tags/Index", "/Cms/Tags");
options.Conventions.AddPageRoute("/CmsKit/Pages/Index", "/Cms/Pages");
options.Conventions.AddPageRoute("/CmsKit/Pages/Create", "/Cms/Pages/Create");
options.Conventions.AddPageRoute("/CmsKit/Pages/Update", "/Cms/Pages/Update");
options.Conventions.AddPageRoute("/CmsKit/Blogs/Index", "/Cms/Blogs");
options.Conventions.AddPageRoute("/CmsKit/BlogPosts/Index", "/Cms/BlogPosts");
options.Conventions.AddPageRoute("/CmsKit/BlogPosts/Create", "/Cms/BlogPosts/Create");
options.Conventions.AddPageRoute("/CmsKit/BlogPosts/Update", "/Cms/BlogPosts/Update");
options.Conventions.AddPageRoute("/CmsKit/Comments/Index", "/Cms/Comments");
options.Conventions.AddPageRoute("/CmsKit/Comments/Details", "/Cms/Details");
});
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
);
});
});
}
}

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

@ -1,5 +1,11 @@
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Linq;
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 +19,92 @@ 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 cmsMenus = new List<ApplicationMenuItem>();
if (GlobalFeatureManager.Instance.IsEnabled<PagesFeature>())
{
if (await context.IsGrantedAsync(CmsKitAdminPermissions.Pages.Default))
{
cmsMenus.Add(new ApplicationMenuItem(
CmsKitAdminMenus.Pages.PagesMenu,
l["Pages"].Value,
"/Cms/Pages"));
}
}
if (GlobalFeatureManager.Instance.IsEnabled<BlogsFeature>())
{
if (await context.IsGrantedAsync(CmsKitAdminPermissions.Blogs.Default))
{
cmsMenus.Add(new ApplicationMenuItem(
CmsKitAdminMenus.Blogs.BlogsMenu,
l["Blogs"],
"/Cms/Blogs"
));
}
if (await context.IsGrantedAsync(CmsKitAdminPermissions.BlogPosts.Default))
{
cmsMenus.Add(new ApplicationMenuItem(
CmsKitAdminMenus.BlogPosts.BlogPostsMenu,
l["BlogPosts"],
"/Cms/BlogPosts"
));
}
}
if (GlobalFeatureManager.Instance.IsEnabled<TagsFeature>())
{
if (await context.IsGrantedAsync(CmsKitAdminPermissions.Tags.Default))
{
cmsMenus.Add(new ApplicationMenuItem(
CmsKitAdminMenus.Tags.TagsMenu,
l["Tags"].Value,
"/Cms/Tags"));
}
}
if (GlobalFeatureManager.Instance.IsEnabled<CommentsFeature>())
{
if (await context.IsGrantedAsync(CmsKitAdminPermissions.Comments.Default))
{
cmsMenus.Add(new ApplicationMenuItem(
CmsKitAdminMenus.Comments.CommentsMenu,
l["Comments"].Value,
"/Cms/Comments"
)
);
}
}
return Task.CompletedTask;
if (cmsMenus.Any())
{
var cmsMenu = context.Menu.FindMenuItem(CmsKitAdminMenus.GroupName);
if (cmsMenu == null)
{
cmsMenu = new ApplicationMenuItem(
CmsKitAdminMenus.GroupName,
l["Cms"],
icon: "far fa-newspaper");
context.Menu.AddItem(cmsMenu);
}
foreach (var menu in cmsMenus)
{
cmsMenu.AddItem(menu);
}
}
}
}
}

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 = "../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 = "../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(CreateBlogDto), 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>

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

@ -0,0 +1,61 @@
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))]
[AutoMap(typeof(UpdateBlogDto), 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();
});
}
}
})
})

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

@ -0,0 +1,45 @@
@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
@using Volo.CmsKit.Admin.Web.Bundles
@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();
});
});

4
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/_ViewImports.cshtml

@ -0,0 +1,4 @@
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI
@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bootstrap
@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bundling

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" />

69
modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/en.json

@ -1,6 +1,18 @@
{
"culture": "en",
"texts": {
"BlogDeletionConfirmationMessage": "The blog '{0}' will be deleted. Are you sure?",
"BlogFeatureNotAvailable": "This feature is not available now. Enable with 'GlobalFeatureManager' to use it.",
"BlogId": "Blog",
"BlogPostDeletionConfirmationMessage": "The blog post '{0}' will be deleted. Are you sure?",
"BlogPosts": "Blog Posts",
"Blogs": "Blogs",
"ChoosePreference": "Choose Preference...",
"Cms": "Cms",
"CmsKit.Comments": "Comments",
"CmsKit.Ratings": "Ratings",
"CmsKit.Reactions": "Reactions",
"CmsKit.Tags": "Tags",
"CmsKit:0002": "Content already exists!",
"CmsKit:0003": "The entity {0} is not taggable.",
"CmsKit:Blog:0001": "The given slug ({Slug}) already exists!",
@ -9,16 +21,45 @@
"CmsKit:Page:0001": "The given url ({0}) already exists.",
"CmsKit:Tag:0002": "The entity is not taggable!",
"CommentAuthorizationExceptionMessage": "Those comments are not allowed for public display.",
"CommentDeletionConfirmationMessage": "This comment and all replies will be deleted!",
"Comments": "Comments",
"ContentDeletionConfirmationMessage": "Are you sure to delete this content?",
"Contents": "Contents",
"CoverImage": "Cover Image",
"CreateBlogPostPage": "New Blog Post",
"CreationTime": "Creation Time",
"Delete": "Delete",
"Detail": "Detail",
"Details": "Details",
"DoYouPreferAdditionalEmails": "Do you prefer additional emails?",
"Edit": "Edit",
"EndDate": "End Date",
"EntityId": "Entity Id",
"EntityType": "Entity Type",
"ExportCSV": "Export CSV",
"Features": "Features",
"GenericDeletionConfirmationMessage": "Are you sure to delete '{0}'?",
"LastModification": "Last Modification",
"LoginToAddComment": "Login to add comment",
"LoginToRate": "Login to rate",
"LoginToReply": "Login to reply",
"Menu:CMS": "CMS",
"Message": "Message",
"MessageDeletionConfirmationMessage": "This comment will be deleted completely.",
"Name": "Name",
"New": "New",
"OK": "OK",
"PageDeletionConfirmationMessage": "Are you sure to delete this page?",
"PageSlugInformation": "Slug is used on url. Your url will be '/pages/{{slug}}'.",
"Permission:BlogManagement": "Blog Management",
"Permission:BlogManagement.Create": "Create",
"Permission:BlogManagement.Delete": "Delete",
"Permission:BlogManagement.Features": "Features",
"Permission:BlogManagement.Update": "Update",
"Permission:BlogPostManagement": "Blog Post Management",
"Permission:BlogPostManagement.Create": "Create",
"Permission:BlogPostManagement.Delete": "Delete",
"Permission:BlogPostManagement.Update": "Update",
"Permission:CmsKit": "CmsKit",
"Permission:Comments": "Comment Management",
"Permission:Comments.Delete": "Delete",
@ -40,14 +81,42 @@
"PickYourReaction": "Pick your reaction",
"RatingUndoMessage": "Your rating will be undo.",
"Read": "Read",
"RepliesToThisComment": "Replies to this comment",
"Reply": "Reply",
"ReplyTo": "Reply to",
"SamplePageMessage": "A sample page for the Pro module",
"SaveChanges": "Save Changes",
"SelectAll": "Select All",
"Send": "Send",
"SendMessage": "Send Message",
"ShortDescription": "Short description",
"Slug": "Slug",
"Source": "Source",
"SourceUrl": "Source Url",
"Star": "Star",
"StartDate": "Start Date",
"Subject": "Subject",
"SubjectPlaceholder": "Please type a subject",
"Submit": "Submit",
"Subscribe": "Subscribe",
"SuccessfullyDeleted": "Successfully deleted!",
"SuccessfullySaved": "Successfully saved!",
"TagDeletionConfirmationMessage": "Are you sure to delete '{0}' tag?",
"Tags": "Tags",
"Text": "Text",
"ThankYou": "Thank you",
"Title": "Title",
"Undo": "Undo",
"Update": "Update",
"UpdatePreferenceSuccessMessage": "Your preferences have been saved.",
"UpdateYourEmailPreferences": "Update your email preferences",
"UploadFailedMessage": "Upload failed.",
"UserId": "User Id",
"Username": "Username",
"YourComment": "Your comment",
"YourEmailAddress": "Your e-mail address",
"YourFullName": "Your full name",
"YourMessage": "Your Message",
"YourReply": "Your reply"
}
}

71
modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/tr.json

@ -1,22 +1,64 @@
{
"culture": "tr",
"texts": {
"BlogDeletionConfirmationMessage": "'{0}' adlı blog silinecek. Emin misiniz?",
"BlogFeatureNotAvailable": "Bu özellik kullanılabilir değil. 'GlobalFeatureManager' ile aktif ederek kullanabilisiniz.",
"BlogId": "Blog",
"BlogPostDeletionConfirmationMessage": "'{0}' başlıklı blog yazısı silinecek. Emin misiniz?",
"BlogPosts": "Blog Yazıları",
"Blogs": "Bloglar",
"ChoosePreference": "Tercih seçiniz...",
"Cms": "Cms",
"CmsKit.Comments": "Yorumlar",
"CmsKit.Ratings": "Puanlama",
"CmsKit.Reactions": "Tepkiler",
"CmsKit.Tags": "Etiketler",
"CmsKit:0002": "İçerik zaten mevcut!",
"CmsKit:0003": "{0} ögesi etiketlenebilir değil.",
"CmsKit:BlogPost:0001": "Aynı url etiketi zaten mevcut.",
"CmsKit:Page:0001": "Girilen url ({0}) kullanımdadır.",
"CmsKit:Tag:0002": "Bu öge etiketlenebilir değil.",
"CommentAuthorizationExceptionMessage": "Bu yorumları görebilmek için yetki gerekir.",
"CommentDeletionConfirmationMessage": "Bu yorum ve buna yapılan tüm yorumlan silinecektir!",
"Comments": "Yorumlar",
"ContentDeletionConfirmationMessage": "Bu içeriği gerçekten silmek istediğinize emin misiniz?",
"Contents": "İçerikler",
"CoverImage": "Kapak Resmi",
"CreateBlogPostPage": "Yeni Blog Yazısı",
"CreationTime": "Oluşturulma Zamanı",
"Delete": "Sil",
"DeleteSubscriptionSubject": "E-posta adresiniz silinmiştir.",
"Detail": "Detay",
"Details": "Detaylar",
"DoYouPreferAdditionalEmails": "Ek e-postaları tercih ediyor musunuz?",
"Edit": "Düzenle",
"EndDate": "Bitiş Tarihi",
"EntityId": "Entity Id",
"EntityType": "Entity Tür",
"ExportCSV": "CSV olarak dışa aktar",
"Features": "Özellikler",
"GenericDeletionConfirmationMessage": "'{0}' kaydını silmek istediğinize emin misiniz?",
"LastModification": "Son Güncellenme",
"LoginToAddComment": "Yorum yapmak için giriş yap",
"LoginToRate": "Oylamak için giriş yapın",
"LoginToReply": "Cevap vermek için giriş yap",
"Menu:CMS": "CMS",
"Message": "Mesaj",
"MessageDeletionConfirmationMessage": "Bu yorum tamamen silinecektir",
"Name": "Ad",
"New": "Yeni",
"OK": "Tamam",
"PageDeletionConfirmationMessage": "Bu sayfayı silmek istediğinize emin misiniz?",
"PageSlugInformation": "Etiket URL'de kullanılır. Url şöyle görünür: '/pages/{{slug}}'.",
"Permission:BlogManagement": "Blog Yönetimi",
"Permission:BlogManagement.Create": "Oluşturma",
"Permission:BlogManagement.Delete": "Silme",
"Permission:BlogManagement.Features": "Özellikler",
"Permission:BlogManagement.Update": "Güncelleme",
"Permission:BlogPostManagement": "Blog Yazıları Yönetimi",
"Permission:BlogPostManagement.Create": "Oluşturma",
"Permission:BlogPostManagement.Delete": "Silme",
"Permission:BlogPostManagement.Update": "Güncelleme",
"Permission:CmsKit": "CmsKit",
"Permission:Contents": "İçerik Yönetimi",
"Permission:Contents.Create": "İçerik Oluşturma",
@ -29,14 +71,43 @@
"PickYourReaction": "Tepkinizi seçin",
"RatingUndoMessage": "Oylamanız geri alınacak.",
"Read": "Oku",
"RepliesToThisComment": "Bu yoruma yapılan yorumlar",
"Reply": "Cevapla",
"ReplyTo": "Cevap",
"SamplePageMessage": "Pro modulünden örnek bir sayfa",
"SaveChanges": "Değişiklikleri Kaydet",
"SelectAll": "Hepsini seç",
"Send": "Gönder",
"SendMessage": "Mesajı Gönder",
"ShortDescription": "Kısa açıklama",
"Slug": "Etiket",
"Source": "Kaynak",
"SourceUrl": "Kaynak Link",
"Star": "Yıldız",
"StartDate": "Başlangıç Tarihi",
"Subject": "Konu",
"SubjectPlaceholder": "Lütfen bir konu yazınız",
"Submit": "Kaydet",
"Subscribe": "Abone ol",
"SuccessfullyDeleted": "Başarıyla silindi!",
"SuccessfullySaved": "Başarıyla kaydedildi!",
"TagDeletionConfirmationMessage": "'{0}' etiketini silmek istediğinize emin misiniz?",
"Tags": "Etiketler",
"Text": "Metin",
"ThankYou": "Teşekkürler",
"Title": "Başlık",
"Undo": "Geri al",
"Update": "Güncelle",
"UpdatePreference": "Tercihleri Güncelle",
"UpdatePreferenceSuccessMessage": "Tercihleriniz kaydedilmiştir.",
"UpdateYourEmailPreferences": "E-posta tercihlerinizi güncelleyin",
"UploadFailedMessage": "Karşıya yükleme işlemi başarısız oldu.",
"UserId": "Kullanıcı Id",
"Username": "Kullanıcı adı",
"YourComment": "Yorumunuz",
"YourEmailAddress": "Email adresiniz",
"YourFullName": "Tam adınız",
"YourMessage": "Mesajınız",
"YourReply": "Cevabınız"
}
}

4
modules/cms-kit/src/Volo.CmsKit.Public.Web/CmsKitPublicWebModule.cs

@ -63,7 +63,9 @@ namespace Volo.CmsKit.Public.Web
{
Configure<RazorPagesOptions>(options =>
{
options.Conventions.AddPageRoute("/CmsKit/Pages/Index", @"/pages/{slug:minlength(1)}");
options.Conventions.AddPageRoute("/Public/CmsKit/Pages/Index", @"/pages/{slug:minlength(1)}");
options.Conventions.AddPageRoute("/Public/CmsKit/Blogs/Index", @"/blogs/{blogSlug:minlength(1)}");
options.Conventions.AddPageRoute("/Public/CmsKit/Blogs/BlogPost", @"/blogs/{blogSlug}/{blogPostSlug:minlength(1)}");
});
}
}

5
modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Blogs/BlogPost.cshtml → modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/BlogPost.cshtml

@ -1,8 +1,7 @@
@page "/blogs/{blogSlug}/{blogPostSlug}"
@page
@using Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.Blogs.BlogPost
@using Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.Blogs.BlogPostComment
@using Volo.CmsKit.Public.Web.Pages.CmsKit.Blogs
@using Volo.CmsKit.Public.Web.Pages
@using Volo.Abp.GlobalFeatures
@using Volo.CmsKit.GlobalFeatures
@ -12,7 +11,7 @@
@inherits CmsKitPublicPageBase
@model BlogPostModel
@model Volo.CmsKit.Public.Web.Pages.Public.CmsKit.Blogs.BlogPostModel
@{
PageLayout.Content.Title = Model.BlogPost.Title;

2
modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Blogs/BlogPost.cshtml.cs → modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/BlogPost.cshtml.cs

@ -10,7 +10,7 @@ using Volo.CmsKit.Blogs;
using Volo.CmsKit.GlobalFeatures;
using Volo.CmsKit.Public.Blogs;
namespace Volo.CmsKit.Public.Web.Pages.CmsKit.Blogs
namespace Volo.CmsKit.Public.Web.Pages.Public.CmsKit.Blogs
{
public class BlogPostModel : CmsKitPublicPageModelBase
{

5
modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Blogs/Index.cshtml → modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/Index.cshtml

@ -1,10 +1,11 @@
@page "/blogs/{blogSlug}"
@page
@using Volo.CmsKit.Public.Web.Pages
@using Volo.CmsKit.Public.Web.Pages.Public.CmsKit.Blogs
@inherits CmsKitPublicPageBase
@model Volo.CmsKit.Public.Web.Pages.CmsKit.Blogs.IndexModel
@model IndexModel
<abp-row id="blogs-container">
@foreach (var blog in Model.Blogs.Items)

2
modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Blogs/Index.cshtml.cs → modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/Index.cshtml.cs

@ -8,7 +8,7 @@ using Volo.Abp.Application.Dtos;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Pagination;
using Volo.CmsKit.Public.Blogs;
namespace Volo.CmsKit.Public.Web.Pages.CmsKit.Blogs
namespace Volo.CmsKit.Public.Web.Pages.Public.CmsKit.Blogs
{
public class IndexModel : CmsKitPublicPageModelBase
{

2
modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Pages/Index.cshtml → modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Pages/Index.cshtml

@ -2,7 +2,7 @@
@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
@model Volo.CmsKit.Public.Web.Pages.Public.CmsKit.Pages.IndexModel
@inject IHtmlLocalizer<CmsKitResource> L
@await Component.InvokeAsync(typeof(DefaultPageViewComponent),

2
modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Pages/Index.cshtml.cs → modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Pages/Index.cshtml.cs

@ -3,7 +3,7 @@ using Microsoft.AspNetCore.Mvc;
using Volo.CmsKit.Public.Pages;
using Volo.CmsKit.Web.Pages;
namespace Volo.CmsKit.Public.Web.Pages.CmsKit.Pages
namespace Volo.CmsKit.Public.Web.Pages.Public.CmsKit.Pages
{
public class IndexModel : CommonPageModel
{

0
modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/_ViewImports.cshtml → modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/_ViewImports.cshtml

Loading…
Cancel
Save