Browse Source

Merge branch 'master' of https://github.com/volosoft/abp

pull/441/head
Halil ibrahim Kalkan 8 years ago
parent
commit
7e664fb7c9
  1. 582
      modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20180906065034_Added_ReadCount_To_Post.Designer.cs
  2. 23
      modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20180906065034_Added_ReadCount_To_Post.cs
  3. 2
      modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/BloggingTestAppDbContextModelSnapshot.cs
  4. 11663
      modules/blogging/app/Volo.BloggingTestApp/Logs/logs.txt
  5. 15
      modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/BloggingPermissionDefinitionProvider.cs
  6. 32
      modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/BloggingPermissions.cs
  7. 2
      modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Blogs/IBlogAppService.cs
  8. 3
      modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Comments/Dtos/CommentDto.cs
  9. 5
      modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Comments/Dtos/CommentWithRepliesDto.cs
  10. 1
      modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Comments/ICommentAppService.cs
  11. 6
      modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Posts/IPostAppService.cs
  12. 2
      modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Posts/PostDto.cs
  13. 3
      modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Posts/PostWithDetailsDto.cs
  14. 3
      modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Posts/UpdatePostDto.cs
  15. 3
      modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Tagging/ITagAppService.cs
  16. 5
      modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Comments/CommentAppService.cs
  17. 32
      modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Posts/PostAppService.cs
  18. 43
      modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Tagging/TagAppService.cs
  19. 6
      modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Comments/CommentConsts.cs
  20. 6
      modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Tagging/TagConsts.cs
  21. 4
      modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Comments/Comment.cs
  22. 1
      modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Comments/ICommentRepository.cs
  23. 6
      modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/IPostTagRepository.cs
  24. 9
      modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/Post.cs
  25. 1
      modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/PostTag.cs
  26. 2
      modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Tagging/ITagRepository.cs
  27. 19
      modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Tagging/Tag.cs
  28. 1
      modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Comments/EfCoreCommentRepository.cs
  29. 2
      modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Posts/EfCorePostRepository.cs
  30. 5
      modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Posts/EfCorePostTagRepository.cs
  31. 6
      modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Tagging/EfCoreTagRepository.cs
  32. 6
      modules/blogging/src/Volo.Blogging.Web/AbpBloggingWebAutoMapperProfile.cs
  33. 33
      modules/blogging/src/Volo.Blogging.Web/BloggingMenuContributor.cs
  34. 9
      modules/blogging/src/Volo.Blogging.Web/BloggingWebModule.cs
  35. 7
      modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/en.json
  36. 9
      modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/tr.json
  37. 43
      modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Detail.cshtml
  38. 2
      modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Detail.cshtml.cs
  39. 26
      modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Index.cshtml
  40. 2
      modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Index.cshtml.cs
  41. 93
      modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Tags/Posts.cshtml
  42. 34
      modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Tags/Posts.cshtml.cs
  43. 2
      modules/blogging/test/Volo.Blogging.Application.Tests/Volo/Blogging/CommentAppService_Tests.cs

582
modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20180906065034_Added_ReadCount_To_Post.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("20180906065034_Added_ReadCount_To_Post")]
partial class Added_ReadCount_To_Post
{
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<int>("ReadCount");
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
}
}
}

23
modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20180906065034_Added_ReadCount_To_Post.cs

@ -0,0 +1,23 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
{
public partial class Added_ReadCount_To_Post : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<int>(
name: "ReadCount",
table: "BlgPosts",
nullable: false,
defaultValue: 0);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "ReadCount",
table: "BlgPosts");
}
}
}

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

@ -414,6 +414,8 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
b.Property<Guid?>("LastModifierId")
.HasColumnName("LastModifierId");
b.Property<int>("ReadCount");
b.Property<string>("Title")
.IsRequired()
.HasColumnName("Title")

11663
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/BloggingPermissionDefinitionProvider.cs

@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Localization;
using Volo.Blogging.Localization;
@ -22,6 +19,16 @@ namespace Volo.Blogging
posts.AddChild(BloggingPermissions.Posts.Update, L("Permission:Edit"));
posts.AddChild(BloggingPermissions.Posts.Delete, L("Permission:Delete"));
posts.AddChild(BloggingPermissions.Posts.Create, L("Permission:Create"));
var tags = bloggingGroup.AddPermission(BloggingPermissions.Tags.Default, L("Permission:Tag"));
tags.AddChild(BloggingPermissions.Tags.Update, L("Permission:Edit"));
tags.AddChild(BloggingPermissions.Tags.Delete, L("Permission:Delete"));
tags.AddChild(BloggingPermissions.Tags.Create, L("Permission:Create"));
var comments = bloggingGroup.AddPermission(BloggingPermissions.Comments.Default, L("Permission:Comments"));
comments.AddChild(BloggingPermissions.Comments.Update, L("Permission:Edit"));
comments.AddChild(BloggingPermissions.Comments.Delete, L("Permission:Delete"));
comments.AddChild(BloggingPermissions.Comments.Create, L("Permission:Create"));
}
private static LocalizableString L(string name)

32
modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/BloggingPermissions.cs

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Volo.Blogging
namespace Volo.Blogging
{
public class BloggingPermissions
{
@ -24,6 +20,22 @@ namespace Volo.Blogging
public const string Create = Default + ".Create";
}
public static class Tags
{
public const string Default = GroupName + ".Tag";
public const string Delete = Default + ".Delete";
public const string Update = Default + ".Update";
public const string Create = Default + ".Create";
}
public static class Comments
{
public const string Default = GroupName + ".Comment";
public const string Delete = Default + ".Delete";
public const string Update = Default + ".Update";
public const string Create = Default + ".Create";
}
public static string[] GetAll()
{
return new[]
@ -36,7 +48,15 @@ namespace Volo.Blogging
Posts.Default,
Posts.Delete,
Posts.Update,
Posts.Create
Posts.Create,
Tags.Default,
Tags.Delete,
Tags.Update,
Tags.Create,
Comments.Default,
Comments.Delete,
Comments.Update,
Comments.Create
};
}
}

2
modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Blogs/IBlogAppService.cs

@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;

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

@ -1,8 +1,5 @@
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
{

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

@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
using Volo.Abp.Application.Dtos;
using System.Collections.Generic;
namespace Volo.Blogging.Comments.Dtos
{

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

@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
using Volo.Blogging.Comments.Dtos;

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

@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
@ -11,7 +9,9 @@ namespace Volo.Blogging.Posts
{
Task<ListResultDto<PostWithDetailsDto>> GetListByBlogId(Guid id);
Task<PostWithDetailsDto> GetByUrlAsync(GetPostInput input);
Task<ListResultDto<PostWithDetailsDto>> GetListByBlogIdAndTagName(Guid blogId, string tagName);
Task<PostWithDetailsDto> GetForReadingAsync(GetPostInput input);
Task<PostWithDetailsDto> GetAsync(Guid id);

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

@ -11,6 +11,8 @@ namespace Volo.Blogging.Posts
public string Url { get; set; }
public int ReadCount { get; set; }
public string Content { get; set; }
}
}

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

@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Text;
using Volo.Abp.Application.Dtos;
using Volo.Blogging.Tagging.Dtos;
@ -16,6 +15,8 @@ namespace Volo.Blogging.Posts
public string Content { get; set; }
public int ReadCount { get; set; }
public int CommentCount { get; set; }
public List<TagDto> Tags { get; set; }

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

@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
using Volo.Abp.Application.Dtos;
namespace Volo.Blogging.Posts
{

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

@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
using Volo.Blogging.Tagging.Dtos;
@ -19,7 +18,7 @@ namespace Volo.Blogging.Tagging
Task DeleteAsync(Guid id);
Task<List<PopularTagDto>> GetPopularTags(GetPopularTagsInput input);
Task<List<TagDto>> GetPopularTags(GetPopularTagsInput input);
}
}

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

@ -1,12 +1,14 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Volo.Abp.Application.Services;
using Volo.Abp.Guids;
using Volo.Blogging.Comments.Dtos;
namespace Volo.Blogging.Comments
{
[Authorize(BloggingPermissions.Comments.Default)]
public class CommentAppService : ApplicationService, ICommentAppService
{
private readonly ICommentRepository _commentRepository;
@ -48,6 +50,7 @@ namespace Volo.Blogging.Comments
ObjectMapper.Map<List<Comment>, List<CommentDto>>(comments));
}
[Authorize(BloggingPermissions.Comments.Create)]
public async Task<CommentDto> CreateAsync(CreateCommentDto input)
{
var comment = new Comment(_guidGenerator.Create(), input.PostId, input.RepliedCommentId,input.Text);
@ -57,6 +60,7 @@ namespace Volo.Blogging.Comments
return ObjectMapper.Map<Comment, CommentDto>(comment);
}
[Authorize(BloggingPermissions.Comments.Update)]
public async Task<CommentDto> UpdateAsync(Guid id, UpdateCommentDto input)
{
var comment = await _commentRepository.GetAsync(id);
@ -68,6 +72,7 @@ namespace Volo.Blogging.Comments
return ObjectMapper.Map<Comment, CommentDto>(comment);
}
[Authorize(BloggingPermissions.Comments.Delete)]
public async Task DeleteAsync(Guid id)
{
await _commentRepository.DeleteAsync(id);

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

@ -5,10 +5,7 @@ using Volo.Abp.Application.Dtos;
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.Comments;
using Volo.Blogging.Tagging;
using Volo.Blogging.Tagging.Dtos;
@ -52,10 +49,21 @@ namespace Volo.Blogging.Posts
return new ListResultDto<PostWithDetailsDto>(postDtos);
}
public async Task<PostWithDetailsDto> GetByUrlAsync(GetPostInput input)
public async Task<ListResultDto<PostWithDetailsDto>> GetListByBlogIdAndTagName(Guid blogId, string tagName)
{
var all = (await GetListByBlogId(blogId)).Items;
var tag = await _tagRepository.GetByNameAsync(tagName);
return new ListResultDto<PostWithDetailsDto>(all.Where(p=>p.Tags.Any(t=>t.Id == tag.Id)).ToList());
}
public async Task<PostWithDetailsDto> GetForReadingAsync(GetPostInput input)
{
var post = await _postRepository.GetPostByUrl(input.BlogId, input.Url);
post.IncreaseReadCount();
var postDto = ObjectMapper.Map<Post, PostWithDetailsDto>(post);
var tagIds = (await _postTagRepository.GetListAsync()).Where(pt => pt.PostId == postDto.Id);
@ -125,6 +133,11 @@ namespace Volo.Blogging.Posts
foreach (var oldTag in oldTags)
{
await _postTagRepository.DeleteAsync(oldTag);
var tag = await _tagRepository.GetAsync(oldTag.TagId);
tag.DecreaseUsageCount();
await _tagRepository.UpdateAsync(tag);
}
var tags = await _tagRepository.GetListAsync();
@ -135,7 +148,12 @@ namespace Volo.Blogging.Posts
if (tag == null)
{
tag = await _tagRepository.InsertAsync(new Tag(newTag));
tag = await _tagRepository.InsertAsync(new Tag(newTag, 1));
}
else
{
tag.IncreaseUsageCount();
tag = await _tagRepository.UpdateAsync(tag);
}
await _postTagRepository.InsertAsync(new PostTag(post.Id, tag.Id));
@ -145,6 +163,10 @@ namespace Volo.Blogging.Posts
private List<string> SplitTags(string tags)
{
if (tags.IsNullOrWhiteSpace())
{
return new List<string>();
}
return new List<string>(tags.Split(",").Select(t=>t.Trim()));
}
}

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

@ -2,12 +2,14 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Volo.Abp.Application.Services;
using Volo.Blogging.Posts;
using Volo.Blogging.Tagging.Dtos;
namespace Volo.Blogging.Tagging
{
[Authorize(BloggingPermissions.Tags.Default)]
public class TagAppService : ApplicationService, ITagAppService
{
private readonly ITagRepository _tagRepository;
@ -35,11 +37,13 @@ namespace Volo.Blogging.Tagging
ObjectMapper.Map<List<Tag>, List<TagDto>>(tags));
}
[Authorize(BloggingPermissions.Tags.Create)]
public async Task<TagDto> CreateAsync(CreateTagDto input)
{
var newTag = await _tagRepository.InsertAsync(
new Tag(
input.Name,
input.Name,
0,
input.Description
)
);
@ -47,6 +51,7 @@ namespace Volo.Blogging.Tagging
return ObjectMapper.Map<Tag, TagDto>(newTag);
}
[Authorize(BloggingPermissions.Tags.Update)]
public async Task<TagDto> UpdateAsync(Guid id, UpdateTagDto input)
{
var tag = await _tagRepository.GetAsync(id);
@ -59,39 +64,21 @@ namespace Volo.Blogging.Tagging
return ObjectMapper.Map<Tag, TagDto>(tag);
}
[Authorize(BloggingPermissions.Tags.Delete)]
public async Task DeleteAsync(Guid id)
{
await _tagRepository.DeleteAsync(id);
}
public async Task<List<PopularTagDto>> GetPopularTags(GetPopularTagsInput input)
public async Task<List<TagDto>> GetPopularTags(GetPopularTagsInput input)
{
var postTags = await _postTagRepository.GetListAsync();
var postTagsGrouped = postTags.GroupBy(x => x.PostId)
.OrderByDescending(g => g.Count())
.SelectMany(g => g).Select(t=>t.TagId).Distinct().ToList();
var popularTagDtos = new List<PopularTagDto>();
for (var i = 0; i < input.ResultCount && i < postTagsGrouped.Count; i++)
{
var tagId = postTagsGrouped[i];
var count = postTags.Count(t => t.TagId == tagId);
if (count < input.MinimumPostCount)
{
break;
}
var tag = await _tagRepository.GetAsync(tagId);
popularTagDtos.Add(new PopularTagDto
{
Tag = ObjectMapper.Map<Tag, TagDto>(tag),
Count = count
});
}
return popularTagDtos;
var postTags = (await _tagRepository.GetListAsync()).OrderByDescending(t=>t.UsageCount)
.WhereIf(input.MinimumPostCount != null, t=>t.UsageCount >= input.MinimumPostCount)
.Take(input.ResultCount).ToList();
return new List<TagDto>(
ObjectMapper.Map<List<Tag>, List<TagDto>>(postTags));
}
}
}

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

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Volo.Blogging.Comments
namespace Volo.Blogging.Comments
{
public class CommentConsts
{

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

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Volo.Blogging.Tagging
namespace Volo.Blogging.Tagging
{
public class TagConsts
{

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

@ -1,11 +1,7 @@
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
{

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

@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;

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

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
using Volo.Abp.Domain.Repositories;
using Volo.Blogging.Tagging;
using Volo.Abp.Domain.Repositories;
namespace Volo.Blogging.Posts
{

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

@ -19,6 +19,9 @@ namespace Volo.Blogging.Posts
[CanBeNull]
public virtual string Content { get; set; }
[CanBeNull]
public virtual int ReadCount { get; protected set; }
public virtual Collection<PostTag> Tags { get; protected set; }
protected Post()
@ -37,6 +40,12 @@ namespace Volo.Blogging.Posts
Tags = new Collection<PostTag>();
}
public virtual Post IncreaseReadCount()
{
ReadCount++;
return this;
}
public virtual Post SetTitle([NotNull] string title)
{
Title = Check.NotNullOrWhiteSpace(title, nameof(title));

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

@ -1,6 +1,5 @@
using System;
using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp.MultiTenancy;
namespace Volo.Blogging.Posts
{

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

@ -9,6 +9,8 @@ namespace Volo.Blogging.Tagging
{
Task<List<Tag>> GetListAsync();
Task<Tag> GetByNameAsync(string name);
Task<List<Tag>> GetListAsync(IEnumerable<Guid> ids);
}
}

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

@ -1,9 +1,7 @@
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
{
@ -20,10 +18,11 @@ namespace Volo.Blogging.Tagging
}
public Tag([NotNull] string name, string description = null)
public Tag([NotNull] string name, int usageCount = 0, string description = null)
{
Name = Check.NotNullOrWhiteSpace(name, nameof(name));
Description = description;
UsageCount = usageCount;
}
public virtual void SetName(string name)
@ -31,6 +30,20 @@ namespace Volo.Blogging.Tagging
Name = Check.NotNullOrWhiteSpace(name, nameof(name));
}
public virtual void IncreaseUsageCount(int number = 1)
{
UsageCount += number;
}
public virtual void DecreaseUsageCount(int number = 1)
{
if (UsageCount <= 0)
{
return;
}
UsageCount -= number;
}
public virtual void SetDescription(string description)
{
Description = description;

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

@ -1,7 +1,6 @@
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;

2
modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Posts/EfCorePostRepository.cs

@ -1,13 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
using Volo.Blogging.Blogs;
using Volo.Blogging.EntityFrameworkCore;
namespace Volo.Blogging.Posts

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

@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
using Volo.Blogging.EntityFrameworkCore;

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

@ -1,7 +1,6 @@
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;
@ -22,6 +21,11 @@ namespace Volo.Blogging.Tagging
return await DbSet.ToListAsync();
}
public async Task<Tag> GetByNameAsync(string name)
{
return await DbSet.FirstOrDefaultAsync(t=>t.Name == name);
}
public async Task<List<Tag>> GetListAsync(IEnumerable<Guid> ids)
{
return await DbSet.Where(c => ids.Contains(c.Id)).ToListAsync();

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

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AutoMapper;
using AutoMapper;
using Volo.Abp.AutoMapper;
using Volo.Blogging.Pages.Blog.Posts;
using Volo.Blogging.Posts;

33
modules/blogging/src/Volo.Blogging.Web/BloggingMenuContributor.cs

@ -0,0 +1,33 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;
using Volo.Abp.UI.Navigation;
using Volo.Blogging.Localization;
namespace Volo.Blogging
{
public class BloggingMenuContributor : IMenuContributor
{
public async Task ConfigureMenuAsync(MenuConfigurationContext context)
{
if (context.Menu.Name == StandardMenus.Main)
{
await ConfigureMainMenu(context);
}
}
private async Task ConfigureMainMenu(MenuConfigurationContext context)
{
var authorizationService = context.ServiceProvider.GetRequiredService<IAuthorizationService>();
var l = context.ServiceProvider.GetRequiredService<IStringLocalizer<BloggingResource>>();
if (await authorizationService.IsGrantedAsync(BloggingPermissions.Blogs.Default))
{
var rootMenuItem = new ApplicationMenuItem("Blogs", l["Menu:Blogs"], "/Blog");
context.Menu.AddItem(rootMenuItem);
}
}
}
}

9
modules/blogging/src/Volo.Blogging.Web/BloggingWebModule.cs

@ -1,6 +1,5 @@
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;
using Volo.Abp.AspNetCore.Mvc.Localization;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap;
using Volo.Abp.AutoMapper;
@ -8,6 +7,7 @@ using Volo.Abp.Localization;
using Volo.Abp.Localization.Resources.AbpValidation;
using Volo.Abp.Modularity;
using Volo.Abp.UI;
using Volo.Abp.UI.Navigation;
using Volo.Abp.VirtualFileSystem;
using Volo.Blogging.Localization;
@ -30,6 +30,12 @@ namespace Volo.Blogging
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.Configure<NavigationOptions>(options =>
{
options.MenuContributors.Add(new BloggingMenuContributor());
});
context.Services.Configure<VirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<BloggingWebModule>("Volo.Blogging");
@ -56,6 +62,7 @@ namespace Volo.Blogging
options.Conventions.AddPageRoute("/Blog/Posts/Detail", "blog/{blogShortName}/{postUrl}");
options.Conventions.AddPageRoute("/Blog/Posts/Edit", "blog/{blogShortName}/posts/edit/{postId}");
options.Conventions.AddPageRoute("/Blog/Posts/New", "blog/{blogShortName}/posts/new");
options.Conventions.AddPageRoute("/Blog/Tags/Posts", "blog/{blogShortName}/{tagName}/posts");
});
context.Services.AddAssemblyOf<BloggingWebModule>();

7
modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/en.json

@ -1,6 +1,7 @@
{
"culture": "en",
"texts": {
"Menu:Blogs": "Blog",
"Title": "Title",
"ContinueReading": "Continue Reading",
"DaysAgo": "days ago",
@ -9,7 +10,11 @@
"PopularTags": "Popular Tags",
"Read": "Read",
"LastPosts": "Last Posts",
"LeaveComment": "Leave Comment",
"TagsInThisArticle": "Tags in this article",
"Posts": "Posts",
"Comment": "Comment"
"Edit": "Edit",
"Comment": "Comment",
"WhatIsNew": "What is new?"
}
}

9
modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/tr.json

@ -1,15 +1,20 @@
{
"culture": "tr",
"texts": {
"Menu:Blogs": "Blog",
"Title": "Başlık",
"ContinueReading": "Okumaya Devam",
"ContinueReading": "Devamı...",
"DaysAgo": "Gün Önce",
"Content": "İçerik",
"SeeAll": "Hepsini Gör",
"PopularTags": "Popüler Etiketler",
"Read": "Okunma",
"LastPosts": "Son Yazılar",
"LeaveComment": "Yorum Bırak",
"TagsInThisArticle": "Makalenin Etiketleri",
"Posts": "Yazılar",
"Comment": "Yorum"
"Edit": "Düzelt",
"Comment": "Yorum",
"WhatIsNew": "Yeniler"
}
}

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

@ -1,6 +1,9 @@
@page
@inherits Volo.Blogging.Pages.Blog.BloggingPage
@using Microsoft.AspNetCore.Authorization
@using Volo.Blogging
@using Volo.Blogging.Pages.Blog.Posts
@inject IAuthorizationService Authorization
@model DetailModel
@{
}
@ -21,40 +24,45 @@
<div class="col-md-12 mx-auto">
<section class="hero-section">
<div class="hero-articles">
<div class="img-container" style="min-height: 480px; background: url(https://cdn-images-1.medium.com/max/800/1*yFcPtGZXbm10e6v9WIXVOQ.png) center center no-repeat; background-size: cover; ">
<div class="img-container" style="min-height: 480px; background: url(https://placeimg.com/800/435/tech) center center no-repeat; background-size: cover; ">
</div>
<div class="hero-content">
<p class="tags">
<p class="tags">
@foreach (var tag in Model.Post.Tags)
{
<a href="#" class="tag">@tag.Name</a>
}
</p>
@foreach (var tag in Model.Post.Tags)
{
<a asp-page="/Blog/Tags/Posts" asp-route-blogShortName="@Model.BlogShortName" asp-route-tagName="@tag.Name" class="tag">@tag.Name</a>
}
</p>
<h1>
<a href="#">@Model.Post.Title</a>
</h1>
</div>
<div class="article-owner">
<div class="article-infos">
<div class="user-card">
<a href="#">
<img src="https://cdn-images-1.medium.com/fit/c/60/60/0*uarpjksge8Mloaa6.jpeg" class="article-avatar">
<img src="https://placeimg.com/60/60/people" class="article-avatar">
</a>
<a href="#">
<strong> @Model.Blog.Name</strong>, @Model.Post.CreationTime
<strong> Halil İbrahim Kalkan</strong>, @Model.Post.CreationTime.ToString("dd/MM/yyyy hh/mm")
</a>
<span class="seperator">|</span>
<a href="#">
<i class="fa fa-eye"></i> 156K @L["Read"]
<i class="fa fa-eye"></i> @Model.Post.ReadCount @L["Read"]
</a>
<span class="seperator">|</span>
<a href="#">
<i class="fa fa-comment"></i> @Model.CommentCount @L["Comment"]
</a>
@if (await Authorization.IsGrantedAsync(BloggingPermissions.Posts.Update))
{
<span class="seperator">|</span>
<a asp-page="./Edit" asp-route-postId="@Model.Post.Id" asp-route-blogShortName="@Model.BlogShortName">
<i class="fa fa-pencil"></i> @L["Edit"]
</a>
}
</div>
</div>
</div>
@ -74,7 +82,7 @@
<div class="row">
<div class="col-md-8 mx-auto">
<section class="post-content">
<p>@Model.FormattedContent</p>
<p>@Html.Raw(Model.FormattedContent)</p>
</section>
</div>
@ -84,13 +92,12 @@
<div class="row">
<div class="col-md-8 mx-auto">
<div class="tags">
<h5>Tags in this article</h5>
<h5>@L["TagsInThisArticle"]</h5>
@foreach (var tag in Model.Post.Tags)
{
<a href="#" class="tag">@tag.Name</a>
<a asp-page="/Blog/Tags/Posts" asp-route-blogShortName="@Model.BlogShortName" asp-route-tagName="@tag.Name" class="tag">@tag.Name</a>
}
</div>
<a asp-page="./Edit" asp-route-postId="@Model.Post.Id" asp-route-blogShortName="@Model.BlogShortName">@L["Edit"]</a>
<div class="comment-form mt-4">
<div class="clearfix bg-light p-4">
<h3 class="mt-0">@L["LeaveComment"]</h3>
@ -116,7 +123,7 @@
<div class="media-body">
<h5 class="comment-owner">
Armağan Ünlü
<span class="float-right">@commentWithRepliesDto.Comment.CreationTime</span>
<span class="float-right">@commentWithRepliesDto.Comment.CreationTime.ToString("dd/MM/yyyy hh/mm")</span>
</h5>
<p>
@commentWithRepliesDto.Comment.Text
@ -161,7 +168,7 @@
<div class="media-body">
<h5 class="comment-owner">
Zlatan Ibrahimovic
<span class="float-right">@reply.CreationTime</span>
<span class="float-right">@reply.CreationTime.ToString("dd/MM/yyyy hh/mm")</span>
</h5>
<p>
@reply.Text

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

@ -65,7 +65,7 @@ namespace Volo.Blogging.Pages.Blog.Posts
private async Task GetData()
{
Blog = await _blogAppService.GetByShortNameAsync(BlogShortName);
Post = await _postAppService.GetByUrlAsync(new GetPostInput { BlogId = Blog.Id, Url = PostUrl });
Post = await _postAppService.GetForReadingAsync(new GetPostInput { BlogId = Blog.Id, Url = PostUrl });
FormattedContent = RenderMarkdown(Post.Content);
CommentsWithReplies = await _commentAppService.GetHierarchicalListOfPostAsync(new GetCommentListOfPostAsync() { PostId = Post.Id });
CountComments();

26
modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Index.cshtml

@ -1,7 +1,9 @@
@page
@inherits Volo.Blogging.Pages.Blog.BloggingPage
@using Microsoft.AspNetCore.Authorization
@using Volo.Blogging
@using Volo.Blogging.Pages.Blog.Posts
@using Volo.Blogging.Posts
@inject IAuthorizationService Authorization
@model Volo.Blogging.Pages.Blog.Posts.IndexModel
@{
@ -22,7 +24,7 @@
<abp-style src="/Pages/Blog/Posts/blogcss/owlcarousel/dist/assets/owl.theme.green.min.css" />
</abp-style-bundle>
}
<a asp-page="./New" asp-route-blogShortName="@Model.BlogShortName">Create New Post</a>
<div class="container hero-container pb-5 bg-white">
<div class="row">
@ -44,14 +46,14 @@
<p class="tags">
@foreach (var tag in post.Tags)
{
<a href="#" class="tag">@tag.Name</a>
<a asp-page="/Blog/Tags/Posts" asp-route-blogShortName="@Model.BlogShortName" asp-route-tagName="@tag.Name" class="tag">@tag.Name</a>
}
</p>
<h2>
<a asp-page="./Detail" asp-route-postUrl="@post.Url" asp-route-blogShortName="@Model.BlogShortName">@post.Title</a>
</h2>
<p class="article-sum">
@(post.Content == null ? "" : (post.Content.Length > 150 ? post.Content.Substring(0,150) : post.Content))
@(post.Content == null ? "" : (post.Content.Length > 150 ? post.Content.Substring(0, 150) + "..." : post.Content))
</p>
<a asp-page="./Detail" asp-route-postUrl="@post.Url" asp-route-blogShortName="@Model.BlogShortName" class="btn btn-primary btn-rounded">@L["ContinueReading"]</a>
@ -67,7 +69,7 @@
</a>
<span class="seperator">|</span>
<a href="#">
<i class="fa fa-eye"></i> 156K @L["Read"]
<i class="fa fa-eye"></i> @post.ReadCount @L["Read"]
</a>
<span class="seperator">|</span>
<a href="#">
@ -92,7 +94,13 @@
</div>
<div class="col-md-4">
<h2>What is new?</h2>
@if (await Authorization.IsGrantedAsync(BloggingPermissions.Posts.Create))
{
<a asp-page="./New" asp-route-blogShortName="@Model.BlogShortName">Create New Post</a>
}
<h2>@L["WhatIsNew"]</h2>
<div class="list-group">
@for (var index = 0; index < Model.Posts.Count && index < 3; index++)
@ -180,7 +188,7 @@
<p class="tags">
@foreach (var tag in post.Tags)
{
<a href="#" class="tag">@tag.Name</a>
<a asp-page="/Blog/Tags/Posts" asp-route-blogShortName="@Model.BlogShortName" asp-route-tagName="@tag.Name" class="tag">@tag.Name</a>
}
</p>
<h3>
@ -200,7 +208,7 @@
</a>
<span class="seperator">|</span>
<a href="#">
<i class="fa fa-eye"></i> 156K
<i class="fa fa-eye"></i> @post.ReadCount
</a>
<span class="seperator">|</span>
<a href="#">
@ -226,7 +234,7 @@
<div class="popular-tags">
@foreach (var popularTag in Model.PopularTags)
{
<a href="#">@popularTag.Tag.Name <span>(@popularTag.Count @L["Posts"])</span></a>
<a asp-page="/Blog/Tags/Posts" asp-route-blogShortName="@Model.BlogShortName" asp-route-tagName="@popularTag.Name">@popularTag.Name <span>(@popularTag.UsageCount @L["Posts"])</span></a>
}
</div>

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

@ -20,7 +20,7 @@ namespace Volo.Blogging.Pages.Blog.Posts
public IReadOnlyList<PostWithDetailsDto> Posts { get; set; }
public IReadOnlyList<PopularTagDto> PopularTags { get; set; }
public IReadOnlyList<TagDto> PopularTags { get; set; }
public IndexModel(IPostAppService postAppService, IBlogAppService blogAppService, ITagAppService tagAppService)
{

93
modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Tags/Posts.cshtml

@ -0,0 +1,93 @@
@page
@inherits Volo.Blogging.Pages.Blog.BloggingPage
@using Volo.Blogging.Pages.Blog.Tags
@model PostsModel
@{
}
@section scripts {
<abp-script-bundle name="@typeof(PostsModel).FullName">
<abp-script src="/Pages/Blog/Posts/blogcss/blog.js" />
</abp-script-bundle>
}
@section styles {
<abp-style-bundle @*name="@typeof(DetailModel).FullName" *@>
<abp-style src="/Pages/Blog/Posts/blogcss/blog.css" />
</abp-style-bundle>
}
<div class="container last-post-section pb-5">
<div class="row">
<div class="col-md-8">
<div class="row">
<div class="col">
<div class="titline">
<h2>#@Model.TagName</h2>
</div>
</div>
</div>
@for (var index = 0; index < Model.Posts.Count; index++)
{
var post = Model.Posts[index];
var oddPost = index % 2 == 1;
<section class="box-articles">
<div class="row @(oddPost?"align-middle":"")">
<div class="col-md-4 order-md-@(oddPost?"last":"first")">
<div class="img-container">
<a asp-page="/Blog/Posts/Detail" asp-route-postUrl="@post.Url" asp-route-blogShortName="@Model.BlogShortName">
<img src="https://placeimg.com/480/270/tech" class="box-article-img">
</a>
<div class="user-link-icons">
<a class="add-bookmark" href="#">
<i class="fa fa-bookmark"></i>
</a>
<a class="share-article" href="#">
<i class="fa fa-share-alt"></i>
</a>
</div>
</div>
</div>
<div class="col-md-8 order-md-@(oddPost?"first":"last")">
<p class="tags">
@foreach (var tag in post.Tags)
{
<a asp-page="/Blog/Tags/Posts" asp-route-blogShortName="@Model.BlogShortName" asp-route-tagName="@tag.Name" class="tag">@tag.Name</a>
}
</p>
<h3>
<a asp-page="/Blog/Posts/Detail" asp-route-postUrl="@post.Url" asp-route-blogShortName="@Model.BlogShortName">@post.Title</a>
</h3>
<p>
@(post.Content == null ? "" : (post.Content.Length > 250 ? post.Content.Substring(0, 150) : post.Content))...
</p>
<div class="article-owner">
<div class="article-infos">
<div class="user-card">
<a href="#">
<img src="https://placeimg.com/120/120/pople" class="article-avatar">
</a>
<a href="#">
<strong>Armağan Ünlü</strong>, @((DateTime.Today - post.CreationTime).Days) @L["DaysAgo"]
</a>
<span class="seperator">|</span>
<a href="#">
<i class="fa fa-eye"></i> @post.ReadCount
</a>
<span class="seperator">|</span>
<a href="#">
<i class="fa fa-comment"></i> @post.CommentCount
</a>
</div>
</div>
</div>
</div>
</div>
</section>
}
</div>
</div>
</div>

34
modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Tags/Posts.cshtml.cs

@ -0,0 +1,34 @@
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Volo.Blogging.Blogs;
using Volo.Blogging.Posts;
namespace Volo.Blogging.Pages.Blog.Tags
{
public class PostsModel : PageModel
{
private readonly IPostAppService _postAppService;
private readonly IBlogAppService _blogAppService;
[BindProperty(SupportsGet = true)]
public string BlogShortName { get; set; }
[BindProperty(SupportsGet = true)]
public string TagName { get; set; }
public IReadOnlyList<PostWithDetailsDto> Posts { get; set; }
public PostsModel(IPostAppService postAppService, IBlogAppService blogAppService)
{
_postAppService = postAppService;
_blogAppService = blogAppService;
}
public async void OnGetAsync()
{
var blog = await _blogAppService.GetByShortNameAsync(BlogShortName);
Posts = (await _postAppService.GetListByBlogIdAndTagName(blog.Id, TagName)).Items;
}
}
}

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

@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Shouldly;
using Volo.Blogging.Comments;

Loading…
Cancel
Save