Browse Source

Blogging module basic comment & tag

pull/7950/head
Yunus Emre Kalkan 8 years ago
parent
commit
05b9359ce9
  1. 574
      modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20180816103331_Added_Tags_And_Comments.Designer.cs
  2. 107
      modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20180816103331_Added_Tags_And_Comments.cs
  3. 582
      modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20180817055949_ReplyComment_Nullable.Designer.cs
  4. 34
      modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20180817055949_ReplyComment_Nullable.cs
  5. 580
      modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20180817060722_ReplyComment_Not_Required.Designer.cs
  6. 51
      modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20180817060722_ReplyComment_Not_Required.cs
  7. 137
      modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/BloggingTestAppDbContextModelSnapshot.cs
  8. 16601
      modules/blogging/app/Volo.BloggingTestApp/Logs/logs.txt
  9. 15
      modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Comments/Dtos/CommentDto.cs
  10. 14
      modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Comments/Dtos/CommentWithRepliesDto.cs
  11. 13
      modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Comments/Dtos/CreateCommentDto.cs
  12. 9
      modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Comments/Dtos/GetCommentListOfPostAsync.cs
  13. 7
      modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Comments/Dtos/UpdateCommentDto.cs
  14. 22
      modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Comments/ICommentAppService.cs
  15. 2
      modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Posts/CreatePostDto.cs
  16. 18
      modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Posts/GetPostForEditOutput.cs
  17. 2
      modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Posts/IPostAppService.cs
  18. 3
      modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Posts/PostWithDetailsDto.cs
  19. 2
      modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Posts/UpdatePostDto.cs
  20. 9
      modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Tagging/Dtos/CreateTagDto.cs
  21. 10
      modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Tagging/Dtos/GetTagListInput.cs
  22. 14
      modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Tagging/Dtos/TagDto.cs
  23. 9
      modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Tagging/Dtos/UpdateTagDto.cs
  24. 22
      modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Tagging/ITagAppService.cs
  25. 7
      modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/BloggingApplicationAutoMapperProfile.cs
  26. 76
      modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Comments/CommentAppService.cs
  27. 77
      modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Posts/PostAppService.cs
  28. 63
      modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Tagging/TagAppService.cs
  29. 11
      modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Comments/CommentConsts.cs
  30. 13
      modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Tagging/TagConsts.cs
  31. 38
      modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Comments/Comment.cs
  32. 15
      modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Comments/ICommentRepository.cs
  33. 12
      modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/IPostTagRepository.cs
  34. 5
      modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/Post.cs
  35. 29
      modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/PostTag.cs
  36. 14
      modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Tagging/ITagRepository.cs
  37. 39
      modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Tagging/Tag.cs
  38. 28
      modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Comments/EfCoreCommentRepository.cs
  39. 8
      modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/EntityFrameworkCore/BloggingDbContext.cs
  40. 41
      modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/EntityFrameworkCore/BloggingDbContextModelBuilderExtensions.cs
  41. 8
      modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/EntityFrameworkCore/IBloggingDbContext.cs
  42. 16
      modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Posts/EfCorePostTagRepository.cs
  43. 30
      modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Tagging/EfCoreTagRepository.cs
  44. 3
      modules/blogging/src/Volo.Blogging.Web/AbpBloggingWebAutoMapperProfile.cs
  45. 53
      modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Detail.cshtml
  46. 45
      modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Detail.cshtml.cs
  47. 1
      modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Edit.cshtml
  48. 11
      modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Edit.cshtml.cs
  49. 4
      modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/New.cshtml
  50. 2
      modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/New.cshtml.cs
  51. 13
      modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/detail.js
  52. 2
      modules/blogging/src/Volo.Blogging.Web/Volo.Blogging.Web.csproj
  53. 38
      modules/blogging/test/Volo.Blogging.Application.Tests/Volo/Blogging/CommentAppService_Tests.cs

574
modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20180816103331_Added_Tags_And_Comments.Designer.cs

@ -0,0 +1,574 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Volo.BloggingTestApp.EntityFrameworkCore;
namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
{
[DbContext(typeof(BloggingTestAppDbContext))]
[Migration("20180816103331_Added_Tags_And_Comments")]
partial class Added_Tags_And_Comments
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "2.1.1-rtm-30846")
.HasAnnotation("Relational:MaxIdentifierLength", 128)
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("ConcurrencyStamp");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(256);
b.Property<string>("NormalizedName")
.IsRequired()
.HasMaxLength(256);
b.Property<Guid?>("TenantId");
b.HasKey("Id");
b.HasIndex("NormalizedName");
b.ToTable("AbpRoles");
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("ClaimType")
.IsRequired()
.HasMaxLength(256);
b.Property<string>("ClaimValue")
.HasMaxLength(1024);
b.Property<Guid>("RoleId");
b.Property<Guid?>("TenantId");
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("AbpRoleClaims");
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd();
b.Property<int>("AccessFailedCount")
.ValueGeneratedOnAdd()
.HasColumnName("AccessFailedCount")
.HasDefaultValue(0);
b.Property<string>("ConcurrencyStamp")
.IsRequired()
.HasColumnName("ConcurrencyStamp")
.HasMaxLength(256);
b.Property<string>("Email")
.HasColumnName("Email")
.HasMaxLength(256);
b.Property<bool>("EmailConfirmed")
.ValueGeneratedOnAdd()
.HasColumnName("EmailConfirmed")
.HasDefaultValue(false);
b.Property<string>("ExtraProperties")
.HasColumnName("ExtraProperties");
b.Property<bool>("LockoutEnabled")
.ValueGeneratedOnAdd()
.HasColumnName("LockoutEnabled")
.HasDefaultValue(false);
b.Property<DateTimeOffset?>("LockoutEnd");
b.Property<string>("NormalizedEmail")
.HasColumnName("NormalizedEmail")
.HasMaxLength(256);
b.Property<string>("NormalizedUserName")
.IsRequired()
.HasColumnName("NormalizedUserName")
.HasMaxLength(256);
b.Property<string>("PasswordHash")
.HasColumnName("PasswordHash")
.HasMaxLength(256);
b.Property<string>("PhoneNumber")
.HasColumnName("PhoneNumber")
.HasMaxLength(16);
b.Property<bool>("PhoneNumberConfirmed")
.ValueGeneratedOnAdd()
.HasColumnName("PhoneNumberConfirmed")
.HasDefaultValue(false);
b.Property<string>("SecurityStamp")
.IsRequired()
.HasColumnName("SecurityStamp")
.HasMaxLength(256);
b.Property<Guid?>("TenantId")
.HasColumnName("TenantId");
b.Property<bool>("TwoFactorEnabled")
.ValueGeneratedOnAdd()
.HasColumnName("TwoFactorEnabled")
.HasDefaultValue(false);
b.Property<string>("UserName")
.IsRequired()
.HasColumnName("UserName")
.HasMaxLength(256);
b.HasKey("Id");
b.HasIndex("Email");
b.HasIndex("NormalizedEmail");
b.HasIndex("NormalizedUserName");
b.HasIndex("UserName");
b.ToTable("AbpUsers");
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("ClaimType")
.IsRequired()
.HasMaxLength(256);
b.Property<string>("ClaimValue")
.HasMaxLength(1024);
b.Property<Guid?>("TenantId");
b.Property<Guid>("UserId");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AbpUserClaims");
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b =>
{
b.Property<Guid>("UserId");
b.Property<string>("LoginProvider")
.HasMaxLength(64);
b.Property<string>("ProviderDisplayName")
.HasMaxLength(128);
b.Property<string>("ProviderKey")
.IsRequired()
.HasMaxLength(196);
b.Property<Guid?>("TenantId");
b.HasKey("UserId", "LoginProvider");
b.HasIndex("LoginProvider", "ProviderKey");
b.ToTable("AbpUserLogins");
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b =>
{
b.Property<Guid>("UserId");
b.Property<Guid>("RoleId");
b.Property<Guid?>("TenantId");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId", "UserId");
b.ToTable("AbpUserRoles");
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b =>
{
b.Property<Guid>("UserId");
b.Property<string>("LoginProvider")
.HasMaxLength(128);
b.Property<string>("Name");
b.Property<Guid?>("TenantId");
b.Property<string>("Value");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AbpUserTokens");
});
modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(128);
b.Property<string>("ProviderKey")
.IsRequired()
.HasMaxLength(64);
b.Property<string>("ProviderName")
.IsRequired()
.HasMaxLength(64);
b.Property<Guid?>("TenantId");
b.HasKey("Id");
b.HasIndex("Name", "ProviderName", "ProviderKey");
b.ToTable("AbpPermissionGrants");
});
modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(128);
b.Property<string>("ProviderKey")
.HasMaxLength(64);
b.Property<string>("ProviderName")
.HasMaxLength(64);
b.Property<string>("Value")
.IsRequired()
.HasMaxLength(2048);
b.HasKey("Id");
b.HasIndex("Name", "ProviderName", "ProviderKey");
b.ToTable("AbpSettings");
});
modelBuilder.Entity("Volo.Blogging.Blogs.Blog", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd();
b.Property<DateTime>("CreationTime")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnName("CreatorId");
b.Property<Guid?>("DeleterId")
.HasColumnName("DeleterId");
b.Property<DateTime?>("DeletionTime")
.HasColumnName("DeletionTime");
b.Property<string>("Description")
.HasColumnName("Description")
.HasMaxLength(1024);
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnName("IsDeleted")
.HasDefaultValue(false);
b.Property<DateTime?>("LastModificationTime")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnName("LastModifierId");
b.Property<string>("Name")
.IsRequired()
.HasColumnName("Name")
.HasMaxLength(256);
b.Property<string>("ShortName")
.IsRequired()
.HasColumnName("ShortName")
.HasMaxLength(32);
b.HasKey("Id");
b.ToTable("BlgBlogs");
});
modelBuilder.Entity("Volo.Blogging.Comments.Comment", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd();
b.Property<DateTime>("CreationTime")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnName("CreatorId");
b.Property<Guid?>("DeleterId")
.HasColumnName("DeleterId");
b.Property<DateTime?>("DeletionTime")
.HasColumnName("DeletionTime");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnName("IsDeleted")
.HasDefaultValue(false);
b.Property<DateTime?>("LastModificationTime")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnName("LastModifierId");
b.Property<Guid>("PostId")
.HasColumnName("PostId");
b.Property<Guid>("RepliedCommentId")
.HasColumnName("RepliedCommentId");
b.Property<string>("Text")
.IsRequired()
.HasColumnName("Text")
.HasMaxLength(1024);
b.HasKey("Id");
b.HasIndex("RepliedCommentId");
b.ToTable("BlgComments");
});
modelBuilder.Entity("Volo.Blogging.Posts.Post", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd();
b.Property<Guid>("BlogId")
.HasColumnName("BlogId");
b.Property<string>("Content")
.HasColumnName("Content")
.HasMaxLength(1048576);
b.Property<DateTime>("CreationTime")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnName("CreatorId");
b.Property<Guid?>("DeleterId")
.HasColumnName("DeleterId");
b.Property<DateTime?>("DeletionTime")
.HasColumnName("DeletionTime");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnName("IsDeleted")
.HasDefaultValue(false);
b.Property<DateTime?>("LastModificationTime")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnName("LastModifierId");
b.Property<string>("Title")
.IsRequired()
.HasColumnName("Title")
.HasMaxLength(512);
b.Property<string>("Url")
.IsRequired()
.HasColumnName("Url")
.HasMaxLength(64);
b.HasKey("Id");
b.HasIndex("BlogId");
b.ToTable("BlgPosts");
});
modelBuilder.Entity("Volo.Blogging.Posts.PostTag", b =>
{
b.Property<Guid>("PostId")
.HasColumnName("PostId");
b.Property<Guid>("TagId")
.HasColumnName("TagId");
b.Property<DateTime>("CreationTime");
b.Property<Guid?>("CreatorId");
b.HasKey("PostId", "TagId");
b.HasIndex("TagId");
b.ToTable("BlgPostTags");
});
modelBuilder.Entity("Volo.Blogging.Tagging.Tag", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd();
b.Property<DateTime>("CreationTime")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnName("CreatorId");
b.Property<Guid?>("DeleterId")
.HasColumnName("DeleterId");
b.Property<DateTime?>("DeletionTime")
.HasColumnName("DeletionTime");
b.Property<string>("Description")
.HasColumnName("Description")
.HasMaxLength(512);
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnName("IsDeleted")
.HasDefaultValue(false);
b.Property<DateTime?>("LastModificationTime")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnName("LastModifierId");
b.Property<string>("Name")
.IsRequired()
.HasColumnName("Name")
.HasMaxLength(64);
b.Property<int>("UsageCount")
.HasColumnName("UsageCount");
b.HasKey("Id");
b.ToTable("BlgTags");
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b =>
{
b.HasOne("Volo.Abp.Identity.IdentityRole")
.WithMany("Claims")
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b =>
{
b.HasOne("Volo.Abp.Identity.IdentityUser")
.WithMany("Claims")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b =>
{
b.HasOne("Volo.Abp.Identity.IdentityUser")
.WithMany("Logins")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b =>
{
b.HasOne("Volo.Abp.Identity.IdentityRole")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("Volo.Abp.Identity.IdentityUser")
.WithMany("Roles")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b =>
{
b.HasOne("Volo.Abp.Identity.IdentityUser")
.WithMany("Tokens")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Volo.Blogging.Comments.Comment", b =>
{
b.HasOne("Volo.Blogging.Comments.Comment")
.WithMany()
.HasForeignKey("RepliedCommentId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Volo.Blogging.Posts.Post", b =>
{
b.HasOne("Volo.Blogging.Blogs.Blog")
.WithMany()
.HasForeignKey("BlogId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Volo.Blogging.Posts.PostTag", b =>
{
b.HasOne("Volo.Blogging.Posts.Post")
.WithMany("Tags")
.HasForeignKey("PostId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("Volo.Blogging.Tagging.Tag")
.WithMany()
.HasForeignKey("TagId")
.OnDelete(DeleteBehavior.Cascade);
});
#pragma warning restore 612, 618
}
}
}

107
modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20180816103331_Added_Tags_And_Comments.cs

@ -0,0 +1,107 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
{
public partial class Added_Tags_And_Comments : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "BlgComments",
columns: table => new
{
Id = table.Column<Guid>(nullable: false),
CreationTime = table.Column<DateTime>(nullable: false),
CreatorId = table.Column<Guid>(nullable: true),
LastModificationTime = table.Column<DateTime>(nullable: true),
LastModifierId = table.Column<Guid>(nullable: true),
IsDeleted = table.Column<bool>(nullable: false, defaultValue: false),
DeleterId = table.Column<Guid>(nullable: true),
DeletionTime = table.Column<DateTime>(nullable: true),
PostId = table.Column<Guid>(nullable: false),
RepliedCommentId = table.Column<Guid>(nullable: false),
Text = table.Column<string>(maxLength: 1024, nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_BlgComments", x => x.Id);
table.ForeignKey(
name: "FK_BlgComments_BlgComments_RepliedCommentId",
column: x => x.RepliedCommentId,
principalTable: "BlgComments",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateTable(
name: "BlgTags",
columns: table => new
{
Id = table.Column<Guid>(nullable: false),
CreationTime = table.Column<DateTime>(nullable: false),
CreatorId = table.Column<Guid>(nullable: true),
LastModificationTime = table.Column<DateTime>(nullable: true),
LastModifierId = table.Column<Guid>(nullable: true),
IsDeleted = table.Column<bool>(nullable: false, defaultValue: false),
DeleterId = table.Column<Guid>(nullable: true),
DeletionTime = table.Column<DateTime>(nullable: true),
Name = table.Column<string>(maxLength: 64, nullable: false),
Description = table.Column<string>(maxLength: 512, nullable: true),
UsageCount = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_BlgTags", x => x.Id);
});
migrationBuilder.CreateTable(
name: "BlgPostTags",
columns: table => new
{
CreationTime = table.Column<DateTime>(nullable: false),
CreatorId = table.Column<Guid>(nullable: true),
PostId = table.Column<Guid>(nullable: false),
TagId = table.Column<Guid>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_BlgPostTags", x => new { x.PostId, x.TagId });
table.ForeignKey(
name: "FK_BlgPostTags_BlgPosts_PostId",
column: x => x.PostId,
principalTable: "BlgPosts",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_BlgPostTags_BlgTags_TagId",
column: x => x.TagId,
principalTable: "BlgTags",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_BlgComments_RepliedCommentId",
table: "BlgComments",
column: "RepliedCommentId");
migrationBuilder.CreateIndex(
name: "IX_BlgPostTags_TagId",
table: "BlgPostTags",
column: "TagId");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "BlgComments");
migrationBuilder.DropTable(
name: "BlgPostTags");
migrationBuilder.DropTable(
name: "BlgTags");
}
}
}

582
modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20180817055949_ReplyComment_Nullable.Designer.cs

@ -0,0 +1,582 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Volo.BloggingTestApp.EntityFrameworkCore;
namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
{
[DbContext(typeof(BloggingTestAppDbContext))]
[Migration("20180817055949_ReplyComment_Nullable")]
partial class ReplyComment_Nullable
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "2.1.1-rtm-30846")
.HasAnnotation("Relational:MaxIdentifierLength", 128)
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("ConcurrencyStamp");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(256);
b.Property<string>("NormalizedName")
.IsRequired()
.HasMaxLength(256);
b.Property<Guid?>("TenantId");
b.HasKey("Id");
b.HasIndex("NormalizedName");
b.ToTable("AbpRoles");
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("ClaimType")
.IsRequired()
.HasMaxLength(256);
b.Property<string>("ClaimValue")
.HasMaxLength(1024);
b.Property<Guid>("RoleId");
b.Property<Guid?>("TenantId");
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("AbpRoleClaims");
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd();
b.Property<int>("AccessFailedCount")
.ValueGeneratedOnAdd()
.HasColumnName("AccessFailedCount")
.HasDefaultValue(0);
b.Property<string>("ConcurrencyStamp")
.IsRequired()
.HasColumnName("ConcurrencyStamp")
.HasMaxLength(256);
b.Property<string>("Email")
.HasColumnName("Email")
.HasMaxLength(256);
b.Property<bool>("EmailConfirmed")
.ValueGeneratedOnAdd()
.HasColumnName("EmailConfirmed")
.HasDefaultValue(false);
b.Property<string>("ExtraProperties")
.HasColumnName("ExtraProperties");
b.Property<bool>("LockoutEnabled")
.ValueGeneratedOnAdd()
.HasColumnName("LockoutEnabled")
.HasDefaultValue(false);
b.Property<DateTimeOffset?>("LockoutEnd");
b.Property<string>("NormalizedEmail")
.HasColumnName("NormalizedEmail")
.HasMaxLength(256);
b.Property<string>("NormalizedUserName")
.IsRequired()
.HasColumnName("NormalizedUserName")
.HasMaxLength(256);
b.Property<string>("PasswordHash")
.HasColumnName("PasswordHash")
.HasMaxLength(256);
b.Property<string>("PhoneNumber")
.HasColumnName("PhoneNumber")
.HasMaxLength(16);
b.Property<bool>("PhoneNumberConfirmed")
.ValueGeneratedOnAdd()
.HasColumnName("PhoneNumberConfirmed")
.HasDefaultValue(false);
b.Property<string>("SecurityStamp")
.IsRequired()
.HasColumnName("SecurityStamp")
.HasMaxLength(256);
b.Property<Guid?>("TenantId")
.HasColumnName("TenantId");
b.Property<bool>("TwoFactorEnabled")
.ValueGeneratedOnAdd()
.HasColumnName("TwoFactorEnabled")
.HasDefaultValue(false);
b.Property<string>("UserName")
.IsRequired()
.HasColumnName("UserName")
.HasMaxLength(256);
b.HasKey("Id");
b.HasIndex("Email");
b.HasIndex("NormalizedEmail");
b.HasIndex("NormalizedUserName");
b.HasIndex("UserName");
b.ToTable("AbpUsers");
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("ClaimType")
.IsRequired()
.HasMaxLength(256);
b.Property<string>("ClaimValue")
.HasMaxLength(1024);
b.Property<Guid?>("TenantId");
b.Property<Guid>("UserId");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AbpUserClaims");
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b =>
{
b.Property<Guid>("UserId");
b.Property<string>("LoginProvider")
.HasMaxLength(64);
b.Property<string>("ProviderDisplayName")
.HasMaxLength(128);
b.Property<string>("ProviderKey")
.IsRequired()
.HasMaxLength(196);
b.Property<Guid?>("TenantId");
b.HasKey("UserId", "LoginProvider");
b.HasIndex("LoginProvider", "ProviderKey");
b.ToTable("AbpUserLogins");
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b =>
{
b.Property<Guid>("UserId");
b.Property<Guid>("RoleId");
b.Property<Guid?>("TenantId");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId", "UserId");
b.ToTable("AbpUserRoles");
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b =>
{
b.Property<Guid>("UserId");
b.Property<string>("LoginProvider")
.HasMaxLength(128);
b.Property<string>("Name");
b.Property<Guid?>("TenantId");
b.Property<string>("Value");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AbpUserTokens");
});
modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(128);
b.Property<string>("ProviderKey")
.IsRequired()
.HasMaxLength(64);
b.Property<string>("ProviderName")
.IsRequired()
.HasMaxLength(64);
b.Property<Guid?>("TenantId");
b.HasKey("Id");
b.HasIndex("Name", "ProviderName", "ProviderKey");
b.ToTable("AbpPermissionGrants");
});
modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(128);
b.Property<string>("ProviderKey")
.HasMaxLength(64);
b.Property<string>("ProviderName")
.HasMaxLength(64);
b.Property<string>("Value")
.IsRequired()
.HasMaxLength(2048);
b.HasKey("Id");
b.HasIndex("Name", "ProviderName", "ProviderKey");
b.ToTable("AbpSettings");
});
modelBuilder.Entity("Volo.Blogging.Blogs.Blog", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd();
b.Property<DateTime>("CreationTime")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnName("CreatorId");
b.Property<Guid?>("DeleterId")
.HasColumnName("DeleterId");
b.Property<DateTime?>("DeletionTime")
.HasColumnName("DeletionTime");
b.Property<string>("Description")
.HasColumnName("Description")
.HasMaxLength(1024);
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnName("IsDeleted")
.HasDefaultValue(false);
b.Property<DateTime?>("LastModificationTime")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnName("LastModifierId");
b.Property<string>("Name")
.IsRequired()
.HasColumnName("Name")
.HasMaxLength(256);
b.Property<string>("ShortName")
.IsRequired()
.HasColumnName("ShortName")
.HasMaxLength(32);
b.HasKey("Id");
b.ToTable("BlgBlogs");
});
modelBuilder.Entity("Volo.Blogging.Comments.Comment", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd();
b.Property<DateTime>("CreationTime")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnName("CreatorId");
b.Property<Guid?>("DeleterId")
.HasColumnName("DeleterId");
b.Property<DateTime?>("DeletionTime")
.HasColumnName("DeletionTime");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnName("IsDeleted")
.HasDefaultValue(false);
b.Property<DateTime?>("LastModificationTime")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnName("LastModifierId");
b.Property<Guid>("PostId")
.HasColumnName("PostId");
b.Property<Guid?>("RepliedCommentId")
.IsRequired()
.HasColumnName("RepliedCommentId");
b.Property<string>("Text")
.IsRequired()
.HasColumnName("Text")
.HasMaxLength(1024);
b.HasKey("Id");
b.HasIndex("PostId");
b.HasIndex("RepliedCommentId");
b.ToTable("BlgComments");
});
modelBuilder.Entity("Volo.Blogging.Posts.Post", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd();
b.Property<Guid>("BlogId")
.HasColumnName("BlogId");
b.Property<string>("Content")
.HasColumnName("Content")
.HasMaxLength(1048576);
b.Property<DateTime>("CreationTime")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnName("CreatorId");
b.Property<Guid?>("DeleterId")
.HasColumnName("DeleterId");
b.Property<DateTime?>("DeletionTime")
.HasColumnName("DeletionTime");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnName("IsDeleted")
.HasDefaultValue(false);
b.Property<DateTime?>("LastModificationTime")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnName("LastModifierId");
b.Property<string>("Title")
.IsRequired()
.HasColumnName("Title")
.HasMaxLength(512);
b.Property<string>("Url")
.IsRequired()
.HasColumnName("Url")
.HasMaxLength(64);
b.HasKey("Id");
b.HasIndex("BlogId");
b.ToTable("BlgPosts");
});
modelBuilder.Entity("Volo.Blogging.Posts.PostTag", b =>
{
b.Property<Guid>("PostId")
.HasColumnName("PostId");
b.Property<Guid>("TagId")
.HasColumnName("TagId");
b.Property<DateTime>("CreationTime");
b.Property<Guid?>("CreatorId");
b.HasKey("PostId", "TagId");
b.HasIndex("TagId");
b.ToTable("BlgPostTags");
});
modelBuilder.Entity("Volo.Blogging.Tagging.Tag", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd();
b.Property<DateTime>("CreationTime")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnName("CreatorId");
b.Property<Guid?>("DeleterId")
.HasColumnName("DeleterId");
b.Property<DateTime?>("DeletionTime")
.HasColumnName("DeletionTime");
b.Property<string>("Description")
.HasColumnName("Description")
.HasMaxLength(512);
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnName("IsDeleted")
.HasDefaultValue(false);
b.Property<DateTime?>("LastModificationTime")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnName("LastModifierId");
b.Property<string>("Name")
.IsRequired()
.HasColumnName("Name")
.HasMaxLength(64);
b.Property<int>("UsageCount")
.HasColumnName("UsageCount");
b.HasKey("Id");
b.ToTable("BlgTags");
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b =>
{
b.HasOne("Volo.Abp.Identity.IdentityRole")
.WithMany("Claims")
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b =>
{
b.HasOne("Volo.Abp.Identity.IdentityUser")
.WithMany("Claims")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b =>
{
b.HasOne("Volo.Abp.Identity.IdentityUser")
.WithMany("Logins")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b =>
{
b.HasOne("Volo.Abp.Identity.IdentityRole")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("Volo.Abp.Identity.IdentityUser")
.WithMany("Roles")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b =>
{
b.HasOne("Volo.Abp.Identity.IdentityUser")
.WithMany("Tokens")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Volo.Blogging.Comments.Comment", b =>
{
b.HasOne("Volo.Blogging.Posts.Post")
.WithMany()
.HasForeignKey("PostId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("Volo.Blogging.Comments.Comment")
.WithMany()
.HasForeignKey("RepliedCommentId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Volo.Blogging.Posts.Post", b =>
{
b.HasOne("Volo.Blogging.Blogs.Blog")
.WithMany()
.HasForeignKey("BlogId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Volo.Blogging.Posts.PostTag", b =>
{
b.HasOne("Volo.Blogging.Posts.Post")
.WithMany("Tags")
.HasForeignKey("PostId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("Volo.Blogging.Tagging.Tag")
.WithMany()
.HasForeignKey("TagId")
.OnDelete(DeleteBehavior.Cascade);
});
#pragma warning restore 612, 618
}
}
}

34
modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20180817055949_ReplyComment_Nullable.cs

@ -0,0 +1,34 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
{
public partial class ReplyComment_Nullable : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateIndex(
name: "IX_BlgComments_PostId",
table: "BlgComments",
column: "PostId");
migrationBuilder.AddForeignKey(
name: "FK_BlgComments_BlgPosts_PostId",
table: "BlgComments",
column: "PostId",
principalTable: "BlgPosts",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_BlgComments_BlgPosts_PostId",
table: "BlgComments");
migrationBuilder.DropIndex(
name: "IX_BlgComments_PostId",
table: "BlgComments");
}
}
}

580
modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20180817060722_ReplyComment_Not_Required.Designer.cs

@ -0,0 +1,580 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Volo.BloggingTestApp.EntityFrameworkCore;
namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
{
[DbContext(typeof(BloggingTestAppDbContext))]
[Migration("20180817060722_ReplyComment_Not_Required")]
partial class ReplyComment_Not_Required
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "2.1.1-rtm-30846")
.HasAnnotation("Relational:MaxIdentifierLength", 128)
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("ConcurrencyStamp");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(256);
b.Property<string>("NormalizedName")
.IsRequired()
.HasMaxLength(256);
b.Property<Guid?>("TenantId");
b.HasKey("Id");
b.HasIndex("NormalizedName");
b.ToTable("AbpRoles");
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("ClaimType")
.IsRequired()
.HasMaxLength(256);
b.Property<string>("ClaimValue")
.HasMaxLength(1024);
b.Property<Guid>("RoleId");
b.Property<Guid?>("TenantId");
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("AbpRoleClaims");
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd();
b.Property<int>("AccessFailedCount")
.ValueGeneratedOnAdd()
.HasColumnName("AccessFailedCount")
.HasDefaultValue(0);
b.Property<string>("ConcurrencyStamp")
.IsRequired()
.HasColumnName("ConcurrencyStamp")
.HasMaxLength(256);
b.Property<string>("Email")
.HasColumnName("Email")
.HasMaxLength(256);
b.Property<bool>("EmailConfirmed")
.ValueGeneratedOnAdd()
.HasColumnName("EmailConfirmed")
.HasDefaultValue(false);
b.Property<string>("ExtraProperties")
.HasColumnName("ExtraProperties");
b.Property<bool>("LockoutEnabled")
.ValueGeneratedOnAdd()
.HasColumnName("LockoutEnabled")
.HasDefaultValue(false);
b.Property<DateTimeOffset?>("LockoutEnd");
b.Property<string>("NormalizedEmail")
.HasColumnName("NormalizedEmail")
.HasMaxLength(256);
b.Property<string>("NormalizedUserName")
.IsRequired()
.HasColumnName("NormalizedUserName")
.HasMaxLength(256);
b.Property<string>("PasswordHash")
.HasColumnName("PasswordHash")
.HasMaxLength(256);
b.Property<string>("PhoneNumber")
.HasColumnName("PhoneNumber")
.HasMaxLength(16);
b.Property<bool>("PhoneNumberConfirmed")
.ValueGeneratedOnAdd()
.HasColumnName("PhoneNumberConfirmed")
.HasDefaultValue(false);
b.Property<string>("SecurityStamp")
.IsRequired()
.HasColumnName("SecurityStamp")
.HasMaxLength(256);
b.Property<Guid?>("TenantId")
.HasColumnName("TenantId");
b.Property<bool>("TwoFactorEnabled")
.ValueGeneratedOnAdd()
.HasColumnName("TwoFactorEnabled")
.HasDefaultValue(false);
b.Property<string>("UserName")
.IsRequired()
.HasColumnName("UserName")
.HasMaxLength(256);
b.HasKey("Id");
b.HasIndex("Email");
b.HasIndex("NormalizedEmail");
b.HasIndex("NormalizedUserName");
b.HasIndex("UserName");
b.ToTable("AbpUsers");
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("ClaimType")
.IsRequired()
.HasMaxLength(256);
b.Property<string>("ClaimValue")
.HasMaxLength(1024);
b.Property<Guid?>("TenantId");
b.Property<Guid>("UserId");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AbpUserClaims");
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b =>
{
b.Property<Guid>("UserId");
b.Property<string>("LoginProvider")
.HasMaxLength(64);
b.Property<string>("ProviderDisplayName")
.HasMaxLength(128);
b.Property<string>("ProviderKey")
.IsRequired()
.HasMaxLength(196);
b.Property<Guid?>("TenantId");
b.HasKey("UserId", "LoginProvider");
b.HasIndex("LoginProvider", "ProviderKey");
b.ToTable("AbpUserLogins");
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b =>
{
b.Property<Guid>("UserId");
b.Property<Guid>("RoleId");
b.Property<Guid?>("TenantId");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId", "UserId");
b.ToTable("AbpUserRoles");
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b =>
{
b.Property<Guid>("UserId");
b.Property<string>("LoginProvider")
.HasMaxLength(128);
b.Property<string>("Name");
b.Property<Guid?>("TenantId");
b.Property<string>("Value");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AbpUserTokens");
});
modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(128);
b.Property<string>("ProviderKey")
.IsRequired()
.HasMaxLength(64);
b.Property<string>("ProviderName")
.IsRequired()
.HasMaxLength(64);
b.Property<Guid?>("TenantId");
b.HasKey("Id");
b.HasIndex("Name", "ProviderName", "ProviderKey");
b.ToTable("AbpPermissionGrants");
});
modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(128);
b.Property<string>("ProviderKey")
.HasMaxLength(64);
b.Property<string>("ProviderName")
.HasMaxLength(64);
b.Property<string>("Value")
.IsRequired()
.HasMaxLength(2048);
b.HasKey("Id");
b.HasIndex("Name", "ProviderName", "ProviderKey");
b.ToTable("AbpSettings");
});
modelBuilder.Entity("Volo.Blogging.Blogs.Blog", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd();
b.Property<DateTime>("CreationTime")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnName("CreatorId");
b.Property<Guid?>("DeleterId")
.HasColumnName("DeleterId");
b.Property<DateTime?>("DeletionTime")
.HasColumnName("DeletionTime");
b.Property<string>("Description")
.HasColumnName("Description")
.HasMaxLength(1024);
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnName("IsDeleted")
.HasDefaultValue(false);
b.Property<DateTime?>("LastModificationTime")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnName("LastModifierId");
b.Property<string>("Name")
.IsRequired()
.HasColumnName("Name")
.HasMaxLength(256);
b.Property<string>("ShortName")
.IsRequired()
.HasColumnName("ShortName")
.HasMaxLength(32);
b.HasKey("Id");
b.ToTable("BlgBlogs");
});
modelBuilder.Entity("Volo.Blogging.Comments.Comment", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd();
b.Property<DateTime>("CreationTime")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnName("CreatorId");
b.Property<Guid?>("DeleterId")
.HasColumnName("DeleterId");
b.Property<DateTime?>("DeletionTime")
.HasColumnName("DeletionTime");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnName("IsDeleted")
.HasDefaultValue(false);
b.Property<DateTime?>("LastModificationTime")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnName("LastModifierId");
b.Property<Guid>("PostId")
.HasColumnName("PostId");
b.Property<Guid?>("RepliedCommentId")
.HasColumnName("RepliedCommentId");
b.Property<string>("Text")
.IsRequired()
.HasColumnName("Text")
.HasMaxLength(1024);
b.HasKey("Id");
b.HasIndex("PostId");
b.HasIndex("RepliedCommentId");
b.ToTable("BlgComments");
});
modelBuilder.Entity("Volo.Blogging.Posts.Post", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd();
b.Property<Guid>("BlogId")
.HasColumnName("BlogId");
b.Property<string>("Content")
.HasColumnName("Content")
.HasMaxLength(1048576);
b.Property<DateTime>("CreationTime")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnName("CreatorId");
b.Property<Guid?>("DeleterId")
.HasColumnName("DeleterId");
b.Property<DateTime?>("DeletionTime")
.HasColumnName("DeletionTime");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnName("IsDeleted")
.HasDefaultValue(false);
b.Property<DateTime?>("LastModificationTime")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnName("LastModifierId");
b.Property<string>("Title")
.IsRequired()
.HasColumnName("Title")
.HasMaxLength(512);
b.Property<string>("Url")
.IsRequired()
.HasColumnName("Url")
.HasMaxLength(64);
b.HasKey("Id");
b.HasIndex("BlogId");
b.ToTable("BlgPosts");
});
modelBuilder.Entity("Volo.Blogging.Posts.PostTag", b =>
{
b.Property<Guid>("PostId")
.HasColumnName("PostId");
b.Property<Guid>("TagId")
.HasColumnName("TagId");
b.Property<DateTime>("CreationTime");
b.Property<Guid?>("CreatorId");
b.HasKey("PostId", "TagId");
b.HasIndex("TagId");
b.ToTable("BlgPostTags");
});
modelBuilder.Entity("Volo.Blogging.Tagging.Tag", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd();
b.Property<DateTime>("CreationTime")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnName("CreatorId");
b.Property<Guid?>("DeleterId")
.HasColumnName("DeleterId");
b.Property<DateTime?>("DeletionTime")
.HasColumnName("DeletionTime");
b.Property<string>("Description")
.HasColumnName("Description")
.HasMaxLength(512);
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnName("IsDeleted")
.HasDefaultValue(false);
b.Property<DateTime?>("LastModificationTime")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnName("LastModifierId");
b.Property<string>("Name")
.IsRequired()
.HasColumnName("Name")
.HasMaxLength(64);
b.Property<int>("UsageCount")
.HasColumnName("UsageCount");
b.HasKey("Id");
b.ToTable("BlgTags");
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b =>
{
b.HasOne("Volo.Abp.Identity.IdentityRole")
.WithMany("Claims")
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b =>
{
b.HasOne("Volo.Abp.Identity.IdentityUser")
.WithMany("Claims")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b =>
{
b.HasOne("Volo.Abp.Identity.IdentityUser")
.WithMany("Logins")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b =>
{
b.HasOne("Volo.Abp.Identity.IdentityRole")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("Volo.Abp.Identity.IdentityUser")
.WithMany("Roles")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b =>
{
b.HasOne("Volo.Abp.Identity.IdentityUser")
.WithMany("Tokens")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Volo.Blogging.Comments.Comment", b =>
{
b.HasOne("Volo.Blogging.Posts.Post")
.WithMany()
.HasForeignKey("PostId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("Volo.Blogging.Comments.Comment")
.WithMany()
.HasForeignKey("RepliedCommentId");
});
modelBuilder.Entity("Volo.Blogging.Posts.Post", b =>
{
b.HasOne("Volo.Blogging.Blogs.Blog")
.WithMany()
.HasForeignKey("BlogId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Volo.Blogging.Posts.PostTag", b =>
{
b.HasOne("Volo.Blogging.Posts.Post")
.WithMany("Tags")
.HasForeignKey("PostId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("Volo.Blogging.Tagging.Tag")
.WithMany()
.HasForeignKey("TagId")
.OnDelete(DeleteBehavior.Cascade);
});
#pragma warning restore 612, 618
}
}
}

51
modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20180817060722_ReplyComment_Not_Required.cs

@ -0,0 +1,51 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
{
public partial class ReplyComment_Not_Required : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_BlgComments_BlgComments_RepliedCommentId",
table: "BlgComments");
migrationBuilder.AlterColumn<Guid>(
name: "RepliedCommentId",
table: "BlgComments",
nullable: true,
oldClrType: typeof(Guid));
migrationBuilder.AddForeignKey(
name: "FK_BlgComments_BlgComments_RepliedCommentId",
table: "BlgComments",
column: "RepliedCommentId",
principalTable: "BlgComments",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_BlgComments_BlgComments_RepliedCommentId",
table: "BlgComments");
migrationBuilder.AlterColumn<Guid>(
name: "RepliedCommentId",
table: "BlgComments",
nullable: false,
oldClrType: typeof(Guid),
oldNullable: true);
migrationBuilder.AddForeignKey(
name: "FK_BlgComments_BlgComments_RepliedCommentId",
table: "BlgComments",
column: "RepliedCommentId",
principalTable: "BlgComments",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
}
}
}

137
modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/BloggingTestAppDbContextModelSnapshot.cs

@ -331,6 +331,54 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
b.ToTable("BlgBlogs");
});
modelBuilder.Entity("Volo.Blogging.Comments.Comment", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd();
b.Property<DateTime>("CreationTime")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnName("CreatorId");
b.Property<Guid?>("DeleterId")
.HasColumnName("DeleterId");
b.Property<DateTime?>("DeletionTime")
.HasColumnName("DeletionTime");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnName("IsDeleted")
.HasDefaultValue(false);
b.Property<DateTime?>("LastModificationTime")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnName("LastModifierId");
b.Property<Guid>("PostId")
.HasColumnName("PostId");
b.Property<Guid?>("RepliedCommentId")
.HasColumnName("RepliedCommentId");
b.Property<string>("Text")
.IsRequired()
.HasColumnName("Text")
.HasMaxLength(1024);
b.HasKey("Id");
b.HasIndex("PostId");
b.HasIndex("RepliedCommentId");
b.ToTable("BlgComments");
});
modelBuilder.Entity("Volo.Blogging.Posts.Post", b =>
{
b.Property<Guid>("Id")
@ -383,6 +431,70 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
b.ToTable("BlgPosts");
});
modelBuilder.Entity("Volo.Blogging.Posts.PostTag", b =>
{
b.Property<Guid>("PostId")
.HasColumnName("PostId");
b.Property<Guid>("TagId")
.HasColumnName("TagId");
b.Property<DateTime>("CreationTime");
b.Property<Guid?>("CreatorId");
b.HasKey("PostId", "TagId");
b.HasIndex("TagId");
b.ToTable("BlgPostTags");
});
modelBuilder.Entity("Volo.Blogging.Tagging.Tag", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd();
b.Property<DateTime>("CreationTime")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnName("CreatorId");
b.Property<Guid?>("DeleterId")
.HasColumnName("DeleterId");
b.Property<DateTime?>("DeletionTime")
.HasColumnName("DeletionTime");
b.Property<string>("Description")
.HasColumnName("Description")
.HasMaxLength(512);
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnName("IsDeleted")
.HasDefaultValue(false);
b.Property<DateTime?>("LastModificationTime")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnName("LastModifierId");
b.Property<string>("Name")
.IsRequired()
.HasColumnName("Name")
.HasMaxLength(64);
b.Property<int>("UsageCount")
.HasColumnName("UsageCount");
b.HasKey("Id");
b.ToTable("BlgTags");
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b =>
{
b.HasOne("Volo.Abp.Identity.IdentityRole")
@ -428,6 +540,18 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Volo.Blogging.Comments.Comment", b =>
{
b.HasOne("Volo.Blogging.Posts.Post")
.WithMany()
.HasForeignKey("PostId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("Volo.Blogging.Comments.Comment")
.WithMany()
.HasForeignKey("RepliedCommentId");
});
modelBuilder.Entity("Volo.Blogging.Posts.Post", b =>
{
b.HasOne("Volo.Blogging.Blogs.Blog")
@ -435,6 +559,19 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
.HasForeignKey("BlogId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Volo.Blogging.Posts.PostTag", b =>
{
b.HasOne("Volo.Blogging.Posts.Post")
.WithMany("Tags")
.HasForeignKey("PostId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("Volo.Blogging.Tagging.Tag")
.WithMany()
.HasForeignKey("TagId")
.OnDelete(DeleteBehavior.Cascade);
});
#pragma warning restore 612, 618
}
}

16601
modules/blogging/app/Volo.BloggingTestApp/Logs/logs.txt

File diff suppressed because it is too large

15
modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Comments/Dtos/CommentDto.cs

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Text;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Domain.Entities.Auditing;
namespace Volo.Blogging.Comments.Dtos
{
public class CommentDto : FullAuditedEntityDto<Guid>
{
public Guid RepliedCommentId { get; set; }
public string Text { get; set; }
}
}

14
modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Comments/Dtos/CommentWithRepliesDto.cs

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Text;
using Volo.Abp.Application.Dtos;
namespace Volo.Blogging.Comments.Dtos
{
public class CommentWithRepliesDto
{
public CommentDto Comment { get; set; }
public List<CommentDto> Replies { get; set; } = new List<CommentDto>();
}
}

13
modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Comments/Dtos/CreateCommentDto.cs

@ -0,0 +1,13 @@
using System;
namespace Volo.Blogging.Comments.Dtos
{
public class CreateCommentDto
{
public Guid? RepliedCommentId { get; set; }
public Guid PostId { get; set; }
public string Text { get; set; }
}
}

9
modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Comments/Dtos/GetCommentListOfPostAsync.cs

@ -0,0 +1,9 @@
using System;
namespace Volo.Blogging.Comments.Dtos
{
public class GetCommentListOfPostAsync
{
public Guid PostId { get; set; }
}
}

7
modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Comments/Dtos/UpdateCommentDto.cs

@ -0,0 +1,7 @@
namespace Volo.Blogging.Comments.Dtos
{
public class UpdateCommentDto
{
public string Text { get; set; }
}
}

22
modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Comments/ICommentAppService.cs

@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
using Volo.Blogging.Comments.Dtos;
namespace Volo.Blogging.Comments
{
public interface ICommentAppService : IApplicationService
{
Task<List<CommentDto>> GetListOfPostAsync(GetCommentListOfPostAsync input);
Task<List<CommentWithRepliesDto>> GetHierarchicalListOfPostAsync(GetCommentListOfPostAsync input);
Task<CommentDto> CreateAsync(CreateCommentDto input);
Task<CommentDto> UpdateAsync(Guid id, UpdateCommentDto input);
Task DeleteAsync(Guid id);
}
}

2
modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Posts/CreatePostDto.cs

@ -18,5 +18,7 @@ namespace Volo.Blogging.Posts
[StringLength(PostConsts.MaxContentLength)]
public string Content { get; set; }
public string Tags { get; set; }
}
}

18
modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Posts/GetPostForEditOutput.cs

@ -1,18 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
using Volo.Abp.Application.Dtos;
namespace Volo.Blogging.Posts
{
public class GetPostForEditOutput : EntityDto<Guid>
{
public Guid BlogId { get; set; }
public string Title { get; set; }
public string Url { get; set; }
public string Content { get; set; }
}
}

2
modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Posts/IPostAppService.cs

@ -15,8 +15,6 @@ namespace Volo.Blogging.Posts
Task<PostWithDetailsDto> GetAsync(Guid id);
Task<GetPostForEditOutput> GetForEditAsync(Guid id);
Task<PostWithDetailsDto> CreateAsync(CreatePostDto input);
Task<PostWithDetailsDto> UpdateAsync(Guid id, UpdatePostDto input);

3
modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Posts/PostWithDetailsDto.cs

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Text;
using Volo.Abp.Application.Dtos;
using Volo.Blogging.Tagging.Dtos;
namespace Volo.Blogging.Posts
{
@ -14,5 +15,7 @@ namespace Volo.Blogging.Posts
public string Url { get; set; }
public string Content { get; set; }
public List<TagDto> Tags { get; set; }
}
}

2
modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Posts/UpdatePostDto.cs

@ -14,5 +14,7 @@ namespace Volo.Blogging.Posts
public string Url { get; set; }
public string Content { get; set; }
public string Tags { get; set; }
}
}

9
modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Tagging/Dtos/CreateTagDto.cs

@ -0,0 +1,9 @@
namespace Volo.Blogging.Tagging.Dtos
{
public class CreateTagDto
{
public string Name { get; set; }
public string Description { get; set; }
}
}

10
modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Tagging/Dtos/GetTagListInput.cs

@ -0,0 +1,10 @@
using System;
using System.Collections.Generic;
namespace Volo.Blogging.Tagging.Dtos
{
public class GetTagListInput
{
public IEnumerable<Guid> Ids { get; set; }
}
}

14
modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Tagging/Dtos/TagDto.cs

@ -0,0 +1,14 @@
using System;
using Volo.Abp.Application.Dtos;
namespace Volo.Blogging.Tagging.Dtos
{
public class TagDto : FullAuditedEntityDto<Guid>
{
public string Name { get; set; }
public string Description { get; set; }
public int UsageCount { get; set; }
}
}

9
modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Tagging/Dtos/UpdateTagDto.cs

@ -0,0 +1,9 @@
namespace Volo.Blogging.Tagging.Dtos
{
public class UpdateTagDto
{
public string Name { get; set; }
public string Description { get; set; }
}
}

22
modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Tagging/ITagAppService.cs

@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
using Volo.Blogging.Tagging.Dtos;
namespace Volo.Blogging.Tagging
{
public interface ITagAppService : IApplicationService
{
Task<List<TagDto>> GetListAsync();
Task<List<TagDto>> GetListAsync(GetTagListInput input);
Task<TagDto> CreateAsync(CreateTagDto input);
Task<TagDto> UpdateAsync(Guid id, UpdateTagDto input);
Task DeleteAsync(Guid id);
}
}

7
modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/BloggingApplicationAutoMapperProfile.cs

@ -1,7 +1,11 @@
using AutoMapper;
using Volo.Abp.AutoMapper;
using Volo.Blogging.Blogs;
using Volo.Blogging.Comments;
using Volo.Blogging.Comments.Dtos;
using Volo.Blogging.Posts;
using Volo.Blogging.Tagging;
using Volo.Blogging.Tagging.Dtos;
namespace Volo.Blogging
{
@ -12,7 +16,8 @@ namespace Volo.Blogging
CreateMap<Blog, BlogDto>();
CreateMap<Post, PostDto>();
CreateMap<Post, PostWithDetailsDto>();
CreateMap<Post, GetPostForEditOutput>();
CreateMap<Comment, CommentDto>();
CreateMap<Tag, TagDto>();
}
}
}

76
modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Comments/CommentAppService.cs

@ -0,0 +1,76 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
using Volo.Abp.Guids;
using Volo.Blogging.Comments.Dtos;
namespace Volo.Blogging.Comments
{
public class CommentAppService : ApplicationService, ICommentAppService
{
private readonly ICommentRepository _commentRepository;
private readonly IGuidGenerator _guidGenerator;
public CommentAppService(ICommentRepository commentRepository, IGuidGenerator guidGenerator)
{
_commentRepository = commentRepository;
_guidGenerator = guidGenerator;
}
public async Task<List<CommentWithRepliesDto>> GetHierarchicalListOfPostAsync(GetCommentListOfPostAsync input)
{
var comments = await GetListOfPostAsync(input);
var hierarchicalComments = new List<CommentWithRepliesDto>();
foreach (var commentDto in comments)
{
var parent = hierarchicalComments.Find(c => c.Comment.Id == commentDto.RepliedCommentId);
if (parent != null)
{
parent.Replies.Add(commentDto);
}
else
{
hierarchicalComments.Add(new CommentWithRepliesDto() { Comment = commentDto });
}
}
return hierarchicalComments;
}
public async Task<List<CommentDto>> GetListOfPostAsync(GetCommentListOfPostAsync input)
{
var comments = await _commentRepository.GetListOfPostAsync(input.PostId);
return new List<CommentDto>(
ObjectMapper.Map<List<Comment>, List<CommentDto>>(comments));
}
public async Task<CommentDto> CreateAsync(CreateCommentDto input)
{
var comment = new Comment(_guidGenerator.Create(), input.PostId, input.RepliedCommentId,input.Text);
comment = await _commentRepository.InsertAsync(comment);
return ObjectMapper.Map<Comment, CommentDto>(comment);
}
public async Task<CommentDto> UpdateAsync(Guid id, UpdateCommentDto input)
{
var comment = await _commentRepository.GetAsync(id);
comment.SetText(input.Text);
comment = await _commentRepository.UpdateAsync(comment);
return ObjectMapper.Map<Comment, CommentDto>(comment);
}
public async Task DeleteAsync(Guid id)
{
await _commentRepository.DeleteAsync(id);
}
}
}

77
modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Posts/PostAppService.cs

@ -6,8 +6,11 @@ using Volo.Abp.Application.Services;
using System.Collections.Generic;
using Microsoft.AspNetCore.Authorization;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Users;
using Volo.Blogging.Blogs;
using Volo.Blogging.Tagging;
using Volo.Blogging.Tagging.Dtos;
namespace Volo.Blogging.Posts
{
@ -15,10 +18,14 @@ namespace Volo.Blogging.Posts
public class PostAppService : ApplicationService, IPostAppService
{
private readonly IPostRepository _postRepository;
private readonly ITagRepository _tagRepository;
private readonly IPostTagRepository _postTagRepository;
public PostAppService(IPostRepository postRepository)
public PostAppService(IPostRepository postRepository, ITagRepository tagRepository, IPostTagRepository postTagRepository)
{
_postRepository = postRepository;
_tagRepository = tagRepository;
_postTagRepository = postTagRepository;
}
public ListResultDto<PostWithDetailsDto> GetListByBlogIdAsync(Guid id)
@ -33,30 +40,30 @@ namespace Volo.Blogging.Posts
{
var post = await _postRepository.GetPostByUrl(input.BlogId, input.Url);
return ObjectMapper.Map<Post, PostWithDetailsDto>(post);
var postDto = ObjectMapper.Map<Post, PostWithDetailsDto>(post);
var tagIds = (await _postTagRepository.GetListAsync()).Where(pt => pt.PostId == postDto.Id);
var tags = await _tagRepository.GetListAsync(tagIds.Select(t => t.TagId));
postDto.Tags = ObjectMapper.Map<List<Tag>, List<TagDto>>(tags);
return postDto;
}
public async Task<PostWithDetailsDto> GetAsync(Guid id)
{
var post = await _postRepository.GetAsync(id);
return ObjectMapper.Map<Post, PostWithDetailsDto>(post);
}
var postDto = ObjectMapper.Map<Post, PostWithDetailsDto>(post);
public async Task<GetPostForEditOutput> GetForEditAsync(Guid id)
{
var post = await _postRepository.GetAsync(id);
var tagIds = (await _postTagRepository.GetListAsync()).Where(pt => pt.PostId == postDto.Id);
var dto = new GetPostForEditOutput
{
Id = post.Id,
BlogId = post.BlogId,
Content = post.Content,
Title = post.Title,
Url = post.Url
};
return dto;
var tags = await _tagRepository.GetListAsync(tagIds.Select(t => t.TagId));
postDto.Tags = ObjectMapper.Map<List<Tag>, List<TagDto>>(tags);
return postDto;
}
[Authorize(BloggingPermissions.Posts.Update)]
@ -70,6 +77,9 @@ namespace Volo.Blogging.Posts
post = await _postRepository.UpdateAsync(post);
var tagList = SplitTags(input.Tags);
await SaveTags(tagList, post);
return ObjectMapper.Map<Post, PostWithDetailsDto>(post);
}
@ -86,7 +96,40 @@ namespace Volo.Blogging.Posts
await _postRepository.InsertAsync(post);
var tagList = SplitTags(input.Tags);
await SaveTags(tagList, post);
return ObjectMapper.Map<Post, PostWithDetailsDto>(post);
}
private async Task SaveTags(List<String> newTags, Post post)
{
var oldTags = (await _postTagRepository.GetListAsync()).Where(pt => pt.PostId == post.Id).ToList();
foreach (var oldTag in oldTags)
{
await _postTagRepository.DeleteAsync(oldTag);
}
var tags = await _tagRepository.GetListAsync();
foreach (var newTag in newTags)
{
var tag = tags.FirstOrDefault(t => t.Name == newTag);
if (tag == null)
{
tag = await _tagRepository.InsertAsync(new Tag(newTag));
}
await _postTagRepository.InsertAsync(new PostTag(post.Id, tag.Id));
}
}
private List<string> SplitTags(string tags)
{
return new List<string>(tags.Split(",").Select(t=>t.Trim()));
}
}
}

63
modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Tagging/TagAppService.cs

@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
using Volo.Blogging.Tagging.Dtos;
namespace Volo.Blogging.Tagging
{
public class TagAppService : ApplicationService, ITagAppService
{
private readonly ITagRepository _tagRepository;
public TagAppService(ITagRepository tagRepository)
{
_tagRepository = tagRepository;
}
public async Task<List<TagDto>> GetListAsync()
{
var tags = await _tagRepository.GetListAsync();
return new List<TagDto>(
ObjectMapper.Map<List<Tag>, List<TagDto>>(tags));
}
public async Task<List<TagDto>> GetListAsync(GetTagListInput input)
{
var tags = await _tagRepository.GetListAsync(input.Ids);
return new List<TagDto>(
ObjectMapper.Map<List<Tag>, List<TagDto>>(tags));
}
public async Task<TagDto> CreateAsync(CreateTagDto input)
{
var newTag = await _tagRepository.InsertAsync(
new Tag(
input.Name,
input.Description
)
);
return ObjectMapper.Map<Tag, TagDto>(newTag);
}
public async Task<TagDto> UpdateAsync(Guid id, UpdateTagDto input)
{
var tag = await _tagRepository.GetAsync(id);
tag.SetName(input.Name);
tag.SetDescription(input.Description);
tag = await _tagRepository.UpdateAsync(tag);
return ObjectMapper.Map<Tag, TagDto>(tag);
}
public async Task DeleteAsync(Guid id)
{
await _tagRepository.DeleteAsync(id);
}
}
}

11
modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Comments/CommentConsts.cs

@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Volo.Blogging.Comments
{
public class CommentConsts
{
public const int MaxTextLength = 1024;
}
}

13
modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Tagging/TagConsts.cs

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Volo.Blogging.Tagging
{
public class TagConsts
{
public const int MaxNameLength = 64;
public const int MaxDescriptionLength = 512;
}
}

38
modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Comments/Comment.cs

@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using JetBrains.Annotations;
using Volo.Abp;
using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp.MultiTenancy;
namespace Volo.Blogging.Comments
{
public class Comment : FullAuditedAggregateRoot<Guid>
{
public virtual Guid PostId { get; protected set; }
public virtual Guid? RepliedCommentId { get; protected set; }
public virtual string Text { get; protected set; }
protected Comment()
{
}
public Comment(Guid id, Guid postId, Guid? repliedCommentId, [NotNull] string text)
{
Id = id;
PostId = postId;
RepliedCommentId = repliedCommentId;
Text = Check.NotNullOrWhiteSpace(text, nameof(text));
}
public void SetText(string text)
{
Text = Check.NotNullOrWhiteSpace(text, nameof(text));
}
}
}

15
modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Comments/ICommentRepository.cs

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
namespace Volo.Blogging.Comments
{
public interface ICommentRepository : IBasicRepository<Comment, Guid>
{
Task<List<Comment>> GetListOfPostAsync(
Guid postId
);
}
}

12
modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/IPostTagRepository.cs

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Text;
using Volo.Abp.Domain.Repositories;
using Volo.Blogging.Tagging;
namespace Volo.Blogging.Posts
{
public interface IPostTagRepository : IBasicRepository<PostTag>
{
}
}

5
modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/Post.cs

@ -1,4 +1,5 @@
using System;
using System.Collections.ObjectModel;
using JetBrains.Annotations;
using Volo.Abp;
using Volo.Abp.Domain.Entities.Auditing;
@ -18,6 +19,8 @@ namespace Volo.Blogging.Posts
[CanBeNull]
public virtual string Content { get; set; }
public virtual Collection<PostTag> Tags { get; protected set; }
protected Post()
{
@ -30,6 +33,8 @@ namespace Volo.Blogging.Posts
BlogId = blogId;
Title = Check.NotNullOrWhiteSpace(title, nameof(title));
Url = Check.NotNullOrWhiteSpace(url, nameof(url));
Tags = new Collection<PostTag>();
}
public virtual Post SetTitle([NotNull] string title)

29
modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/PostTag.cs

@ -0,0 +1,29 @@
using System;
using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp.MultiTenancy;
namespace Volo.Blogging.Posts
{
public class PostTag : CreationAuditedEntity
{
public virtual Guid PostId { get; protected set; }
public virtual Guid TagId { get; protected set; }
protected PostTag()
{
}
public PostTag(Guid postId, Guid tagId)
{
PostId = postId;
TagId = tagId;
}
public override object[] GetKeys()
{
return new object[] { PostId, TagId };
}
}
}

14
modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Tagging/ITagRepository.cs

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
namespace Volo.Blogging.Tagging
{
public interface ITagRepository : IBasicRepository<Tag, Guid>
{
Task<List<Tag>> GetListAsync();
Task<List<Tag>> GetListAsync(IEnumerable<Guid> ids);
}
}

39
modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Tagging/Tag.cs

@ -0,0 +1,39 @@
using System;
using JetBrains.Annotations;
using Volo.Abp;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp.MultiTenancy;
namespace Volo.Blogging.Tagging
{
public class Tag : FullAuditedAggregateRoot<Guid>
{
public virtual string Name { get; protected set; }
public virtual string Description { get; protected set; }
public virtual int UsageCount { get; protected internal set; }
protected Tag()
{
}
public Tag([NotNull] string name, string description = null)
{
Name = Check.NotNullOrWhiteSpace(name, nameof(name));
Description = description;
}
public virtual void SetName(string name)
{
Name = Check.NotNullOrWhiteSpace(name, nameof(name));
}
public virtual void SetDescription(string description)
{
Description = description;
}
}
}

28
modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Comments/EfCoreCommentRepository.cs

@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
using Volo.Blogging.EntityFrameworkCore;
namespace Volo.Blogging.Comments
{
public class EfCoreCommentRepository : EfCoreRepository<IBloggingDbContext, Comment, Guid>, ICommentRepository
{
public EfCoreCommentRepository(IDbContextProvider<IBloggingDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
public async Task<List<Comment>> GetListOfPostAsync(Guid postId)
{
return await DbSet
.Where(a => a.PostId == postId)
.OrderBy(a => a.CreationTime)
.ToListAsync();
}
}
}

8
modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/EntityFrameworkCore/BloggingDbContext.cs

@ -2,7 +2,9 @@
using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore;
using Volo.Blogging.Blogs;
using Volo.Blogging.Comments;
using Volo.Blogging.Posts;
using Volo.Blogging.Tagging;
namespace Volo.Blogging.EntityFrameworkCore
{
@ -15,6 +17,12 @@ namespace Volo.Blogging.EntityFrameworkCore
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
public DbSet<Tag> Tags { get; set; }
public DbSet<PostTag> PostTags { get; set; }
public DbSet<Comment> Comments { get; set; }
public BloggingDbContext(DbContextOptions<BloggingDbContext> options)
: base(options)

41
modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/EntityFrameworkCore/BloggingDbContextModelBuilderExtensions.cs

@ -4,7 +4,9 @@ using Microsoft.EntityFrameworkCore;
using Volo.Abp;
using Volo.Abp.EntityFrameworkCore.Modeling;
using Volo.Blogging.Blogs;
using Volo.Blogging.Comments;
using Volo.Blogging.Posts;
using Volo.Blogging.Tagging;
namespace Volo.Blogging.EntityFrameworkCore
{
@ -41,8 +43,47 @@ namespace Volo.Blogging.EntityFrameworkCore
b.Property(x => x.Url).IsRequired().HasMaxLength(PostConsts.MaxUrlLength).HasColumnName(nameof(Post.Url));
b.Property(x => x.Content).IsRequired(false).HasMaxLength(PostConsts.MaxContentLength).HasColumnName(nameof(Post.Content));
b.HasMany(question => question.Tags).WithOne().HasForeignKey(qt => qt.PostId);
b.HasOne<Blog>().WithMany().IsRequired().HasForeignKey(p => p.BlogId);
});
builder.Entity<Comment>(b =>
{
b.ToTable(options.TablePrefix + "Comments", options.Schema);
b.ConfigureFullAudited();
b.Property(x => x.Text).IsRequired().HasMaxLength(CommentConsts.MaxTextLength).HasColumnName(nameof(Comment.Text));
b.Property(x => x.RepliedCommentId).HasColumnName(nameof(Comment.RepliedCommentId));
b.Property(x => x.PostId).IsRequired().HasColumnName(nameof(Comment.PostId));
b.HasOne<Comment>().WithMany().HasForeignKey(p => p.RepliedCommentId);
b.HasOne<Post>().WithMany().IsRequired().HasForeignKey(p => p.PostId);
});
builder.Entity<Tag>(b =>
{
b.ToTable(options.TablePrefix + "Tags", options.Schema);
b.ConfigureFullAudited();
b.Property(x => x.Name).IsRequired().HasMaxLength(TagConsts.MaxNameLength).HasColumnName(nameof(Tag.Name));
b.Property(x => x.Description).HasMaxLength(TagConsts.MaxDescriptionLength).HasColumnName(nameof(Tag.Description));
b.Property(x => x.UsageCount).HasColumnName(nameof(Tag.UsageCount));
b.HasMany<PostTag>().WithOne().HasForeignKey(qt => qt.TagId);
});
builder.Entity<PostTag>(b =>
{
b.ToTable(options.TablePrefix + "PostTags", options.Schema);
b.Property(x => x.PostId).HasColumnName(nameof(PostTag.PostId));
b.Property(x => x.TagId).HasColumnName(nameof(PostTag.TagId));
b.HasKey(x => new { x.PostId, x.TagId });
});
}
}
}

8
modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/EntityFrameworkCore/IBloggingDbContext.cs

@ -2,7 +2,9 @@
using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore;
using Volo.Blogging.Blogs;
using Volo.Blogging.Comments;
using Volo.Blogging.Posts;
using Volo.Blogging.Tagging;
namespace Volo.Blogging.EntityFrameworkCore
{
@ -12,5 +14,11 @@ namespace Volo.Blogging.EntityFrameworkCore
DbSet<Blog> Blogs { get; set; }
DbSet<Post> Posts { get; set; }
DbSet<Comment> Comments { get; set; }
DbSet<PostTag> PostTags { get; set; }
DbSet<Tag> Tags { get; set; }
}
}

16
modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Posts/EfCorePostTagRepository.cs

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Text;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
using Volo.Blogging.EntityFrameworkCore;
namespace Volo.Blogging.Posts
{
public class EfCorePostTagRepository : EfCoreRepository<IBloggingDbContext, PostTag>, IPostTagRepository
{
public EfCorePostTagRepository(IDbContextProvider<IBloggingDbContext> dbContextProvider) : base(dbContextProvider)
{
}
}
}

30
modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Tagging/EfCoreTagRepository.cs

@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
using Volo.Blogging.EntityFrameworkCore;
namespace Volo.Blogging.Tagging
{
public class EfCoreTagRepository : EfCoreRepository<IBloggingDbContext, Tag, Guid>, ITagRepository
{
public EfCoreTagRepository(IDbContextProvider<IBloggingDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
public async Task<List<Tag>> GetListAsync()
{
return await DbSet.ToListAsync();
}
public async Task<List<Tag>> GetListAsync(IEnumerable<Guid> ids)
{
return await DbSet.Where(c => ids.Contains(c.Id)).ToListAsync();
}
}
}

3
modules/blogging/src/Volo.Blogging.Web/AbpBloggingWebAutoMapperProfile.cs

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AutoMapper;
using Volo.Abp.AutoMapper;
using Volo.Blogging.Pages.Blog.Posts;
using Volo.Blogging.Posts;
@ -12,7 +13,7 @@ namespace Volo.Blogging
{
public AbpBloggingWebAutoMapperProfile()
{
CreateMap<GetPostForEditOutput, EditPostViewModel>();
CreateMap<PostWithDetailsDto, EditPostViewModel>().Ignore(x=>x.Tags);
CreateMap<NewModel.CreatePostViewModel, CreatePostDto>();
}
}

53
modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Detail.cshtml

@ -4,6 +4,12 @@
@{
}
@section scripts {
<abp-script-bundle name="@typeof(DetailModel).FullName">
<abp-script src="/Pages/Blog/Posts/detail.js" />
</abp-script-bundle>
}
<h2>@Model.Post.Title</h2>
<p>@Model.Post.Content</p>
@ -12,4 +18,49 @@
<i>Posted to @Model.Blog.Name On @Model.Post.CreationTime</i>
</p>
<a asp-page="./Edit" asp-route-postId="@Model.Post.Id" asp-route-blogShortName="@Model.BlogShortName">edit</a>
<abp-row>
@foreach (var tag in Model.Post.Tags)
{
<span abp-badge-pill="Warning">@tag.Name</span>
}
</abp-row>
<a>comment </a>
<a asp-page="./Edit" asp-route-postId="@Model.Post.Id" asp-route-blogShortName="@Model.BlogShortName">edit</a>
@foreach (var commentWithRepliesDto in Model.CommentsWithReplies)
{
<abp-row>
<abp-column offset-sm="_3" size-sm="_7" v-align="Start">
@commentWithRepliesDto.Comment.Text
<br />
@commentWithRepliesDto.Comment.CreationTime
</abp-column>
<abp-column size-sm="_2" v-align="End">
<button type="button" data-button="@commentWithRepliesDto.Comment.Id">
Reply
</button>
</abp-column>
</abp-row>
<br />
foreach (var reply in commentWithRepliesDto.Replies)
{
<abp-row>
<abp-column offset-sm="_6" size-sm="_2">
@reply.Text
<br />
@reply.CreationTime
</abp-column>
</abp-row>
}
<div class="m-separator m-separator--dashed"></div>
}
<form method="post">
<input name="postId" value="@Model.Post.Id" hidden/>
<input name="repliedCommentId" id="repliedCommentId" hidden/>
<textarea type="text" name="text" id="textBoxId"></textarea>
<abp-button button-type="Primary" type="submit" text="submit" />
</form>

45
modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Detail.cshtml.cs

@ -1,11 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Volo.Abp.Domain.Entities;
using Volo.Blogging.Blogs;
using Volo.Blogging.Comments;
using Volo.Blogging.Comments.Dtos;
using Volo.Blogging.Posts;
namespace Volo.Blogging.Pages.Blog.Posts
@ -14,6 +14,7 @@ namespace Volo.Blogging.Pages.Blog.Posts
{
private readonly IPostAppService _postAppService;
private readonly IBlogAppService _blogAppService;
private readonly ICommentAppService _commentAppService;
[BindProperty(SupportsGet = true)]
public string BlogShortName { get; set; }
@ -21,20 +22,54 @@ namespace Volo.Blogging.Pages.Blog.Posts
[BindProperty(SupportsGet = true)]
public string PostUrl { get; set; }
[BindProperty]
public PostDetailsViewModel NewComment { get; set; }
public PostWithDetailsDto Post { get; set; }
public IReadOnlyList<CommentWithRepliesDto> CommentsWithReplies { get; set; }
public BlogDto Blog { get; set; }
public DetailModel(IPostAppService postAppService, IBlogAppService blogAppService)
public DetailModel(IPostAppService postAppService, IBlogAppService blogAppService, ICommentAppService commentAppService)
{
_postAppService = postAppService;
_blogAppService = blogAppService;
_commentAppService = commentAppService;
}
public async void OnGetAsync()
{
await GetData();
}
public async void OnGet()
public async void OnPostAsync()
{
await _commentAppService.CreateAsync(new CreateCommentDto()
{
RepliedCommentId = NewComment.RepliedCommentId,
PostId = NewComment.PostId,
Text = NewComment.Text
});
await GetData();
}
private async Task GetData()
{
Blog = await _blogAppService.GetByShortNameAsync(BlogShortName);
Post = await _postAppService.GetByUrlAsync(new GetPostInput {BlogId = Blog.Id , Url = PostUrl});
Post = await _postAppService.GetByUrlAsync(new GetPostInput { BlogId = Blog.Id, Url = PostUrl });
CommentsWithReplies = await _commentAppService.GetHierarchicalListOfPostAsync(new GetCommentListOfPostAsync() { PostId = Post.Id });
}
public class PostDetailsViewModel
{
public Guid? RepliedCommentId { get; set; }
public Guid PostId { get; set; }
public string Text { get; set; }
}
}
}

1
modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Edit.cshtml

@ -12,6 +12,7 @@
<form method="post">
<abp-input asp-for="@Model.Post.Title" auto-focus="true" />
<abp-input asp-for="@Model.Post.Url" />
<abp-input asp-for="@Model.Post.Tags" />
<div class="form-group">
<label>@L["Content"]</label>

11
modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Edit.cshtml.cs

@ -1,5 +1,6 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages;
@ -27,8 +28,9 @@ namespace Volo.Blogging.Pages.Blog.Posts
public async void OnGet()
{
var postDto = await _postAppService.GetForEditAsync(new Guid(PostId));
Post = ObjectMapper.Map<GetPostForEditOutput, EditPostViewModel>(postDto);
var postDto = await _postAppService.GetAsync(new Guid(PostId));
Post = ObjectMapper.Map<PostWithDetailsDto, EditPostViewModel>(postDto);
Post.Tags = String.Join(", ", postDto.Tags.Select(p=>p.Name).ToArray());
}
public async Task<ActionResult> OnPost()
@ -38,7 +40,8 @@ namespace Volo.Blogging.Pages.Blog.Posts
BlogId = Post.BlogId,
Title = Post.Title,
Url = Post.Url,
Content = Post.Content
Content = Post.Content,
Tags = Post.Tags
};
var editedPost = await _postAppService.UpdateAsync(Post.Id, post);
@ -66,5 +69,7 @@ namespace Volo.Blogging.Pages.Blog.Posts
[StringLength(PostConsts.MaxContentLength)]
public string Content { get; set; }
public string Tags { get; set; }
}
}

4
modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/New.cshtml

@ -1,8 +1,7 @@
@page
@using Volo.Abp.AspNetCore.Mvc.UI.Packages.Lodash
@using Volo.Abp.AspNetCore.Mvc.UI.Packages.TuiEditor
@using Volo.Blogging.Pages.Blog.Posts
@model NewModel
@model Volo.Blogging.Pages.Blog.Posts.NewModel
@inherits Volo.Blogging.Pages.Blog.BloggingPage
@section styles {
<abp-style-bundle @*name="@typeof(NewModel).FullName"*@>
@ -25,6 +24,7 @@
<abp-input asp-for="Post.Url" />
<abp-input asp-for="Post.Content" />
<abp-input asp-for="Post.Tags" />
<div class="form-group">

2
modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/New.cshtml.cs

@ -61,6 +61,8 @@ namespace Volo.Blogging.Pages.Blog.Posts
[HiddenInput]
[StringLength(PostConsts.MaxContentLength)]
public string Content { get; set; }
public string Tags { get; set; }
}
}
}

13
modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/detail.js

@ -0,0 +1,13 @@
(function ($) {
$('button[type="button"]').click(function () {
var data = $(this).attr('data-button');
if (data == '') {
return;
}
$('#repliedCommentId').val(data);
$('#textBoxId').focus();
});
})(jQuery);

2
modules/blogging/src/Volo.Blogging.Web/Volo.Blogging.Web.csproj

@ -32,6 +32,8 @@
<Content Remove="Pages\**\*.cshtml" />
<Content Remove="Localization\Resources\**\*.json" />
<Content Remove="Properties\launchSettings.json" />
<None Remove="Pages\Blog\Posts\detail.js" />
<EmbeddedResource Include="Pages\Blog\Posts\detail.js" />
<EmbeddedResource Include="Pages\Blog\Posts\edit.js" />
<EmbeddedResource Include="Pages\Blog\Posts\new.css" />
<EmbeddedResource Include="Pages\Blog\Posts\new.js" />

38
modules/blogging/test/Volo.Blogging.Application.Tests/Volo/Blogging/CommentAppService_Tests.cs

@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Shouldly;
using Volo.Blogging.Comments;
using Volo.Blogging.Posts;
using Xunit;
namespace Volo.Blogging
{
public class CommentAppService_Tests : BloggingApplicationTestBase
{
private readonly ICommentAppService _commentAppService;
private readonly ICommentRepository _commentRepository;
private readonly IPostRepository _postRepository;
public CommentAppService_Tests()
{
_commentAppService = GetRequiredService<ICommentAppService>(); ;
_commentRepository = GetRequiredService<ICommentRepository>(); ;
_postRepository = GetRequiredService<IPostRepository>(); ;
}
[Fact]
public async Task Should_Get_List_Of_Comments()
{
var post = await _postRepository.InsertAsync(new Post(Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid(), "asd", "asd"));
var comment1 = await _commentRepository.InsertAsync(new Comment(Guid.NewGuid(), post.Id, Guid.Empty, "qweasd"));
var comment2 = await _commentRepository.InsertAsync(new Comment(Guid.NewGuid(), post.Id, comment1.Id, "qweasd"));
var comments = await _commentRepository.GetListOfPostAsync(post.Id);
comments.Count.ShouldBe(2);
}
}
}
Loading…
Cancel
Save