Browse Source

blogging module basic read count

pull/441/head
Yunus Emre Kalkan 8 years ago
parent
commit
ff6f019c2e
  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. 4
      modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/BloggingTestAppDbContextModelSnapshot.cs
  4. 2
      modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Posts/IPostAppService.cs
  5. 2
      modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Posts/PostDto.cs
  6. 2
      modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Posts/PostWithDetailsDto.cs
  7. 4
      modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Posts/PostAppService.cs
  8. 9
      modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/Post.cs
  9. 6
      modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Detail.cshtml
  10. 2
      modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Detail.cshtml.cs
  11. 4
      modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Index.cshtml
  12. 2
      modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Tags/Posts.cshtml

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

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

@ -3,6 +3,8 @@ using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Volo.BloggingTestApp.EntityFrameworkCore;
namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
{
@ -412,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")

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

@ -11,7 +11,7 @@ namespace Volo.Blogging.Posts
Task<ListResultDto<PostWithDetailsDto>> GetListByBlogIdAndTagName(Guid blogId, string tagName);
Task<PostWithDetailsDto> GetByUrlAsync(GetPostInput input);
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; }
}
}

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

@ -15,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; }

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

@ -58,10 +58,12 @@ namespace Volo.Blogging.Posts
return new ListResultDto<PostWithDetailsDto>(all.Where(p=>p.Tags.Any(t=>t.Id == tag.Id)).ToList());
}
public async Task<PostWithDetailsDto> GetByUrlAsync(GetPostInput input)
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);

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

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

@ -28,18 +28,14 @@
</div>
<div class="hero-content">
<p class="tags">
<p class="tags">
@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>
</p>
<h1>
<a href="#">@Model.Post.Title</a>
</h1>
</div>
<div class="article-owner">
<div class="article-infos">
@ -52,7 +48,7 @@
</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="#">

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();

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

@ -69,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="#">
@ -208,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="#">

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

@ -73,7 +73,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="#">

Loading…
Cancel
Save