mirror of https://github.com/abpframework/abp.git
committed by
GitHub
88 changed files with 6013 additions and 17 deletions
File diff suppressed because it is too large
@ -0,0 +1,46 @@ |
|||||
|
using System; |
||||
|
using Microsoft.EntityFrameworkCore.Migrations; |
||||
|
|
||||
|
namespace Volo.CmsKit.Migrations |
||||
|
{ |
||||
|
public partial class Added_Page : Migration |
||||
|
{ |
||||
|
protected override void Up(MigrationBuilder migrationBuilder) |
||||
|
{ |
||||
|
migrationBuilder.CreateTable( |
||||
|
name: "CmsPages", |
||||
|
columns: table => new |
||||
|
{ |
||||
|
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false), |
||||
|
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), |
||||
|
Title = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false), |
||||
|
Url = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false), |
||||
|
Description = table.Column<string>(type: "nvarchar(515)", maxLength: 515, nullable: true), |
||||
|
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true), |
||||
|
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true), |
||||
|
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false), |
||||
|
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), |
||||
|
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true), |
||||
|
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), |
||||
|
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false), |
||||
|
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), |
||||
|
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true) |
||||
|
}, |
||||
|
constraints: table => |
||||
|
{ |
||||
|
table.PrimaryKey("PK_CmsPages", x => x.Id); |
||||
|
}); |
||||
|
|
||||
|
migrationBuilder.CreateIndex( |
||||
|
name: "IX_CmsPages_TenantId_Url", |
||||
|
table: "CmsPages", |
||||
|
columns: new[] { "TenantId", "Url" }); |
||||
|
} |
||||
|
|
||||
|
protected override void Down(MigrationBuilder migrationBuilder) |
||||
|
{ |
||||
|
migrationBuilder.DropTable( |
||||
|
name: "CmsPages"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
File diff suppressed because it is too large
@ -0,0 +1,24 @@ |
|||||
|
using Microsoft.EntityFrameworkCore.Migrations; |
||||
|
|
||||
|
namespace Volo.CmsKit.Migrations |
||||
|
{ |
||||
|
public partial class Updated_Tag_Removed_HexColor : Migration |
||||
|
{ |
||||
|
protected override void Up(MigrationBuilder migrationBuilder) |
||||
|
{ |
||||
|
migrationBuilder.DropColumn( |
||||
|
name: "HexColor", |
||||
|
table: "CmsTags"); |
||||
|
} |
||||
|
|
||||
|
protected override void Down(MigrationBuilder migrationBuilder) |
||||
|
{ |
||||
|
migrationBuilder.AddColumn<string>( |
||||
|
name: "HexColor", |
||||
|
table: "CmsTags", |
||||
|
type: "nvarchar(6)", |
||||
|
maxLength: 6, |
||||
|
nullable: true); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,37 @@ |
|||||
|
.jq-stars { |
||||
|
display: inline-block; |
||||
|
} |
||||
|
|
||||
|
.jq-rating-label { |
||||
|
font-size: 22px; |
||||
|
display: inline-block; |
||||
|
position: relative; |
||||
|
vertical-align: top; |
||||
|
font-family: helvetica, arial, verdana; |
||||
|
} |
||||
|
|
||||
|
.jq-star { |
||||
|
width: 100px; |
||||
|
height: 100px; |
||||
|
display: inline-block; |
||||
|
cursor: pointer; |
||||
|
} |
||||
|
|
||||
|
.jq-star-svg { |
||||
|
width: 100%; |
||||
|
height: 100% ; |
||||
|
} |
||||
|
|
||||
|
.jq-star:hover .fs-star-svg polygon { |
||||
|
} |
||||
|
|
||||
|
.jq-star-svg polygon { |
||||
|
stroke: #000; |
||||
|
stroke-linejoin: round; |
||||
|
} |
||||
|
|
||||
|
/* un-used */ |
||||
|
.jq-shadow { |
||||
|
-webkit-filter: drop-shadow( -2px -2px 2px #888 ); |
||||
|
filter: drop-shadow( -2px -2px 2px #888 ); |
||||
|
} |
||||
@ -0,0 +1 @@ |
|||||
|
!function(a){"use strict";var b="starRating",c=function(){},d={totalStars:5,useFullStars:!1,emptyColor:"lightgray",hoverColor:"orange",activeColor:"gold",useGradient:!0,readOnly:!1,disableAfterRate:!0,starGradient:{start:"#FEF7CD",end:"#FF9511"},strokeWidth:0,strokeColor:"black",initialRating:0,starSize:40,callback:c,onHover:c,onLeave:c},e=function(c,e){var f;this.element=c,this.$el=a(c),this.settings=a.extend({},d,e),f=this.$el.data("rating")||this.settings.initialRating,this._state={rating:(Math.round(2*f)/2).toFixed(1)},this._uid=Math.floor(999*Math.random()),e.starGradient||this.settings.useGradient||(this.settings.starGradient.start=this.settings.starGradient.end=this.settings.activeColor),this._defaults=d,this._name=b,this.init()},f={init:function(){this.renderMarkup(),this.addListeners(),this.initRating()},addListeners:function(){this.settings.readOnly||(this.$stars.on("mouseover",this.hoverRating.bind(this)),this.$stars.on("mouseout",this.restoreState.bind(this)),this.$stars.on("click",this.handleRating.bind(this)))},hoverRating:function(a){var b=this.getIndex(a);this.paintStars(b,"hovered"),this.settings.onHover(b+1,this._state.rating,this.$el)},handleRating:function(a){var b=this.getIndex(a),c=b+1;this.applyRating(c,this.$el),this.executeCallback(c,this.$el),this.settings.disableAfterRate&&this.$stars.off()},applyRating:function(a){var b=a-1;this.paintStars(b,"active"),this._state.rating=b+1},restoreState:function(a){var b=this.getIndex(a),c=this._state.rating||-1;this.paintStars(c-1,"active"),this.settings.onLeave(b+1,this._state.rating,this.$el)},getIndex:function(b){var c=a(b.currentTarget),d=c.width(),e=a(b.target).attr("data-side");e=e?e:this.getOffsetByPixel(b,c,d),e=this.settings.useFullStars?"right":e;var f=c.index()-("left"===e?.5:0);return f=.5>f&&b.offsetX<d/4?-1:f},getOffsetByPixel:function(a,b,c){var d=a.pageX-b.offset().left;return c/2>=d&&!this.settings.useFullStars?"left":"right"},initRating:function(){this.paintStars(this._state.rating-1,"active")},paintStars:function(b,c){var d,e,f,g;a.each(this.$stars,function(h,i){d=a(i).find('polygon[data-side="left"]'),e=a(i).find('polygon[data-side="right"]'),f=g=b>=h?c:"empty",f=h-b===.5?c:f,d.attr("class","svg-"+f+"-"+this._uid),e.attr("class","svg-"+g+"-"+this._uid)}.bind(this))},renderMarkup:function(){for(var a='<div class="jq-star" style="width:'+this.settings.starSize+"px; height:"+this.settings.starSize+'px;"><svg version="1.0" class="jq-star-svg" shape-rendering="geometricPrecision" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="305px" height="305px" viewBox="60 -62 309 309" style="enable-background:new 64 -59 305 305; stroke-width:'+this.settings.strokeWidth+'px;" xml:space="preserve"><style type="text/css">.svg-empty-'+this._uid+"{fill:url(#"+this._uid+"_SVGID_1_);}.svg-hovered-"+this._uid+"{fill:url(#"+this._uid+"_SVGID_2_);}.svg-active-"+this._uid+"{fill:url(#"+this._uid+"_SVGID_3_);}</style>"+this.getLinearGradient(this._uid+"_SVGID_1_",this.settings.emptyColor,this.settings.emptyColor)+this.getLinearGradient(this._uid+"_SVGID_2_",this.settings.hoverColor,this.settings.hoverColor)+this.getLinearGradient(this._uid+"_SVGID_3_",this.settings.starGradient.start,this.settings.starGradient.end)+'<polygon data-side="left" class="svg-empty-'+this._uid+'" points="281.1,129.8 364,55.7 255.5,46.8 214,-59 172.5,46.8 64,55.4 146.8,129.7 121.1,241 213.9,181.1 213.9,181 306.5,241 " style="stroke: '+this.settings.strokeColor+'"/><polygon data-side="right" class="svg-empty-'+this._uid+'" points="364,55.7 255.5,46.8 214,-59 213.9,181 306.5,241 281.1,129.8 " style="stroke-dasharray: 230 232 210 0; stroke: '+this.settings.strokeColor+'"/></svg></div>',b="",c=0;c<this.settings.totalStars;c++)b+=a;this.$el.append(b),this.$stars=this.$el.find(".jq-star")},getLinearGradient:function(a,b,c){return'<linearGradient id="'+a+'" gradientUnits="userSpaceOnUse" x1="121.1501" y1="-70.35" x2="121.15" y2="125.0045"><stop offset="0" style="stop-color:'+b+'"/><stop offset="1" style="stop-color:'+c+'"/> </linearGradient>'},executeCallback:function(a,b){var c=this.settings.callback;c(a,b)}},g={unload:function(){var c="plugin_"+b,d=a(this),e=d.data(c).$stars;e.off(),d.removeData(c).remove()},setRating:function(c,d){var e="plugin_"+b,f=a(this),g=f.data(e);c>g.settings.totalStars||0>c||(d&&(c=Math.round(c)),g.applyRating(c))},getRating:function(){var c="plugin_"+b,d=a(this),e=d.data(c);return e._state.rating}};a.extend(e.prototype,f),a.fn[b]=function(c){if(!a.isPlainObject(c)){if(g.hasOwnProperty(c))return g[c].apply(this,Array.prototype.slice.call(arguments,1));a.error("Method "+c+" does not exist on "+b+".js")}return this.each(function(){a.data(this,"plugin_"+b)||a.data(this,"plugin_"+b,new e(this,c))})}}(jQuery,window,document); |
||||
@ -0,0 +1,7 @@ |
|||||
|
namespace Volo.CmsKit |
||||
|
{ |
||||
|
public class CmsKitCommonRemoteServiceConsts |
||||
|
{ |
||||
|
public const string RemoteServiceName = "CmsKitCommon"; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
|
||||
|
namespace Volo.CmsKit.Contents |
||||
|
{ |
||||
|
public class ContentDto : EntityDto<Guid> |
||||
|
{ |
||||
|
public string Value { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
namespace Volo.CmsKit.Contents |
||||
|
{ |
||||
|
public class GetContentInput |
||||
|
{ |
||||
|
public string EntityType { get; set; } |
||||
|
public string EntityId { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace Volo.CmsKit.Contents |
||||
|
{ |
||||
|
public interface IContentAppService |
||||
|
{ |
||||
|
Task<ContentDto> GetAsync(GetContentInput input); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
using Volo.Abp.Validation; |
||||
|
|
||||
|
namespace Volo.CmsKit.Pages |
||||
|
{ |
||||
|
public class CheckUrlInputDto |
||||
|
{ |
||||
|
[Required] |
||||
|
public string Url { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
using Volo.Abp.Validation; |
||||
|
|
||||
|
namespace Volo.CmsKit.Pages |
||||
|
{ |
||||
|
public class CreatePageInputDto |
||||
|
{ |
||||
|
[Required] |
||||
|
public string Title { get; set; } |
||||
|
|
||||
|
[Required] |
||||
|
public string Url { get; set; } |
||||
|
|
||||
|
public string Description { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,20 @@ |
|||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
using Volo.Abp.Validation; |
||||
|
using Volo.CmsKit.Contents; |
||||
|
|
||||
|
namespace Volo.CmsKit.Pages |
||||
|
{ |
||||
|
public class CreatePageWithContentInputDto |
||||
|
{ |
||||
|
[Required] |
||||
|
public string Title { get; set; } |
||||
|
|
||||
|
[Required] |
||||
|
public string Url { get; set; } |
||||
|
|
||||
|
public string Description { get; set; } |
||||
|
|
||||
|
[Required] |
||||
|
public string Content { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,25 @@ |
|||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using JetBrains.Annotations; |
||||
|
|
||||
|
namespace Volo.CmsKit.Pages |
||||
|
{ |
||||
|
public interface IPageAppService |
||||
|
{ |
||||
|
Task<PageDto> GetAsync(Guid id); |
||||
|
|
||||
|
Task<PageDto> GetByUrlAsync([NotNull] string url); |
||||
|
|
||||
|
Task<PageDto> CreatePageAsync(CreatePageInputDto input); |
||||
|
|
||||
|
Task<PageDto> CreatePageWithContentAsync(CreatePageWithContentInputDto input); |
||||
|
|
||||
|
Task<PageDto> UpdatePageAsync(Guid id, UpdatePageInputDto input); |
||||
|
|
||||
|
Task<bool> DoesUrlExistAsync(CheckUrlInputDto input); |
||||
|
|
||||
|
Task UpdatePageContentAsync(Guid id, UpdatePageContentInputDto input); |
||||
|
|
||||
|
Task DeleteAsync(Guid id); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
|
||||
|
namespace Volo.CmsKit.Pages |
||||
|
{ |
||||
|
public class PageDto : EntityDto<Guid> |
||||
|
{ |
||||
|
public string Title { get; set; } |
||||
|
|
||||
|
public string Url { get; set; } |
||||
|
|
||||
|
public string Description { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
using Volo.CmsKit.Contents; |
||||
|
|
||||
|
namespace Volo.CmsKit.Pages |
||||
|
{ |
||||
|
public class PageWithContentDto : EntityDto<Guid> |
||||
|
{ |
||||
|
public string Title { get; set; } |
||||
|
|
||||
|
public string Url { get; set; } |
||||
|
|
||||
|
public string Description { get; set; } |
||||
|
|
||||
|
public ContentDto Content { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
using Volo.Abp.Validation; |
||||
|
using Volo.CmsKit.Contents; |
||||
|
|
||||
|
namespace Volo.CmsKit.Pages |
||||
|
{ |
||||
|
public class UpdatePageContentInputDto |
||||
|
{ |
||||
|
[Required] |
||||
|
public string Content { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
using Volo.Abp.Validation; |
||||
|
|
||||
|
namespace Volo.CmsKit.Pages |
||||
|
{ |
||||
|
public class UpdatePageInputDto |
||||
|
{ |
||||
|
[Required] |
||||
|
public string Title { get; set; } |
||||
|
|
||||
|
[Required] |
||||
|
public string Url { get; set; } |
||||
|
|
||||
|
public string Description { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
|
||||
|
namespace Volo.CmsKit.Tags |
||||
|
{ |
||||
|
public class GetRelatedTagsInput |
||||
|
{ |
||||
|
[Required] |
||||
|
public string EntityType { get; set; } |
||||
|
|
||||
|
[Required] |
||||
|
public string EntityId { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Application.Services; |
||||
|
|
||||
|
namespace Volo.CmsKit.Tags |
||||
|
{ |
||||
|
public interface ITagAppService : IApplicationService |
||||
|
{ |
||||
|
Task<List<TagDto>> GetAllRelatedTagsAsync(GetRelatedTagsInput input); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
|
||||
|
namespace Volo.CmsKit.Tags |
||||
|
{ |
||||
|
public class TagDto : EntityDto<Guid> |
||||
|
{ |
||||
|
public string EntityType { get; set; } |
||||
|
|
||||
|
public string Name { get; protected set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,19 @@ |
|||||
|
using AutoMapper; |
||||
|
using Volo.CmsKit.Contents; |
||||
|
using Volo.CmsKit.Pages; |
||||
|
using Volo.CmsKit.Tags; |
||||
|
|
||||
|
namespace Volo.CmsKit |
||||
|
{ |
||||
|
public class CmsKitCommonApplicationAutoMapperProfile : Profile |
||||
|
{ |
||||
|
public CmsKitCommonApplicationAutoMapperProfile() |
||||
|
{ |
||||
|
CreateMap<Content, ContentDto>(); |
||||
|
|
||||
|
CreateMap<Tag, TagDto>(); |
||||
|
|
||||
|
CreateMap<Page, PageDto>(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,28 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace Volo.CmsKit.Contents |
||||
|
{ |
||||
|
public class ContentAppService : CmsKitAppServiceBase, IContentAppService |
||||
|
{ |
||||
|
protected readonly IContentRepository ContentRepository; |
||||
|
|
||||
|
public ContentAppService(IContentRepository contentRepository) |
||||
|
{ |
||||
|
ContentRepository = contentRepository; |
||||
|
} |
||||
|
|
||||
|
public virtual async Task<ContentDto> GetAsync(GetContentInput input) |
||||
|
{ |
||||
|
var entity = await ContentRepository.GetAsync( |
||||
|
input.EntityType, |
||||
|
input.EntityId, |
||||
|
CurrentTenant.Id); |
||||
|
|
||||
|
return ObjectMapper.Map<Content, ContentDto>(entity); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,114 @@ |
|||||
|
using System; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp; |
||||
|
using Volo.CmsKit.Contents; |
||||
|
|
||||
|
namespace Volo.CmsKit.Pages |
||||
|
{ |
||||
|
public class PageAppService : CmsKitAppServiceBase, IPageAppService |
||||
|
{ |
||||
|
protected readonly IPageRepository PageRepository; |
||||
|
protected readonly IContentRepository ContentRepository; |
||||
|
|
||||
|
public PageAppService(IPageRepository pageRepository, IContentRepository contentRepository) |
||||
|
{ |
||||
|
PageRepository = pageRepository; |
||||
|
ContentRepository = contentRepository; |
||||
|
} |
||||
|
|
||||
|
public virtual async Task<PageDto> GetAsync(Guid id) |
||||
|
{ |
||||
|
var page = await PageRepository.GetAsync(id); |
||||
|
|
||||
|
return ObjectMapper.Map<Page, PageDto>(page); |
||||
|
} |
||||
|
|
||||
|
public virtual async Task<PageDto> GetByUrlAsync(string url) |
||||
|
{ |
||||
|
var page = await PageRepository.GetByUrlAsync(url); |
||||
|
|
||||
|
return ObjectMapper.Map<Page, PageDto>(page); |
||||
|
} |
||||
|
|
||||
|
public virtual async Task<PageDto> CreatePageAsync(CreatePageInputDto input) |
||||
|
{ |
||||
|
var page = await CreatePageAsync(input.Title, input.Url, input.Description); |
||||
|
|
||||
|
await PageRepository.InsertAsync(page); |
||||
|
|
||||
|
return ObjectMapper.Map<Page, PageDto>(page); |
||||
|
} |
||||
|
|
||||
|
public virtual async Task<PageDto> CreatePageWithContentAsync(CreatePageWithContentInputDto input) |
||||
|
{ |
||||
|
var page = await CreatePageAsync(input.Title, input.Url, input.Description); |
||||
|
|
||||
|
await PageRepository.InsertAsync(page); |
||||
|
|
||||
|
var content = new Content( |
||||
|
GuidGenerator.Create(), |
||||
|
nameof(Page), |
||||
|
page.Id.ToString(), |
||||
|
input.Content, |
||||
|
page.TenantId); |
||||
|
|
||||
|
await ContentRepository.InsertAsync(content); |
||||
|
|
||||
|
return ObjectMapper.Map<Page, PageDto>(page); |
||||
|
} |
||||
|
|
||||
|
public virtual async Task<PageDto> UpdatePageAsync(Guid id, UpdatePageInputDto input) |
||||
|
{ |
||||
|
var page = await PageRepository.GetAsync(id); |
||||
|
|
||||
|
if (page.Url != input.Url) |
||||
|
{ |
||||
|
await CheckPageUrlAsync(input.Url); |
||||
|
} |
||||
|
|
||||
|
page.Title = input.Title; |
||||
|
page.Url = input.Url; |
||||
|
page.Description = input.Description; |
||||
|
|
||||
|
await PageRepository.UpdateAsync(page); |
||||
|
|
||||
|
return ObjectMapper.Map<Page, PageDto>(page); |
||||
|
} |
||||
|
|
||||
|
public virtual Task<bool> DoesUrlExistAsync(CheckUrlInputDto input) |
||||
|
{ |
||||
|
return PageRepository.DoesExistAsync(input.Url); |
||||
|
} |
||||
|
|
||||
|
public virtual async Task UpdatePageContentAsync(Guid id, UpdatePageContentInputDto input) |
||||
|
{ |
||||
|
var pageContent = await ContentRepository.GetAsync(nameof(Page), id.ToString()); |
||||
|
|
||||
|
pageContent.SetValue(input.Content); |
||||
|
|
||||
|
await ContentRepository.UpdateAsync(pageContent); |
||||
|
} |
||||
|
|
||||
|
public virtual async Task DeleteAsync(Guid id) |
||||
|
{ |
||||
|
await ContentRepository.DeleteAsync(nameof(Page), id.ToString(), CurrentTenant?.Id, CancellationToken.None); |
||||
|
await PageRepository.DeleteAsync(id, cancellationToken: CancellationToken.None); |
||||
|
} |
||||
|
|
||||
|
protected virtual async Task<Page> CreatePageAsync(string title, string url, string description) |
||||
|
{ |
||||
|
await CheckPageUrlAsync(url); |
||||
|
|
||||
|
return new Page(GuidGenerator.Create(), title, url, description, CurrentTenant?.Id); |
||||
|
} |
||||
|
|
||||
|
protected virtual async Task CheckPageUrlAsync(string url) |
||||
|
{ |
||||
|
if (await PageRepository.DoesExistAsync(url)) |
||||
|
{ |
||||
|
throw new UserFriendlyException("Url exist"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,34 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace Volo.CmsKit.Tags |
||||
|
{ |
||||
|
public class TagAppService : CmsKitAppServiceBase, ITagAppService |
||||
|
{ |
||||
|
protected readonly ITagManager TagManager; |
||||
|
protected readonly ITagRepository TagRepository; |
||||
|
protected readonly IEntityTagRepository EntityTagRepository; |
||||
|
|
||||
|
public TagAppService( |
||||
|
ITagManager tagManager, |
||||
|
ITagRepository tagRepository, |
||||
|
IEntityTagRepository entityTagRepository) |
||||
|
{ |
||||
|
TagManager = tagManager; |
||||
|
TagRepository = tagRepository; |
||||
|
EntityTagRepository = entityTagRepository; |
||||
|
} |
||||
|
|
||||
|
public virtual async Task<List<TagDto>> GetAllRelatedTagsAsync(GetRelatedTagsInput input) |
||||
|
{ |
||||
|
var entities = await TagRepository.GetAllRelatedTagsAsync( |
||||
|
input.EntityType, |
||||
|
input.EntityId, |
||||
|
CurrentTenant.Id); |
||||
|
|
||||
|
return ObjectMapper.Map<List<Tag>, List<TagDto>>(entities); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,27 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Volo.Abp; |
||||
|
using Volo.CmsKit.Contents; |
||||
|
|
||||
|
namespace Volo.CmsKit.Controllers.Contents |
||||
|
{ |
||||
|
|
||||
|
[RemoteService(Name = CmsKitCommonRemoteServiceConsts.RemoteServiceName)] |
||||
|
[Area("cms-kit")] |
||||
|
[Route("api/cms-kit/contents")] |
||||
|
public class ContentController : CmsKitControllerBase, IContentAppService |
||||
|
{ |
||||
|
protected readonly IContentAppService _contentAppService; |
||||
|
|
||||
|
public ContentController(IContentAppService contentAppService) |
||||
|
{ |
||||
|
_contentAppService = contentAppService; |
||||
|
} |
||||
|
|
||||
|
[HttpGet] |
||||
|
public virtual Task<ContentDto> GetAsync(GetContentInput input) |
||||
|
{ |
||||
|
return _contentAppService.GetAsync(input); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,77 @@ |
|||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Volo.Abp; |
||||
|
using Volo.CmsKit.Pages; |
||||
|
|
||||
|
namespace Volo.CmsKit.Controllers.Pages |
||||
|
{ |
||||
|
[RemoteService(Name = CmsKitCommonRemoteServiceConsts.RemoteServiceName)] |
||||
|
[Area("cms-kit")] |
||||
|
[Route("api/cms-kit/pages")] |
||||
|
public class PageController : CmsKitControllerBase, IPageAppService |
||||
|
{ |
||||
|
protected readonly IPageAppService PageAppService; |
||||
|
|
||||
|
public PageController(IPageAppService pageAppService) |
||||
|
{ |
||||
|
PageAppService = pageAppService; |
||||
|
} |
||||
|
|
||||
|
[HttpGet] |
||||
|
[Route("{id}")] |
||||
|
public virtual Task<PageDto> GetAsync(Guid id) |
||||
|
{ |
||||
|
return PageAppService.GetAsync(id); |
||||
|
} |
||||
|
|
||||
|
[HttpGet] |
||||
|
[Route("url/{url}")] |
||||
|
public Task<PageDto> GetByUrlAsync(string url) |
||||
|
{ |
||||
|
return PageAppService.GetByUrlAsync(url); |
||||
|
} |
||||
|
|
||||
|
[HttpPost] |
||||
|
[Route("create")] |
||||
|
public virtual Task<PageDto> CreatePageAsync(CreatePageInputDto input) |
||||
|
{ |
||||
|
return PageAppService.CreatePageAsync(input); |
||||
|
} |
||||
|
|
||||
|
[HttpPost] |
||||
|
[Route("create-with-content")] |
||||
|
public virtual Task<PageDto> CreatePageWithContentAsync(CreatePageWithContentInputDto input) |
||||
|
{ |
||||
|
return PageAppService.CreatePageWithContentAsync(input); |
||||
|
} |
||||
|
|
||||
|
[HttpPut] |
||||
|
[Route("{id}")] |
||||
|
public virtual Task<PageDto> UpdatePageAsync(Guid id, UpdatePageInputDto input) |
||||
|
{ |
||||
|
return PageAppService.UpdatePageAsync(id, input); |
||||
|
} |
||||
|
|
||||
|
[HttpPost] |
||||
|
[Route("does-url-exist")] |
||||
|
public virtual Task<bool> DoesUrlExistAsync(CheckUrlInputDto input) |
||||
|
{ |
||||
|
return PageAppService.DoesUrlExistAsync(input); |
||||
|
} |
||||
|
|
||||
|
[HttpPut] |
||||
|
[Route("update-content/{id}")] |
||||
|
public virtual Task UpdatePageContentAsync(Guid id, UpdatePageContentInputDto input) |
||||
|
{ |
||||
|
return PageAppService.UpdatePageContentAsync(id, input); |
||||
|
} |
||||
|
|
||||
|
[HttpDelete] |
||||
|
[Route("{id}")] |
||||
|
public virtual Task DeleteAsync(Guid id) |
||||
|
{ |
||||
|
return PageAppService.DeleteAsync(id); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,27 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Volo.Abp; |
||||
|
using Volo.CmsKit.Tags; |
||||
|
|
||||
|
namespace Volo.CmsKit.Controllers.Tags |
||||
|
{ |
||||
|
[RemoteService(Name = CmsKitCommonRemoteServiceConsts.RemoteServiceName)] |
||||
|
[Area("cms-kit")] |
||||
|
[Route("api/cms-kit/tags")] |
||||
|
public class TagController : CmsKitControllerBase, ITagAppService |
||||
|
{ |
||||
|
protected readonly ITagAppService TagAppService; |
||||
|
|
||||
|
public TagController(ITagAppService tagAppService) |
||||
|
{ |
||||
|
TagAppService = tagAppService; |
||||
|
} |
||||
|
|
||||
|
[HttpGet] |
||||
|
public Task<List<TagDto>> GetAllRelatedTagsAsync(GetRelatedTagsInput input) |
||||
|
{ |
||||
|
return TagAppService.GetAllRelatedTagsAsync(input); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace Volo.CmsKit.Web.Contents |
||||
|
{ |
||||
|
public interface IContentRenderer |
||||
|
{ |
||||
|
Task<string> RenderAsync(string value); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,13 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace Volo.CmsKit.Web.Contents |
||||
|
{ |
||||
|
public class PlainTextContentRenderer : IContentRenderer, ITransientDependency |
||||
|
{ |
||||
|
public Task<string> RenderAsync(string value) |
||||
|
{ |
||||
|
return Task.FromResult(value); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,15 @@ |
|||||
|
@page "{pageUrl}" |
||||
|
@using Microsoft.AspNetCore.Mvc.Localization |
||||
|
@using Volo.CmsKit.Localization |
||||
|
@using Volo.CmsKit.Web.Pages.CmsKit.Pages |
||||
|
@using Volo.CmsKit.Web.Pages.CmsKit.Shared.Components.Pages |
||||
|
@model IndexModel |
||||
|
@inject IHtmlLocalizer<CmsKitResource> L |
||||
|
|
||||
|
@await Component.InvokeAsync(typeof(DefaultPageViewComponent), |
||||
|
new |
||||
|
{ |
||||
|
pageId = Model.Page.Id, |
||||
|
title = Model.Page.Title, |
||||
|
description = Model.Page.Description |
||||
|
}) |
||||
@ -0,0 +1,26 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Volo.CmsKit.Pages; |
||||
|
|
||||
|
namespace Volo.CmsKit.Web.Pages.CmsKit.Pages |
||||
|
{ |
||||
|
public class IndexModel : CommonPageModel |
||||
|
{ |
||||
|
[BindProperty(SupportsGet = true)] |
||||
|
public string PageUrl { get; set; } |
||||
|
|
||||
|
protected readonly IPageAppService PageAppService; |
||||
|
|
||||
|
public PageDto Page; |
||||
|
|
||||
|
public IndexModel(IPageAppService pageAppService) |
||||
|
{ |
||||
|
PageAppService = pageAppService; |
||||
|
} |
||||
|
|
||||
|
public async Task OnGetAsync() |
||||
|
{ |
||||
|
Page = await PageAppService.GetByUrlAsync(PageUrl); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,55 @@ |
|||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Volo.Abp.AspNetCore.Mvc; |
||||
|
using Volo.CmsKit.Contents; |
||||
|
using Volo.CmsKit.Web.Contents; |
||||
|
|
||||
|
namespace Volo.CmsKit.Web.Pages.CmsKit.Shared.Components.Contents |
||||
|
{ |
||||
|
[ViewComponent(Name = "CmsContent")] |
||||
|
public class ContentViewComponent : AbpViewComponent |
||||
|
{ |
||||
|
private readonly IContentRenderer contentRenderer; |
||||
|
private readonly IContentAppService contentAppService; |
||||
|
|
||||
|
public ContentViewComponent( |
||||
|
IContentRenderer contentRenderer, |
||||
|
IContentAppService contentAppService) |
||||
|
{ |
||||
|
this.contentRenderer = contentRenderer; |
||||
|
this.contentAppService = contentAppService; |
||||
|
} |
||||
|
|
||||
|
public virtual async Task<IViewComponentResult> InvokeAsync( |
||||
|
string entityType, |
||||
|
string entityId) |
||||
|
{ |
||||
|
var content = await contentAppService.GetAsync(new GetContentInput |
||||
|
{ |
||||
|
EntityId = entityId, |
||||
|
EntityType = entityType |
||||
|
}); |
||||
|
|
||||
|
var viewModel = new ContentViewModel |
||||
|
{ |
||||
|
EntityId = entityId, |
||||
|
EntityType = entityType, |
||||
|
ContentId = content.Id, |
||||
|
Rendered = await contentRenderer.RenderAsync(content.Value) |
||||
|
}; |
||||
|
|
||||
|
return View("~/Pages/CmsKit/Shared/Components/Contents/Default.cshtml", viewModel); |
||||
|
} |
||||
|
|
||||
|
public class ContentViewModel |
||||
|
{ |
||||
|
public Guid ContentId { get; set; } |
||||
|
public string EntityType { get; set; } |
||||
|
|
||||
|
public string EntityId { get; set; } |
||||
|
|
||||
|
public string Rendered { get; set; } |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,7 @@ |
|||||
|
@using Microsoft.AspNetCore.Mvc.Localization |
||||
|
@using Volo.CmsKit.Localization |
||||
|
@model Volo.CmsKit.Web.Pages.CmsKit.Shared.Components.Contents.ContentViewComponent.ContentViewModel |
||||
|
|
||||
|
<div> |
||||
|
@Html.Raw(Model.Rendered) |
||||
|
</div> |
||||
@ -0,0 +1,21 @@ |
|||||
|
@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bootstrap |
||||
|
|
||||
|
@using Microsoft.AspNetCore.Mvc.RazorPages |
||||
|
@using Volo.CmsKit.Web.Pages.CmsKit.Shared.Components.Contents |
||||
|
@model Volo.CmsKit.Web.Pages.CmsKit.Shared.Components.Pages.PageViewModel |
||||
|
|
||||
|
<abp-card> |
||||
|
<abp-card-header> |
||||
|
<h3> |
||||
|
@Model.Title |
||||
|
</h3> |
||||
|
</abp-card-header> |
||||
|
|
||||
|
<abp-card-body> |
||||
|
<p> |
||||
|
@Model.Description |
||||
|
</p> |
||||
|
|
||||
|
@await Component.InvokeAsync(typeof(ContentViewComponent), new { entityType = nameof(Page), entityId = Model.Id.ToString() }) |
||||
|
</abp-card-body> |
||||
|
</abp-card> |
||||
@ -0,0 +1,40 @@ |
|||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Volo.Abp.AspNetCore.Mvc; |
||||
|
using Volo.CmsKit.Pages; |
||||
|
|
||||
|
namespace Volo.CmsKit.Web.Pages.CmsKit.Shared.Components.Pages |
||||
|
{ |
||||
|
[ViewComponent(Name = "CmsDefaultPage")] |
||||
|
public class DefaultPageViewComponent : AbpViewComponent |
||||
|
{ |
||||
|
protected readonly IPageAppService PageAppService; |
||||
|
|
||||
|
public DefaultPageViewComponent(IPageAppService pageAppService) |
||||
|
{ |
||||
|
PageAppService = pageAppService; |
||||
|
} |
||||
|
|
||||
|
public virtual async Task<IViewComponentResult> InvokeAsync(Guid pageId, string title, string description) |
||||
|
{ |
||||
|
var model = new PageViewModel |
||||
|
{ |
||||
|
Id = pageId, |
||||
|
Title = title, |
||||
|
Description = description |
||||
|
}; |
||||
|
|
||||
|
return View("~/Pages/CmsKit/Shared/Components/Pages/Default.cshtml", model); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public class PageViewModel |
||||
|
{ |
||||
|
public Guid Id { get; set; } |
||||
|
|
||||
|
public string Title { get; set; } |
||||
|
|
||||
|
public string Description { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,13 @@ |
|||||
|
@using Volo.CmsKit.Web.Pages.CmsKit.Shared.Components.Tags |
||||
|
|
||||
|
@model TagViewComponent.TagViewModel |
||||
|
|
||||
|
@if (Model.Tags != null) |
||||
|
{ |
||||
|
foreach (var tag in Model.Tags) |
||||
|
{ |
||||
|
<span class="cmskit-tag"> |
||||
|
@tag.Name |
||||
|
</span> |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,49 @@ |
|||||
|
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.CmsKit.Tags; |
||||
|
|
||||
|
namespace Volo.CmsKit.Web.Pages.CmsKit.Shared.Components.Tags |
||||
|
{ |
||||
|
[ViewComponent(Name = "CmsTags")] |
||||
|
public class TagViewComponent : AbpViewComponent |
||||
|
{ |
||||
|
protected readonly ITagAppService TagAppService; |
||||
|
|
||||
|
public TagViewComponent(ITagAppService tagAppService) |
||||
|
{ |
||||
|
TagAppService = tagAppService; |
||||
|
} |
||||
|
|
||||
|
public virtual async Task<IViewComponentResult> InvokeAsync( |
||||
|
string entityType, |
||||
|
string entityId) |
||||
|
{ |
||||
|
var tagDtos = await TagAppService.GetAllRelatedTagsAsync(new GetRelatedTagsInput |
||||
|
{ |
||||
|
EntityId = entityId, |
||||
|
EntityType = entityType |
||||
|
}); |
||||
|
|
||||
|
var viewModel = new TagViewModel |
||||
|
{ |
||||
|
EntityId = entityId, |
||||
|
EntityType = entityType, |
||||
|
Tags = tagDtos |
||||
|
}; |
||||
|
|
||||
|
return View("~/Pages/CmsKit/Shared/Components/Tags/Default.cshtml", viewModel); |
||||
|
} |
||||
|
|
||||
|
public class TagViewModel |
||||
|
{ |
||||
|
public List<TagDto> Tags { get; set; } |
||||
|
public string EntityId { get; set; } |
||||
|
public string EntityType { get; set; } |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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 |
||||
@ -0,0 +1,13 @@ |
|||||
|
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; |
||||
|
using Volo.CmsKit.Localization; |
||||
|
|
||||
|
namespace Volo.CmsKit.Web.Pages |
||||
|
{ |
||||
|
public abstract class CommonPageModel : AbpPageModel |
||||
|
{ |
||||
|
protected CommonPageModel() |
||||
|
{ |
||||
|
LocalizationResourceType = typeof(CmsKitResource); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,15 @@ |
|||||
|
using System; |
||||
|
using Volo.CmsKit.Entities; |
||||
|
|
||||
|
namespace Volo.CmsKit.Contents |
||||
|
{ |
||||
|
public static class ContentConsts |
||||
|
{ |
||||
|
public static int MaxEntityTypeLength { get; set; } = CmsEntityConsts.MaxEntityTypeLength; |
||||
|
|
||||
|
public static int MaxEntityIdLength { get; set; } = CmsEntityConsts.MaxEntityIdLength; |
||||
|
|
||||
|
// TODO: consider
|
||||
|
public static int MaxValueLength = int.MaxValue; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using Volo.Abp.GlobalFeatures; |
||||
|
|
||||
|
namespace Volo.CmsKit.GlobalFeatures |
||||
|
{ |
||||
|
[GlobalFeatureName(Name)] |
||||
|
public class ContentsFeature : GlobalFeature |
||||
|
{ |
||||
|
public const string Name = "CmsKit.Contents"; |
||||
|
|
||||
|
internal ContentsFeature( |
||||
|
[NotNull] GlobalCmsKitFeatures cmsKit |
||||
|
) : base(cmsKit) |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using Volo.Abp.GlobalFeatures; |
||||
|
|
||||
|
namespace Volo.CmsKit.GlobalFeatures |
||||
|
{ |
||||
|
[GlobalFeatureName(Name)] |
||||
|
public class TagsFeature : GlobalFeature |
||||
|
{ |
||||
|
public const string Name = "CmsKit.Tags"; |
||||
|
|
||||
|
internal TagsFeature( |
||||
|
[NotNull] GlobalCmsKitFeatures cmsKit |
||||
|
) : base(cmsKit) |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
namespace Volo.CmsKit.Pages |
||||
|
{ |
||||
|
public class PageConsts |
||||
|
{ |
||||
|
public static int MaxTitleLength = 256; |
||||
|
|
||||
|
public static int MaxUrlLength = 256; |
||||
|
|
||||
|
public static int MaxDescriptionLength = 515; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
using Volo.CmsKit.Entities; |
||||
|
|
||||
|
namespace Volo.CmsKit.Tags |
||||
|
{ |
||||
|
public static class TagConsts |
||||
|
{ |
||||
|
public static int MaxEntityTypeLength { get; set; } = CmsEntityConsts.MaxEntityTypeLength; |
||||
|
|
||||
|
public static int MaxNameLength { get; set; } = 32; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,38 @@ |
|||||
|
using System; |
||||
|
using JetBrains.Annotations; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Domain.Entities.Auditing; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
|
||||
|
namespace Volo.CmsKit.Contents |
||||
|
{ |
||||
|
public class Content : FullAuditedAggregateRoot<Guid>, IMultiTenant |
||||
|
{ |
||||
|
public virtual Guid? TenantId { get; set; } |
||||
|
|
||||
|
public virtual string EntityType { get; set; } |
||||
|
|
||||
|
public virtual string EntityId { get; set; } |
||||
|
|
||||
|
public virtual string Value { get; protected set; } |
||||
|
|
||||
|
protected Content() |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
public Content(Guid id, [NotNull] string entityType, [NotNull] string entityId, [NotNull] string value, Guid? tenantId = null) : base(id) |
||||
|
{ |
||||
|
EntityType = Check.NotNullOrWhiteSpace(entityType, nameof(entityType), ContentConsts.MaxEntityTypeLength); |
||||
|
EntityId = Check.NotNullOrWhiteSpace(entityId, nameof(entityId), ContentConsts.MaxEntityIdLength); |
||||
|
SetValue(value); |
||||
|
|
||||
|
TenantId = tenantId; |
||||
|
} |
||||
|
|
||||
|
public void SetValue([NotNull] string value) |
||||
|
{ |
||||
|
Value = Check.NotNullOrWhiteSpace(value, nameof(value), ContentConsts.MaxValueLength); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,25 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using System; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Domain.Repositories; |
||||
|
|
||||
|
namespace Volo.CmsKit.Contents |
||||
|
{ |
||||
|
public interface IContentRepository : IBasicRepository<Content, Guid> |
||||
|
{ |
||||
|
Task<Content> GetAsync( |
||||
|
[NotNull] string entityType, |
||||
|
[NotNull] string entityId, |
||||
|
Guid? tenantId = null, |
||||
|
CancellationToken cancellationToken = default); |
||||
|
|
||||
|
Task<Content> FindAsync( |
||||
|
[NotNull] string entityType, |
||||
|
[NotNull] string entityId, |
||||
|
Guid? tenantId = null, |
||||
|
CancellationToken cancellationToken = default); |
||||
|
|
||||
|
Task DeleteAsync([NotNull] string entityType, [NotNull] string entityId, Guid? tenantId = null, CancellationToken cancellationToken = default); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,15 @@ |
|||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Domain.Repositories; |
||||
|
|
||||
|
namespace Volo.CmsKit.Pages |
||||
|
{ |
||||
|
public interface IPageRepository : IBasicRepository<Page, Guid> |
||||
|
{ |
||||
|
Task<Page> GetByUrlAsync(string url); |
||||
|
|
||||
|
Task<Page> FindByUrlAsync(string url); |
||||
|
|
||||
|
Task<bool> DoesExistAsync(string url); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,33 @@ |
|||||
|
using System; |
||||
|
using JetBrains.Annotations; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Domain.Entities.Auditing; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
|
||||
|
namespace Volo.CmsKit.Pages |
||||
|
{ |
||||
|
public class Page : FullAuditedAggregateRoot<Guid>, IMultiTenant |
||||
|
{ |
||||
|
public Guid? TenantId { get; set; } |
||||
|
|
||||
|
public virtual string Title { get; set; } |
||||
|
|
||||
|
public virtual string Url { get; set; } |
||||
|
|
||||
|
public virtual string Description { get; set; } |
||||
|
|
||||
|
protected Page() |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
public Page(Guid id, [NotNull] string title, [NotNull] string url, [CanBeNull] string description, Guid? tenantId = null) : base(id) |
||||
|
{ |
||||
|
Title = Check.NotNullOrWhiteSpace(title, nameof(title), PageConsts.MaxTitleLength); |
||||
|
Url = Check.NotNullOrWhiteSpace(url, nameof(url), PageConsts.MaxUrlLength); |
||||
|
Description = Check.Length(description, nameof(description), PageConsts.MaxDescriptionLength); |
||||
|
|
||||
|
TenantId = tenantId; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,32 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.Domain.Entities; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
|
||||
|
namespace Volo.CmsKit.Tags |
||||
|
{ |
||||
|
public class EntityTag : Entity, IMultiTenant |
||||
|
{ |
||||
|
public virtual Guid TagId { get; set; } |
||||
|
|
||||
|
public virtual string EntityId { get; set; } |
||||
|
|
||||
|
public virtual Guid? TenantId { get; set; } |
||||
|
|
||||
|
protected EntityTag() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public EntityTag(Guid tagId, string entityId, Guid? tenantId = null) |
||||
|
{ |
||||
|
TagId = tagId; |
||||
|
EntityId = entityId; |
||||
|
TenantId = tenantId; |
||||
|
} |
||||
|
|
||||
|
public override object[] GetKeys() |
||||
|
{ |
||||
|
return new object[] { TagId, EntityId }; |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
using Volo.Abp.Domain.Repositories; |
||||
|
|
||||
|
namespace Volo.CmsKit.Tags |
||||
|
{ |
||||
|
public interface IEntityTagRepository : IBasicRepository<EntityTag> |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,30 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using System; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Domain.Services; |
||||
|
using Volo.CmsKit.Tags; |
||||
|
|
||||
|
namespace Volo.CmsKit.Tags |
||||
|
{ |
||||
|
public interface ITagManager : IDomainService |
||||
|
{ |
||||
|
Task<Tag> InsertAsync( |
||||
|
Guid id, |
||||
|
[NotNull] string entityType, |
||||
|
[NotNull] string name, |
||||
|
Guid? tenantId = null, |
||||
|
CancellationToken cancellationToken = default); |
||||
|
|
||||
|
Task<Tag> UpdateAsync( |
||||
|
Guid id, |
||||
|
[NotNull] string name, |
||||
|
CancellationToken cancellationToken = default); |
||||
|
|
||||
|
Task<Tag> GetOrAddAsync( |
||||
|
[NotNull] string entityType, |
||||
|
[NotNull] string name, |
||||
|
Guid? tenantId = null, |
||||
|
CancellationToken cancellationToken = default); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,36 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Domain.Repositories; |
||||
|
|
||||
|
namespace Volo.CmsKit.Tags |
||||
|
{ |
||||
|
public interface ITagRepository : IBasicRepository<Tag, Guid> |
||||
|
{ |
||||
|
Task<Tag> GetAsync( |
||||
|
[NotNull] string entityType, |
||||
|
[NotNull] string name, |
||||
|
Guid? tenantId = null, |
||||
|
CancellationToken cancellationToken = default); |
||||
|
|
||||
|
Task<bool> AnyAsync( |
||||
|
[NotNull] string entityType, |
||||
|
[NotNull] string name, |
||||
|
Guid? tenantId = null, |
||||
|
CancellationToken cancellationToken = default); |
||||
|
|
||||
|
Task<Tag> FindAsync( |
||||
|
[NotNull] string entityType, |
||||
|
[NotNull] string name, |
||||
|
Guid? tenantId = null, |
||||
|
CancellationToken cancellationToken = default); |
||||
|
|
||||
|
Task<List<Tag>> GetAllRelatedTagsAsync( |
||||
|
[NotNull] string entityType, |
||||
|
[NotNull] string entityId, |
||||
|
Guid? tenantId = null, |
||||
|
CancellationToken cancellationToken = default); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,37 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using System; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Domain.Entities.Auditing; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
|
||||
|
namespace Volo.CmsKit.Tags |
||||
|
{ |
||||
|
public class Tag : FullAuditedAggregateRoot<Guid>, IMultiTenant |
||||
|
{ |
||||
|
public string EntityType { get; set; } |
||||
|
|
||||
|
public string Name { get; protected set; } |
||||
|
|
||||
|
public Guid? TenantId { get; set; } |
||||
|
|
||||
|
protected Tag() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public Tag( |
||||
|
Guid id, |
||||
|
[NotNull] string entityType, |
||||
|
[NotNull] string name, |
||||
|
Guid? tenantId = null) : base(id) |
||||
|
{ |
||||
|
EntityType = Check.NotNullOrWhiteSpace(entityType, nameof(entityType), TagConsts.MaxEntityTypeLength); |
||||
|
SetName(name); |
||||
|
TenantId = tenantId; |
||||
|
} |
||||
|
|
||||
|
public void SetName(string name) |
||||
|
{ |
||||
|
Name = Check.NotNullOrWhiteSpace(name, nameof(name), TagConsts.MaxNameLength); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,73 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using System; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Domain.Services; |
||||
|
|
||||
|
namespace Volo.CmsKit.Tags |
||||
|
{ |
||||
|
public class TagManager : DomainService, ITagManager |
||||
|
{ |
||||
|
private readonly ITagRepository _tagRepository; |
||||
|
|
||||
|
public TagManager(ITagRepository tagRepository) |
||||
|
{ |
||||
|
_tagRepository = tagRepository; |
||||
|
} |
||||
|
|
||||
|
public async Task<Tag> GetOrAddAsync( |
||||
|
[NotNull] string entityType, |
||||
|
[NotNull] string name, |
||||
|
Guid? tenantId = null, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
var entity = await _tagRepository.FindAsync(entityType, name, tenantId, cancellationToken); |
||||
|
|
||||
|
if (entity == null) |
||||
|
{ |
||||
|
entity = await InsertAsync(GuidGenerator.Create(), entityType, name, tenantId, cancellationToken); |
||||
|
} |
||||
|
|
||||
|
return entity; |
||||
|
} |
||||
|
|
||||
|
public async Task<Tag> InsertAsync( |
||||
|
Guid id, |
||||
|
[NotNull] string entityType, |
||||
|
[NotNull] string name, |
||||
|
Guid? tenantId = null, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
if (await _tagRepository.AnyAsync(entityType, name, tenantId, cancellationToken)) |
||||
|
{ |
||||
|
throw new BusinessException(message: "Tag already exist!"); // Already Exist
|
||||
|
} |
||||
|
|
||||
|
return await _tagRepository.InsertAsync( |
||||
|
new Tag( |
||||
|
id, |
||||
|
entityType, |
||||
|
name, |
||||
|
tenantId), |
||||
|
cancellationToken: cancellationToken); |
||||
|
} |
||||
|
|
||||
|
public async Task<Tag> UpdateAsync( |
||||
|
Guid id, |
||||
|
[NotNull] string name, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
var entity = await _tagRepository.GetAsync(id, cancellationToken: cancellationToken); |
||||
|
|
||||
|
if (name != entity.Name && await _tagRepository.AnyAsync(entity.EntityType, name, entity.TenantId, cancellationToken)) |
||||
|
{ |
||||
|
throw new BusinessException(message: "Tag already exist!"); // Already Exist
|
||||
|
} |
||||
|
|
||||
|
entity.SetName(name); |
||||
|
|
||||
|
return await _tagRepository.UpdateAsync(entity); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,55 @@ |
|||||
|
using System; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Domain.Repositories.EntityFrameworkCore; |
||||
|
using Volo.Abp.EntityFrameworkCore; |
||||
|
using Volo.CmsKit.EntityFrameworkCore; |
||||
|
|
||||
|
namespace Volo.CmsKit.Contents |
||||
|
{ |
||||
|
public class EfCoreContentRepository : EfCoreRepository<ICmsKitDbContext, Content, Guid>, IContentRepository |
||||
|
{ |
||||
|
public EfCoreContentRepository(IDbContextProvider<ICmsKitDbContext> dbContextProvider) : base(dbContextProvider) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public Task<Content> GetAsync( |
||||
|
string entityType, |
||||
|
string entityId, |
||||
|
Guid? tenantId = null, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
return GetAsync(x => |
||||
|
!x.IsDeleted && |
||||
|
x.EntityType == entityType && |
||||
|
x.EntityId == entityId && |
||||
|
x.TenantId == tenantId, |
||||
|
cancellationToken: cancellationToken |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
public Task<Content> FindAsync( |
||||
|
string entityType, |
||||
|
string entityId, |
||||
|
Guid? tenantId = null, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
return FindAsync(x => |
||||
|
!x.IsDeleted && |
||||
|
x.EntityType == entityType && |
||||
|
x.EntityId == entityId && |
||||
|
x.TenantId == tenantId, |
||||
|
cancellationToken: cancellationToken |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
public Task DeleteAsync(string entityType, string entityId, Guid? tenantId = null, CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
return DeleteAsync(x => |
||||
|
x.EntityType == entityType && |
||||
|
x.EntityId == entityId && |
||||
|
x.TenantId == tenantId, |
||||
|
cancellationToken: cancellationToken); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,31 @@ |
|||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.EntityFrameworkCore; |
||||
|
using Volo.Abp.Domain.Repositories.EntityFrameworkCore; |
||||
|
using Volo.Abp.EntityFrameworkCore; |
||||
|
using Volo.CmsKit.EntityFrameworkCore; |
||||
|
|
||||
|
namespace Volo.CmsKit.Pages |
||||
|
{ |
||||
|
public class EfCorePageRepository : EfCoreRepository<ICmsKitDbContext, Page, Guid>, IPageRepository |
||||
|
{ |
||||
|
public EfCorePageRepository(IDbContextProvider<ICmsKitDbContext> dbContextProvider) : base(dbContextProvider) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public Task<Page> GetByUrlAsync(string url) |
||||
|
{ |
||||
|
return GetAsync(x => x.Url == url); |
||||
|
} |
||||
|
|
||||
|
public Task<Page> FindByUrlAsync(string url) |
||||
|
{ |
||||
|
return FindAsync(x => x.Url == url); |
||||
|
} |
||||
|
|
||||
|
public Task<bool> DoesExistAsync(string url) |
||||
|
{ |
||||
|
return DbSet.AnyAsync(x => x.Url == url); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,13 @@ |
|||||
|
using Volo.Abp.Domain.Repositories.EntityFrameworkCore; |
||||
|
using Volo.Abp.EntityFrameworkCore; |
||||
|
using Volo.CmsKit.EntityFrameworkCore; |
||||
|
|
||||
|
namespace Volo.CmsKit.Tags |
||||
|
{ |
||||
|
public class EfCoreEntityTagRepository: EfCoreRepository<ICmsKitDbContext, EntityTag>, IEntityTagRepository |
||||
|
{ |
||||
|
public EfCoreEntityTagRepository(IDbContextProvider<ICmsKitDbContext> dbContextProvider) : base(dbContextProvider) |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,80 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using Microsoft.EntityFrameworkCore; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Domain.Repositories; |
||||
|
using Volo.Abp.Domain.Repositories.EntityFrameworkCore; |
||||
|
using Volo.Abp.EntityFrameworkCore; |
||||
|
using Volo.Abp.VirtualFileSystem; |
||||
|
using Volo.CmsKit.EntityFrameworkCore; |
||||
|
|
||||
|
namespace Volo.CmsKit.Tags |
||||
|
{ |
||||
|
public class EfCoreTagRepository : EfCoreRepository<ICmsKitDbContext, Tag, Guid>, ITagRepository |
||||
|
{ |
||||
|
public EfCoreTagRepository(IDbContextProvider<ICmsKitDbContext> dbContextProvider) : base(dbContextProvider) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public virtual Task<bool> AnyAsync( |
||||
|
[NotNull] string entityType, |
||||
|
[NotNull] string name, |
||||
|
Guid? tenantId = null, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
return DbSet.AnyAsync(x => |
||||
|
x.EntityType == entityType && |
||||
|
x.Name == name && |
||||
|
x.TenantId == tenantId, |
||||
|
cancellationToken); |
||||
|
} |
||||
|
|
||||
|
public virtual Task<Tag> GetAsync( |
||||
|
[NotNull] string entityType, |
||||
|
[NotNull] string name, |
||||
|
Guid? tenantId = null, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
return GetAsync(x => |
||||
|
x.EntityType == entityType && |
||||
|
x.Name == name && |
||||
|
x.TenantId == tenantId, |
||||
|
cancellationToken: cancellationToken); |
||||
|
} |
||||
|
|
||||
|
public virtual Task<Tag> FindAsync( |
||||
|
[NotNull] string entityType, |
||||
|
[NotNull] string name, |
||||
|
Guid? tenantId = null, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
return FindAsync(x => |
||||
|
x.EntityType == entityType && |
||||
|
x.Name == name && |
||||
|
x.TenantId == tenantId, |
||||
|
cancellationToken: cancellationToken); |
||||
|
} |
||||
|
|
||||
|
public virtual async Task<List<Tag>> GetAllRelatedTagsAsync( |
||||
|
[NotNull] string entityType, |
||||
|
[NotNull] string entityId, |
||||
|
Guid? tenantId = null, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
var entityTagIds = await DbContext.Set<EntityTag>() |
||||
|
.Where(q => q.EntityId == entityId && q.TenantId == tenantId) |
||||
|
.Select(q => q.TagId) |
||||
|
.ToListAsync(cancellationToken: GetCancellationToken(cancellationToken)); |
||||
|
|
||||
|
var query = DbSet |
||||
|
.Where(x => x.EntityType == entityType && |
||||
|
x.TenantId == tenantId && |
||||
|
entityTagIds.Contains(x.Id)); |
||||
|
|
||||
|
return await query.ToListAsync(cancellationToken: GetCancellationToken(cancellationToken)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,55 @@ |
|||||
|
using System; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Domain.Repositories.MongoDB; |
||||
|
using Volo.Abp.MongoDB; |
||||
|
using Volo.CmsKit.Contents; |
||||
|
|
||||
|
namespace Volo.CmsKit.MongoDB.Contents |
||||
|
{ |
||||
|
public class MongoContentRepository : MongoDbRepository<ICmsKitMongoDbContext, Content, Guid>, IContentRepository |
||||
|
{ |
||||
|
public MongoContentRepository(IMongoDbContextProvider<ICmsKitMongoDbContext> dbContextProvider) : base(dbContextProvider) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public Task<Content> GetAsync( |
||||
|
string entityType, |
||||
|
string entityId, |
||||
|
Guid? tenantId = null, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
return GetAsync(x => |
||||
|
!x.IsDeleted && |
||||
|
x.EntityType == entityType && |
||||
|
x.EntityId == entityId && |
||||
|
x.TenantId == tenantId, |
||||
|
cancellationToken: cancellationToken |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
public Task<Content> FindAsync( |
||||
|
string entityType, |
||||
|
string entityId, |
||||
|
Guid? tenantId = null, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
return FindAsync(x => |
||||
|
!x.IsDeleted && |
||||
|
x.EntityType == entityType && |
||||
|
x.EntityId == entityId && |
||||
|
x.TenantId == tenantId, |
||||
|
cancellationToken: cancellationToken |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
public Task DeleteAsync(string entityType, string entityId, Guid? tenantId = null, CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
return DeleteAsync(x => |
||||
|
x.EntityType == entityType && |
||||
|
x.EntityId == entityId && |
||||
|
x.TenantId == tenantId, |
||||
|
cancellationToken: cancellationToken); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,31 @@ |
|||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using MongoDB.Driver.Linq; |
||||
|
using Volo.Abp.Domain.Repositories.MongoDB; |
||||
|
using Volo.Abp.MongoDB; |
||||
|
using Volo.CmsKit.Pages; |
||||
|
|
||||
|
namespace Volo.CmsKit.MongoDB.Pages |
||||
|
{ |
||||
|
public class MongoPageRepository : MongoDbRepository<ICmsKitMongoDbContext, Page, Guid>, IPageRepository |
||||
|
{ |
||||
|
public MongoPageRepository(IMongoDbContextProvider<ICmsKitMongoDbContext> dbContextProvider) : base(dbContextProvider) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public Task<Page> GetByUrlAsync(string url) |
||||
|
{ |
||||
|
return GetAsync(x => x.Url == url); |
||||
|
} |
||||
|
|
||||
|
public Task<Page> FindByUrlAsync(string url) |
||||
|
{ |
||||
|
return FindAsync(x => x.Url == url); |
||||
|
} |
||||
|
|
||||
|
public Task<bool> DoesExistAsync(string url) |
||||
|
{ |
||||
|
return GetMongoQueryable().AnyAsync(x => x.Url == url); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,13 @@ |
|||||
|
using Volo.Abp.Domain.Repositories.MongoDB; |
||||
|
using Volo.Abp.MongoDB; |
||||
|
using Volo.CmsKit.Tags; |
||||
|
|
||||
|
namespace Volo.CmsKit.MongoDB.Tags |
||||
|
{ |
||||
|
public class MongoEntityTagRepository: MongoDbRepository<ICmsKitMongoDbContext, EntityTag>, IEntityTagRepository |
||||
|
{ |
||||
|
public MongoEntityTagRepository(IMongoDbContextProvider<ICmsKitMongoDbContext> dbContextProvider) : base(dbContextProvider) |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,83 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using MongoDB.Driver; |
||||
|
using MongoDB.Driver.Linq; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Domain.Repositories.MongoDB; |
||||
|
using Volo.Abp.MongoDB; |
||||
|
using Volo.CmsKit.Tags; |
||||
|
using Tag = Volo.CmsKit.Tags.Tag; |
||||
|
|
||||
|
namespace Volo.CmsKit.MongoDB.Tags |
||||
|
{ |
||||
|
public class MongoTagRepository : MongoDbRepository<ICmsKitMongoDbContext, Volo.CmsKit.Tags.Tag, Guid>, ITagRepository |
||||
|
{ |
||||
|
public MongoTagRepository(IMongoDbContextProvider<ICmsKitMongoDbContext> dbContextProvider) : base(dbContextProvider) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public Task<bool> AnyAsync( |
||||
|
[NotNull] string entityType, |
||||
|
[NotNull] string name, |
||||
|
Guid? tenantId = null, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
return GetMongoQueryable() |
||||
|
.AnyAsync(x => |
||||
|
x.EntityType == entityType && |
||||
|
x.Name == name && |
||||
|
x.TenantId == tenantId, |
||||
|
cancellationToken); |
||||
|
} |
||||
|
|
||||
|
public Task<Tag> GetAsync( |
||||
|
[NotNull] string entityType, |
||||
|
[NotNull] string name, |
||||
|
Guid? tenantId = null, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
return GetAsync(x => |
||||
|
x.EntityType == entityType && |
||||
|
x.Name == name && |
||||
|
x.TenantId == tenantId, |
||||
|
cancellationToken: cancellationToken); |
||||
|
} |
||||
|
|
||||
|
public Task<Tag> FindAsync( |
||||
|
[NotNull] string entityType, |
||||
|
[NotNull] string name, |
||||
|
Guid? tenantId = null, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
return FindAsync(x => |
||||
|
x.EntityType == entityType && |
||||
|
x.Name == name && |
||||
|
x.TenantId == tenantId, |
||||
|
cancellationToken: cancellationToken); |
||||
|
} |
||||
|
|
||||
|
public virtual async Task<List<Tag>> GetAllRelatedTagsAsync( |
||||
|
[NotNull] string entityType, |
||||
|
[NotNull] string entityId, |
||||
|
Guid? tenantId = null, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
var entityTagIds = await DbContext.EntityTags.AsQueryable() |
||||
|
.Where(q => q.EntityId == entityId && q.TenantId == tenantId) |
||||
|
.Select(q => q.TagId) |
||||
|
.ToListAsync(cancellationToken: GetCancellationToken(cancellationToken)); |
||||
|
|
||||
|
var query = await Collection.FindAsync(Builders<Tag>.Filter.And(new[] |
||||
|
{ |
||||
|
Builders<Tag>.Filter.Eq(x =>x.EntityType, entityType), |
||||
|
Builders<Tag>.Filter.Eq(x =>x.TenantId, tenantId), |
||||
|
Builders<Tag>.Filter.In(x => x.Id, entityTagIds), |
||||
|
})); |
||||
|
|
||||
|
var result = await query.ToListAsync(cancellationToken: GetCancellationToken(cancellationToken)); |
||||
|
return result; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,104 @@ |
|||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using Shouldly; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Volo.CmsKit.Tags |
||||
|
{ |
||||
|
public class TagManager_Tests : CmsKitDomainTestBase |
||||
|
{ |
||||
|
private readonly CmsKitTestData _cmsKitTestData; |
||||
|
private readonly TagManager _tagManager; |
||||
|
|
||||
|
private readonly ITagRepository _tagRepository; |
||||
|
|
||||
|
public TagManager_Tests() |
||||
|
{ |
||||
|
_cmsKitTestData = GetRequiredService<CmsKitTestData>(); |
||||
|
_tagManager = GetRequiredService<TagManager>(); |
||||
|
_tagRepository = GetRequiredService<ITagRepository>(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task ShouldAddWhenGettingAsync() |
||||
|
{ |
||||
|
var newTagEntityType = "testEntity"; |
||||
|
var newTagName = "test_tag_2123"; |
||||
|
|
||||
|
var doesExist = await _tagRepository.AnyAsync(newTagEntityType, newTagName); |
||||
|
|
||||
|
doesExist.ShouldBeFalse(); |
||||
|
|
||||
|
var newTag = await _tagManager.GetOrAddAsync(newTagEntityType, newTagName); |
||||
|
|
||||
|
newTag.ShouldNotBeNull(); |
||||
|
|
||||
|
var doesExistAgain = await _tagRepository.AnyAsync(newTagEntityType, newTagName); |
||||
|
|
||||
|
doesExistAgain.ShouldBeTrue(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task ShouldNotAddWhenGettingAsync() |
||||
|
{ |
||||
|
var tagName = _cmsKitTestData.Content_1_Tags[0]; |
||||
|
|
||||
|
var tag = await _tagRepository.GetAsync(_cmsKitTestData.Content_1_EntityType, tagName); |
||||
|
|
||||
|
var newTag = await _tagManager.GetOrAddAsync(_cmsKitTestData.Content_1_EntityType, tag.Name); |
||||
|
|
||||
|
newTag.ShouldNotBeNull(); |
||||
|
|
||||
|
newTag.Id.ShouldBe(tag.Id); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task ShouldInsert() |
||||
|
{ |
||||
|
var tag = await _tagManager.InsertAsync(Guid.NewGuid(), "test", "test"); |
||||
|
|
||||
|
tag.ShouldNotBeNull(); |
||||
|
|
||||
|
var doesExist = await _tagRepository.AnyAsync("test", "test"); |
||||
|
|
||||
|
doesExist.ShouldBeTrue(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task ShouldNotInsert() |
||||
|
{ |
||||
|
var type = _cmsKitTestData.Content_1_EntityType; |
||||
|
var name = _cmsKitTestData.Content_1_Tags[0]; |
||||
|
|
||||
|
Should.Throw<Exception>(async () => await _tagManager.InsertAsync(Guid.NewGuid(), type, name)); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task ShouldUpdate() |
||||
|
{ |
||||
|
var type = _cmsKitTestData.Content_1_EntityType; |
||||
|
var name = _cmsKitTestData.Content_1_Tags[0]; |
||||
|
var newName = name + "-updated"; |
||||
|
|
||||
|
var tag = await _tagRepository.GetAsync(type, name); |
||||
|
|
||||
|
await _tagManager.UpdateAsync(tag.Id, newName); |
||||
|
|
||||
|
var updatedTag = await _tagRepository.GetAsync(type, newName); |
||||
|
|
||||
|
updatedTag.Id.ShouldBe(tag.Id); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task ShouldNotUpdate() |
||||
|
{ |
||||
|
var type = _cmsKitTestData.Content_1_EntityType; |
||||
|
var name = _cmsKitTestData.Content_1_Tags[0]; |
||||
|
var newName = _cmsKitTestData.Content_1_Tags[1]; |
||||
|
|
||||
|
var tag = await _tagRepository.GetAsync(type, name); |
||||
|
|
||||
|
Should.Throw<Exception>(async () => await _tagManager.UpdateAsync(tag.Id, newName)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
using Volo.CmsKit.Contents; |
||||
|
|
||||
|
namespace Volo.CmsKit.EntityFrameworkCore.Contents |
||||
|
{ |
||||
|
public class ContentRepository_Test : ContentRepository_Tests<CmsKitEntityFrameworkCoreTestModule> |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
using Volo.CmsKit.Tags; |
||||
|
|
||||
|
namespace Volo.CmsKit.EntityFrameworkCore.Tags |
||||
|
{ |
||||
|
public class TagRepository_Test : TagRepository_Test<CmsKitEntityFrameworkCoreTestModule> |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
using Volo.CmsKit.Contents; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Volo.CmsKit.MongoDB.Contents |
||||
|
{ |
||||
|
[Collection(MongoTestCollection.Name)] |
||||
|
public class ContentRepository_Test : ContentRepository_Tests<CmsKitMongoDbTestModule> |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
using Volo.CmsKit.Tags; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Volo.CmsKit.MongoDB.Tags |
||||
|
{ |
||||
|
[Collection(MongoTestCollection.Name)] |
||||
|
public class TagRepository_Test : TagRepository_Test<CmsKitMongoDbTestModule> |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,63 @@ |
|||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using Shouldly; |
||||
|
using Volo.Abp.Domain.Entities; |
||||
|
using Volo.Abp.Modularity; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Volo.CmsKit.Contents |
||||
|
{ |
||||
|
public abstract class ContentRepository_Tests<TStartupModule> : CmsKitTestBase<TStartupModule> |
||||
|
where TStartupModule : IAbpModule |
||||
|
{ |
||||
|
private readonly CmsKitTestData _cmsKitTestData; |
||||
|
private readonly IContentRepository _contentRepository; |
||||
|
|
||||
|
protected ContentRepository_Tests() |
||||
|
{ |
||||
|
_cmsKitTestData = GetRequiredService<CmsKitTestData>(); |
||||
|
_contentRepository = GetRequiredService<IContentRepository>(); |
||||
|
} |
||||
|
|
||||
|
[Theory] |
||||
|
[InlineData("Lyrics", "1", "First things first")] |
||||
|
[InlineData("LyricsAlso", "2", "Second thing second")] |
||||
|
public async Task ShouldGetAsync(string entityType, string entityId, string contentStartsWith = null) |
||||
|
{ |
||||
|
var content = await _contentRepository.GetAsync(entityType, entityId); |
||||
|
|
||||
|
content.ShouldNotBeNull(); |
||||
|
|
||||
|
if (contentStartsWith != null) |
||||
|
{ |
||||
|
content.Value.ShouldStartWith(contentStartsWith); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task ShouldNotGetAsync() |
||||
|
{ |
||||
|
Should.Throw<EntityNotFoundException>( |
||||
|
async () |
||||
|
=> |
||||
|
await _contentRepository.GetAsync("not_exist_entity", Guid.NewGuid().ToString())); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task ShouldFindAsync() |
||||
|
{ |
||||
|
var content = |
||||
|
await _contentRepository.FindAsync(_cmsKitTestData.Content_1_EntityType, _cmsKitTestData.Content_1_Id); |
||||
|
|
||||
|
content.ShouldNotBeNull(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task ShouldNotFindAsync() |
||||
|
{ |
||||
|
var content = await _contentRepository.FindAsync("not_exist_entity", Guid.NewGuid().ToString()); |
||||
|
|
||||
|
content.ShouldBeNull(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,116 @@ |
|||||
|
using System; |
||||
|
using System.Linq; |
||||
|
using System.Threading.Tasks; |
||||
|
using Shouldly; |
||||
|
using Volo.Abp.Domain.Entities; |
||||
|
using Volo.Abp.Modularity; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Volo.CmsKit.Tags |
||||
|
{ |
||||
|
public abstract class TagRepository_Test<TStartupModule> : CmsKitTestBase<TStartupModule> |
||||
|
where TStartupModule : IAbpModule |
||||
|
{ |
||||
|
private readonly CmsKitTestData _cmsKitTestData; |
||||
|
private readonly ITagRepository _tagRepository; |
||||
|
|
||||
|
protected TagRepository_Test() |
||||
|
{ |
||||
|
_cmsKitTestData = GetRequiredService<CmsKitTestData>(); |
||||
|
_tagRepository = GetRequiredService<ITagRepository>(); |
||||
|
} |
||||
|
|
||||
|
[Theory] |
||||
|
[InlineData("Lyrics", "Imagine Dragons")] |
||||
|
[InlineData("Lyrics", "Music")] |
||||
|
[InlineData("LyricsAlso", "Imagine Dragons")] |
||||
|
[InlineData("LyricsAlso", "Music")] |
||||
|
[InlineData("LyricsAlso", "Most Loved Part")] |
||||
|
public async Task ShouldGetAsync(string entityType, string name) |
||||
|
{ |
||||
|
var tag = await _tagRepository.GetAsync(entityType, name); |
||||
|
|
||||
|
tag.ShouldNotBeNull(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task ShouldNotGetAsync() |
||||
|
{ |
||||
|
Should.Throw<EntityNotFoundException>( |
||||
|
async () => await _tagRepository.GetAsync("not_exist_entity", Guid.NewGuid().ToString()) |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
[Theory] |
||||
|
[InlineData("Lyrics", "Imagine Dragons")] |
||||
|
[InlineData("Lyrics", "Music")] |
||||
|
[InlineData("LyricsAlso", "Imagine Dragons")] |
||||
|
[InlineData("LyricsAlso", "Music")] |
||||
|
[InlineData("LyricsAlso", "Most Loved Part")] |
||||
|
public async Task ShouldExistAsync(string entityType, string name) |
||||
|
{ |
||||
|
var tag = await _tagRepository.AnyAsync(entityType, name); |
||||
|
|
||||
|
tag.ShouldBeTrue(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task ShouldNotExistAsync() |
||||
|
{ |
||||
|
var tag = await _tagRepository.AnyAsync("not_exist_entity", Guid.NewGuid().ToString()); |
||||
|
|
||||
|
tag.ShouldBeFalse(); |
||||
|
} |
||||
|
|
||||
|
[Theory] |
||||
|
[InlineData("Lyrics", "Imagine Dragons")] |
||||
|
[InlineData("Lyrics", "Music")] |
||||
|
[InlineData("LyricsAlso", "Imagine Dragons")] |
||||
|
[InlineData("LyricsAlso", "Music")] |
||||
|
[InlineData("LyricsAlso", "Most Loved Part")] |
||||
|
public async Task ShouldFindAsync(string entityType, string name) |
||||
|
{ |
||||
|
var tag = await _tagRepository.FindAsync(entityType, name); |
||||
|
|
||||
|
tag.ShouldNotBeNull(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task ShouldNotFindAsync() |
||||
|
{ |
||||
|
var tag = await _tagRepository.FindAsync("not_exist_entity", Guid.NewGuid().ToString()); |
||||
|
|
||||
|
tag.ShouldBeNull(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_Get_Related_Tags() |
||||
|
{ |
||||
|
var content_1_tags = await _tagRepository.GetAllRelatedTagsAsync(_cmsKitTestData.Content_1_EntityType, _cmsKitTestData.EntityId1); |
||||
|
|
||||
|
content_1_tags.Count.ShouldBe(_cmsKitTestData.Content_1_Tags.Length); |
||||
|
|
||||
|
foreach (var tag in content_1_tags) |
||||
|
{ |
||||
|
_cmsKitTestData.Content_1_Tags.Contains(tag.Name).ShouldBeTrue(); |
||||
|
} |
||||
|
|
||||
|
var content_2_tags = await _tagRepository.GetAllRelatedTagsAsync(_cmsKitTestData.Content_2_EntityType, _cmsKitTestData.EntityId2); |
||||
|
|
||||
|
content_2_tags.Count.ShouldBe(_cmsKitTestData.Content_2_Tags.Length); |
||||
|
|
||||
|
foreach (var tag in content_2_tags) |
||||
|
{ |
||||
|
_cmsKitTestData.Content_2_Tags.Contains(tag.Name).ShouldBeTrue(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_Not_Get_Related_Tags() |
||||
|
{ |
||||
|
var tags = await _tagRepository.GetAllRelatedTagsAsync("not_exist_entity", Guid.NewGuid().ToString()); |
||||
|
|
||||
|
tags.Count.ShouldBe(0); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue