Browse Source

Merge pull request #19418 from abpframework/salihozkara/blogImprovements

Blogging module improvements and add single blog mode
pull/19537/head
oykuermann 2 years ago
committed by GitHub
parent
commit
0f14ed9d8b
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 1562
      modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20240404113615_SyncMigrations.Designer.cs
  2. 638
      modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20240404113615_SyncMigrations.cs
  3. 95
      modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/BloggingTestAppDbContextModelSnapshot.cs
  4. 1
      modules/blogging/app/Volo.BloggingTestApp/BloggingTestAppModule.cs
  5. 2
      modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Members/MemberAppService.cs
  6. 2
      modules/blogging/src/Volo.Blogging.Web/AbpBloggingWebAutoMapperProfile.cs
  7. 14
      modules/blogging/src/Volo.Blogging.Web/BloggingUrlOptions.cs
  8. 30
      modules/blogging/src/Volo.Blogging.Web/BloggingWebModule.cs
  9. 6
      modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/BloggingPageHelper.cs
  10. 25
      modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/BloggingPageModel.cs
  11. 3
      modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Index.cshtml
  12. 12
      modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Index.cshtml.cs
  13. 6
      modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Members/Index.cshtml
  14. 20
      modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Members/Index.cshtml.cs
  15. 0
      modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Members/Index.css
  16. 0
      modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Members/Index.js
  17. 24
      modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Detail.cshtml
  18. 26
      modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Detail.cshtml.cs
  19. 4
      modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Edit.cshtml
  20. 26
      modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Edit.cshtml.cs
  21. 43
      modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Index.cshtml
  22. 32
      modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Index.cshtml.cs
  23. 4
      modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/New.cshtml
  24. 22
      modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/New.cshtml.cs

1562
modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20240404113615_SyncMigrations.Designer.cs

File diff suppressed because it is too large

638
modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20240404113615_SyncMigrations.cs

@ -0,0 +1,638 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
{
/// <inheritdoc />
public partial class SyncMigrations : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "Twitter",
table: "BlgUsers",
type: "nvarchar(128)",
maxLength: 128,
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(64)",
oldMaxLength: 64,
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "Linkedin",
table: "BlgUsers",
type: "nvarchar(256)",
maxLength: 256,
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(64)",
oldMaxLength: 64,
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "JobTitle",
table: "BlgUsers",
type: "nvarchar(128)",
maxLength: 128,
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(32)",
oldMaxLength: 32,
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "Github",
table: "BlgUsers",
type: "nvarchar(256)",
maxLength: 256,
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(64)",
oldMaxLength: 64,
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "ExtraProperties",
table: "BlgUsers",
type: "nvarchar(max)",
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "nvarchar(max)",
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "ConcurrencyStamp",
table: "BlgUsers",
type: "nvarchar(40)",
maxLength: 40,
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "nvarchar(40)",
oldMaxLength: 40,
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "Company",
table: "BlgUsers",
type: "nvarchar(256)",
maxLength: 256,
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(128)",
oldMaxLength: 128,
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "ExtraProperties",
table: "BlgTags",
type: "nvarchar(max)",
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "nvarchar(max)",
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "ConcurrencyStamp",
table: "BlgTags",
type: "nvarchar(40)",
maxLength: 40,
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "nvarchar(40)",
oldMaxLength: 40,
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "ExtraProperties",
table: "BlgPosts",
type: "nvarchar(max)",
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "nvarchar(max)",
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "ConcurrencyStamp",
table: "BlgPosts",
type: "nvarchar(40)",
maxLength: 40,
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "nvarchar(40)",
oldMaxLength: 40,
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "ExtraProperties",
table: "BlgComments",
type: "nvarchar(max)",
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "nvarchar(max)",
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "ConcurrencyStamp",
table: "BlgComments",
type: "nvarchar(40)",
maxLength: 40,
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "nvarchar(40)",
oldMaxLength: 40,
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "ExtraProperties",
table: "BlgBlogs",
type: "nvarchar(max)",
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "nvarchar(max)",
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "ConcurrencyStamp",
table: "BlgBlogs",
type: "nvarchar(40)",
maxLength: 40,
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "nvarchar(40)",
oldMaxLength: 40,
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "ExtraProperties",
table: "AbpUsers",
type: "nvarchar(max)",
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "nvarchar(max)",
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "ConcurrencyStamp",
table: "AbpUsers",
type: "nvarchar(40)",
maxLength: 40,
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "nvarchar(40)",
oldMaxLength: 40,
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "ExtraProperties",
table: "AbpSecurityLogs",
type: "nvarchar(max)",
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "nvarchar(max)",
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "ConcurrencyStamp",
table: "AbpSecurityLogs",
type: "nvarchar(40)",
maxLength: 40,
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "nvarchar(40)",
oldMaxLength: 40,
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "ExtraProperties",
table: "AbpRoles",
type: "nvarchar(max)",
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "nvarchar(max)",
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "ConcurrencyStamp",
table: "AbpRoles",
type: "nvarchar(40)",
maxLength: 40,
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "nvarchar(40)",
oldMaxLength: 40,
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "ExtraProperties",
table: "AbpOrganizationUnits",
type: "nvarchar(max)",
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "nvarchar(max)",
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "ConcurrencyStamp",
table: "AbpOrganizationUnits",
type: "nvarchar(40)",
maxLength: 40,
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "nvarchar(40)",
oldMaxLength: 40,
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "ExtraProperties",
table: "AbpClaimTypes",
type: "nvarchar(max)",
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "nvarchar(max)",
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "ConcurrencyStamp",
table: "AbpClaimTypes",
type: "nvarchar(40)",
maxLength: 40,
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "nvarchar(40)",
oldMaxLength: 40,
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "ExtraProperties",
table: "AbpBlobs",
type: "nvarchar(max)",
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "nvarchar(max)",
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "ConcurrencyStamp",
table: "AbpBlobs",
type: "nvarchar(40)",
maxLength: 40,
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "nvarchar(40)",
oldMaxLength: 40,
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "ExtraProperties",
table: "AbpBlobContainers",
type: "nvarchar(max)",
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "nvarchar(max)",
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "ConcurrencyStamp",
table: "AbpBlobContainers",
type: "nvarchar(40)",
maxLength: 40,
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "nvarchar(40)",
oldMaxLength: 40,
oldNullable: true);
migrationBuilder.CreateTable(
name: "AbpSettingDefinitions",
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),
Description = table.Column<string>(type: "nvarchar(512)", maxLength: 512, nullable: true),
DefaultValue = table.Column<string>(type: "nvarchar(2048)", maxLength: 2048, nullable: true),
IsVisibleToClients = table.Column<bool>(type: "bit", nullable: false),
Providers = table.Column<string>(type: "nvarchar(1024)", maxLength: 1024, nullable: true),
IsInherited = table.Column<bool>(type: "bit", nullable: false),
IsEncrypted = table.Column<bool>(type: "bit", nullable: false),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AbpSettingDefinitions", x => x.Id);
});
migrationBuilder.CreateIndex(
name: "IX_AbpSettingDefinitions_Name",
table: "AbpSettingDefinitions",
column: "Name",
unique: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "AbpSettingDefinitions");
migrationBuilder.AlterColumn<string>(
name: "Twitter",
table: "BlgUsers",
type: "nvarchar(64)",
maxLength: 64,
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(128)",
oldMaxLength: 128,
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "Linkedin",
table: "BlgUsers",
type: "nvarchar(64)",
maxLength: 64,
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(256)",
oldMaxLength: 256,
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "JobTitle",
table: "BlgUsers",
type: "nvarchar(32)",
maxLength: 32,
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(128)",
oldMaxLength: 128,
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "Github",
table: "BlgUsers",
type: "nvarchar(64)",
maxLength: 64,
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(256)",
oldMaxLength: 256,
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "ExtraProperties",
table: "BlgUsers",
type: "nvarchar(max)",
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(max)");
migrationBuilder.AlterColumn<string>(
name: "ConcurrencyStamp",
table: "BlgUsers",
type: "nvarchar(40)",
maxLength: 40,
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(40)",
oldMaxLength: 40);
migrationBuilder.AlterColumn<string>(
name: "Company",
table: "BlgUsers",
type: "nvarchar(128)",
maxLength: 128,
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(256)",
oldMaxLength: 256,
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "ExtraProperties",
table: "BlgTags",
type: "nvarchar(max)",
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(max)");
migrationBuilder.AlterColumn<string>(
name: "ConcurrencyStamp",
table: "BlgTags",
type: "nvarchar(40)",
maxLength: 40,
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(40)",
oldMaxLength: 40);
migrationBuilder.AlterColumn<string>(
name: "ExtraProperties",
table: "BlgPosts",
type: "nvarchar(max)",
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(max)");
migrationBuilder.AlterColumn<string>(
name: "ConcurrencyStamp",
table: "BlgPosts",
type: "nvarchar(40)",
maxLength: 40,
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(40)",
oldMaxLength: 40);
migrationBuilder.AlterColumn<string>(
name: "ExtraProperties",
table: "BlgComments",
type: "nvarchar(max)",
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(max)");
migrationBuilder.AlterColumn<string>(
name: "ConcurrencyStamp",
table: "BlgComments",
type: "nvarchar(40)",
maxLength: 40,
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(40)",
oldMaxLength: 40);
migrationBuilder.AlterColumn<string>(
name: "ExtraProperties",
table: "BlgBlogs",
type: "nvarchar(max)",
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(max)");
migrationBuilder.AlterColumn<string>(
name: "ConcurrencyStamp",
table: "BlgBlogs",
type: "nvarchar(40)",
maxLength: 40,
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(40)",
oldMaxLength: 40);
migrationBuilder.AlterColumn<string>(
name: "ExtraProperties",
table: "AbpUsers",
type: "nvarchar(max)",
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(max)");
migrationBuilder.AlterColumn<string>(
name: "ConcurrencyStamp",
table: "AbpUsers",
type: "nvarchar(40)",
maxLength: 40,
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(40)",
oldMaxLength: 40);
migrationBuilder.AlterColumn<string>(
name: "ExtraProperties",
table: "AbpSecurityLogs",
type: "nvarchar(max)",
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(max)");
migrationBuilder.AlterColumn<string>(
name: "ConcurrencyStamp",
table: "AbpSecurityLogs",
type: "nvarchar(40)",
maxLength: 40,
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(40)",
oldMaxLength: 40);
migrationBuilder.AlterColumn<string>(
name: "ExtraProperties",
table: "AbpRoles",
type: "nvarchar(max)",
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(max)");
migrationBuilder.AlterColumn<string>(
name: "ConcurrencyStamp",
table: "AbpRoles",
type: "nvarchar(40)",
maxLength: 40,
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(40)",
oldMaxLength: 40);
migrationBuilder.AlterColumn<string>(
name: "ExtraProperties",
table: "AbpOrganizationUnits",
type: "nvarchar(max)",
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(max)");
migrationBuilder.AlterColumn<string>(
name: "ConcurrencyStamp",
table: "AbpOrganizationUnits",
type: "nvarchar(40)",
maxLength: 40,
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(40)",
oldMaxLength: 40);
migrationBuilder.AlterColumn<string>(
name: "ExtraProperties",
table: "AbpClaimTypes",
type: "nvarchar(max)",
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(max)");
migrationBuilder.AlterColumn<string>(
name: "ConcurrencyStamp",
table: "AbpClaimTypes",
type: "nvarchar(40)",
maxLength: 40,
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(40)",
oldMaxLength: 40);
migrationBuilder.AlterColumn<string>(
name: "ExtraProperties",
table: "AbpBlobs",
type: "nvarchar(max)",
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(max)");
migrationBuilder.AlterColumn<string>(
name: "ConcurrencyStamp",
table: "AbpBlobs",
type: "nvarchar(40)",
maxLength: 40,
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(40)",
oldMaxLength: 40);
migrationBuilder.AlterColumn<string>(
name: "ExtraProperties",
table: "AbpBlobContainers",
type: "nvarchar(max)",
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(max)");
migrationBuilder.AlterColumn<string>(
name: "ConcurrencyStamp",
table: "AbpBlobContainers",
type: "nvarchar(40)",
maxLength: 40,
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(40)",
oldMaxLength: 40);
}
}
}

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

@ -19,7 +19,7 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
#pragma warning disable 612, 618 #pragma warning disable 612, 618
modelBuilder modelBuilder
.HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer)
.HasAnnotation("ProductVersion", "7.0.1") .HasAnnotation("ProductVersion", "8.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 128); .HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
@ -32,6 +32,7 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
b.Property<string>("ConcurrencyStamp") b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken() .IsConcurrencyToken()
.IsRequired()
.HasMaxLength(40) .HasMaxLength(40)
.HasColumnType("nvarchar(40)") .HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp"); .HasColumnName("ConcurrencyStamp");
@ -44,6 +45,7 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
.HasColumnType("varbinary(max)"); .HasColumnType("varbinary(max)");
b.Property<string>("ExtraProperties") b.Property<string>("ExtraProperties")
.IsRequired()
.HasColumnType("nvarchar(max)") .HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties"); .HasColumnName("ExtraProperties");
@ -73,11 +75,13 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
b.Property<string>("ConcurrencyStamp") b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken() .IsConcurrencyToken()
.IsRequired()
.HasMaxLength(40) .HasMaxLength(40)
.HasColumnType("nvarchar(40)") .HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp"); .HasColumnName("ConcurrencyStamp");
b.Property<string>("ExtraProperties") b.Property<string>("ExtraProperties")
.IsRequired()
.HasColumnType("nvarchar(max)") .HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties"); .HasColumnName("ExtraProperties");
@ -105,6 +109,7 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
b.Property<string>("ConcurrencyStamp") b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken() .IsConcurrencyToken()
.IsRequired()
.HasMaxLength(40) .HasMaxLength(40)
.HasColumnType("nvarchar(40)") .HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp"); .HasColumnName("ConcurrencyStamp");
@ -114,6 +119,7 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
.HasColumnType("nvarchar(256)"); .HasColumnType("nvarchar(256)");
b.Property<string>("ExtraProperties") b.Property<string>("ExtraProperties")
.IsRequired()
.HasColumnType("nvarchar(max)") .HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties"); .HasColumnName("ExtraProperties");
@ -179,6 +185,7 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
b.Property<string>("ConcurrencyStamp") b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken() .IsConcurrencyToken()
.IsRequired()
.HasMaxLength(40) .HasMaxLength(40)
.HasColumnType("nvarchar(40)") .HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp"); .HasColumnName("ConcurrencyStamp");
@ -187,6 +194,7 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
.HasColumnType("int"); .HasColumnType("int");
b.Property<string>("ExtraProperties") b.Property<string>("ExtraProperties")
.IsRequired()
.HasColumnType("nvarchar(max)") .HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties"); .HasColumnName("ExtraProperties");
@ -279,6 +287,7 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
b.Property<string>("ConcurrencyStamp") b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken() .IsConcurrencyToken()
.IsRequired()
.HasMaxLength(40) .HasMaxLength(40)
.HasColumnType("nvarchar(40)") .HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp"); .HasColumnName("ConcurrencyStamp");
@ -291,6 +300,7 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
.HasColumnType("datetime2"); .HasColumnType("datetime2");
b.Property<string>("ExtraProperties") b.Property<string>("ExtraProperties")
.IsRequired()
.HasColumnType("nvarchar(max)") .HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties"); .HasColumnName("ExtraProperties");
@ -340,6 +350,7 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
b.Property<string>("ConcurrencyStamp") b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken() .IsConcurrencyToken()
.IsRequired()
.HasMaxLength(40) .HasMaxLength(40)
.HasColumnType("nvarchar(40)") .HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp"); .HasColumnName("ConcurrencyStamp");
@ -376,6 +387,7 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
.HasColumnType("int"); .HasColumnType("int");
b.Property<string>("ExtraProperties") b.Property<string>("ExtraProperties")
.IsRequired()
.HasColumnType("nvarchar(max)") .HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties"); .HasColumnName("ExtraProperties");
@ -660,6 +672,7 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
b.Property<string>("ConcurrencyStamp") b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken() .IsConcurrencyToken()
.IsRequired()
.HasMaxLength(40) .HasMaxLength(40)
.HasColumnType("nvarchar(40)") .HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp"); .HasColumnName("ConcurrencyStamp");
@ -690,6 +703,7 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
.HasColumnType("int"); .HasColumnType("int");
b.Property<string>("ExtraProperties") b.Property<string>("ExtraProperties")
.IsRequired()
.HasColumnType("nvarchar(max)") .HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties"); .HasColumnName("ExtraProperties");
@ -898,6 +912,55 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
b.ToTable("AbpSettings", (string)null); b.ToTable("AbpSettings", (string)null);
}); });
modelBuilder.Entity("Volo.Abp.SettingManagement.SettingDefinitionRecord", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("DefaultValue")
.HasMaxLength(2048)
.HasColumnType("nvarchar(2048)");
b.Property<string>("Description")
.HasMaxLength(512)
.HasColumnType("nvarchar(512)");
b.Property<string>("DisplayName")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("ExtraProperties")
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
b.Property<bool>("IsEncrypted")
.HasColumnType("bit");
b.Property<bool>("IsInherited")
.HasColumnType("bit");
b.Property<bool>("IsVisibleToClients")
.HasColumnType("bit");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("Providers")
.HasMaxLength(1024)
.HasColumnType("nvarchar(1024)");
b.HasKey("Id");
b.HasIndex("Name")
.IsUnique();
b.ToTable("AbpSettingDefinitions", (string)null);
});
modelBuilder.Entity("Volo.Blogging.Blogs.Blog", b => modelBuilder.Entity("Volo.Blogging.Blogs.Blog", b =>
{ {
b.Property<Guid>("Id") b.Property<Guid>("Id")
@ -906,6 +969,7 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
b.Property<string>("ConcurrencyStamp") b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken() .IsConcurrencyToken()
.IsRequired()
.HasMaxLength(40) .HasMaxLength(40)
.HasColumnType("nvarchar(40)") .HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp"); .HasColumnName("ConcurrencyStamp");
@ -932,6 +996,7 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
.HasColumnName("Description"); .HasColumnName("Description");
b.Property<string>("ExtraProperties") b.Property<string>("ExtraProperties")
.IsRequired()
.HasColumnType("nvarchar(max)") .HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties"); .HasColumnName("ExtraProperties");
@ -974,6 +1039,7 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
b.Property<string>("ConcurrencyStamp") b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken() .IsConcurrencyToken()
.IsRequired()
.HasMaxLength(40) .HasMaxLength(40)
.HasColumnType("nvarchar(40)") .HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp"); .HasColumnName("ConcurrencyStamp");
@ -995,6 +1061,7 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
.HasColumnName("DeletionTime"); .HasColumnName("DeletionTime");
b.Property<string>("ExtraProperties") b.Property<string>("ExtraProperties")
.IsRequired()
.HasColumnType("nvarchar(max)") .HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties"); .HasColumnName("ExtraProperties");
@ -1047,6 +1114,7 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
b.Property<string>("ConcurrencyStamp") b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken() .IsConcurrencyToken()
.IsRequired()
.HasMaxLength(40) .HasMaxLength(40)
.HasColumnType("nvarchar(40)") .HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp"); .HasColumnName("ConcurrencyStamp");
@ -1083,6 +1151,7 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
.HasColumnName("Description"); .HasColumnName("Description");
b.Property<string>("ExtraProperties") b.Property<string>("ExtraProperties")
.IsRequired()
.HasColumnType("nvarchar(max)") .HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties"); .HasColumnName("ExtraProperties");
@ -1158,6 +1227,7 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
b.Property<string>("ConcurrencyStamp") b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken() .IsConcurrencyToken()
.IsRequired()
.HasMaxLength(40) .HasMaxLength(40)
.HasColumnType("nvarchar(40)") .HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp"); .HasColumnName("ConcurrencyStamp");
@ -1184,6 +1254,7 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
.HasColumnName("Description"); .HasColumnName("Description");
b.Property<string>("ExtraProperties") b.Property<string>("ExtraProperties")
.IsRequired()
.HasColumnType("nvarchar(max)") .HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties"); .HasColumnName("ExtraProperties");
@ -1228,12 +1299,13 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
.HasColumnName("Biography"); .HasColumnName("Biography");
b.Property<string>("Company") b.Property<string>("Company")
.HasMaxLength(128) .HasMaxLength(256)
.HasColumnType("nvarchar(128)") .HasColumnType("nvarchar(256)")
.HasColumnName("Company"); .HasColumnName("Company");
b.Property<string>("ConcurrencyStamp") b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken() .IsConcurrencyToken()
.IsRequired()
.HasMaxLength(40) .HasMaxLength(40)
.HasColumnType("nvarchar(40)") .HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp"); .HasColumnName("ConcurrencyStamp");
@ -1251,12 +1323,13 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
.HasColumnName("EmailConfirmed"); .HasColumnName("EmailConfirmed");
b.Property<string>("ExtraProperties") b.Property<string>("ExtraProperties")
.IsRequired()
.HasColumnType("nvarchar(max)") .HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties"); .HasColumnName("ExtraProperties");
b.Property<string>("Github") b.Property<string>("Github")
.HasMaxLength(64) .HasMaxLength(256)
.HasColumnType("nvarchar(64)") .HasColumnType("nvarchar(256)")
.HasColumnName("Github"); .HasColumnName("Github");
b.Property<bool>("IsActive") b.Property<bool>("IsActive")
@ -1264,13 +1337,13 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
.HasColumnName("IsActive"); .HasColumnName("IsActive");
b.Property<string>("JobTitle") b.Property<string>("JobTitle")
.HasMaxLength(32) .HasMaxLength(128)
.HasColumnType("nvarchar(32)") .HasColumnType("nvarchar(128)")
.HasColumnName("JobTitle"); .HasColumnName("JobTitle");
b.Property<string>("Linkedin") b.Property<string>("Linkedin")
.HasMaxLength(64) .HasMaxLength(256)
.HasColumnType("nvarchar(64)") .HasColumnType("nvarchar(256)")
.HasColumnName("Linkedin"); .HasColumnName("Linkedin");
b.Property<string>("Name") b.Property<string>("Name")
@ -1299,8 +1372,8 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
.HasColumnName("TenantId"); .HasColumnName("TenantId");
b.Property<string>("Twitter") b.Property<string>("Twitter")
.HasMaxLength(64) .HasMaxLength(128)
.HasColumnType("nvarchar(64)") .HasColumnType("nvarchar(128)")
.HasColumnName("Twitter"); .HasColumnName("Twitter");
b.Property<string>("UserName") b.Property<string>("UserName")

1
modules/blogging/app/Volo.BloggingTestApp/BloggingTestAppModule.cs

@ -78,6 +78,7 @@ namespace Volo.BloggingTestApp
Configure<BloggingUrlOptions>(options => Configure<BloggingUrlOptions>(options =>
{ {
options.RoutePrefix = null; options.RoutePrefix = null;
options.SingleBlogMode.Enabled = true;
}); });
Configure<AbpDbConnectionOptions>(options => Configure<AbpDbConnectionOptions>(options =>

2
modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Members/MemberAppService.cs

@ -17,7 +17,7 @@ public class MemberAppService : BloggingAppServiceBase, IMemberAppService
public virtual async Task<BlogUserDto> FindAsync(string username) public virtual async Task<BlogUserDto> FindAsync(string username)
{ {
var user = await _userRepository.FindAsync(x => x.UserName == username); var user = await _userRepository.FindAsync(x => x.UserName == username && x.IsActive);
if (user == null) if (user == null)
{ {

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

@ -1,6 +1,6 @@
using AutoMapper; using AutoMapper;
using Volo.Abp.AutoMapper; using Volo.Abp.AutoMapper;
using Volo.Blogging.Pages.Blog.Posts; using Volo.Blogging.Pages.Blogs.Posts;
using Volo.Blogging.Posts; using Volo.Blogging.Posts;
namespace Volo.Blogging namespace Volo.Blogging

14
modules/blogging/src/Volo.Blogging.Web/BloggingUrlOptions.cs

@ -20,6 +20,9 @@ namespace Volo.Blogging
/// Used to specify ignore paths if the route prefix is null or empty. /// Used to specify ignore paths if the route prefix is null or empty.
/// </summary> /// </summary>
public List<string> IgnoredPaths { get; } = new (); public List<string> IgnoredPaths { get; } = new ();
public SingleBlogModeOptions SingleBlogMode { get; } = new ();
private string GetFormattedRoutePrefix() private string GetFormattedRoutePrefix()
{ {
@ -31,4 +34,15 @@ namespace Volo.Blogging
return _routePrefix.EnsureEndsWith('/').EnsureStartsWith('/'); return _routePrefix.EnsureEndsWith('/').EnsureStartsWith('/');
} }
} }
public class SingleBlogModeOptions
{
/// <summary>
/// Determines whether to enable single blog mode by removing the blog name from the routing.
/// When enabled, only a single blog is allowed within the module.
/// </summary>
public bool Enabled { get; set; }
public string BlogName { get; set; }
}
} }

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

@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Mvc.RazorPages; using System;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
@ -79,7 +80,7 @@ namespace Volo.Blogging
options.IgnoredPaths.AddRange(new[] options.IgnoredPaths.AddRange(new[]
{ {
"error", "ApplicationConfigurationScript", "ServiceProxyScript", "Languages/Switch", "error", "ApplicationConfigurationScript", "ServiceProxyScript", "Languages/Switch",
"ApplicationLocalizationScript" "ApplicationLocalizationScript", "members"
}); });
}); });
@ -91,11 +92,26 @@ namespace Volo.Blogging
var routePrefix = urlOptions.RoutePrefix; var routePrefix = urlOptions.RoutePrefix;
options.Conventions.AddPageRoute("/Blogs/Posts/Index", routePrefix + "{blogShortName:blogNameConstraint}"); if (urlOptions.SingleBlogMode.Enabled)
options.Conventions.AddPageRoute("/Blogs/Posts/Detail", routePrefix + "{blogShortName:blogNameConstraint}/{postUrl}"); {
options.Conventions.AddPageRoute("/Blogs/Posts/Edit", routePrefix + "{blogShortName}/posts/{postId}/edit"); options.Conventions.AddPageRoute("/Blogs/Posts/Index", routePrefix);
options.Conventions.AddPageRoute("/Blogs/Posts/New", routePrefix + "{blogShortName}/posts/new"); options.Conventions.AddPageRoute("/Blogs/Posts/Detail", routePrefix + "{postUrl}");
options.Conventions.AddPageRoute("/Members/Index", routePrefix + "members/{userName}"); options.Conventions.AddPageRoute("/Blogs/Posts/Edit", routePrefix + "posts/{postId}/edit");
options.Conventions.AddPageRoute("/Blogs/Posts/New", routePrefix + "posts/new");
}
else
{
if (!routePrefix.IsNullOrWhiteSpace())
{
options.Conventions.AddPageRoute("/Blogs/Index", routePrefix);
}
options.Conventions.AddPageRoute("/Blogs/Posts/Index", routePrefix + "{blogShortName:blogNameConstraint}");
options.Conventions.AddPageRoute("/Blogs/Posts/Detail", routePrefix + "{blogShortName:blogNameConstraint}/{postUrl}");
options.Conventions.AddPageRoute("/Blogs/Posts/Edit", routePrefix + "{blogShortName}/posts/{postId}/edit");
options.Conventions.AddPageRoute("/Blogs/Posts/New", routePrefix + "{blogShortName}/posts/new");
}
options.Conventions.AddPageRoute("/Blogs/Members/Index", routePrefix + "members/{userName}");
}); });
Configure<DynamicJavaScriptProxyOptions>(options => Configure<DynamicJavaScriptProxyOptions>(options =>

6
modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/BloggingPageHelper.cs

@ -1,16 +1,14 @@
using System; using System;
using System.Globalization;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using Markdig;
using Microsoft.AspNetCore.Html; using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Mvc.Localization; using Microsoft.AspNetCore.Mvc.Localization;
using Markdig;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.Localization;
using Volo.Blogging.Localization; using Volo.Blogging.Localization;
namespace Volo.Blogging.Pages.Blog namespace Volo.Blogging.Pages.Blogs
{ {
public class BloggingPageHelper : ITransientDependency public class BloggingPageHelper : ITransientDependency
{ {

25
modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/BloggingPageModel.cs

@ -1,6 +1,11 @@
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; using System;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages;
using Volo.Blogging.Blogs;
using Volo.Blogging.Blogs.Dtos;
namespace Volo.Blogging.Pages.Blog namespace Volo.Blogging.Pages.Blogs
{ {
public abstract class BloggingPageModel : AbpPageModel public abstract class BloggingPageModel : AbpPageModel
{ {
@ -8,5 +13,21 @@ namespace Volo.Blogging.Pages.Blog
{ {
ObjectMapperContext = typeof(BloggingWebModule); ObjectMapperContext = typeof(BloggingWebModule);
} }
protected async Task<BlogDto> GetBlogAsync(IBlogAppService blogAppService, BloggingUrlOptions blogOptions, string blogShortName)
{
if (!blogOptions.SingleBlogMode.Enabled)
{
return await blogAppService.GetByShortNameAsync(blogShortName);
}
if (!blogOptions.SingleBlogMode.BlogName.IsNullOrEmpty())
{
return await blogAppService.GetByShortNameAsync(blogOptions.SingleBlogMode.BlogName);
}
var blogs = await blogAppService.GetListAsync();
return blogs.Items.Count == 1 ? blogs.Items[0] : blogs.Items.SingleOrDefault(x => x.ShortName == blogShortName);
}
} }
} }

3
modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Index.cshtml

@ -1,9 +1,8 @@
@page @page
@using Volo.Blogging.Pages.Blog
@using Microsoft.AspNetCore.Mvc.Localization @using Microsoft.AspNetCore.Mvc.Localization
@using Volo.Blogging.Localization @using Volo.Blogging.Localization
@inject IHtmlLocalizer<BloggingResource> L @inject IHtmlLocalizer<BloggingResource> L
@model IndexModel @model Volo.Blogging.Pages.Blogs.IndexModel
@{ @{
ViewBag.PageTitle = "Blogs"; ViewBag.PageTitle = "Blogs";
} }

12
modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Index.cshtml.cs

@ -1,25 +1,33 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; using Volo.Abp.AspNetCore.Mvc.UI.RazorPages;
using Volo.Blogging.Blogs; using Volo.Blogging.Blogs;
using Volo.Blogging.Blogs.Dtos; using Volo.Blogging.Blogs.Dtos;
namespace Volo.Blogging.Pages.Blog namespace Volo.Blogging.Pages.Blogs
{ {
public class IndexModel : AbpPageModel public class IndexModel : AbpPageModel
{ {
private readonly IBlogAppService _blogAppService; private readonly IBlogAppService _blogAppService;
private readonly BloggingUrlOptions _blogOptions;
public IReadOnlyList<BlogDto> Blogs { get; private set; } public IReadOnlyList<BlogDto> Blogs { get; private set; }
public IndexModel(IBlogAppService blogAppService) public IndexModel(IBlogAppService blogAppService, IOptions<BloggingUrlOptions> blogOptions)
{ {
_blogAppService = blogAppService; _blogAppService = blogAppService;
_blogOptions = blogOptions.Value;
} }
public virtual async Task<IActionResult> OnGetAsync() public virtual async Task<IActionResult> OnGetAsync()
{ {
if (_blogOptions.SingleBlogMode.Enabled)
{
return RedirectToPage("./Posts/Index");
}
var result = await _blogAppService.GetListAsync(); var result = await _blogAppService.GetListAsync();
if (result.Items.Count == 1) if (result.Items.Count == 1)

6
modules/blogging/src/Volo.Blogging.Web/Pages/Members/Index.cshtml → modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Members/Index.cshtml

@ -5,7 +5,7 @@
@using Volo.Abp.Users @using Volo.Abp.Users
@using Volo.Blogging.Areas.Blog.Helpers.TagHelpers @using Volo.Blogging.Areas.Blog.Helpers.TagHelpers
@using Volo.Blogging.Localization @using Volo.Blogging.Localization
@model Volo.Blogging.Pages.Members.IndexModel @model Volo.Blogging.Pages.Blogs.Members.IndexModel
@inject IStringLocalizer<BloggingResource> L @inject IStringLocalizer<BloggingResource> L
@inject ICurrentUser CurrentUser @inject ICurrentUser CurrentUser
@{ @{
@ -13,11 +13,11 @@
} }
@section scripts { @section scripts {
<abp-script src="/Pages/Members/Index.js" /> <abp-script src="/Pages/Blogs/Members/Index.js" />
} }
@section styles { @section styles {
<abp-style src="/Pages/Members/Index.css"/> <abp-style src="/Pages/Blogs/Members/Index.css"/>
} }
<main> <main>

20
modules/blogging/src/Volo.Blogging.Web/Pages/Members/Index.cshtml.cs → modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Members/Index.cshtml.cs

@ -3,12 +3,13 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; using Volo.Abp.AspNetCore.Mvc.UI.RazorPages;
using Volo.Blogging.Blogs; using Volo.Blogging.Blogs;
using Volo.Blogging.Members; using Volo.Blogging.Members;
using Volo.Blogging.Posts; using Volo.Blogging.Posts;
namespace Volo.Blogging.Pages.Members; namespace Volo.Blogging.Pages.Blogs.Members;
public class IndexModel : AbpPageModel public class IndexModel : AbpPageModel
{ {
@ -18,6 +19,8 @@ public class IndexModel : AbpPageModel
private readonly IBlogAppService _blogAppService; private readonly IBlogAppService _blogAppService;
private readonly BloggingUrlOptions _blogOptions;
public BlogUserDto User { get; set; } public BlogUserDto User { get; set; }
public List<PostWithDetailsDto> Posts { get; set; } public List<PostWithDetailsDto> Posts { get; set; }
@ -26,11 +29,12 @@ public class IndexModel : AbpPageModel
[BindProperty] [BindProperty]
public CustomIdentityBlogUserUpdateDto CustomUserUpdate { get; set; } public CustomIdentityBlogUserUpdateDto CustomUserUpdate { get; set; }
public IndexModel(IPostAppService postAppService, IMemberAppService memberAppService, IBlogAppService blogAppService) public IndexModel(IPostAppService postAppService, IMemberAppService memberAppService, IBlogAppService blogAppService, IOptions<BloggingUrlOptions> blogOptions)
{ {
_postAppService = postAppService; _postAppService = postAppService;
_memberAppService = memberAppService; _memberAppService = memberAppService;
_blogAppService = blogAppService; _blogAppService = blogAppService;
_blogOptions = blogOptions.Value;
} }
public async Task<IActionResult> OnGetAsync(string userName) public async Task<IActionResult> OnGetAsync(string userName)
@ -58,20 +62,24 @@ public class IndexModel : AbpPageModel
public async Task<IActionResult> OnPostAsync() public async Task<IActionResult> OnPostAsync()
{ {
await _memberAppService.UpdateUserProfileAsync(CustomUserUpdate); await _memberAppService.UpdateUserProfileAsync(CustomUserUpdate);
return RedirectToPage("/Blogs/Members/Index", new { userName = CurrentUser.UserName });
return Redirect($"/members/{CurrentUser.UserName}");
} }
public string GetBlogPostUrl(PostWithDetailsDto post) public string GetBlogPostUrl(PostWithDetailsDto post)
{ {
if (_blogOptions.SingleBlogMode.Enabled)
{
return Url.Page("/Blogs/Posts/Detail", new { postUrl = post.Url });
}
var blogShortName = BlogShortNameMap[post.BlogId]; var blogShortName = BlogShortNameMap[post.BlogId];
return "/" + blogShortName + "/" + post.Url; return Url.Page("/Blogs/Posts/Detail", new { blogShortName = blogShortName, postUrl = post.Url });
} }
public string GetMemberProfileUrl(BlogUserDto user) public string GetMemberProfileUrl(BlogUserDto user)
{ {
return "/members/" + user.UserName; return Url.Page("/Blogs/Members/Index", new { userName = user.UserName });
} }
} }

0
modules/blogging/src/Volo.Blogging.Web/Pages/Members/Index.css → modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Members/Index.css

0
modules/blogging/src/Volo.Blogging.Web/Pages/Members/Index.js → modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Members/Index.js

24
modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Detail.cshtml

@ -5,7 +5,6 @@
@using Microsoft.Extensions.Options @using Microsoft.Extensions.Options
@using Volo.Abp.Users @using Volo.Abp.Users
@using Volo.Blogging @using Volo.Blogging
@using Volo.Blogging.Pages.Blog.Posts
@using Volo.Blogging.Areas.Blog.Helpers.TagHelpers @using Volo.Blogging.Areas.Blog.Helpers.TagHelpers
@using Volo.Abp.AspNetCore.Mvc.UI.Packages.Prismjs @using Volo.Abp.AspNetCore.Mvc.UI.Packages.Prismjs
@using Volo.Blogging.SocialMedia @using Volo.Blogging.SocialMedia
@ -14,11 +13,12 @@
@using Microsoft.AspNetCore.Mvc.Localization @using Microsoft.AspNetCore.Mvc.Localization
@using Microsoft.AspNetCore.Mvc.TagHelpers @using Microsoft.AspNetCore.Mvc.TagHelpers
@using Volo.Blogging.Localization @using Volo.Blogging.Localization
@using Volo.Blogging.Pages.Blog @using Volo.Blogging.Pages.Blogs
@using Volo.Blogging.Pages.Blogs.Posts
@inject IHtmlLocalizer<BloggingResource> L @inject IHtmlLocalizer<BloggingResource> L
@inject BloggingPageHelper BloggingPageHelper @inject BloggingPageHelper BloggingPageHelper
@inject ICurrentUser CurrentUser @inject ICurrentUser CurrentUser
@model DetailModel @model Volo.Blogging.Pages.Blogs.Posts.DetailModel
@{ @{
ViewBag.Title = Model.Post.Title; ViewBag.Title = Model.Post.Title;
ViewBag.Description = Model.Post.Description; ViewBag.Description = Model.Post.Description;
@ -67,7 +67,7 @@
<div class="col-auto pe-1"> <div class="col-auto pe-1">
@if (Model.Post.Writer != null) @if (Model.Post.Writer != null)
{ {
<a href="/Members/@Model.Post.Writer.UserName" aria-label="Go to user profile"> <a href="@Url.Page("/Blogs/Members/Index", new {userName = Model.Post.Writer.UserName})" aria-label="Go to user profile">
<img gravatar-email="@Model.Post.Writer.Email" default-image="Identicon" class="article-avatar" alt="User Avatar"/> <img gravatar-email="@Model.Post.Writer.Email" default-image="Identicon" class="article-avatar" alt="User Avatar"/>
</a> </a>
} }
@ -76,7 +76,7 @@
@if (Model.Post.Writer != null) @if (Model.Post.Writer != null)
{ {
<h5 class="mt-2 mb-1"> <h5 class="mt-2 mb-1">
<a href="/Members/@Model.Post.Writer.UserName"> <a href="@Url.Page("/Blogs/Members/Index", new {userName = Model.Post.Writer.UserName})">
@(Model.Post.Writer.UserName) @(Model.Post.Writer.UserName)
</a> </a>
<span>@BloggingPageHelper.GetLocalizedTimeAgoText(Model.Post.CreationTime)</span> <span>@BloggingPageHelper.GetLocalizedTimeAgoText(Model.Post.CreationTime)</span>
@ -141,7 +141,7 @@
<div class="col-auto pe-2"> <div class="col-auto pe-2">
@if (Model.Post.Writer != null) @if (Model.Post.Writer != null)
{ {
<a href="/Members/@Model.Post.Writer.UserName" aria-label="Go to user profile"> <a href="@Url.Page("/Blogs/Members/Index", new {userName = Model.Post.Writer.UserName})" aria-label="Go to user profile">
<img gravatar-email="@Model.Post.Writer.Email" default-image="Identicon" class="article-avatar rounded-circle" alt="User Avatar"/> <img gravatar-email="@Model.Post.Writer.Email" default-image="Identicon" class="article-avatar rounded-circle" alt="User Avatar"/>
</a> </a>
} }
@ -151,7 +151,7 @@
{ {
<h5 class="mt-2 mb-1"> <h5 class="mt-2 mb-1">
<a href="/Members/@Model.Post.Writer.UserName"> <a href="@Url.Page("/Blogs/Members/Index", new {userName = Model.Post.Writer.UserName})">
@if (Model.Post.Writer.Name != null && Model.Post.Writer.Surname != null) @if (Model.Post.Writer.Name != null && Model.Post.Writer.Surname != null)
{ {
<p class="fw-bold pt-2 fs-5">@Model.Post.Writer.Name @Model.Post.Writer.Surname</p> <p class="fw-bold pt-2 fs-5">@Model.Post.Writer.Name @Model.Post.Writer.Surname</p>
@ -172,7 +172,7 @@
@if (CurrentUser.Id.HasValue && CurrentUser.Id.Value == Model.Post.Writer?.Id) @if (CurrentUser.Id.HasValue && CurrentUser.Id.Value == Model.Post.Writer?.Id)
{ {
<a class="fw-lighter" href="/Members/@Model.Post.Writer?.UserName#edit-profile">@L["EditProfile"] <i class="fas fa-edit"></i></a> <a class="fw-lighter" href="@(Url.Page("/Blogs/Members/Index", new {userName = Model.Post.Writer.UserName}))#edit-profile">@L["EditProfile"] <i class="fas fa-edit"></i></a>
} }
</div> </div>
@if (Model.LatestPosts.Count > 1) @if (Model.LatestPosts.Count > 1)
@ -194,14 +194,14 @@
{ {
<div class="row"> <div class="row">
<div class="col-auto pe-1"> <div class="col-auto pe-1">
<a href="/Members/@post.Writer.UserName" aria-label="Go to user profile"> <a href="@Url.Page("/Blogs/Members/Index", new {userName = Model.Post.Writer.UserName})" aria-label="Go to user profile">
<img gravatar-email="@post.Writer.Email" default-image="Identicon" class="last-post-image" alt="User Avatar"/> <img gravatar-email="@post.Writer.Email" default-image="Identicon" class="last-post-image" alt="User Avatar"/>
</a> </a>
</div> </div>
<div class="col"> <div class="col">
<h5 class="last-post-name"> <h5 class="last-post-name">
<a href="/Members/@post.Writer!.UserName"> <a href="@Url.Page("/Blogs/Members/Index", new {userName = Model.Post.Writer.UserName})">
@(post.Writer!.UserName) @(post.Writer!.UserName)
</a> </a>
</h5> </h5>
@ -456,13 +456,13 @@ else
var post = Model.PostsList[index]; var post = Model.PostsList[index];
<div class="post-item"> <div class="post-item">
<div class="post-type-cont"> <div class="post-type-cont">
<a href="/members/@Model.Post.Writer.UserName" class="text-decoration-none"> <a href="@Url.Page("/Blogs/Members/Index", new {userName = 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"/> <img gravatar-email="@Model.Post.Writer.Email" default-image="Identicon" class="post-member-img rounded-circle d-block"/>
</a> </a>
</div> </div>
<div class="post-detail-cont"> <div class="post-detail-cont">
<div class="post-info fs-12 mb-2"> <div class="post-info fs-12 mb-2">
<a href="/members/@Model.Post.Writer.UserName" class="text-decoration-none"> <a href="@Url.Page("/Blogs/Members/Index", new {userName = Model.Post.Writer.UserName})" class="text-decoration-none">
<span class="text-dark dot">@Model.Post.Writer.UserName</span> <span class="text-dark dot">@Model.Post.Writer.UserName</span>
</a> </a>
<span class="text-dark-200">@post.CreationTime.ToString("MMMM yyyy")</span> <span class="text-dark-200">@post.CreationTime.ToString("MMMM yyyy")</span>

26
modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Detail.cshtml.cs

@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Web; using System.Web;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; using Microsoft.Extensions.Options;
using Volo.Blogging.Blogs; using Volo.Blogging.Blogs;
using Volo.Blogging.Blogs.Dtos; using Volo.Blogging.Blogs.Dtos;
using Volo.Blogging.Comments; using Volo.Blogging.Comments;
@ -11,7 +11,7 @@ using Volo.Blogging.Comments.Dtos;
using Volo.Blogging.Pages.Blogs.Shared.Helpers; using Volo.Blogging.Pages.Blogs.Shared.Helpers;
using Volo.Blogging.Posts; using Volo.Blogging.Posts;
namespace Volo.Blogging.Pages.Blog.Posts namespace Volo.Blogging.Pages.Blogs.Posts
{ {
public class DetailModel : BloggingPageModel public class DetailModel : BloggingPageModel
{ {
@ -19,6 +19,7 @@ namespace Volo.Blogging.Pages.Blog.Posts
private readonly IPostAppService _postAppService; private readonly IPostAppService _postAppService;
private readonly IBlogAppService _blogAppService; private readonly IBlogAppService _blogAppService;
private readonly ICommentAppService _commentAppService; private readonly ICommentAppService _commentAppService;
private readonly BloggingUrlOptions _blogOptions;
[BindProperty(SupportsGet = true)] [BindProperty(SupportsGet = true)]
public string BlogShortName { get; set; } public string BlogShortName { get; set; }
@ -47,11 +48,12 @@ namespace Volo.Blogging.Pages.Blog.Posts
[BindProperty(SupportsGet = true)] [BindProperty(SupportsGet = true)]
public string TagName { get; set; } public string TagName { get; set; }
public DetailModel(IPostAppService postAppService, IBlogAppService blogAppService, ICommentAppService commentAppService) public DetailModel(IPostAppService postAppService, IBlogAppService blogAppService, ICommentAppService commentAppService, IOptions<BloggingUrlOptions> blogOptions)
{ {
_postAppService = postAppService; _postAppService = postAppService;
_blogAppService = blogAppService; _blogAppService = blogAppService;
_commentAppService = commentAppService; _commentAppService = commentAppService;
_blogOptions = blogOptions.Value;
} }
public virtual async Task<IActionResult> OnGetAsync() public virtual async Task<IActionResult> OnGetAsync()
@ -60,6 +62,17 @@ namespace Volo.Blogging.Pages.Blog.Posts
{ {
return NotFound(); return NotFound();
} }
if (_blogOptions.SingleBlogMode.Enabled)
{
BlogShortName = _blogOptions.SingleBlogMode.BlogName;
}
Blog = await GetBlogAsync(_blogAppService, _blogOptions, BlogShortName);
if(Blog == null)
{
return NotFound();
}
await GetData(); await GetData();
@ -76,6 +89,12 @@ namespace Volo.Blogging.Pages.Blog.Posts
}); });
FocusCommentId = comment.Id; FocusCommentId = comment.Id;
Blog = await GetBlogAsync(_blogAppService, _blogOptions, BlogShortName);
if(Blog == null)
{
return NotFound();
}
await GetData(); await GetData();
@ -84,7 +103,6 @@ namespace Volo.Blogging.Pages.Blog.Posts
private async Task GetData() private async Task GetData()
{ {
Blog = await _blogAppService.GetByShortNameAsync(BlogShortName);
Post = await _postAppService.GetForReadingAsync(new GetPostInput { BlogId = Blog.Id, Url = PostUrl }); Post = await _postAppService.GetForReadingAsync(new GetPostInput { BlogId = Blog.Id, Url = PostUrl });
PostsList = Post.Writer != null PostsList = Post.Writer != null

4
modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Edit.cshtml

@ -1,11 +1,11 @@
@page @page
@using Volo.Abp.AspNetCore.Mvc.UI.Packages.TuiEditor @using Volo.Abp.AspNetCore.Mvc.UI.Packages.TuiEditor
@using Volo.Blogging.Pages.Blog.Posts
@using Volo.Blogging.Posts @using Volo.Blogging.Posts
@using Microsoft.AspNetCore.Mvc.Localization @using Microsoft.AspNetCore.Mvc.Localization
@using Volo.Blogging.Localization @using Volo.Blogging.Localization
@using Volo.Blogging.Pages.Blogs.Posts
@inject IHtmlLocalizer<BloggingResource> L @inject IHtmlLocalizer<BloggingResource> L
@model EditModel @model Volo.Blogging.Pages.Blogs.Posts.EditModel
@{ @{
ViewBag.PageTitle = "Edit Blog Post"; ViewBag.PageTitle = "Edit Blog Post";
} }

26
modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Edit.cshtml.cs

@ -1,24 +1,26 @@
using System; using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; using Microsoft.Extensions.Options;
using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Entities;
using Volo.Abp.Validation; using Volo.Abp.Validation;
using Volo.Blogging.Blogs; using Volo.Blogging.Blogs;
using Volo.Blogging.Pages.Blogs.Shared.Helpers; using Volo.Blogging.Pages.Blogs.Shared.Helpers;
using Volo.Blogging.Posts; using Volo.Blogging.Posts;
namespace Volo.Blogging.Pages.Blog.Posts namespace Volo.Blogging.Pages.Blogs.Posts
{ {
public class EditModel : BloggingPageModel public class EditModel : BloggingPageModel
{ {
private readonly IPostAppService _postAppService; private readonly IPostAppService _postAppService;
private readonly IBlogAppService _blogAppService; private readonly IBlogAppService _blogAppService;
private readonly IAuthorizationService _authorization; private readonly IAuthorizationService _authorization;
private readonly BloggingUrlOptions _blogOptions;
[BindProperty(SupportsGet = true)] [BindProperty(SupportsGet = true)]
public string BlogShortName { get; set; } public string BlogShortName { get; set; }
@ -29,11 +31,12 @@ namespace Volo.Blogging.Pages.Blog.Posts
[BindProperty] [BindProperty]
public EditPostViewModel Post { get; set; } public EditPostViewModel Post { get; set; }
public EditModel(IPostAppService postAppService, IBlogAppService blogAppService, IAuthorizationService authorization) public EditModel(IPostAppService postAppService, IBlogAppService blogAppService, IAuthorizationService authorization, IOptions<BloggingUrlOptions> blogOptions)
{ {
_postAppService = postAppService; _postAppService = postAppService;
_blogAppService = blogAppService; _blogAppService = blogAppService;
_authorization = authorization; _authorization = authorization;
_blogOptions = blogOptions.Value;
} }
public virtual async Task<ActionResult> OnGetAsync() public virtual async Task<ActionResult> OnGetAsync()
@ -42,6 +45,12 @@ namespace Volo.Blogging.Pages.Blog.Posts
{ {
return Redirect("/"); return Redirect("/");
} }
if (_blogOptions.SingleBlogMode.Enabled)
{
BlogShortName = _blogOptions.SingleBlogMode.BlogName;
}
if (BlogNameControlHelper.IsProhibitedFileFormatName(BlogShortName)) if (BlogNameControlHelper.IsProhibitedFileFormatName(BlogShortName))
{ {
return NotFound(); return NotFound();
@ -73,7 +82,16 @@ namespace Volo.Blogging.Pages.Blog.Posts
var editedPost = await _postAppService.UpdateAsync(Post.Id, post); var editedPost = await _postAppService.UpdateAsync(Post.Id, post);
var blog = await _blogAppService.GetAsync(editedPost.BlogId); var blog = await _blogAppService.GetAsync(editedPost.BlogId);
return RedirectToPage("/Blogs/Posts/Detail", new { blogShortName = blog.ShortName, postUrl = editedPost.Url }); Dictionary<string, object> routeValues = new()
{
{ nameof(DetailModel.PostUrl), editedPost.Url }
};
if (!_blogOptions.SingleBlogMode.Enabled)
{
routeValues.Add(nameof(DetailModel.BlogShortName), blog.ShortName);
}
return RedirectToPage("/Blogs/Posts/Detail", routeValues);
} }
} }

43
modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Index.cshtml

@ -4,15 +4,17 @@
@using Volo.Abp.AspNetCore.Mvc.UI.Packages.OwlCarousel @using Volo.Abp.AspNetCore.Mvc.UI.Packages.OwlCarousel
@using Volo.Blogging @using Volo.Blogging
@inject IAuthorizationService Authorization @inject IAuthorizationService Authorization
@model Volo.Blogging.Pages.Blog.Posts.IndexModel @model IndexModel
@using Microsoft.Extensions.Localization @using Microsoft.Extensions.Localization
@using Microsoft.Extensions.Options
@using Volo.Blogging.Localization @using Volo.Blogging.Localization
@using Volo.Blogging.Pages.Blog @using Volo.Blogging.Pages.Blogs
@using IndexModel = Volo.Blogging.Pages.Blog.Posts.IndexModel @using IndexModel = Volo.Blogging.Pages.Blogs.Posts.IndexModel
@inject IStringLocalizer<BloggingResource> L @inject IStringLocalizer<BloggingResource> L
@inject BloggingPageHelper BloggingPageHelper @inject BloggingPageHelper BloggingPageHelper
@{ @{
ViewBag.Title = "Read All Blog Posts"; ViewBag.Title = "Read All Blog Posts";
var blogShortNameRouteParam = Model.BlogOptions.SingleBlogMode.Enabled ? null : Model.BlogShortName;
} }
@section scripts { @section scripts {
<abp-script-bundle name="@typeof(IndexModel).FullName"> <abp-script-bundle name="@typeof(IndexModel).FullName">
@ -27,7 +29,6 @@
<abp-style src="/Pages/Blogs/Shared/Styles/blog.css" /> <abp-style src="/Pages/Blogs/Shared/Styles/blog.css" />
</abp-style-bundle> </abp-style-bundle>
} }
<div class="vs-blog blah"> <div class="vs-blog blah">
<div class="container"> <div class="container">
<div class="pb-3"> <div class="pb-3">
@ -39,18 +40,18 @@
var post = Model.Posts[index]; var post = Model.Posts[index];
<div class="hero-articles"> <div class="hero-articles">
<div class="img-container"> <div class="img-container">
<a asp-page="./Detail" asp-route-postUrl="@post.Url" asp-route-blogShortName="@Model.BlogShortName"> <a asp-page="./Detail" asp-route-postUrl="@post.Url" asp-route-blogShortName="@blogShortNameRouteParam">
<img src="@post.CoverImage" class="hero-article-img" alt="@post.Title cover image"> <img src="@post.CoverImage" class="hero-article-img" alt="@post.Title cover image">
</a> </a>
</div> </div>
<div class="hero-content pt-3"> <div class="hero-content pt-3">
<h2> <h2>
<a asp-page="./Detail" asp-route-postUrl="@post.Url" asp-route-blogShortName="@Model.BlogShortName">@post.Title</a> <a asp-page="./Detail" asp-route-postUrl="@post.Url" asp-route-blogShortName="@blogShortNameRouteParam">@post.Title</a>
</h2> </h2>
<p class="article-sum"> <p class="article-sum">
@Html.Raw(BloggingPageHelper.GetShortContent(post.Content)) @Html.Raw(BloggingPageHelper.GetShortContent(post.Content))
</p> </p>
<a asp-page="./Detail" asp-route-postUrl="@post.Url" asp-route-blogShortName="@Model.BlogShortName" class="read-more-btn">@L["ContinueReading"] &#8594;</a> <a asp-page="./Detail" asp-route-postUrl="@post.Url" asp-route-blogShortName="@blogShortNameRouteParam" class="read-more-btn">@L["ContinueReading"] &#8594;</a>
</div> </div>
@if (post.Writer != null) @if (post.Writer != null)
@ -60,13 +61,13 @@
<div class="user-card"> <div class="user-card">
<div class="row"> <div class="row">
<div class="col-auto pe-1"> <div class="col-auto pe-1">
<a href="/Members/@post.Writer.UserName"> <a href="@Url.Page("/Blogs/Members/Index", new {userName = post.Writer.UserName})">
<img gravatar-email="@post.Writer.Email" default-image="Identicon" class="article-avatar" alt="@post.Writer.UserName avatar" /> <img gravatar-email="@post.Writer.Email" default-image="Identicon" class="article-avatar" alt="@post.Writer.UserName avatar" />
</a> </a>
</div> </div>
<div class="col ps-1"> <div class="col ps-1">
<h5 class="mt-2 mb-1"> <h5 class="mt-2 mb-1">
<a href="/Members/@post.Writer.UserName"> <a href="@Url.Page("/Blogs/Members/Index", new {userName = post.Writer.UserName})">
@post.Writer.UserName @post.Writer.UserName
</a> </a>
<span>@BloggingPageHelper.GetLocalizedTimeAgoText(post.CreationTime)</span> <span>@BloggingPageHelper.GetLocalizedTimeAgoText(post.CreationTime)</span>
@ -84,7 +85,7 @@
<p class="tags"> <p class="tags">
@foreach (var tag in post.Tags) @foreach (var tag in post.Tags)
{ {
<a asp-page="/Blogs/Posts/Index" asp-route-blogShortName="@Model.BlogShortName" asp-route-tagName="@tag.Name" class="tag">@tag.Name</a> <a asp-page="/Blogs/Posts/Index" asp-route-blogShortName="@blogShortNameRouteParam" asp-route-tagName="@tag.Name" class="tag">@tag.Name</a>
} }
</p> </p>
@ -97,7 +98,7 @@
@if (await Authorization.IsGrantedAsync(BloggingPermissions.Posts.Create)) @if (await Authorization.IsGrantedAsync(BloggingPermissions.Posts.Create))
{ {
<a class="btn btn-primary btn-rounded mb-3 active " asp-page="./New" asp-route-blogShortName="@Model.BlogShortName">@L["CreateANewPost"]</a> <a class="btn btn-primary btn-rounded mb-3 active " asp-page="./New" asp-route-blogShortName="@blogShortNameRouteParam">@L["CreateANewPost"]</a>
} }
<div class="list-group"> <div class="list-group">
@ -109,14 +110,14 @@
<div class="row align-middle"> <div class="row align-middle">
<div class="col-4"> <div class="col-4">
<div class="img-container"> <div class="img-container">
<a asp-page="./Detail" asp-route-postUrl="@post.Url" asp-route-blogShortName="@Model.BlogShortName"> <a asp-page="./Detail" asp-route-postUrl="@post.Url" asp-route-blogShortName="@blogShortNameRouteParam">
<img src="@post.CoverImage" class="box-article-img" alt="@post.Title cover image"> <img src="@post.CoverImage" class="box-article-img" alt="@post.Title cover image">
</a> </a>
</div> </div>
</div> </div>
<div class="col-8 ps-0"> <div class="col-8 ps-0">
<h3 class="font-125"> <h3 class="font-125">
<a asp-page="./Detail" asp-route-postUrl="@post.Url" asp-route-blogShortName="@Model.BlogShortName">@post.Title</a> <a asp-page="./Detail" asp-route-postUrl="@post.Url" asp-route-blogShortName="@blogShortNameRouteParam">@post.Title</a>
</h3> </h3>
@if (post.Writer != null) @if (post.Writer != null)
@ -127,7 +128,7 @@
@if (post.Writer != null) @if (post.Writer != null)
{ {
<h5 class="mt-2 mb-1"> <h5 class="mt-2 mb-1">
<a href="/Members/@post.Writer.UserName"> <a href="@Url.Page("/Blogs/Members/Index", new {userName = post.Writer.UserName})">
@post.Writer.UserName @post.Writer.UserName
</a> </a>
<span>@BloggingPageHelper.GetLocalizedTimeAgoText(post.CreationTime)</span> <span>@BloggingPageHelper.GetLocalizedTimeAgoText(post.CreationTime)</span>
@ -169,19 +170,19 @@
<div class="row"> <div class="row">
<div class="col-md-4"> <div class="col-md-4">
<div class="img-container"> <div class="img-container">
<a asp-page="./Detail" asp-route-postUrl="@post.Url" asp-route-blogShortName="@Model.BlogShortName"> <a asp-page="./Detail" asp-route-postUrl="@post.Url" asp-route-blogShortName="@blogShortNameRouteParam">
<img src="@post.CoverImage" class="box-article-img" alt="@post.Title cover image"> <img src="@post.CoverImage" class="box-article-img" alt="@post.Title cover image">
</a> </a>
</div> </div>
</div> </div>
<div class="col"> <div class="col">
<h3> <h3>
<a asp-page="./Detail" asp-route-postUrl="@post.Url" asp-route-blogShortName="@Model.BlogShortName">@post.Title</a> <a asp-page="./Detail" asp-route-postUrl="@post.Url" asp-route-blogShortName="@blogShortNameRouteParam">@post.Title</a>
</h3> </h3>
<p> <p>
@Html.Raw(BloggingPageHelper.GetShortContent(post.Content)) @Html.Raw(BloggingPageHelper.GetShortContent(post.Content))
</p> </p>
<a asp-page="./Detail" asp-route-postUrl="@post.Url" asp-route-blogShortName="@Model.BlogShortName" class="read-more-btn">@L["ContinueReading"] &#8594;</a> <a asp-page="./Detail" asp-route-postUrl="@post.Url" asp-route-blogShortName="@blogShortNameRouteParam" class="read-more-btn">@L["ContinueReading"] &#8594;</a>
@if (post.Writer != null) @if (post.Writer != null)
{ {
@ -190,13 +191,13 @@
<div class="user-card"> <div class="user-card">
<div class="row"> <div class="row">
<div class="col-auto pe-1"> <div class="col-auto pe-1">
<a href="/Members/@post.Writer.UserName"> <a href="@Url.Page("/Blogs/Members/Index", new {userName = post.Writer.UserName})">
<img gravatar-email="@post.Writer.Email" default-image="Identicon" class="article-avatar" alt="@post.Writer.UserName avatar" /> <img gravatar-email="@post.Writer.Email" default-image="Identicon" class="article-avatar" alt="@post.Writer.UserName avatar" />
</a> </a>
</div> </div>
<div class="col ps-1"> <div class="col ps-1">
<h5 class="mt-2 mb-1"> <h5 class="mt-2 mb-1">
<a href="/Members/@post.Writer.UserName"> <a href="@Url.Page("/Blogs/Members/Index", new {userName = post.Writer.UserName})">
@post.Writer.UserName @post.Writer.UserName
</a> </a>
<span>@BloggingPageHelper.GetLocalizedTimeAgoText(post.CreationTime)</span> <span>@BloggingPageHelper.GetLocalizedTimeAgoText(post.CreationTime)</span>
@ -213,7 +214,7 @@
<p class="tags"> <p class="tags">
@foreach (var tag in post.Tags) @foreach (var tag in post.Tags)
{ {
<a asp-page="/Blogs/Posts/Index" asp-route-blogShortName="@Model.BlogShortName" asp-route-tagName="@tag.Name" class="tag">@tag.Name</a> <a asp-page="/Blogs/Posts/Index" asp-route-blogShortName="@blogShortNameRouteParam" asp-route-tagName="@tag.Name" class="tag">@tag.Name</a>
} }
</p> </p>
</div> </div>
@ -234,7 +235,7 @@
<div class="tags"> <div class="tags">
@foreach (var popularTag in Model.PopularTags) @foreach (var popularTag in Model.PopularTags)
{ {
<a class="tag" asp-page="/Blogs/Posts/Index" asp-route-blogShortName="@Model.BlogShortName" asp-route-tagName="@popularTag.Name">@popularTag.Name <small>(@popularTag.UsageCount)</small></a> <a class="tag" asp-page="/Blogs/Posts/Index" asp-route-blogShortName="@blogShortNameRouteParam" asp-route-tagName="@popularTag.Name">@popularTag.Name <small>(@popularTag.UsageCount)</small></a>
} }
</div> </div>
</div> </div>

32
modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Index.cshtml.cs

@ -1,8 +1,7 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; using Microsoft.Extensions.Options;
using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Entities;
using Volo.Blogging.Blogs; using Volo.Blogging.Blogs;
using Volo.Blogging.Blogs.Dtos; using Volo.Blogging.Blogs.Dtos;
@ -11,13 +10,14 @@ using Volo.Blogging.Posts;
using Volo.Blogging.Tagging; using Volo.Blogging.Tagging;
using Volo.Blogging.Tagging.Dtos; using Volo.Blogging.Tagging.Dtos;
namespace Volo.Blogging.Pages.Blog.Posts namespace Volo.Blogging.Pages.Blogs.Posts
{ {
public class IndexModel : BloggingPageModel public class IndexModel : BloggingPageModel
{ {
private readonly IPostAppService _postAppService; private readonly IPostAppService _postAppService;
private readonly IBlogAppService _blogAppService; private readonly IBlogAppService _blogAppService;
private readonly ITagAppService _tagAppService; private readonly ITagAppService _tagAppService;
public BloggingUrlOptions BlogOptions { get; }
[BindProperty(SupportsGet = true)] [BindProperty(SupportsGet = true)]
public string BlogShortName { get; set; } public string BlogShortName { get; set; }
@ -31,11 +31,12 @@ namespace Volo.Blogging.Pages.Blog.Posts
public IReadOnlyList<TagDto> PopularTags { get; set; } public IReadOnlyList<TagDto> PopularTags { get; set; }
public IndexModel(IPostAppService postAppService, IBlogAppService blogAppService, ITagAppService tagAppService) public IndexModel(IPostAppService postAppService, IBlogAppService blogAppService, ITagAppService tagAppService, IOptions<BloggingUrlOptions> blogOptions)
{ {
_postAppService = postAppService; _postAppService = postAppService;
_blogAppService = blogAppService; _blogAppService = blogAppService;
_tagAppService = tagAppService; _tagAppService = tagAppService;
BlogOptions = blogOptions.Value;
} }
public virtual async Task<ActionResult> OnGetAsync() public virtual async Task<ActionResult> OnGetAsync()
@ -47,11 +48,18 @@ namespace Volo.Blogging.Pages.Blog.Posts
try try
{ {
Blog = await _blogAppService.GetByShortNameAsync(BlogShortName); Blog = await GetBlogAsync(_blogAppService, BlogOptions, BlogShortName);
if(Blog == null)
{
return BlogNotFoundResult();
}
BlogShortName = Blog.ShortName;
} }
catch (EntityNotFoundException) catch (EntityNotFoundException)
{ {
return RedirectToPage("/Blogs/Index"); return BlogNotFoundResult();
} }
Posts = (await _postAppService.GetListByBlogIdAndTagNameAsync(Blog.Id, TagName)).Items; Posts = (await _postAppService.GetListByBlogIdAndTagNameAsync(Blog.Id, TagName)).Items;
@ -59,5 +67,15 @@ namespace Volo.Blogging.Pages.Blog.Posts
return Page(); return Page();
} }
protected virtual ActionResult BlogNotFoundResult()
{
if (BlogOptions.SingleBlogMode.Enabled)
{
return NotFound();
}
return RedirectToPage("/Blogs/Index");
}
} }
} }

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

@ -1,11 +1,11 @@
@page @page
@using Volo.Abp.AspNetCore.Mvc.UI.Packages.TuiEditor @using Volo.Abp.AspNetCore.Mvc.UI.Packages.TuiEditor
@using Volo.Blogging.Pages.Blog.Posts
@using Volo.Blogging.Posts @using Volo.Blogging.Posts
@using Microsoft.AspNetCore.Mvc.Localization @using Microsoft.AspNetCore.Mvc.Localization
@using Volo.Blogging.Localization @using Volo.Blogging.Localization
@using Volo.Blogging.Pages.Blogs.Posts
@inject IHtmlLocalizer<BloggingResource> L @inject IHtmlLocalizer<BloggingResource> L
@model NewModel @model Volo.Blogging.Pages.Blogs.Posts.NewModel
@{ @{
ViewBag.PageTitle = @L["NewBlogPost"]; ViewBag.PageTitle = @L["NewBlogPost"];
} }

22
modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/New.cshtml.cs

@ -1,18 +1,18 @@
using System; using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Net; using System.Net;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages;
using Volo.Abp.Validation; using Volo.Abp.Validation;
using Volo.Blogging.Blogs; using Volo.Blogging.Blogs;
using Volo.Blogging.Blogs.Dtos; using Volo.Blogging.Blogs.Dtos;
using Volo.Blogging.Pages.Blogs.Shared.Helpers; using Volo.Blogging.Pages.Blogs.Shared.Helpers;
using Volo.Blogging.Posts; using Volo.Blogging.Posts;
namespace Volo.Blogging.Pages.Blog.Posts namespace Volo.Blogging.Pages.Blogs.Posts
{ {
public class NewModel : BloggingPageModel public class NewModel : BloggingPageModel
{ {
@ -48,7 +48,9 @@ namespace Volo.Blogging.Pages.Blog.Posts
return NotFound(); return NotFound();
} }
Blog = await _blogAppService.GetByShortNameAsync(BlogShortName); Blog = await GetBlogAsync(_blogAppService, _blogOptions, BlogShortName);
BlogShortName = Blog.ShortName;
Post = new CreatePostViewModel Post = new CreatePostViewModel
{ {
BlogId = Blog.Id BlogId = Blog.Id
@ -70,9 +72,17 @@ namespace Volo.Blogging.Pages.Blog.Posts
var postWithDetailsDto = await _postAppService.CreateAsync(ObjectMapper.Map<CreatePostViewModel, CreatePostDto>(Post)); var postWithDetailsDto = await _postAppService.CreateAsync(ObjectMapper.Map<CreatePostViewModel, CreatePostDto>(Post));
//TODO: Try Url.Page(...) Dictionary<string, object> routeValues = new()
var urlPrefix = _blogOptions.RoutePrefix; {
return Redirect(Url.Content($"~{urlPrefix}{WebUtility.UrlEncode(blog.ShortName)}/{WebUtility.UrlEncode(postWithDetailsDto.Url)}")); { nameof(DetailModel.PostUrl), postWithDetailsDto.Url }
};
if (!_blogOptions.SingleBlogMode.Enabled)
{
routeValues.Add(nameof(DetailModel.BlogShortName), blog.ShortName);
}
return RedirectToPage("/Blogs/Posts/Detail", routeValues);
} }
public class CreatePostViewModel public class CreatePostViewModel

Loading…
Cancel
Save