blogging module: member page has been edited and improvements have been made to the shipment detail page

pull/16503/head
Onur Pıçakcı 2 years ago
parent 9a1148e312
commit 9651fc22d8

@ -0,0 +1,226 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
{
/// <inheritdoc />
public partial class AddedBlogUserOptionals : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "Biography",
table: "BlgUsers",
type: "nvarchar(1000)",
maxLength: 1000,
nullable: true);
migrationBuilder.AddColumn<string>(
name: "Company",
table: "BlgUsers",
type: "nvarchar(128)",
maxLength: 128,
nullable: true);
migrationBuilder.AddColumn<string>(
name: "Github",
table: "BlgUsers",
type: "nvarchar(64)",
maxLength: 64,
nullable: true);
migrationBuilder.AddColumn<string>(
name: "JobTitle",
table: "BlgUsers",
type: "nvarchar(32)",
maxLength: 32,
nullable: true);
migrationBuilder.AddColumn<string>(
name: "Linkedin",
table: "BlgUsers",
type: "nvarchar(64)",
maxLength: 64,
nullable: true);
migrationBuilder.AddColumn<string>(
name: "Twitter",
table: "BlgUsers",
type: "nvarchar(64)",
maxLength: 64,
nullable: true);
migrationBuilder.AddColumn<string>(
name: "WebSite",
table: "BlgUsers",
type: "nvarchar(256)",
maxLength: 256,
nullable: true);
migrationBuilder.AddColumn<int>(
name: "EntityVersion",
table: "AbpUsers",
type: "int",
nullable: false,
defaultValue: 0);
migrationBuilder.AddColumn<DateTimeOffset>(
name: "LastPasswordChangeTime",
table: "AbpUsers",
type: "datetimeoffset",
nullable: true);
migrationBuilder.AddColumn<bool>(
name: "ShouldChangePasswordOnNextLogin",
table: "AbpUsers",
type: "bit",
nullable: false,
defaultValue: false);
migrationBuilder.AddColumn<int>(
name: "EntityVersion",
table: "AbpRoles",
type: "int",
nullable: false,
defaultValue: 0);
migrationBuilder.AddColumn<int>(
name: "EntityVersion",
table: "AbpOrganizationUnits",
type: "int",
nullable: false,
defaultValue: 0);
migrationBuilder.CreateTable(
name: "AbpPermissionGroups",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
Name = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
DisplayName = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AbpPermissionGroups", x => x.Id);
});
migrationBuilder.CreateTable(
name: "AbpPermissions",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
GroupName = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
Name = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
ParentName = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
DisplayName = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
IsEnabled = table.Column<bool>(type: "bit", nullable: false),
MultiTenancySide = table.Column<byte>(type: "tinyint", nullable: false),
Providers = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
StateCheckers = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AbpPermissions", x => x.Id);
});
migrationBuilder.CreateTable(
name: "AbpUserDelegations",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
SourceUserId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
TargetUserId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
StartTime = table.Column<DateTime>(type: "datetime2", nullable: false),
EndTime = table.Column<DateTime>(type: "datetime2", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AbpUserDelegations", x => x.Id);
});
migrationBuilder.CreateIndex(
name: "IX_AbpPermissionGroups_Name",
table: "AbpPermissionGroups",
column: "Name",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_AbpPermissions_GroupName",
table: "AbpPermissions",
column: "GroupName");
migrationBuilder.CreateIndex(
name: "IX_AbpPermissions_Name",
table: "AbpPermissions",
column: "Name",
unique: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "AbpPermissionGroups");
migrationBuilder.DropTable(
name: "AbpPermissions");
migrationBuilder.DropTable(
name: "AbpUserDelegations");
migrationBuilder.DropColumn(
name: "Biography",
table: "BlgUsers");
migrationBuilder.DropColumn(
name: "Company",
table: "BlgUsers");
migrationBuilder.DropColumn(
name: "Github",
table: "BlgUsers");
migrationBuilder.DropColumn(
name: "JobTitle",
table: "BlgUsers");
migrationBuilder.DropColumn(
name: "Linkedin",
table: "BlgUsers");
migrationBuilder.DropColumn(
name: "Twitter",
table: "BlgUsers");
migrationBuilder.DropColumn(
name: "WebSite",
table: "BlgUsers");
migrationBuilder.DropColumn(
name: "EntityVersion",
table: "AbpUsers");
migrationBuilder.DropColumn(
name: "LastPasswordChangeTime",
table: "AbpUsers");
migrationBuilder.DropColumn(
name: "ShouldChangePasswordOnNextLogin",
table: "AbpUsers");
migrationBuilder.DropColumn(
name: "EntityVersion",
table: "AbpRoles");
migrationBuilder.DropColumn(
name: "EntityVersion",
table: "AbpOrganizationUnits");
}
}
}

@ -19,10 +19,10 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer)
.HasAnnotation("ProductVersion", "6.0.0")
.HasAnnotation("ProductVersion", "7.0.1")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("Volo.Abp.BlobStoring.Database.DatabaseBlob", b =>
{
@ -183,6 +183,9 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
.HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp");
b.Property<int>("EntityVersion")
.HasColumnType("int");
b.Property<string>("ExtraProperties")
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
@ -369,6 +372,9 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
.HasDefaultValue(false)
.HasColumnName("EmailConfirmed");
b.Property<int>("EntityVersion")
.HasColumnType("int");
b.Property<string>("ExtraProperties")
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
@ -397,6 +403,9 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
.HasColumnType("uniqueidentifier")
.HasColumnName("LastModifierId");
b.Property<DateTimeOffset?>("LastPasswordChangeTime")
.HasColumnType("datetimeoffset");
b.Property<bool>("LockoutEnabled")
.ValueGeneratedOnAdd()
.HasColumnType("bit")
@ -445,6 +454,9 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
.HasColumnType("nvarchar(256)")
.HasColumnName("SecurityStamp");
b.Property<bool>("ShouldChangePasswordOnNextLogin")
.HasColumnType("bit");
b.Property<string>("Surname")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)")
@ -507,6 +519,33 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
b.ToTable("AbpUserClaims", (string)null);
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUserDelegation", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<DateTime>("EndTime")
.HasColumnType("datetime2");
b.Property<Guid>("SourceUserId")
.HasColumnType("uniqueidentifier");
b.Property<DateTime>("StartTime")
.HasColumnType("datetime2");
b.Property<Guid>("TargetUserId")
.HasColumnType("uniqueidentifier");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.HasKey("Id");
b.ToTable("AbpUserDelegations", (string)null);
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b =>
{
b.Property<Guid>("UserId")
@ -647,6 +686,9 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
.HasColumnType("nvarchar(128)")
.HasColumnName("DisplayName");
b.Property<int>("EntityVersion")
.HasColumnType("int");
b.Property<string>("ExtraProperties")
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
@ -708,6 +750,59 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
b.ToTable("AbpOrganizationUnitRoles", (string)null);
});
modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionDefinitionRecord", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("DisplayName")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("ExtraProperties")
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
b.Property<string>("GroupName")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<bool>("IsEnabled")
.HasColumnType("bit");
b.Property<byte>("MultiTenancySide")
.HasColumnType("tinyint");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("ParentName")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("Providers")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("StateCheckers")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.HasKey("Id");
b.HasIndex("GroupName");
b.HasIndex("Name")
.IsUnique();
b.ToTable("AbpPermissions", (string)null);
});
modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b =>
{
b.Property<Guid>("Id")
@ -742,6 +837,34 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
b.ToTable("AbpPermissionGrants", (string)null);
});
modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGroupDefinitionRecord", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("DisplayName")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("ExtraProperties")
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.HasKey("Id");
b.HasIndex("Name")
.IsUnique();
b.ToTable("AbpPermissionGroups", (string)null);
});
modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b =>
{
b.Property<Guid>("Id")
@ -1099,6 +1222,16 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("Biography")
.HasMaxLength(1000)
.HasColumnType("nvarchar(1000)")
.HasColumnName("Biography");
b.Property<string>("Company")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)")
.HasColumnName("Company");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasMaxLength(40)
@ -1121,10 +1254,25 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
b.Property<string>("Github")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)")
.HasColumnName("Github");
b.Property<bool>("IsActive")
.HasColumnType("bit")
.HasColumnName("IsActive");
b.Property<string>("JobTitle")
.HasMaxLength(32)
.HasColumnType("nvarchar(32)")
.HasColumnName("JobTitle");
b.Property<string>("Linkedin")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)")
.HasColumnName("Linkedin");
b.Property<string>("Name")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)")
@ -1150,12 +1298,22 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.Property<string>("Twitter")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)")
.HasColumnName("Twitter");
b.Property<string>("UserName")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)")
.HasColumnName("UserName");
b.Property<string>("WebSite")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)")
.HasColumnName("WebSite");
b.HasKey("Id");
b.ToTable("BlgUsers", (string)null);

@ -0,0 +1,38 @@
using System.ComponentModel.DataAnnotations;
using Volo.Blogging.Users;
namespace Volo.Blogging.Members;
public class CustomIdentityBlogUserUpdateDto
{
[StringLength(UserConsts.MaxNameLength)]
public string Name { get; set; }
[StringLength(UserConsts.MaxSurnameLength)]
public string Surname { get; set; }
[RegularExpression(@"^((?!\s).)*$", ErrorMessage= "PersonalSiteUrlValidationMessage")]
[StringLength(UserConsts.MaxWebSiteLength)]
public string WebSite { get; set; }
[RegularExpression(@"^((?!\s).)*$", ErrorMessage= "TwitterUserNameValidationMessage")]
[StringLength(UserConsts.MaxTwitterLength)]
public string Twitter { get; set; }
[RegularExpression(@"^((?!\s).)*$", ErrorMessage= "GitHubUserNameValidationMessage")]
[StringLength(UserConsts.MaxGithubLength)]
public string Github { get; set; }
[RegularExpression(@"^((?!\s).)*$", ErrorMessage= "LinkedinUrlValidationMessage")]
[StringLength(UserConsts.MaxLinkedinLength)]
public string Linkedin { get; set; }
[StringLength(UserConsts.MaxCompanyLength)]
public string Company { get; set; }
[StringLength(UserConsts.MaxJobTitleLength)]
public string JobTitle { get; set; }
[StringLength(UserConsts.MaxBiographyLength)]
public string Biography { get; set; }
}

@ -7,4 +7,6 @@ namespace Volo.Blogging.Members;
public interface IMemberAppService : IApplicationService
{
Task<BlogUserDto> FindAsync(string username);
Task UpdateUserProfileAsync(CustomIdentityBlogUserUpdateDto input);
}

@ -8,6 +8,10 @@ namespace Volo.Blogging.Posts
{
public Guid? TenantId { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
@ -17,7 +21,21 @@ namespace Volo.Blogging.Posts
public string PhoneNumber { get; set; }
public bool PhoneNumberConfirmed { get; set; }
public string WebSite { get; set; }
public string Twitter { get; set; }
public string Github { get; set; }
public string Linkedin { get; set; }
public string Company { get; set; }
public string JobTitle { get; set; }
public string Biography { get; set; }
public Dictionary<string, object> ExtraProperties { get; set; }
}
}

@ -26,4 +26,21 @@ public class MemberAppService : BloggingAppServiceBase, IMemberAppService
return ObjectMapper.Map<BlogUser, BlogUserDto>(user);
}
public async Task UpdateUserProfileAsync(CustomIdentityBlogUserUpdateDto input)
{
var user = await _userRepository.GetAsync(CurrentUser.Id.Value);
user.Name = input.Name;
user.Surname = input.Surname;
user.WebSite = input.WebSite;
user.Twitter = input.Twitter;
user.Github = input.Github;
user.Linkedin = input.Linkedin;
user.Company = input.Company;
user.JobTitle = input.JobTitle;
user.Biography = input.Biography;
await _userRepository.UpdateAsync(user);
}
}

@ -61,6 +61,17 @@
"FileUploadInfo": "Drag, drop, or paste a copied image.",
"PostDescriptionHint": "* Will be rendered in the article link preview, supports HTML",
"ReadMore": "Continue Reading",
"MemberNotPublishedPostYet": "No posts yet!"
"MemberNotPublishedPostYet": "No posts yet!",
"UpdateUserWebSiteInfo": "Example: https://johndoe.com",
"UpdateUserTwitterInfo": "Example: johndoe",
"UpdateUserGithubInfo": "Example: johndoe",
"UpdateUserLinkedinInfo": "Example: https://www.linkedin.com/...",
"UpdateUserCompanyInfo": "Example: Volosoft",
"UpdateUserJobTitleInfo": "Example: Software Developer",
"WebSite": "Web Site",
"UserName": "Username",
"FullURL": "Full URL",
"JobTitle": "Job Title",
"PersonalWebsite": "PERSONAL WEBSITE"
}
}

@ -0,0 +1,22 @@
namespace Volo.Blogging.Users;
public class UserConsts
{
public const int MaxNameLength = 64;
public const int MaxSurnameLength = 64;
public const int MaxBiographyLength = 1000;
public const int MaxWebSiteLength = 256;
public const int MaxTwitterLength = 64;
public const int MaxGithubLength = 64;
public const int MaxLinkedinLength = 64;
public const int MaxCompanyLength = 128;
public const int MaxJobTitleLength = 32;
}

@ -1,4 +1,5 @@
using System;
using JetBrains.Annotations;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Users;
@ -23,6 +24,27 @@ namespace Volo.Blogging.Users
public virtual string PhoneNumber { get; protected set; }
public virtual bool PhoneNumberConfirmed { get; protected set; }
[CanBeNull]
public string WebSite { get; set; }
[CanBeNull]
public string Twitter { get; set; }
[CanBeNull]
public string Github { get; set; }
[CanBeNull]
public string Linkedin { get; set; }
[CanBeNull]
public string Company { get; set; }
[CanBeNull]
public string JobTitle { get; set; }
[CanBeNull]
public string Biography { get; set; }
protected BlogUser()
{

@ -26,8 +26,16 @@ namespace Volo.Blogging.EntityFrameworkCore
builder.Entity<BlogUser>(b =>
{
b.ToTable(AbpBloggingDbProperties.DbTablePrefix + "Users", AbpBloggingDbProperties.DbSchema);
b.ConfigureByConvention();
b.Property<string>(nameof(BlogUser.Biography)).HasMaxLength(UserConsts.MaxBiographyLength).HasColumnName(nameof(BlogUser.Biography));
b.Property<string>(nameof(BlogUser.WebSite)).HasMaxLength(UserConsts.MaxWebSiteLength).HasColumnName(nameof(BlogUser.WebSite));
b.Property<string>(nameof(BlogUser.Twitter)).HasMaxLength(UserConsts.MaxTwitterLength).HasColumnName(nameof(BlogUser.Twitter));
b.Property<string>(nameof(BlogUser.Github)).HasMaxLength(UserConsts.MaxGithubLength).HasColumnName(nameof(BlogUser.Github));
b.Property<string>(nameof(BlogUser.Linkedin)).HasMaxLength(UserConsts.MaxLinkedinLength).HasColumnName(nameof(BlogUser.Linkedin));
b.Property<string>(nameof(BlogUser.Company)).HasMaxLength(UserConsts.MaxCompanyLength).HasColumnName(nameof(BlogUser.Company));
b.Property<string>(nameof(BlogUser.JobTitle)).HasMaxLength(UserConsts.MaxJobTitleLength).HasColumnName(nameof(BlogUser.JobTitle));
b.ConfigureAbpUser();
b.ApplyObjectExtensionMappings();

@ -25,4 +25,12 @@ public partial class MembersClientProxy : ClientProxyBase<IMemberAppService>, IM
{ typeof(string), username }
});
}
public Task UpdateUserProfileAsync(CustomIdentityBlogUserUpdateDto input)
{
return RequestAsync(nameof(UpdateUserProfileAsync), new ClientProxyRequestTypeValue
{
{ typeof(CustomIdentityBlogUserUpdateDto), input }
});
}
}

@ -1,4 +1,5 @@
@page
@using System.Globalization
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Http.Extensions
@using Microsoft.Extensions.Options
@ -11,6 +12,13 @@
@inject IAuthorizationService Authorization
@inject IOptionsSnapshot<BloggingTwitterOptions> twitterOptions
@using Microsoft.AspNetCore.Mvc.Localization
@using Microsoft.AspNetCore.Mvc.TagHelpers
@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Alert
@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Blockquote
@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button
@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Grid
@using Volo.Abp.AspNetCore.Mvc.UI.Bundling.TagHelpers
@using Volo.Blogging.Localization
@using Volo.Blogging.Pages.Blog
@inject IHtmlLocalizer<BloggingResource> L
@ -355,6 +363,51 @@
{
<a abp-button="Primary" class="btn-rounded float-end active mt-3" href="/Account/Login?returnUrl=@System.Web.HttpUtility.UrlEncode(@Request.Path)">@L["LeaveComment"]</a>
}
<div class="hero articles">
<div class="hero content">
<h3>More from @CultureInfo.CurrentCulture.TextInfo.ToTitleCase(Model.Post.Writer.UserName)</h3>
@for (var index = 1; index < Model.PostsList.Count && index < 5; index++)
{
var post = Model.PostsList[index];
<div class="post-item">
<div class="post-type-cont">
<a href="/members/@Model.Post.Writer.UserName" class="text-decoration-none">
<img gravatar-email="@Model.Post.Writer.Email" default-image="Identicon" class="post-member-img rounded-circle d-block"/>
</a>
<span class="post-type">
<i class="fas fa-pen-nib"></i>
@L["Blog"].Value.ToUpper()
</span>
</div>
<div class="post-detail-cont">
<div class="post-info fs-12 mb-2">
<a href="/members/@Model.Post.Writer.UserName" class="text-decoration-none">
<span class="text-dark dot">@Model.Post.Writer.UserName</span>
</a>
<span class="text-dark-200">@post.CreationTime.ToString("MMMM yyyy")</span>
</div>
<h2 class="post-title mt-2">
<a asp-page="./Detail" asp-route-postUrl="@post.Url">
@post.Title
</a>
</h2>
<p class="post-desc">
<a asp-page="./Detail" asp-route-postUrl="@post.Url">
@post.Description.TruncateWithPostfix(150)
</a>
<a asp-page="./Detail" asp-route-postUrl="@post.Url" class="readMore">@L["ReadMore"]</a>
</p>
</div>
<div class="post-img-cont">
<div class="post-list-span text-center post">
<img src="@post.CoverImage" class="box-articles">
</div>
</div>
</div>
}
</div>
</div>
</div>
</div>
</div>

@ -40,6 +40,8 @@ namespace Volo.Blogging.Pages.Blog.Posts
public BlogDto Blog { get; set; }
public List<PostWithDetailsDto> PostsList { get; set; }
public DetailModel(IPostAppService postAppService, IBlogAppService blogAppService, ICommentAppService commentAppService)
{
_postAppService = postAppService;
@ -79,6 +81,7 @@ namespace Volo.Blogging.Pages.Blog.Posts
{
Blog = await _blogAppService.GetByShortNameAsync(BlogShortName);
Post = await _postAppService.GetForReadingAsync(new GetPostInput { BlogId = Blog.Id, Url = PostUrl });
PostsList = await _postAppService.GetListByUserIdAsync(Post.Writer.Id);
CommentsWithReplies = await _commentAppService.GetHierarchicalListOfPostAsync(Post.Id);
CountComments();
}

@ -1,7 +1,12 @@
@page
@using System.Globalization
@using Microsoft.Extensions.Localization
@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab
@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Utils
@using Volo.Abp.AspNetCore.Mvc.UI.Bundling.TagHelpers
@using Volo.Abp.Users
@using Volo.Blogging
@using Volo.Blogging.Areas.Blog.Helpers.TagHelpers
@using Volo.Blogging.Localization
@model Volo.Blogging.Pages.Members.IndexModel
@inject IStringLocalizer<BloggingResource> L
@ -23,12 +28,69 @@
<div class="d-inline-block position-relative">
<img gravatar-email="@Model.User.Email" default-image="Identicon" class="post-member-img rounded-circle d-block"/>
</div>
@if (Model.User.UserName != null)
@if (Model.User.Name != null && Model.User.Surname != null)
{
<h2 class="m-0">@Model.User.UserName</h2>
<h2 class="m-1">@Model.User.Name @Model.User.Surname</h2>
}
<small class="d-block mt-4">@L["UserName"].Value.ToUpper()</small>
@if (Model.User.Company != null)
{
<h4 class="m-2">@Model.User.Company</h4>
}
@if (Model.User.JobTitle != null)
{
<h4>@Model.User.JobTitle</h4>
}
<small class="d-block">@L["UserName"].Value.ToUpper()</small>
<h5>@Model.User.UserName</h5>
@if (Model.User.WebSite != null)
{
<small>@L["PersonalWebsite"].Value.ToUpper()</small>
<h5>
<a href="@Model.User.WebSite">@Model.User.WebSite</a>
</h5>
}
@if (Model.User.Twitter != null || Model.User.Github != null || Model.User.Linkedin != null)
{
<small>@L["Social"].Value.ToUpper()</small>
<ul class="d-flex justify-content-center">
@if (Model.User.Twitter != null)
{
<li class="mx-3">
<a href="https://twitter.com/@Model.User.Twitter">
<div class="icon-twitter-v1"></div>
</a>
</li>
}
@if (Model.User.Github != null)
{
<li class="mx-3">
<a href="https://github.com/@Model.User.Github">
<div class="icon-github large bg-dark"></div>
</a>
</li>
}
@if (Model.User.Linkedin != null)
{
<li class="mx-3">
<a href="@Model.User.Linkedin">
<div class="icon-linkedin-v1"></div>
</a>
</li>
}
</ul>
}
@if (Model.User.Biography != null)
{
<div class="m-2 mt-4">
<small>@L["Biography"].Value.ToUpper()</small>
<p>@Model.User.Biography</p>
</div>
}
</div>
</div>
</div>
@ -36,7 +98,7 @@
{
<div class="col-md-8">
<abp-tabs>
<abp-tab name="all-posts" title="All Blog Posts">
<abp-tab name="all-posts" title="Blog Posts">
<div class="mt-4 pt-3">
@foreach (var post in Model.Posts)
{
@ -80,6 +142,42 @@
}
</div>
</abp-tab>
@if (CurrentUser.UserName == Model.User.UserName)
{
<abp-tab name="edit-profile" title="Edit Profile">
<div class="mt-4 mb-3 pt-3">
<form method="post" id="UpdateUserProfileForm">
<abp-row>
<abp-column size="_12" v-align="Center">
<abp-input class="form-control" asp-for="CustomUserUpdate.Name" required-symbol="false" label="@($"{L["Name"].Value} ({L["Optional"].Value})")" value="@Model.User.Name"></abp-input>
<abp-input class="form-control" asp-for="CustomUserUpdate.Surname" required-symbol="false" label="@($"{L["Surname"].Value} ({L["Optional"].Value})")" value="@Model.User.Surname"></abp-input>
<abp-input class="form-control" asp-for="CustomUserUpdate.WebSite" required-symbol="false" label="@($"{L["WebSite"].Value} ({L["Optional"].Value})")" value="@Model.User.WebSite" info="@L["UpdateUserWebSiteInfo"].Value"></abp-input>
<abp-input class="form-control" asp-for="CustomUserUpdate.Twitter" required-symbol="false" label="Twitter @($"{L["UserName"].Value} ({L["Optional"].Value})")" value="@Model.User.Twitter" info="@L["UpdateUserTwitterInfo"].Value"></abp-input>
<abp-input class="form-control" asp-for="CustomUserUpdate.Github" required-symbol="false" label="Github @($"{L["UserName"].Value} ({L["Optional"].Value})")" value="@Model.User.Github" info="@L["UpdateUserGithubInfo"].Value"></abp-input>
<abp-input class="form-control" asp-for="CustomUserUpdate.Linkedin" required-symbol="false" label="Linkedin @($"{L["FullURL"].Value} ({L["Optional"].Value})")" value="@Model.User.Linkedin" info="@L["UpdateUserLinkedinInfo"].Value"></abp-input>
<abp-input class="form-control" asp-for="CustomUserUpdate.Company" required-symbol="false" label="@($"{L["Company"].Value} ({L["Optional"].Value})")" value="@Model.User.Company" info="@L["UpdateUserCompanyInfo"].Value"></abp-input>
<abp-input class="form-control" asp-for="CustomUserUpdate.JobTitle" required-symbol="false" label="@($"{L["JobTitle"].Value} ({L["Optional"].Value})")" value="@Model.User.JobTitle" info="@L["UpdateUserJobTitleInfo"].Value"></abp-input>
<div class="mb-3">
<label class="form-label">@L["Biography"] (@L["Optional"])</label>
<textarea id="CustomUserUpdate_Biography" name="CustomUserUpdate.Biography" class="form-control " rows="7" data-val-length="The field Biography must be a string with a maximum length of 1000." data-val-length-max="1000" maxlength="1000">@Model.User.Biography</textarea>
</div>
</abp-column>
</abp-row>
<div class="d-grid gap-2">
<button id="btnSubmit" type="submit" class="btn btn-primary">@L["Submit"]</button>
</div>
</form>
</div>
</abp-tab>
}
</abp-tabs>
</div>
}

@ -23,6 +23,9 @@ public class IndexModel : AbpPageModel
public Dictionary<Guid, string> BlogShortNameMap { get; set; }
[BindProperty]
public CustomIdentityBlogUserUpdateDto CustomUserUpdate { get; set; }
public IndexModel(IPostAppService postAppService, IMemberAppService memberAppService, IBlogAppService blogAppService)
{
_postAppService = postAppService;
@ -51,6 +54,14 @@ public class IndexModel : AbpPageModel
return Page();
}
public async Task<IActionResult> OnPostAsync()
{
await _memberAppService.UpdateUserProfileAsync(CustomUserUpdate);
return Redirect($"/members/{CurrentUser.UserName}");
}
public string GetBlogPostUrl(PostWithDetailsDto post)
{
var blogShortName = BlogShortNameMap[post.BlogId];

Loading…
Cancel
Save