From 232186aada85989c944be8d793a46a3c69f6cc7a Mon Sep 17 00:00:00 2001 From: maliming Date: Wed, 12 Feb 2020 22:16:25 +0800 Subject: [PATCH] Cache documents in the local database for the documents module. --- modules/docs/Volo.Docs.sln | 4 +- ...20181225134002_Initial20181225.Designer.cs | 465 ------------ .../20200212135141_init.Designer.cs | 670 ++++++++++++++++++ ...tial20181225.cs => 20200212135141_init.cs} | 68 +- .../VoloDocsDbContextModelSnapshot.cs | 323 +++++++-- .../docs/app/VoloDocs.Web/VoloDocs.Web.csproj | 7 +- .../app/VoloDocs.Web/VoloDocsWebModule.cs | 23 +- .../DocsAdminPermissionDefinitionProvider.cs | 3 + .../Volo/Docs/Admin/DocsAdminPermissions.cs | 6 + .../Documents/IDocumentAdminAppService.cs | 12 + .../Admin/Documents/PullAllDocumentInput.cs | 17 + .../Docs/Admin/Documents/PullDocumentInput.cs | 20 + .../Documents/DocumentAdminAppService.cs | 99 +++ .../Docs/Admin/DocumentsAdminController.cs | 36 + .../Docs/Documents/DocumentWithDetailsDto.cs | 26 +- .../Docs/Documents/IDocumentAppService.cs | 2 +- .../Volo/Docs/Documents/DocumentAppService.cs | 76 +- .../Volo/Docs/Projects/ProjectAppService.cs | 10 +- .../Volo/Docs/Documents/DocumentConsts.cs | 8 + .../Volo/Docs/Documents}/NavigationNode.cs | 24 + .../Volo/Docs/DocsDomainModule.cs | 6 +- .../Volo/Docs/Documents/Document.cs | 104 ++- .../Docs/Documents/DocumentContributor.cs | 30 +- ...oreFactory.cs => DocumentSourceFactory.cs} | 16 +- .../Docs/Documents/DocumentSourceOptions.cs | 15 + .../Docs/Documents/DocumentStoreOptions.cs | 15 - .../Docs/Documents/IDocumentRepository.cs | 13 + .../{IDocumentStore.cs => IDocumentSource.cs} | 2 +- .../Docs/Documents/IDocumentSourceFactory.cs | 7 + .../Docs/Documents/IDocumentStoreFactory.cs | 7 - ...ntStore.cs => FileSystemDocumentSource.cs} | 30 +- .../Projects/ProjectFileSystemExtensions.cs | 2 +- ...cumentStore.cs => GithubDocumentSource.cs} | 47 +- .../Documents/GithubRepositoryManager.cs | 11 + .../Documents/IGithubRepositoryManager.cs | 1 + .../Projects/ProjectGithubExtensions.cs | 2 +- .../Volo/Docs/Localization/Domain/en.json | 5 +- .../Volo/Docs/Localization/Domain/tr.json | 5 +- .../Docs/Localization/Domain/zh-Hans.json | 5 +- .../Docs/Localization/Domain/zh-Hant.json | 5 +- .../Volo.Docs.EntityFrameworkCore.csproj | 6 + .../Documents/EFCoreDocumentRepository.cs | 23 + .../Docs/EntityFrameworkCore/DocsDbContext.cs | 5 + .../DocsDbContextModelBuilderExtensions.cs | 33 +- .../DocsEntityFrameworkCoreModule.cs | 2 + .../EntityFrameworkCore/IDocsDbContext.cs | 5 + .../Docs/Documents/DocsDocumentController.cs | 2 +- .../Docs/Documents/MongoDocumentRepository.cs | 25 + .../Docs/MongoDB/BloggingMongoDbModule.cs | 2 + .../Volo/Docs/MongoDB/DocsMongoDbContext.cs | 2 + .../MongoDB/DocsMongoDbContextExtensions.cs | 6 + .../Volo/Docs/MongoDB/IDocsMongoDbContext.cs | 3 +- .../Documents/TagHelpers/TreeTagHelper.cs | 17 +- .../Volo.Docs.Web/DocsWebAutoMapperProfile.cs | 3 +- .../Models/NavigationWithDetailsDto.cs | 30 - .../Pages/Documents/Project/Index.cshtml | 8 +- .../Pages/Documents/Project/Index.cshtml.cs | 8 +- .../Volo/Docs/DocumentStoreFactory_Tests.cs | 8 +- .../Volo/Docs/GithubDocumentStore_Tests.cs | 18 +- .../Volo/Docs/DocsTestDataBuilder.cs | 2 +- 60 files changed, 1701 insertions(+), 734 deletions(-) delete mode 100644 modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20181225134002_Initial20181225.Designer.cs create mode 100644 modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20200212135141_init.Designer.cs rename modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/{20181225134002_Initial20181225.cs => 20200212135141_init.cs} (83%) create mode 100644 modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Documents/IDocumentAdminAppService.cs create mode 100644 modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Documents/PullAllDocumentInput.cs create mode 100644 modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Documents/PullDocumentInput.cs create mode 100644 modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/Documents/DocumentAdminAppService.cs create mode 100644 modules/docs/src/Volo.Docs.Admin.HttpApi/Volo/Docs/Admin/DocumentsAdminController.cs rename modules/docs/src/{Volo.Docs.Web/Models => Volo.Docs.Domain.Shared/Volo/Docs/Documents}/NavigationNode.cs (63%) rename modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/{DocumentStoreFactory.cs => DocumentSourceFactory.cs} (54%) create mode 100644 modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/DocumentSourceOptions.cs delete mode 100644 modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/DocumentStoreOptions.cs create mode 100644 modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/IDocumentRepository.cs rename modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/{IDocumentStore.cs => IDocumentSource.cs} (91%) create mode 100644 modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/IDocumentSourceFactory.cs delete mode 100644 modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/IDocumentStoreFactory.cs rename modules/docs/src/Volo.Docs.Domain/Volo/Docs/FileSystem/Documents/{FileSystemDocumentStore.cs => FileSystemDocumentSource.cs} (75%) rename modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/{GithubDocumentStore.cs => GithubDocumentSource.cs} (86%) create mode 100644 modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/Documents/EFCoreDocumentRepository.cs create mode 100644 modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Documents/MongoDocumentRepository.cs delete mode 100644 modules/docs/src/Volo.Docs.Web/Models/NavigationWithDetailsDto.cs diff --git a/modules/docs/Volo.Docs.sln b/modules/docs/Volo.Docs.sln index 74e748ac9b..1c32767baa 100644 --- a/modules/docs/Volo.Docs.sln +++ b/modules/docs/Volo.Docs.sln @@ -57,9 +57,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VoloDocs.Web", "app\VoloDoc EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VoloDocs.Migrator", "app\VoloDocs.Migrator\VoloDocs.Migrator.csproj", "{8A5E5001-C017-44A8-ADDA-DC66C102556E}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Docs.MongoDB", "src\Volo.Docs.MongoDB\Volo.Docs.MongoDB.csproj", "{DBE846CD-1BED-4F2C-ABF2-94F6240BCB9B}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Docs.MongoDB", "src\Volo.Docs.MongoDB\Volo.Docs.MongoDB.csproj", "{DBE846CD-1BED-4F2C-ABF2-94F6240BCB9B}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Docs.MongoDB.Tests", "test\Volo.Docs.MongoDB.Tests\Volo.Docs.MongoDB.Tests.csproj", "{C5E2A2A3-D54D-4C2E-97BA-EA50A49ED7AD}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Docs.MongoDB.Tests", "test\Volo.Docs.MongoDB.Tests\Volo.Docs.MongoDB.Tests.csproj", "{C5E2A2A3-D54D-4C2E-97BA-EA50A49ED7AD}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20181225134002_Initial20181225.Designer.cs b/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20181225134002_Initial20181225.Designer.cs deleted file mode 100644 index ab8c782832..0000000000 --- a/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20181225134002_Initial20181225.Designer.cs +++ /dev/null @@ -1,465 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using VoloDocs.EntityFrameworkCore; - -namespace VoloDocs.EntityFrameworkCore.Migrations -{ - [DbContext(typeof(VoloDocsDbContext))] - [Migration("20181225134002_Initial20181225")] - partial class Initial20181225 - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "2.1.1-rtm-30846") - .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .IsRequired() - .HasColumnName("ConcurrencyStamp") - .HasMaxLength(256); - - b.Property("Description") - .HasMaxLength(256); - - b.Property("ExtraProperties") - .HasColumnName("ExtraProperties"); - - b.Property("IsStatic"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(256); - - b.Property("Regex") - .HasMaxLength(512); - - b.Property("RegexDescription") - .HasMaxLength(128); - - b.Property("Required"); - - b.Property("ValueType"); - - b.HasKey("Id"); - - b.ToTable("AbpClaimTypes"); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .IsRequired() - .HasColumnName("ConcurrencyStamp") - .HasMaxLength(256); - - b.Property("ExtraProperties") - .HasColumnName("ExtraProperties"); - - b.Property("IsDefault") - .HasColumnName("IsDefault"); - - b.Property("IsPublic") - .HasColumnName("IsPublic"); - - b.Property("IsStatic") - .HasColumnName("IsStatic"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(256); - - b.Property("NormalizedName") - .IsRequired() - .HasMaxLength(256); - - b.Property("TenantId"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName"); - - b.ToTable("AbpRoles"); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ClaimType") - .IsRequired() - .HasMaxLength(256); - - b.Property("ClaimValue") - .HasMaxLength(1024); - - b.Property("RoleId"); - - b.Property("TenantId"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AbpRoleClaims"); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("AccessFailedCount") - .ValueGeneratedOnAdd() - .HasColumnName("AccessFailedCount") - .HasDefaultValue(0); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnName("ConcurrencyStamp"); - - b.Property("CreationTime") - .HasColumnName("CreationTime"); - - b.Property("CreatorId") - .HasColumnName("CreatorId"); - - b.Property("DeleterId") - .HasColumnName("DeleterId"); - - b.Property("DeletionTime") - .HasColumnName("DeletionTime"); - - b.Property("Email") - .HasColumnName("Email") - .HasMaxLength(256); - - b.Property("EmailConfirmed") - .ValueGeneratedOnAdd() - .HasColumnName("EmailConfirmed") - .HasDefaultValue(false); - - b.Property("ExtraProperties") - .HasColumnName("ExtraProperties"); - - b.Property("IsDeleted") - .ValueGeneratedOnAdd() - .HasColumnName("IsDeleted") - .HasDefaultValue(false); - - b.Property("LastModificationTime") - .HasColumnName("LastModificationTime"); - - b.Property("LastModifierId") - .HasColumnName("LastModifierId"); - - b.Property("LockoutEnabled") - .ValueGeneratedOnAdd() - .HasColumnName("LockoutEnabled") - .HasDefaultValue(false); - - b.Property("LockoutEnd"); - - b.Property("Name") - .HasColumnName("Name") - .HasMaxLength(64); - - b.Property("NormalizedEmail") - .HasColumnName("NormalizedEmail") - .HasMaxLength(256); - - b.Property("NormalizedUserName") - .IsRequired() - .HasColumnName("NormalizedUserName") - .HasMaxLength(256); - - b.Property("PasswordHash") - .HasColumnName("PasswordHash") - .HasMaxLength(256); - - b.Property("PhoneNumber") - .HasColumnName("PhoneNumber") - .HasMaxLength(16); - - b.Property("PhoneNumberConfirmed") - .ValueGeneratedOnAdd() - .HasColumnName("PhoneNumberConfirmed") - .HasDefaultValue(false); - - b.Property("SecurityStamp") - .IsRequired() - .HasColumnName("SecurityStamp") - .HasMaxLength(256); - - b.Property("Surname") - .HasColumnName("Surname") - .HasMaxLength(64); - - b.Property("TenantId") - .HasColumnName("TenantId"); - - b.Property("TwoFactorEnabled") - .ValueGeneratedOnAdd() - .HasColumnName("TwoFactorEnabled") - .HasDefaultValue(false); - - b.Property("UserName") - .IsRequired() - .HasColumnName("UserName") - .HasMaxLength(256); - - b.HasKey("Id"); - - b.HasIndex("Email"); - - b.HasIndex("NormalizedEmail"); - - b.HasIndex("NormalizedUserName"); - - b.HasIndex("UserName"); - - b.ToTable("AbpUsers"); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ClaimType") - .IsRequired() - .HasMaxLength(256); - - b.Property("ClaimValue") - .HasMaxLength(1024); - - b.Property("TenantId"); - - b.Property("UserId"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AbpUserClaims"); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => - { - b.Property("UserId"); - - b.Property("LoginProvider") - .HasMaxLength(64); - - b.Property("ProviderDisplayName") - .HasMaxLength(128); - - b.Property("ProviderKey") - .IsRequired() - .HasMaxLength(196); - - b.Property("TenantId"); - - b.HasKey("UserId", "LoginProvider"); - - b.HasIndex("LoginProvider", "ProviderKey"); - - b.ToTable("AbpUserLogins"); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => - { - b.Property("UserId"); - - b.Property("RoleId"); - - b.Property("TenantId"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId", "UserId"); - - b.ToTable("AbpUserRoles"); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => - { - b.Property("UserId"); - - b.Property("LoginProvider") - .HasMaxLength(64); - - b.Property("Name") - .HasMaxLength(128); - - b.Property("TenantId"); - - b.Property("Value"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AbpUserTokens"); - }); - - modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128); - - b.Property("ProviderKey") - .IsRequired() - .HasMaxLength(64); - - b.Property("ProviderName") - .IsRequired() - .HasMaxLength(64); - - b.Property("TenantId"); - - b.HasKey("Id"); - - b.HasIndex("Name", "ProviderName", "ProviderKey"); - - b.ToTable("AbpPermissionGrants"); - }); - - modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128); - - b.Property("ProviderKey") - .HasMaxLength(64); - - b.Property("ProviderName") - .HasMaxLength(64); - - b.Property("Value") - .IsRequired() - .HasMaxLength(2048); - - b.HasKey("Id"); - - b.HasIndex("Name", "ProviderName", "ProviderKey"); - - b.ToTable("AbpSettings"); - }); - - modelBuilder.Entity("Volo.Docs.Projects.Project", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnName("ConcurrencyStamp"); - - b.Property("DefaultDocumentName") - .IsRequired() - .HasMaxLength(128); - - b.Property("DocumentStoreType"); - - b.Property("ExtraProperties") - .HasColumnName("ExtraProperties"); - - b.Property("Format"); - - b.Property("LatestVersionBranchName") - .HasMaxLength(128); - - b.Property("MainWebsiteUrl"); - - b.Property("MinimumVersion"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128); - - b.Property("NavigationDocumentName") - .IsRequired() - .HasMaxLength(128); - - b.Property("ShortName") - .IsRequired() - .HasMaxLength(32); - - b.HasKey("Id"); - - b.ToTable("DocsProjects"); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => - { - b.HasOne("Volo.Abp.Identity.IdentityRole") - .WithMany("Claims") - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => - { - b.HasOne("Volo.Abp.Identity.IdentityUser") - .WithMany("Claims") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => - { - b.HasOne("Volo.Abp.Identity.IdentityUser") - .WithMany("Logins") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => - { - b.HasOne("Volo.Abp.Identity.IdentityRole") - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade); - - b.HasOne("Volo.Abp.Identity.IdentityUser") - .WithMany("Roles") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => - { - b.HasOne("Volo.Abp.Identity.IdentityUser") - .WithMany("Tokens") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20200212135141_init.Designer.cs b/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20200212135141_init.Designer.cs new file mode 100644 index 0000000000..3c21209e8c --- /dev/null +++ b/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20200212135141_init.Designer.cs @@ -0,0 +1,670 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using VoloDocs.EntityFrameworkCore; + +namespace VoloDocs.EntityFrameworkCore.Migrations +{ + [DbContext(typeof(VoloDocsDbContext))] + [Migration("20200212135141_init")] + partial class init + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.1") + .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasColumnName("ConcurrencyStamp") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property("Description") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties") + .HasColumnType("nvarchar(max)"); + + b.Property("IsStatic") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property("Regex") + .HasColumnType("nvarchar(512)") + .HasMaxLength(512); + + b.Property("RegexDescription") + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("Required") + .HasColumnType("bit"); + + b.Property("ValueType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("AbpClaimTypes"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasColumnName("ConcurrencyStamp") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties") + .HasColumnType("nvarchar(max)"); + + b.Property("IsDefault") + .HasColumnName("IsDefault") + .HasColumnType("bit"); + + b.Property("IsPublic") + .HasColumnName("IsPublic") + .HasColumnType("bit"); + + b.Property("IsStatic") + .HasColumnName("IsStatic") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property("NormalizedName") + .IsRequired() + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName"); + + b.ToTable("AbpRoles"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("ClaimType") + .IsRequired() + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(1024)") + .HasMaxLength(1024); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AbpRoleClaims"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AccessFailedCount") + .ValueGeneratedOnAdd() + .HasColumnName("AccessFailedCount") + .HasColumnType("int") + .HasDefaultValue(0); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeleterId") + .HasColumnName("DeleterId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeletionTime") + .HasColumnName("DeletionTime") + .HasColumnType("datetime2"); + + b.Property("Email") + .IsRequired() + .HasColumnName("Email") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property("EmailConfirmed") + .ValueGeneratedOnAdd() + .HasColumnName("EmailConfirmed") + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties") + .HasColumnType("nvarchar(max)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnName("IsDeleted") + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime") + .HasColumnType("datetime2"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId") + .HasColumnType("uniqueidentifier"); + + b.Property("LockoutEnabled") + .ValueGeneratedOnAdd() + .HasColumnName("LockoutEnabled") + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("Name") + .HasColumnName("Name") + .HasColumnType("nvarchar(64)") + .HasMaxLength(64); + + b.Property("NormalizedEmail") + .IsRequired() + .HasColumnName("NormalizedEmail") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property("NormalizedUserName") + .IsRequired() + .HasColumnName("NormalizedUserName") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property("PasswordHash") + .HasColumnName("PasswordHash") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property("PhoneNumber") + .HasColumnName("PhoneNumber") + .HasColumnType("nvarchar(16)") + .HasMaxLength(16); + + b.Property("PhoneNumberConfirmed") + .ValueGeneratedOnAdd() + .HasColumnName("PhoneNumberConfirmed") + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("SecurityStamp") + .IsRequired() + .HasColumnName("SecurityStamp") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property("Surname") + .HasColumnName("Surname") + .HasColumnType("nvarchar(64)") + .HasMaxLength(64); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); + + b.Property("TwoFactorEnabled") + .ValueGeneratedOnAdd() + .HasColumnName("TwoFactorEnabled") + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("UserName") + .IsRequired() + .HasColumnName("UserName") + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("Email"); + + b.HasIndex("NormalizedEmail"); + + b.HasIndex("NormalizedUserName"); + + b.HasIndex("UserName"); + + b.ToTable("AbpUsers"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("ClaimType") + .IsRequired() + .HasColumnType("nvarchar(256)") + .HasMaxLength(256); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(1024)") + .HasMaxLength(1024); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AbpUserClaims"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(64)") + .HasMaxLength(64); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("ProviderKey") + .IsRequired() + .HasColumnType("nvarchar(196)") + .HasMaxLength(196); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("UserId", "LoginProvider"); + + b.HasIndex("LoginProvider", "ProviderKey"); + + b.ToTable("AbpUserLogins"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId", "UserId"); + + b.ToTable("AbpUserRoles"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(64)") + .HasMaxLength(64); + + b.Property("Name") + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AbpUserTokens"); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("ProviderKey") + .IsRequired() + .HasColumnType("nvarchar(64)") + .HasMaxLength(64); + + b.Property("ProviderName") + .IsRequired() + .HasColumnType("nvarchar(64)") + .HasMaxLength(64); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey"); + + b.ToTable("AbpPermissionGrants"); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(64)") + .HasMaxLength(64); + + b.Property("ProviderName") + .HasColumnType("nvarchar(64)") + .HasMaxLength(64); + + b.Property("Value") + .IsRequired() + .HasColumnType("nvarchar(2048)") + .HasMaxLength(2048); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey"); + + b.ToTable("AbpSettings"); + }); + + modelBuilder.Entity("Volo.Docs.Documents.Document", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("Content") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("EditLink") + .HasColumnType("nvarchar(2048)") + .HasMaxLength(2048); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties") + .HasColumnType("nvarchar(max)"); + + b.Property("FileName") + .IsRequired() + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("Format") + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("LanguageCode") + .IsRequired() + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("LastCachedTime") + .HasColumnType("datetime2"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetime2"); + + b.Property("LocalDirectory") + .HasColumnType("nvarchar(512)") + .HasMaxLength(512); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(255)") + .HasMaxLength(255); + + b.Property("ProjectId") + .HasColumnType("uniqueidentifier"); + + b.Property("RawRootUrl") + .HasColumnType("nvarchar(2048)") + .HasMaxLength(2048); + + b.Property("RootUrl") + .HasColumnType("nvarchar(2048)") + .HasMaxLength(2048); + + b.Property("UpdatedCount") + .HasColumnType("int"); + + b.Property("Version") + .IsRequired() + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.HasKey("Id"); + + b.ToTable("DocsDocuments"); + }); + + modelBuilder.Entity("Volo.Docs.Documents.DocumentContributor", b => + { + b.Property("DocumentId") + .HasColumnType("uniqueidentifier"); + + b.Property("Username") + .HasColumnType("nvarchar(450)"); + + b.Property("AvatarUrl") + .HasColumnType("nvarchar(max)"); + + b.Property("UserProfileUrl") + .HasColumnType("nvarchar(max)"); + + b.HasKey("DocumentId", "Username"); + + b.ToTable("DocsDocumentContributors"); + }); + + modelBuilder.Entity("Volo.Docs.Projects.Project", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("DefaultDocumentName") + .IsRequired() + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("DocumentStoreType") + .HasColumnType("nvarchar(max)"); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties") + .HasColumnType("nvarchar(max)"); + + b.Property("Format") + .HasColumnType("nvarchar(max)"); + + b.Property("LatestVersionBranchName") + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("MainWebsiteUrl") + .HasColumnType("nvarchar(max)"); + + b.Property("MinimumVersion") + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("NavigationDocumentName") + .IsRequired() + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("ParametersDocumentName") + .IsRequired() + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("ShortName") + .IsRequired() + .HasColumnType("nvarchar(32)") + .HasMaxLength(32); + + b.HasKey("Id"); + + b.ToTable("DocsProjects"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany("Claims") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Claims") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Logins") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Roles") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Tokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Docs.Documents.DocumentContributor", b => + { + b.HasOne("Volo.Docs.Documents.Document", null) + .WithMany("Contributors") + .HasForeignKey("DocumentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20181225134002_Initial20181225.cs b/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20200212135141_init.cs similarity index 83% rename from modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20181225134002_Initial20181225.cs rename to modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20200212135141_init.cs index abae1bbc04..cb18bebed6 100644 --- a/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20181225134002_Initial20181225.cs +++ b/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20200212135141_init.cs @@ -3,7 +3,7 @@ using Microsoft.EntityFrameworkCore.Migrations; namespace VoloDocs.EntityFrameworkCore.Migrations { - public partial class Initial20181225 : Migration + public partial class init : Migration { protected override void Up(MigrationBuilder migrationBuilder) { @@ -95,8 +95,8 @@ namespace VoloDocs.EntityFrameworkCore.Migrations NormalizedUserName = table.Column(maxLength: 256, nullable: false), Name = table.Column(maxLength: 64, nullable: true), Surname = table.Column(maxLength: 64, nullable: true), - Email = table.Column(maxLength: 256, nullable: true), - NormalizedEmail = table.Column(maxLength: 256, nullable: true), + Email = table.Column(maxLength: 256, nullable: false), + NormalizedEmail = table.Column(maxLength: 256, nullable: false), EmailConfirmed = table.Column(nullable: false, defaultValue: false), PasswordHash = table.Column(maxLength: 256, nullable: true), SecurityStamp = table.Column(maxLength: 256, nullable: false), @@ -112,6 +112,33 @@ namespace VoloDocs.EntityFrameworkCore.Migrations table.PrimaryKey("PK_AbpUsers", x => x.Id); }); + migrationBuilder.CreateTable( + name: "DocsDocuments", + columns: table => new + { + Id = table.Column(nullable: false), + ExtraProperties = table.Column(nullable: true), + ConcurrencyStamp = table.Column(nullable: true), + ProjectId = table.Column(nullable: false), + Name = table.Column(maxLength: 255, nullable: false), + Version = table.Column(maxLength: 128, nullable: false), + LanguageCode = table.Column(maxLength: 128, nullable: false), + FileName = table.Column(maxLength: 128, nullable: false), + Content = table.Column(nullable: false), + Format = table.Column(maxLength: 128, nullable: true), + EditLink = table.Column(maxLength: 2048, nullable: true), + RootUrl = table.Column(maxLength: 2048, nullable: true), + RawRootUrl = table.Column(maxLength: 2048, nullable: true), + LocalDirectory = table.Column(maxLength: 512, nullable: true), + LastUpdatedTime = table.Column(nullable: false), + UpdatedCount = table.Column(nullable: false), + LastCachedTime = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_DocsDocuments", x => x.Id); + }); + migrationBuilder.CreateTable( name: "DocsProjects", columns: table => new @@ -124,6 +151,7 @@ namespace VoloDocs.EntityFrameworkCore.Migrations Format = table.Column(nullable: true), DefaultDocumentName = table.Column(maxLength: 128, nullable: false), NavigationDocumentName = table.Column(maxLength: 128, nullable: false), + ParametersDocumentName = table.Column(maxLength: 128, nullable: false), MinimumVersion = table.Column(nullable: true), DocumentStoreType = table.Column(nullable: true), MainWebsiteUrl = table.Column(nullable: true), @@ -180,9 +208,9 @@ namespace VoloDocs.EntityFrameworkCore.Migrations name: "AbpUserLogins", columns: table => new { - TenantId = table.Column(nullable: true), UserId = table.Column(nullable: false), LoginProvider = table.Column(maxLength: 64, nullable: false), + TenantId = table.Column(nullable: true), ProviderKey = table.Column(maxLength: 196, nullable: false), ProviderDisplayName = table.Column(maxLength: 128, nullable: true) }, @@ -201,9 +229,9 @@ namespace VoloDocs.EntityFrameworkCore.Migrations name: "AbpUserRoles", columns: table => new { - TenantId = table.Column(nullable: true), UserId = table.Column(nullable: false), - RoleId = table.Column(nullable: false) + RoleId = table.Column(nullable: false), + TenantId = table.Column(nullable: true) }, constraints: table => { @@ -226,10 +254,10 @@ namespace VoloDocs.EntityFrameworkCore.Migrations name: "AbpUserTokens", columns: table => new { - TenantId = table.Column(nullable: true), UserId = table.Column(nullable: false), LoginProvider = table.Column(maxLength: 64, nullable: false), Name = table.Column(maxLength: 128, nullable: false), + TenantId = table.Column(nullable: true), Value = table.Column(nullable: true) }, constraints: table => @@ -243,6 +271,26 @@ namespace VoloDocs.EntityFrameworkCore.Migrations onDelete: ReferentialAction.Cascade); }); + migrationBuilder.CreateTable( + name: "DocsDocumentContributors", + columns: table => new + { + DocumentId = table.Column(nullable: false), + Username = table.Column(nullable: false), + UserProfileUrl = table.Column(nullable: true), + AvatarUrl = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_DocsDocumentContributors", x => new { x.DocumentId, x.Username }); + table.ForeignKey( + name: "FK_DocsDocumentContributors_DocsDocuments_DocumentId", + column: x => x.DocumentId, + principalTable: "DocsDocuments", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + migrationBuilder.CreateIndex( name: "IX_AbpPermissionGrants_Name_ProviderName_ProviderKey", table: "AbpPermissionGrants", @@ -325,6 +373,9 @@ namespace VoloDocs.EntityFrameworkCore.Migrations migrationBuilder.DropTable( name: "AbpUserTokens"); + migrationBuilder.DropTable( + name: "DocsDocumentContributors"); + migrationBuilder.DropTable( name: "DocsProjects"); @@ -333,6 +384,9 @@ namespace VoloDocs.EntityFrameworkCore.Migrations migrationBuilder.DropTable( name: "AbpUsers"); + + migrationBuilder.DropTable( + name: "DocsDocuments"); } } } diff --git a/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/VoloDocsDbContextModelSnapshot.cs b/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/VoloDocsDbContextModelSnapshot.cs index 0a93515c64..1c595ac3f8 100644 --- a/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/VoloDocsDbContextModelSnapshot.cs +++ b/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/VoloDocsDbContextModelSnapshot.cs @@ -15,42 +15,52 @@ namespace VoloDocs.EntityFrameworkCore.Migrations { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "2.1.1-rtm-30846") + .HasAnnotation("ProductVersion", "3.1.1") .HasAnnotation("Relational:MaxIdentifierLength", 128) .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); b.Property("ConcurrencyStamp") .IsConcurrencyToken() .IsRequired() .HasColumnName("ConcurrencyStamp") + .HasColumnType("nvarchar(256)") .HasMaxLength(256); b.Property("Description") + .HasColumnType("nvarchar(256)") .HasMaxLength(256); b.Property("ExtraProperties") - .HasColumnName("ExtraProperties"); + .HasColumnName("ExtraProperties") + .HasColumnType("nvarchar(max)"); - b.Property("IsStatic"); + b.Property("IsStatic") + .HasColumnType("bit"); b.Property("Name") .IsRequired() + .HasColumnType("nvarchar(256)") .HasMaxLength(256); b.Property("Regex") + .HasColumnType("nvarchar(512)") .HasMaxLength(512); b.Property("RegexDescription") + .HasColumnType("nvarchar(128)") .HasMaxLength(128); - b.Property("Required"); + b.Property("Required") + .HasColumnType("bit"); - b.Property("ValueType"); + b.Property("ValueType") + .HasColumnType("int"); b.HasKey("Id"); @@ -60,35 +70,44 @@ namespace VoloDocs.EntityFrameworkCore.Migrations modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); b.Property("ConcurrencyStamp") .IsConcurrencyToken() .IsRequired() .HasColumnName("ConcurrencyStamp") + .HasColumnType("nvarchar(256)") .HasMaxLength(256); b.Property("ExtraProperties") - .HasColumnName("ExtraProperties"); + .HasColumnName("ExtraProperties") + .HasColumnType("nvarchar(max)"); b.Property("IsDefault") - .HasColumnName("IsDefault"); + .HasColumnName("IsDefault") + .HasColumnType("bit"); b.Property("IsPublic") - .HasColumnName("IsPublic"); + .HasColumnName("IsPublic") + .HasColumnType("bit"); b.Property("IsStatic") - .HasColumnName("IsStatic"); + .HasColumnName("IsStatic") + .HasColumnType("bit"); b.Property("Name") .IsRequired() + .HasColumnType("nvarchar(256)") .HasMaxLength(256); b.Property("NormalizedName") .IsRequired() + .HasColumnType("nvarchar(256)") .HasMaxLength(256); - b.Property("TenantId"); + b.Property("TenantId") + .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -100,18 +119,22 @@ namespace VoloDocs.EntityFrameworkCore.Migrations modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .HasColumnType("uniqueidentifier"); b.Property("ClaimType") .IsRequired() + .HasColumnType("nvarchar(256)") .HasMaxLength(256); b.Property("ClaimValue") + .HasColumnType("nvarchar(1024)") .HasMaxLength(1024); - b.Property("RoleId"); + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); - b.Property("TenantId"); + b.Property("TenantId") + .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -123,105 +146,133 @@ namespace VoloDocs.EntityFrameworkCore.Migrations modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); b.Property("AccessFailedCount") .ValueGeneratedOnAdd() .HasColumnName("AccessFailedCount") + .HasColumnType("int") .HasDefaultValue(0); b.Property("ConcurrencyStamp") .IsConcurrencyToken() - .HasColumnName("ConcurrencyStamp"); + .HasColumnName("ConcurrencyStamp") + .HasColumnType("nvarchar(max)"); b.Property("CreationTime") - .HasColumnName("CreationTime"); + .HasColumnName("CreationTime") + .HasColumnType("datetime2"); b.Property("CreatorId") - .HasColumnName("CreatorId"); + .HasColumnName("CreatorId") + .HasColumnType("uniqueidentifier"); b.Property("DeleterId") - .HasColumnName("DeleterId"); + .HasColumnName("DeleterId") + .HasColumnType("uniqueidentifier"); b.Property("DeletionTime") - .HasColumnName("DeletionTime"); + .HasColumnName("DeletionTime") + .HasColumnType("datetime2"); b.Property("Email") + .IsRequired() .HasColumnName("Email") + .HasColumnType("nvarchar(256)") .HasMaxLength(256); b.Property("EmailConfirmed") .ValueGeneratedOnAdd() .HasColumnName("EmailConfirmed") + .HasColumnType("bit") .HasDefaultValue(false); b.Property("ExtraProperties") - .HasColumnName("ExtraProperties"); + .HasColumnName("ExtraProperties") + .HasColumnType("nvarchar(max)"); b.Property("IsDeleted") .ValueGeneratedOnAdd() .HasColumnName("IsDeleted") + .HasColumnType("bit") .HasDefaultValue(false); b.Property("LastModificationTime") - .HasColumnName("LastModificationTime"); + .HasColumnName("LastModificationTime") + .HasColumnType("datetime2"); b.Property("LastModifierId") - .HasColumnName("LastModifierId"); + .HasColumnName("LastModifierId") + .HasColumnType("uniqueidentifier"); b.Property("LockoutEnabled") .ValueGeneratedOnAdd() .HasColumnName("LockoutEnabled") + .HasColumnType("bit") .HasDefaultValue(false); - b.Property("LockoutEnd"); + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); b.Property("Name") .HasColumnName("Name") + .HasColumnType("nvarchar(64)") .HasMaxLength(64); b.Property("NormalizedEmail") + .IsRequired() .HasColumnName("NormalizedEmail") + .HasColumnType("nvarchar(256)") .HasMaxLength(256); b.Property("NormalizedUserName") .IsRequired() .HasColumnName("NormalizedUserName") + .HasColumnType("nvarchar(256)") .HasMaxLength(256); b.Property("PasswordHash") .HasColumnName("PasswordHash") + .HasColumnType("nvarchar(256)") .HasMaxLength(256); b.Property("PhoneNumber") .HasColumnName("PhoneNumber") + .HasColumnType("nvarchar(16)") .HasMaxLength(16); b.Property("PhoneNumberConfirmed") .ValueGeneratedOnAdd() .HasColumnName("PhoneNumberConfirmed") + .HasColumnType("bit") .HasDefaultValue(false); b.Property("SecurityStamp") .IsRequired() .HasColumnName("SecurityStamp") + .HasColumnType("nvarchar(256)") .HasMaxLength(256); b.Property("Surname") .HasColumnName("Surname") + .HasColumnType("nvarchar(64)") .HasMaxLength(64); b.Property("TenantId") - .HasColumnName("TenantId"); + .HasColumnName("TenantId") + .HasColumnType("uniqueidentifier"); b.Property("TwoFactorEnabled") .ValueGeneratedOnAdd() .HasColumnName("TwoFactorEnabled") + .HasColumnType("bit") .HasDefaultValue(false); b.Property("UserName") .IsRequired() .HasColumnName("UserName") + .HasColumnType("nvarchar(256)") .HasMaxLength(256); b.HasKey("Id"); @@ -240,18 +291,22 @@ namespace VoloDocs.EntityFrameworkCore.Migrations modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .HasColumnType("uniqueidentifier"); b.Property("ClaimType") .IsRequired() + .HasColumnType("nvarchar(256)") .HasMaxLength(256); b.Property("ClaimValue") + .HasColumnType("nvarchar(1024)") .HasMaxLength(1024); - b.Property("TenantId"); + b.Property("TenantId") + .HasColumnType("uniqueidentifier"); - b.Property("UserId"); + b.Property("UserId") + .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -262,19 +317,24 @@ namespace VoloDocs.EntityFrameworkCore.Migrations modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => { - b.Property("UserId"); + b.Property("UserId") + .HasColumnType("uniqueidentifier"); b.Property("LoginProvider") + .HasColumnType("nvarchar(64)") .HasMaxLength(64); b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(128)") .HasMaxLength(128); b.Property("ProviderKey") .IsRequired() + .HasColumnType("nvarchar(196)") .HasMaxLength(196); - b.Property("TenantId"); + b.Property("TenantId") + .HasColumnType("uniqueidentifier"); b.HasKey("UserId", "LoginProvider"); @@ -285,11 +345,14 @@ namespace VoloDocs.EntityFrameworkCore.Migrations modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => { - b.Property("UserId"); + b.Property("UserId") + .HasColumnType("uniqueidentifier"); - b.Property("RoleId"); + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); - b.Property("TenantId"); + b.Property("TenantId") + .HasColumnType("uniqueidentifier"); b.HasKey("UserId", "RoleId"); @@ -300,17 +363,22 @@ namespace VoloDocs.EntityFrameworkCore.Migrations modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => { - b.Property("UserId"); + b.Property("UserId") + .HasColumnType("uniqueidentifier"); b.Property("LoginProvider") + .HasColumnType("nvarchar(64)") .HasMaxLength(64); b.Property("Name") + .HasColumnType("nvarchar(128)") .HasMaxLength(128); - b.Property("TenantId"); + b.Property("TenantId") + .HasColumnType("uniqueidentifier"); - b.Property("Value"); + b.Property("Value") + .HasColumnType("nvarchar(max)"); b.HasKey("UserId", "LoginProvider", "Name"); @@ -320,21 +388,26 @@ namespace VoloDocs.EntityFrameworkCore.Migrations modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); b.Property("Name") .IsRequired() + .HasColumnType("nvarchar(128)") .HasMaxLength(128); b.Property("ProviderKey") .IsRequired() + .HasColumnType("nvarchar(64)") .HasMaxLength(64); b.Property("ProviderName") .IsRequired() + .HasColumnType("nvarchar(64)") .HasMaxLength(64); - b.Property("TenantId"); + b.Property("TenantId") + .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -346,20 +419,25 @@ namespace VoloDocs.EntityFrameworkCore.Migrations modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); b.Property("Name") .IsRequired() + .HasColumnType("nvarchar(128)") .HasMaxLength(128); b.Property("ProviderKey") + .HasColumnType("nvarchar(64)") .HasMaxLength(64); b.Property("ProviderName") + .HasColumnType("nvarchar(64)") .HasMaxLength(64); b.Property("Value") .IsRequired() + .HasColumnType("nvarchar(2048)") .HasMaxLength(2048); b.HasKey("Id"); @@ -369,43 +447,155 @@ namespace VoloDocs.EntityFrameworkCore.Migrations b.ToTable("AbpSettings"); }); + modelBuilder.Entity("Volo.Docs.Documents.Document", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("Content") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("EditLink") + .HasColumnType("nvarchar(2048)") + .HasMaxLength(2048); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties") + .HasColumnType("nvarchar(max)"); + + b.Property("FileName") + .IsRequired() + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("Format") + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("LanguageCode") + .IsRequired() + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("LastCachedTime") + .HasColumnType("datetime2"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetime2"); + + b.Property("LocalDirectory") + .HasColumnType("nvarchar(512)") + .HasMaxLength(512); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(255)") + .HasMaxLength(255); + + b.Property("ProjectId") + .HasColumnType("uniqueidentifier"); + + b.Property("RawRootUrl") + .HasColumnType("nvarchar(2048)") + .HasMaxLength(2048); + + b.Property("RootUrl") + .HasColumnType("nvarchar(2048)") + .HasMaxLength(2048); + + b.Property("UpdatedCount") + .HasColumnType("int"); + + b.Property("Version") + .IsRequired() + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.HasKey("Id"); + + b.ToTable("DocsDocuments"); + }); + + modelBuilder.Entity("Volo.Docs.Documents.DocumentContributor", b => + { + b.Property("DocumentId") + .HasColumnType("uniqueidentifier"); + + b.Property("Username") + .HasColumnType("nvarchar(450)"); + + b.Property("AvatarUrl") + .HasColumnType("nvarchar(max)"); + + b.Property("UserProfileUrl") + .HasColumnType("nvarchar(max)"); + + b.HasKey("DocumentId", "Username"); + + b.ToTable("DocsDocumentContributors"); + }); + modelBuilder.Entity("Volo.Docs.Projects.Project", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); b.Property("ConcurrencyStamp") .IsConcurrencyToken() - .HasColumnName("ConcurrencyStamp"); + .HasColumnName("ConcurrencyStamp") + .HasColumnType("nvarchar(max)"); b.Property("DefaultDocumentName") .IsRequired() + .HasColumnType("nvarchar(128)") .HasMaxLength(128); - b.Property("DocumentStoreType"); + b.Property("DocumentStoreType") + .HasColumnType("nvarchar(max)"); b.Property("ExtraProperties") - .HasColumnName("ExtraProperties"); + .HasColumnName("ExtraProperties") + .HasColumnType("nvarchar(max)"); - b.Property("Format"); + b.Property("Format") + .HasColumnType("nvarchar(max)"); b.Property("LatestVersionBranchName") + .HasColumnType("nvarchar(128)") .HasMaxLength(128); - b.Property("MainWebsiteUrl"); + b.Property("MainWebsiteUrl") + .HasColumnType("nvarchar(max)"); - b.Property("MinimumVersion"); + b.Property("MinimumVersion") + .HasColumnType("nvarchar(max)"); b.Property("Name") .IsRequired() + .HasColumnType("nvarchar(128)") .HasMaxLength(128); b.Property("NavigationDocumentName") .IsRequired() + .HasColumnType("nvarchar(128)") + .HasMaxLength(128); + + b.Property("ParametersDocumentName") + .IsRequired() + .HasColumnType("nvarchar(128)") .HasMaxLength(128); b.Property("ShortName") .IsRequired() + .HasColumnType("nvarchar(32)") .HasMaxLength(32); b.HasKey("Id"); @@ -415,47 +605,62 @@ namespace VoloDocs.EntityFrameworkCore.Migrations modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => { - b.HasOne("Volo.Abp.Identity.IdentityRole") + b.HasOne("Volo.Abp.Identity.IdentityRole", null) .WithMany("Claims") .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade); + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); }); modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => { - b.HasOne("Volo.Abp.Identity.IdentityUser") + b.HasOne("Volo.Abp.Identity.IdentityUser", null) .WithMany("Claims") .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); }); modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => { - b.HasOne("Volo.Abp.Identity.IdentityUser") + b.HasOne("Volo.Abp.Identity.IdentityUser", null) .WithMany("Logins") .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); }); modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => { - b.HasOne("Volo.Abp.Identity.IdentityRole") + b.HasOne("Volo.Abp.Identity.IdentityRole", null) .WithMany() .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade); + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); - b.HasOne("Volo.Abp.Identity.IdentityUser") + b.HasOne("Volo.Abp.Identity.IdentityUser", null) .WithMany("Roles") .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); }); modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => { - b.HasOne("Volo.Abp.Identity.IdentityUser") + b.HasOne("Volo.Abp.Identity.IdentityUser", null) .WithMany("Tokens") .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Docs.Documents.DocumentContributor", b => + { + b.HasOne("Volo.Docs.Documents.Document", null) + .WithMany("Contributors") + .HasForeignKey("DocumentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); }); #pragma warning restore 612, 618 } diff --git a/modules/docs/app/VoloDocs.Web/VoloDocs.Web.csproj b/modules/docs/app/VoloDocs.Web/VoloDocs.Web.csproj index a4243c1701..3cc24371b8 100644 --- a/modules/docs/app/VoloDocs.Web/VoloDocs.Web.csproj +++ b/modules/docs/app/VoloDocs.Web/VoloDocs.Web.csproj @@ -1,4 +1,4 @@ - + @@ -19,6 +19,10 @@ + + all + runtime; build; native; contentfiles; analyzers + @@ -34,6 +38,7 @@ + diff --git a/modules/docs/app/VoloDocs.Web/VoloDocsWebModule.cs b/modules/docs/app/VoloDocs.Web/VoloDocsWebModule.cs index 3e37206f31..d46ae6e021 100644 --- a/modules/docs/app/VoloDocs.Web/VoloDocsWebModule.cs +++ b/modules/docs/app/VoloDocs.Web/VoloDocsWebModule.cs @@ -31,6 +31,7 @@ using VoloDocs.EntityFrameworkCore; using Localization.Resources.AbpUi; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Hosting; +using Volo.Abp.Account; using Volo.Abp.Validation.Localization; namespace VoloDocs.Web @@ -43,6 +44,7 @@ namespace VoloDocs.Web typeof(VoloDocsEntityFrameworkCoreModule), typeof(AbpAutofacModule), typeof(AbpAccountWebModule), + typeof(AbpAccountApplicationModule), typeof(AbpIdentityWebModule), typeof(AbpIdentityApplicationModule), typeof(AbpPermissionManagementDomainIdentityModule), @@ -142,6 +144,12 @@ namespace VoloDocs.Web var env = context.GetEnvironment(); app.UseVirtualFiles(); + app.UseRouting(); + + app.UseAuthentication(); + app.UseAuthorization(); + + app.UseAbpRequestLocalization(); app.UseSwagger(); app.UseSwaggerUI(options => @@ -149,24 +157,11 @@ namespace VoloDocs.Web options.SwaggerEndpoint("/swagger/v1/swagger.json", "Support APP API"); }); - app.UseAuthentication(); - - app.UseAbpRequestLocalization(); - app.UseStatusCodePagesWithReExecute("/error/{0}"); //app.UseMiddleware(); - app.UseMvc(routes => - { - routes.MapRoute( - name: "defaultWithArea", - template: "{area}/{controller=Home}/{action=Index}/{id?}"); - - routes.MapRoute( - name: "default", - template: "{controller=Home}/{action=Index}/{id?}"); - }); + app.UseMvcWithDefaultRouteAndArea(); using (var scope = context.ServiceProvider.CreateScope()) { diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/DocsAdminPermissionDefinitionProvider.cs b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/DocsAdminPermissionDefinitionProvider.cs index 9ad0411d15..c7bb12e3bb 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/DocsAdminPermissionDefinitionProvider.cs +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/DocsAdminPermissionDefinitionProvider.cs @@ -14,6 +14,9 @@ namespace Volo.Docs.Admin projects.AddChild(DocsAdminPermissions.Projects.Update, L("Permission:Edit")); projects.AddChild(DocsAdminPermissions.Projects.Delete, L("Permission:Delete")); projects.AddChild(DocsAdminPermissions.Projects.Create, L("Permission:Create")); + + group.AddPermission(DocsAdminPermissions.Documents.Default, L("Permission:Documents")); + } private static LocalizableString L(string name) diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/DocsAdminPermissions.cs b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/DocsAdminPermissions.cs index 341f4c5819..26c1c46254 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/DocsAdminPermissions.cs +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/DocsAdminPermissions.cs @@ -14,6 +14,12 @@ namespace Volo.Docs.Admin public const string Create = Default + ".Create"; } + public static class Documents + { + public const string Default = GroupName + ".Documents"; + } + + public static string[] GetAll() { return ReflectionHelper.GetPublicConstantsRecursively(typeof(DocsAdminPermissions)); diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Documents/IDocumentAdminAppService.cs b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Documents/IDocumentAdminAppService.cs new file mode 100644 index 0000000000..6adab29c74 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Documents/IDocumentAdminAppService.cs @@ -0,0 +1,12 @@ +using System.Threading.Tasks; +using Volo.Abp.Application.Services; + +namespace Volo.Docs.Admin.Documents +{ + public interface IDocumentAdminAppService : IApplicationService + { + Task PullAllAsync(PullAllDocumentInput input); + + Task PullAsync(PullDocumentInput input); + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Documents/PullAllDocumentInput.cs b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Documents/PullAllDocumentInput.cs new file mode 100644 index 0000000000..d796c00e64 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Documents/PullAllDocumentInput.cs @@ -0,0 +1,17 @@ +using System; +using System.ComponentModel.DataAnnotations; +using Volo.Docs.Documents; + +namespace Volo.Docs.Admin.Documents +{ + public class PullAllDocumentInput + { + public Guid ProjectId { get; set; } + + [StringLength(DocumentConsts.MaxLanguageCodeNameLength)] + public string LanguageCode { get; set; } + + [StringLength(DocumentConsts.MaxVersionNameLength)] + public string Version { get; set; } + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Documents/PullDocumentInput.cs b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Documents/PullDocumentInput.cs new file mode 100644 index 0000000000..fcc9816b02 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Documents/PullDocumentInput.cs @@ -0,0 +1,20 @@ +using System; +using System.ComponentModel.DataAnnotations; +using Volo.Docs.Documents; + +namespace Volo.Docs.Admin.Documents +{ + public class PullDocumentInput + { + public Guid ProjectId { get; set; } + + [StringLength(DocumentConsts.MaxNameLength)] + public string Name { get; set; } + + [StringLength(DocumentConsts.MaxLanguageCodeNameLength)] + public string LanguageCode { get; set; } + + [StringLength(DocumentConsts.MaxVersionNameLength)] + public string Version { get; set; } + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/Documents/DocumentAdminAppService.cs b/modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/Documents/DocumentAdminAppService.cs new file mode 100644 index 0000000000..e50e0c4d03 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/Documents/DocumentAdminAppService.cs @@ -0,0 +1,99 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Newtonsoft.Json; +using Volo.Abp.Application.Services; +using Volo.Docs.Documents; +using Volo.Docs.Projects; + +namespace Volo.Docs.Admin.Documents +{ + [Authorize(DocsAdminPermissions.Documents.Default)] + public class DocumentAdminAppService : ApplicationService, IDocumentAdminAppService + { + private readonly IProjectRepository _projectRepository; + private readonly IDocumentRepository _documentRepository; + private readonly IDocumentSourceFactory _documentStoreFactory; + + public DocumentAdminAppService(IProjectRepository projectRepository, + IDocumentRepository documentRepository, + IDocumentSourceFactory documentStoreFactory) + { + _projectRepository = projectRepository; + _documentRepository = documentRepository; + _documentStoreFactory = documentStoreFactory; + } + + public async Task PullAllAsync(PullAllDocumentInput input) + { + var project = await _projectRepository.GetAsync(input.ProjectId); + + var navigationFile = await GetDocumentAsync( + project, + project.NavigationDocumentName, + input.LanguageCode, + input.Version + ); + + var nav = JsonConvert.DeserializeObject(navigationFile.Content); + var leafs = nav.Items.GetAllNodes(x => x.Items) + .Where(x => x.IsLeaf && !x.Path.IsNullOrWhiteSpace()) + .ToList(); + + var source = _documentStoreFactory.Create(project.DocumentStoreType); + + var documents = new List(); + foreach (var leaf in leafs) + { + var sourceDocument = + await source.GetDocumentAsync(project, leaf.Path, input.LanguageCode, input.Version); + documents.Add(sourceDocument); + } + + foreach (var document in documents) + { + var oldDocument = await _documentRepository.FindAsync(document.ProjectId, document.Name, + document.LanguageCode, + document.Version); + + if (oldDocument != null) + { + await _documentRepository.DeleteAsync(oldDocument); + } + + await _documentRepository.InsertAsync(document); + } + } + + public async Task PullAsync(PullDocumentInput input) + { + var project = await _projectRepository.GetAsync(input.ProjectId); + + var source = _documentStoreFactory.Create(project.DocumentStoreType); + var sourceDocument = await source.GetDocumentAsync(project, input.Name, input.LanguageCode, input.Version); + + var oldDocument = await _documentRepository.FindAsync(sourceDocument.ProjectId, sourceDocument.Name, + sourceDocument.LanguageCode, sourceDocument.Version); + + if (oldDocument != null) + { + await _documentRepository.DeleteAsync(oldDocument); + } + + await _documentRepository.InsertAsync(sourceDocument); + } + + private async Task GetDocumentAsync( + Project project, + string documentName, + string languageCode, + string version) + { + version = string.IsNullOrWhiteSpace(version) ? project.LatestVersionBranchName : version; + var source = _documentStoreFactory.Create(project.DocumentStoreType); + return await source.GetDocumentAsync(project, documentName, languageCode, version); + } + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.HttpApi/Volo/Docs/Admin/DocumentsAdminController.cs b/modules/docs/src/Volo.Docs.Admin.HttpApi/Volo/Docs/Admin/DocumentsAdminController.cs new file mode 100644 index 0000000000..75f610d3e5 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Admin.HttpApi/Volo/Docs/Admin/DocumentsAdminController.cs @@ -0,0 +1,36 @@ +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Volo.Abp; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Docs.Admin.Documents; + +namespace Volo.Docs.Admin +{ + [RemoteService] + [Area("docs")] + [ControllerName("DocumentsAdmin")] + [Route("api/docs/admin/documents")] + public class DocumentsAdminController : AbpController, IDocumentAdminAppService + { + private readonly IDocumentAdminAppService _documentAdminAppService; + + public DocumentsAdminController(IDocumentAdminAppService documentAdminAppService) + { + _documentAdminAppService = documentAdminAppService; + } + + [HttpPost] + [Route("PullAll")] + public Task PullAllAsync(PullAllDocumentInput input) + { + return _documentAdminAppService.PullAllAsync(input); + } + + [HttpPost] + [Route("Pull")] + public Task PullAsync(PullDocumentInput input) + { + return _documentAdminAppService.PullAsync(input); + } + } +} diff --git a/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/DocumentWithDetailsDto.cs b/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/DocumentWithDetailsDto.cs index 44b2ef6861..c78a46d2ef 100644 --- a/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/DocumentWithDetailsDto.cs +++ b/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/DocumentWithDetailsDto.cs @@ -7,23 +7,31 @@ namespace Volo.Docs.Documents [Serializable] public class DocumentWithDetailsDto { - public string Title { get; set; } + public virtual string Name { get; set; } - public string Content { get; set; } + public virtual string Version { get; set; } - public string Format { get; set; } + public virtual string LanguageCode { get; set; } - public string EditLink { get; set; } + public virtual string FileName { get; set; } - public string RootUrl { get; set; } + public virtual string Content { get; set; } - public string RawRootUrl { get; set; } + public virtual string Format { get; set; } - public string Version { get; set; } + public virtual string EditLink { get; set; } - public string LocalDirectory { get; set; } + public virtual string RootUrl { get; set; } - public string FileName { get; set; } + public virtual string RawRootUrl { get; set; } + + public virtual string LocalDirectory { get; set; } + + public virtual DateTime LastUpdatedTime { get; set; } + + public virtual int UpdatedCount { get; set; } + + public virtual DateTime LastCachedTime { get; set; } public ProjectDto Project { get; set; } diff --git a/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/IDocumentAppService.cs b/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/IDocumentAppService.cs index cfc4840824..b1195e0254 100644 --- a/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/IDocumentAppService.cs +++ b/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/IDocumentAppService.cs @@ -9,7 +9,7 @@ namespace Volo.Docs.Documents Task GetDefaultAsync(GetDefaultDocumentInput input); - Task GetNavigationAsync(GetNavigationDocumentInput input); + Task GetNavigationAsync(GetNavigationDocumentInput input); Task GetParametersAsync(GetParametersDocumentInput input); diff --git a/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/DocumentAppService.cs b/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/DocumentAppService.cs index 839c63860b..6037a6739d 100644 --- a/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/DocumentAppService.cs +++ b/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/DocumentAppService.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.Hosting; @@ -13,22 +14,22 @@ namespace Volo.Docs.Documents public class DocumentAppService : DocsAppServiceBase, IDocumentAppService { private readonly IProjectRepository _projectRepository; - private readonly IDocumentStoreFactory _documentStoreFactory; - protected IDistributedCache DocumentCache { get; } + private readonly IDocumentRepository _documentRepository; + private readonly IDocumentSourceFactory _documentStoreFactory; protected IDistributedCache LanguageCache { get; } protected IDistributedCache ResourceCache { get; } protected IHostEnvironment HostEnvironment { get; } public DocumentAppService( IProjectRepository projectRepository, - IDocumentStoreFactory documentStoreFactory, - IDistributedCache documentCache, + IDocumentRepository documentRepository, + IDocumentSourceFactory documentStoreFactory, IDistributedCache languageCache, IDistributedCache resourceCache, IHostEnvironment hostEnvironment) { _projectRepository = projectRepository; + _documentRepository = documentRepository; _documentStoreFactory = documentStoreFactory; - DocumentCache = documentCache; LanguageCache = languageCache; ResourceCache = resourceCache; HostEnvironment = hostEnvironment; @@ -58,16 +59,37 @@ namespace Volo.Docs.Documents ); } - public virtual async Task GetNavigationAsync(GetNavigationDocumentInput input) + public virtual async Task GetNavigationAsync(GetNavigationDocumentInput input) { var project = await _projectRepository.GetAsync(input.ProjectId); - return await GetDocumentWithDetailsDtoAsync( + var navigationDocument = await GetDocumentWithDetailsDtoAsync( project, project.NavigationDocumentName, input.LanguageCode, input.Version ); + + var navigationNode = JsonConvert.DeserializeObject(navigationDocument.Content); + + var leafs = navigationNode.Items.GetAllNodes(x => x.Items) + .Where(x => x.IsLeaf && !x.Path.IsNullOrWhiteSpace()) + .ToList(); + + foreach (var leaf in leafs) + { + var document = await GetDocumentWithDetailsDtoAsync( + project, + leaf.Path, + input.LanguageCode, + input.Version + ); + + leaf.LastUpdatedTime = document.LastUpdatedTime; + leaf.UpdatedCount = document.UpdatedCount; + } + + return navigationNode; } public async Task GetResourceAsync(GetDocumentResourceInput input) @@ -78,8 +100,8 @@ namespace Volo.Docs.Documents async Task GetResourceAsync() { - var store = _documentStoreFactory.Create(project.DocumentStoreType); - var documentResource = await store.GetResource(project, input.Name, input.LanguageCode, input.Version); + var source = _documentStoreFactory.Create(project.DocumentStoreType); + var documentResource = await source.GetResource(project, input.Name, input.LanguageCode, input.Version); return ObjectMapper.Map(documentResource); } @@ -136,32 +158,35 @@ namespace Volo.Docs.Documents { version = string.IsNullOrWhiteSpace(version) ? project.LatestVersionBranchName : version; - var cacheKey = $"Document@{project.ShortName}#{languageCode}#{documentName}#{version}"; - async Task GetDocumentAsync() { - Logger.LogInformation($"Not found in the cache. Requesting {documentName} from the store..."); - var store = _documentStoreFactory.Create(project.DocumentStoreType); - var document = await store.GetDocumentAsync(project, documentName, languageCode, version); + Logger.LogInformation($"Not found in the cache. Requesting {documentName} from the source..."); + + var source = _documentStoreFactory.Create(project.DocumentStoreType); + var sourceDocument = await source.GetDocumentAsync(project, documentName, languageCode, version); + + await _documentRepository.InsertAsync(sourceDocument); + Logger.LogInformation($"Document retrieved: {documentName}"); - return CreateDocumentWithDetailsDto(project, document); + + return CreateDocumentWithDetailsDto(project, sourceDocument); } + /* if (HostEnvironment.IsDevelopment()) + { + return await GetDocumentAsync(); + }*/ + + var document = await _documentRepository.FindAsync(project.Id, documentName, languageCode, version); + + //TODO: Configurable cache time? + if (document == null || document.LastCachedTime + TimeSpan.FromHours(12) < DateTime.Now) { return await GetDocumentAsync(); } - return await DocumentCache.GetOrAddAsync( - cacheKey, - GetDocumentAsync, - () => new DistributedCacheEntryOptions - { - //TODO: Configurable? - AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(2), - SlidingExpiration = TimeSpan.FromMinutes(30) - } - ); + return CreateDocumentWithDetailsDto(project, document); } protected virtual DocumentWithDetailsDto CreateDocumentWithDetailsDto(Project project, Document document) @@ -171,6 +196,5 @@ namespace Volo.Docs.Documents documentDto.Contributors = ObjectMapper.Map, List>(document.Contributors); return documentDto; } - } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Application/Volo/Docs/Projects/ProjectAppService.cs b/modules/docs/src/Volo.Docs.Application/Volo/Docs/Projects/ProjectAppService.cs index 13d2ad0ced..c05857f588 100644 --- a/modules/docs/src/Volo.Docs.Application/Volo/Docs/Projects/ProjectAppService.cs +++ b/modules/docs/src/Volo.Docs.Application/Volo/Docs/Projects/ProjectAppService.cs @@ -15,18 +15,18 @@ namespace Volo.Docs.Projects { private readonly IProjectRepository _projectRepository; private readonly IDistributedCache> _versionCache; - private readonly IDocumentStoreFactory _documentStoreFactory; + private readonly IDocumentSourceFactory _documentSource; protected IDistributedCache LanguageCache { get; } public ProjectAppService( IProjectRepository projectRepository, IDistributedCache> versionCache, - IDocumentStoreFactory documentStoreFactory, + IDocumentSourceFactory documentSource, IDistributedCache languageCache) { _projectRepository = projectRepository; _versionCache = versionCache; - _documentStoreFactory = documentStoreFactory; + _documentSource = documentSource; LanguageCache = languageCache; } @@ -68,7 +68,7 @@ namespace Volo.Docs.Projects protected virtual async Task> GetVersionsAsync(Project project) { - var store = _documentStoreFactory.Create(project.DocumentStoreType); + var store = _documentSource.Create(project.DocumentStoreType); var versions = await store.GetVersionsAsync(project); if (!versions.Any()) @@ -108,7 +108,7 @@ namespace Volo.Docs.Projects private async Task GetLanguageListInternalAsync(string shortName, string version) { var project = await _projectRepository.GetByShortNameAsync(shortName); - var store = _documentStoreFactory.Create(project.DocumentStoreType); + var store = _documentSource.Create(project.DocumentStoreType); async Task GetLanguagesAsync() { diff --git a/modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/Documents/DocumentConsts.cs b/modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/Documents/DocumentConsts.cs index 04371e3dff..f629abd0a4 100644 --- a/modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/Documents/DocumentConsts.cs +++ b/modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/Documents/DocumentConsts.cs @@ -3,5 +3,13 @@ public static class DocumentConsts { public const int MaxNameLength = 255; + public const int MaxVersionNameLength = 128; + public const int MaxLanguageCodeNameLength = 128; + public const int MaxFileNameNameLength = 128; + public const int MaxFormatNameLength = 128; + public const int MaxEditLinkLength = 2048; + public const int MaxRootUrlLength = 2048; + public const int MaxRawRootUrlLength = 2048; + public const int MaxLocalDirectoryLength = 512; } } diff --git a/modules/docs/src/Volo.Docs.Web/Models/NavigationNode.cs b/modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/Documents/NavigationNode.cs similarity index 63% rename from modules/docs/src/Volo.Docs.Web/Models/NavigationNode.cs rename to modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/Documents/NavigationNode.cs index c8996a4837..4042344581 100644 --- a/modules/docs/src/Volo.Docs.Web/Models/NavigationNode.cs +++ b/modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/Documents/NavigationNode.cs @@ -22,6 +22,10 @@ namespace Volo.Docs.Documents public bool IsEmpty => Text == null && Path == null; + public DateTime? LastUpdatedTime { get; set; } + + public int UpdatedCount { get; set; } + public bool IsSelected(string documentName) { if (documentName == null) @@ -50,4 +54,24 @@ namespace Volo.Docs.Documents return false; } } + + public static class NavigationNodeExtension + { + public static IEnumerable GetAllNodes(this IEnumerable source, Func> selector) + { + if (source == null) + { + yield break; + } + + foreach (var item in source) + { + yield return item; + foreach (var subItem in GetAllNodes(selector(item), selector)) + { + yield return subItem; + } + } + } + } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/DocsDomainModule.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/DocsDomainModule.cs index 91618b950a..81f681403d 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/DocsDomainModule.cs +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/DocsDomainModule.cs @@ -32,10 +32,10 @@ namespace Volo.Docs .AddVirtualJson("/Volo/Docs/Localization/Domain"); }); - Configure(options => + Configure(options => { - options.Stores[GithubDocumentStore.Type] = typeof(GithubDocumentStore); - options.Stores[FileSystemDocumentStore.Type] = typeof(FileSystemDocumentStore); + options.Sources[GithubDocumentSource.Type] = typeof(GithubDocumentSource); + options.Sources[FileSystemDocumentSource.Type] = typeof(FileSystemDocumentSource); }); context.Services.AddHttpClient(GithubRepositoryManager.HttpClientName, client => diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/Document.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/Document.cs index edec595bc0..ded3fa8530 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/Document.cs +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/Document.cs @@ -1,27 +1,109 @@ +using System; using System.Collections.Generic; +using System.Linq; +using JetBrains.Annotations; +using Volo.Abp; +using Volo.Abp.Domain.Entities; namespace Volo.Docs.Documents { - public class Document + public class Document : AggregateRoot { - public string Title { get; set; } + public virtual Guid ProjectId { get; protected set; } - public string Content { get; set; } + public virtual string Name { get; protected set; } - public string Format { get; set; } + public virtual string Version { get; protected set; } - public string EditLink { get; set; } + public virtual string LanguageCode { get; protected set; } - public string RootUrl { get; set; } + public virtual string FileName { get; set; } - public string RawRootUrl { get; set; } + public virtual string Content { get; set; } - public string Version { get; set; } + public virtual string Format { get; set; } - public string LocalDirectory { get; set; } + public virtual string EditLink { get; set; } - public string FileName { get; set; } + public virtual string RootUrl { get; set; } - public List Contributors { get; set; } + public virtual string RawRootUrl { get; set; } + + public virtual string LocalDirectory { get; set; } + + public virtual DateTime LastUpdatedTime { get; set; } + + public virtual int UpdatedCount { get; set; } + + public virtual DateTime LastCachedTime { get; set; } + + public virtual List Contributors { get; set; } + + protected Document() + { + Contributors = new List(); + ExtraProperties = new Dictionary(); + } + + public Document( + Guid id, + Guid projectId, + [NotNull] string name, + [NotNull] string version, + [NotNull] string languageCode, + [NotNull] string fileName, + [NotNull] string content, + [NotNull] string format, + [NotNull] string editLink, + [NotNull] string rootUrl, + [NotNull] string rawRootUrl, + [NotNull] string localDirectory, + DateTime lastUpdatedTime, + int updatedCount, + DateTime lastCachedTime + ) + { + Id = id; + ProjectId = projectId; + + Name = Check.NotNullOrWhiteSpace(name, nameof(name)); + Version = Check.NotNullOrWhiteSpace(version, nameof(version)); + LanguageCode = Check.NotNullOrWhiteSpace(languageCode, nameof(languageCode)); + FileName = Check.NotNullOrWhiteSpace(fileName, nameof(fileName)); + Content = Check.NotNullOrWhiteSpace(content, nameof(content)); + Format = Check.NotNullOrWhiteSpace(format, nameof(format)); + EditLink = Check.NotNullOrWhiteSpace(editLink, nameof(editLink)); + RootUrl = Check.NotNullOrWhiteSpace(rootUrl, nameof(rootUrl)); + RawRootUrl = Check.NotNullOrWhiteSpace(rawRootUrl, nameof(rawRootUrl)); + LocalDirectory = Check.NotNull(localDirectory, nameof(localDirectory)); + LastUpdatedTime = lastUpdatedTime; + UpdatedCount = updatedCount; + LastCachedTime = lastCachedTime; + + Contributors = new List(); + ExtraProperties = new Dictionary(); + } + + public virtual void AddContributor(string username, string userProfileUrl, string avatarUrl) + { + Contributors.AddIfNotContains(new DocumentContributor(Id, username, userProfileUrl, avatarUrl)); + } + + public virtual void RemoveAllContributors() + { + Contributors.Clear(); + } + + public virtual void RemoveContributor(string username, string userProfileUrl, string avatarUrl) + { + Contributors.RemoveAll(r => + r.Username == username && r.UserProfileUrl == userProfileUrl && r.AvatarUrl == avatarUrl); + } + + public virtual DocumentContributor FindContributor(string username, string userProfileUrl, string avatarUrl) + { + return Contributors.FirstOrDefault(r => + r.Username == username && r.UserProfileUrl == userProfileUrl && r.AvatarUrl == avatarUrl); + } } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/DocumentContributor.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/DocumentContributor.cs index e405ae767c..1351b0a4ca 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/DocumentContributor.cs +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/DocumentContributor.cs @@ -1,15 +1,39 @@ using System; -using System.Collections.Generic; -using System.Text; +using Volo.Abp.Domain.Entities; namespace Volo.Docs.Documents { - public class DocumentContributor + public class DocumentContributor : Entity { + public Guid DocumentId { get; set; } + public string Username { get; set; } public string UserProfileUrl { get; set; } public string AvatarUrl { get; set; } + + protected DocumentContributor() + { + + } + + public virtual bool Equals(Guid documentId, string username) + { + return DocumentId == documentId && Username == username; + } + + public DocumentContributor(Guid documentId, string username, string userProfileUrl, string avatarUrl) + { + DocumentId = documentId; + Username = username; + UserProfileUrl = userProfileUrl; + AvatarUrl = avatarUrl; + } + + public override object[] GetKeys() + { + return new object[] { DocumentId, Username }; + } } } diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/DocumentStoreFactory.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/DocumentSourceFactory.cs similarity index 54% rename from modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/DocumentStoreFactory.cs rename to modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/DocumentSourceFactory.cs index 9e13dd2fd8..88ec294850 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/DocumentStoreFactory.cs +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/DocumentSourceFactory.cs @@ -6,28 +6,28 @@ using Volo.Abp.DependencyInjection; namespace Volo.Docs.Documents { - public class DocumentStoreFactory : IDocumentStoreFactory, ITransientDependency + public class DocumentSourceFactory : IDocumentSourceFactory, ITransientDependency { - protected DocumentStoreOptions Options { get; } + protected DocumentSourceOptions Options { get; } protected IServiceProvider ServiceProvider { get; } - public DocumentStoreFactory( + public DocumentSourceFactory( IServiceProvider serviceProvider, - IOptions options) + IOptions options) { Options = options.Value; ServiceProvider = serviceProvider; } - public virtual IDocumentStore Create(string storeType) + public virtual IDocumentSource Create(string sourceType) { - var serviceType = Options.Stores.GetOrDefault(storeType); + var serviceType = Options.Sources.GetOrDefault(sourceType); if (serviceType == null) { - throw new ApplicationException($"Unknown document store: {storeType}"); + throw new ApplicationException($"Unknown document store: {sourceType}"); } - return (IDocumentStore) ServiceProvider.GetRequiredService(serviceType); + return (IDocumentSource) ServiceProvider.GetRequiredService(serviceType); } } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/DocumentSourceOptions.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/DocumentSourceOptions.cs new file mode 100644 index 0000000000..ccfc36cbfe --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/DocumentSourceOptions.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; + +namespace Volo.Docs.Documents +{ + public class DocumentSourceOptions + { + public Dictionary Sources { get; set; } + + public DocumentSourceOptions() + { + Sources = new Dictionary(); + } + } +} diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/DocumentStoreOptions.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/DocumentStoreOptions.cs deleted file mode 100644 index fcc5781d98..0000000000 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/DocumentStoreOptions.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace Volo.Docs.Documents -{ - public class DocumentStoreOptions - { - public Dictionary Stores { get; set; } - - public DocumentStoreOptions() - { - Stores = new Dictionary(); - } - } -} diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/IDocumentRepository.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/IDocumentRepository.cs new file mode 100644 index 0000000000..b9e0edaee5 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/IDocumentRepository.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Volo.Abp.Domain.Repositories; + +namespace Volo.Docs.Documents +{ + public interface IDocumentRepository : IBasicRepository + { + Task FindAsync(Guid projectId, string name, string languageCode, string version); + } +} diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/IDocumentStore.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/IDocumentSource.cs similarity index 91% rename from modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/IDocumentStore.cs rename to modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/IDocumentSource.cs index 3cbf2c40f2..e9d2779bd3 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/IDocumentStore.cs +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/IDocumentSource.cs @@ -6,7 +6,7 @@ using Volo.Docs.Projects; namespace Volo.Docs.Documents { - public interface IDocumentStore : IDomainService + public interface IDocumentSource : IDomainService { Task GetDocumentAsync(Project project, string documentName, string languageCode, string version); diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/IDocumentSourceFactory.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/IDocumentSourceFactory.cs new file mode 100644 index 0000000000..41e5481c14 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/IDocumentSourceFactory.cs @@ -0,0 +1,7 @@ +namespace Volo.Docs.Documents +{ + public interface IDocumentSourceFactory + { + IDocumentSource Create(string sourceType); + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/IDocumentStoreFactory.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/IDocumentStoreFactory.cs deleted file mode 100644 index 3a997eb26d..0000000000 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/IDocumentStoreFactory.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Volo.Docs.Documents -{ - public interface IDocumentStoreFactory - { - IDocumentStore Create(string storeType); - } -} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/FileSystem/Documents/FileSystemDocumentStore.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/FileSystem/Documents/FileSystemDocumentSource.cs similarity index 75% rename from modules/docs/src/Volo.Docs.Domain/Volo/Docs/FileSystem/Documents/FileSystemDocumentStore.cs rename to modules/docs/src/Volo.Docs.Domain/Volo/Docs/FileSystem/Documents/FileSystemDocumentSource.cs index 085ce9a917..6b28b42e17 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/FileSystem/Documents/FileSystemDocumentStore.cs +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/FileSystem/Documents/FileSystemDocumentSource.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.IO; using System.Security; using System.Threading.Tasks; @@ -11,7 +12,7 @@ using Volo.Docs.Projects; namespace Volo.Docs.FileSystem.Documents { - public class FileSystemDocumentStore : DomainService, IDocumentStore + public class FileSystemDocumentSource : DomainService, IDocumentSource { public const string Type = "FileSystem"; @@ -30,16 +31,21 @@ namespace Volo.Docs.FileSystem.Documents localDirectory = documentName.Substring(0, documentName.LastIndexOf('/')); } - return new Document - { - Content = content, - FileName = Path.GetFileName(path), - Format = project.Format, - LocalDirectory = localDirectory, - Title = documentName, - RawRootUrl = $"/document-resources?projectId={project.Id.ToString()}&version={version}&languageCode={languageCode}&name=", - RootUrl = "/" - }; + return new Document(GuidGenerator.Create(), + project.Id, + documentName, + version, + languageCode, + Path.GetFileName(path), + content, + project.Format, + path, + "/", + $"/document-resources?projectId={project.Id.ToString()}&version={version}&languageCode={languageCode}&name=", + localDirectory, + File.GetLastWriteTime(path), + File.GetLastWriteTime(path) == File.GetCreationTime(path) ? 1 : 2, + DateTime.Now); } public Task> GetVersionsAsync(Project project) diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/FileSystem/Projects/ProjectFileSystemExtensions.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/FileSystem/Projects/ProjectFileSystemExtensions.cs index 904e7b9e29..f0fc44e39e 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/FileSystem/Projects/ProjectFileSystemExtensions.cs +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/FileSystem/Projects/ProjectFileSystemExtensions.cs @@ -24,7 +24,7 @@ namespace Volo.Docs.FileSystem.Projects { Check.NotNull(project, nameof(project)); - if (project.DocumentStoreType != FileSystemDocumentStore.Type) + if (project.DocumentStoreType != FileSystemDocumentSource.Type) { throw new ApplicationException("Given project has not a FileSystem document store!"); } diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/GithubDocumentStore.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/GithubDocumentSource.cs similarity index 86% rename from modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/GithubDocumentStore.cs rename to modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/GithubDocumentSource.cs index c84772ff26..ffe6f042be 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/GithubDocumentStore.cs +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/GithubDocumentSource.cs @@ -16,13 +16,13 @@ namespace Volo.Docs.GitHub.Documents { //TODO: Needs more refactoring - public class GithubDocumentStore : DomainService, IDocumentStore + public class GithubDocumentSource : DomainService, IDocumentSource { public const string Type = "GitHub"; private readonly IGithubRepositoryManager _githubRepositoryManager; - public GithubDocumentStore(IGithubRepositoryManager githubRepositoryManager) + public GithubDocumentSource(IGithubRepositoryManager githubRepositoryManager) { _githubRepositoryManager = githubRepositoryManager; } @@ -47,20 +47,23 @@ namespace Volo.Docs.GitHub.Documents fileName = documentName.Substring(documentName.LastIndexOf('/') + 1); } - return new Document - { - Title = documentName, - EditLink = editLink, - RootUrl = rootUrl, - RawRootUrl = rawRootUrl, - Format = project.Format, - LocalDirectory = localDirectory, - FileName = fileName, - Contributors = new List(), - //Contributors = !isNavigationDocument && !isParameterDocument && !isPartialTemplatesDocumentName ? await GetContributors(commitHistoryUrl, token, userAgent): new List(), - Version = version, - Content = await DownloadWebContentAsStringAsync(rawDocumentUrl, token, userAgent) - }; + var fileCommits = await GetFileCommitsAsync(project, version, $"docs/{languageCode}/{documentName}"); + + return new Document(GuidGenerator.Create(), + project.Id, + documentName, + version, + languageCode, + fileName, + await DownloadWebContentAsStringAsync(rawDocumentUrl, token, userAgent), + project.Format, + editLink, + rootUrl, + rawRootUrl, + localDirectory, + fileCommits.FirstOrDefault()?.Commit.Author.Date.DateTime ?? DateTime.MinValue, + fileCommits.Count, + DateTime.Now); } public async Task> GetVersionsAsync(Project project) @@ -124,6 +127,15 @@ namespace Volo.Docs.GitHub.Documents return await _githubRepositoryManager.GetReleasesAsync(ownerName, repositoryName, project.GetGitHubAccessTokenOrNull()); } + private async Task> GetFileCommitsAsync(Project project, string version, string filename) + { + var url = project.GetGitHubUrl(); + var ownerName = GetOwnerNameFromUrl(url); + var repositoryName = GetRepositoryNameFromUrl(url); + return await _githubRepositoryManager.GetFileCommitsAsync(ownerName, repositoryName, + version, filename, project.GetGitHubAccessTokenOrNull()); + } + protected virtual string GetOwnerNameFromUrl(string url) { try @@ -183,6 +195,7 @@ namespace Volo.Docs.GitHub.Documents } } + /* private async Task> GetContributors(string url, string token, string userAgent) { var contributors = new List(); @@ -215,7 +228,7 @@ namespace Volo.Docs.GitHub.Documents return contributors; } - + */ private static string CalculateRawRootUrlWithLanguageCode(string rootUrl, string languageCode) { return (rootUrl diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/GithubRepositoryManager.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/GithubRepositoryManager.cs index d19f70c2cd..787dcbba48 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/GithubRepositoryManager.cs +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/GithubRepositoryManager.cs @@ -64,5 +64,16 @@ namespace Volo.Docs.GitHub.Documents .Release .GetAll(name, repositoryName)).ToList(); } + + public async Task> GetFileCommitsAsync(string name, string repositoryName, string version, string filename, string token) + { + var client = token.IsNullOrWhiteSpace() + ? new GitHubClient(new ProductHeaderValue(name)) + : new GitHubClient(new ProductHeaderValue(name), new InMemoryCredentialStore(new Credentials(token))); + + var repo = await client.Repository.Get(name, repositoryName); + var request = new CommitRequest { Path = filename, Sha = version }; + return await client.Repository.Commit.GetAll(repo.Id, request); + } } } diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/IGithubRepositoryManager.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/IGithubRepositoryManager.cs index 519b9829d5..fa81ba695b 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/IGithubRepositoryManager.cs +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/IGithubRepositoryManager.cs @@ -15,5 +15,6 @@ namespace Volo.Docs.GitHub.Documents Task> GetReleasesAsync(string name, string repositoryName, string token); + Task> GetFileCommitsAsync(string name, string repositoryName, string version, string filename, string token); } } diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Projects/ProjectGithubExtensions.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Projects/ProjectGithubExtensions.cs index 3d2170a121..ff1979d037 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Projects/ProjectGithubExtensions.cs +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Projects/ProjectGithubExtensions.cs @@ -57,7 +57,7 @@ namespace Volo.Docs.GitHub.Projects { Check.NotNull(project, nameof(project)); - if (project.DocumentStoreType != GithubDocumentStore.Type) + if (project.DocumentStoreType != GithubDocumentSource.Type) { throw new ApplicationException("Given project has not a Github document store!"); } diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en.json index 1750f82e61..5115dd1489 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en.json @@ -7,6 +7,7 @@ "ShareOn": "Share on", "Version": "Version", "Edit": "Edit", + "LastEditTime": "Last edit", "Delete": "Delete", "InThisDocument": "In this document", "GoToTop": "Go to top", @@ -16,6 +17,8 @@ "NavigationDocumentNotFound": "This version does not have a navigation document!", "DocumentNotFoundInSelectedLanguage": "Document in the language you wanted is not found. Document in the default language is shown.", "FilterTopics": "Filter topics", - "MultipleVersionDocumentInfo": "This document has multiple versions. Select the options best fit for you." + "MultipleVersionDocumentInfo": "This document has multiple versions. Select the options best fit for you.", + "New": "New", + "Upd": "Upd" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/tr.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/tr.json index 440273022f..a546f626dc 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/tr.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/tr.json @@ -7,6 +7,7 @@ "ShareOn": "Paylaş", "Version": "Versiyon", "Edit": "Düzenle", + "LastEditTime": "Son Düzenleme", "Delete": "Sil", "InThisDocument": "Bu dökümanda", "GoToTop": "En üste çık", @@ -15,6 +16,8 @@ "DocumentNotFound": "Aradığınız döküman bulunamadı!", "NavigationDocumentNotFound": "Bu döküman için menü bulunamadı!", "DocumentNotFoundInSelectedLanguage": "İstediğiniz dilde belge bulunamadı. Varsayılan dilde belge gösterilir.", - "MultipleVersionDocumentInfo": "Bu dökümanın birden çok versiyonu bulunmaktadır. Sizin için en uygun olan seçenekleri seçiniz." + "MultipleVersionDocumentInfo": "Bu dökümanın birden çok versiyonu bulunmaktadır. Sizin için en uygun olan seçenekleri seçiniz.", + "New": "Yeni", + "Upd": "güncellenmiş" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/zh-Hans.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/zh-Hans.json index 410374b4fd..bbc0014c95 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/zh-Hans.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/zh-Hans.json @@ -7,6 +7,7 @@ "ShareOn": "分享到", "Version": "版本", "Edit": "编辑", + "LastEditTime": "上次编辑", "Delete": "删除", "InThisDocument": "在本文中", "GoToTop": "到顶部", @@ -15,6 +16,8 @@ "DocumentNotFound": "找不到请求的文档!", "NavigationDocumentNotFound": "这个版本没有导航文件!", "DocumentNotFoundInSelectedLanguage": "本文档不适用于所选语言, 将以默认语言显示文档.", - "FilterTopics": "过滤主题" + "FilterTopics": "过滤主题", + "New": "新文档", + "Upd": "更新" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/zh-Hant.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/zh-Hant.json index 34ded108f1..9d24c75510 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/zh-Hant.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/zh-Hant.json @@ -7,6 +7,7 @@ "ShareOn": "分享到", "Version": "版本", "Edit": "編輯", + "LastEditTime": "上次編輯", "Delete": "刪除", "InThisDocument": "在此文件中", "GoToTop": "到最上方", @@ -15,6 +16,8 @@ "DocumentNotFound": "找不到要求的文件!", "NavigationDocumentNotFound": "這個版本沒有導覽文件!", "DocumentNotFoundInSelectedLanguage": "本文件不適用於所選語系,將以預設語系顯示.", - "FilterTopics": "過濾主題" + "FilterTopics": "過濾主題", + "New": "新文檔", + "Upd": "更新" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo.Docs.EntityFrameworkCore.csproj b/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo.Docs.EntityFrameworkCore.csproj index cd0dbdf97c..d8bf0d7fc6 100644 --- a/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo.Docs.EntityFrameworkCore.csproj +++ b/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo.Docs.EntityFrameworkCore.csproj @@ -10,6 +10,12 @@ + + + + + + diff --git a/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/Documents/EFCoreDocumentRepository.cs b/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/Documents/EFCoreDocumentRepository.cs new file mode 100644 index 0000000000..e965bd11a6 --- /dev/null +++ b/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/Documents/EFCoreDocumentRepository.cs @@ -0,0 +1,23 @@ +using System; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Volo.Abp.Domain.Repositories.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore; +using Volo.Docs.EntityFrameworkCore; + +namespace Volo.Docs.Documents +{ + public class EFCoreDocumentRepository : EfCoreRepository, IDocumentRepository + { + public EFCoreDocumentRepository(IDbContextProvider dbContextProvider) + : base(dbContextProvider) + { + } + + public async Task FindAsync(Guid projectId, string name, string languageCode, string version) + { + return await DbSet.FirstOrDefaultAsync(x => + x.ProjectId == projectId && x.Name == name && x.LanguageCode == languageCode && x.Version == version); + } + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/DocsDbContext.cs b/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/DocsDbContext.cs index 1f6a43b825..7c1c635617 100644 --- a/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/DocsDbContext.cs +++ b/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/DocsDbContext.cs @@ -1,6 +1,7 @@ using Microsoft.EntityFrameworkCore; using Volo.Abp.Data; using Volo.Abp.EntityFrameworkCore; +using Volo.Docs.Documents; using Volo.Docs.Projects; namespace Volo.Docs.EntityFrameworkCore @@ -10,6 +11,10 @@ namespace Volo.Docs.EntityFrameworkCore { public DbSet Projects { get; set; } + public DbSet Documents { get; set; } + + public DbSet DocumentContributors { get; set; } + public DocsDbContext(DbContextOptions options) : base(options) { diff --git a/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/DocsDbContextModelBuilderExtensions.cs b/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/DocsDbContextModelBuilderExtensions.cs index f6a17b68d7..64a85db140 100644 --- a/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/DocsDbContextModelBuilderExtensions.cs +++ b/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/DocsDbContextModelBuilderExtensions.cs @@ -3,6 +3,7 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore; using Volo.Abp; using Volo.Abp.EntityFrameworkCore.Modeling; +using Volo.Docs.Documents; using Volo.Docs.Projects; namespace Volo.Docs.EntityFrameworkCore @@ -26,8 +27,7 @@ namespace Volo.Docs.EntityFrameworkCore { b.ToTable(options.TablePrefix + "Projects", options.Schema); - b.ConfigureConcurrencyStamp(); - b.ConfigureExtraProperties(); + b.ConfigureByConvention(); b.Property(x => x.Name).IsRequired().HasMaxLength(ProjectConsts.MaxNameLength); b.Property(x => x.ShortName).IsRequired().HasMaxLength(ProjectConsts.MaxShortNameLength); @@ -36,6 +36,35 @@ namespace Volo.Docs.EntityFrameworkCore b.Property(x => x.ParametersDocumentName).IsRequired().HasMaxLength(ProjectConsts.MaxParametersDocumentNameLength); b.Property(x => x.LatestVersionBranchName).HasMaxLength(ProjectConsts.MaxLatestVersionBranchNameLength); }); + + builder.Entity(b => + { + b.ToTable(options.TablePrefix + "Documents", options.Schema); + + b.ConfigureByConvention(); + + b.Property(x => x.Name).IsRequired().HasMaxLength(DocumentConsts.MaxNameLength); + b.Property(x => x.Version).IsRequired().HasMaxLength(DocumentConsts.MaxVersionNameLength); + b.Property(x => x.LanguageCode).IsRequired().HasMaxLength(DocumentConsts.MaxLanguageCodeNameLength); + b.Property(x => x.FileName).IsRequired().HasMaxLength(DocumentConsts.MaxFileNameNameLength); + b.Property(x => x.Content).IsRequired(); + b.Property(x => x.Format).HasMaxLength(DocumentConsts.MaxFormatNameLength); + b.Property(x => x.EditLink).HasMaxLength(DocumentConsts.MaxEditLinkLength); + b.Property(x => x.RootUrl).HasMaxLength(DocumentConsts.MaxRootUrlLength); + b.Property(x => x.RawRootUrl).HasMaxLength(DocumentConsts.MaxRawRootUrlLength); + b.Property(x => x.LocalDirectory).HasMaxLength(DocumentConsts.MaxLocalDirectoryLength); + + b.HasMany(x => x.Contributors).WithOne() + .HasForeignKey(x => new { x.DocumentId }) + .IsRequired(); + }); + + builder.Entity(b => + { + b.ToTable(options.TablePrefix + "DocumentContributors", options.Schema); + + b.HasKey(x => new { x.DocumentId, x.Username }); + }); } } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/DocsEntityFrameworkCoreModule.cs b/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/DocsEntityFrameworkCoreModule.cs index 459a96516b..6e6b780666 100644 --- a/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/DocsEntityFrameworkCoreModule.cs +++ b/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/DocsEntityFrameworkCoreModule.cs @@ -1,6 +1,7 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.EntityFrameworkCore; using Volo.Abp.Modularity; +using Volo.Docs.Documents; using Volo.Docs.Projects; namespace Volo.Docs.EntityFrameworkCore @@ -15,6 +16,7 @@ namespace Volo.Docs.EntityFrameworkCore context.Services.AddAbpDbContext(options => { options.AddRepository(); + options.AddRepository(); }); } } diff --git a/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/IDocsDbContext.cs b/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/IDocsDbContext.cs index 4f11d438e7..6e96604592 100644 --- a/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/IDocsDbContext.cs +++ b/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/IDocsDbContext.cs @@ -1,6 +1,7 @@ using Microsoft.EntityFrameworkCore; using Volo.Abp.Data; using Volo.Abp.EntityFrameworkCore; +using Volo.Docs.Documents; using Volo.Docs.Projects; namespace Volo.Docs.EntityFrameworkCore @@ -9,5 +10,9 @@ namespace Volo.Docs.EntityFrameworkCore public interface IDocsDbContext : IEfCoreDbContext { DbSet Projects { get; set; } + + DbSet Documents { get; set; } + + DbSet DocumentContributors { get; set; } } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.HttpApi/Volo/Docs/Documents/DocsDocumentController.cs b/modules/docs/src/Volo.Docs.HttpApi/Volo/Docs/Documents/DocsDocumentController.cs index 9ff91c8b17..a066a92f23 100644 --- a/modules/docs/src/Volo.Docs.HttpApi/Volo/Docs/Documents/DocsDocumentController.cs +++ b/modules/docs/src/Volo.Docs.HttpApi/Volo/Docs/Documents/DocsDocumentController.cs @@ -34,7 +34,7 @@ namespace Volo.Docs.Documents [HttpGet] [Route("navigation")] - public virtual Task GetNavigationAsync(GetNavigationDocumentInput input) + public Task GetNavigationAsync(GetNavigationDocumentInput input) { return DocumentAppService.GetNavigationAsync(input); } diff --git a/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Documents/MongoDocumentRepository.cs b/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Documents/MongoDocumentRepository.cs new file mode 100644 index 0000000000..5e7cc5871a --- /dev/null +++ b/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Documents/MongoDocumentRepository.cs @@ -0,0 +1,25 @@ +using System; +using System.Threading.Tasks; +using MongoDB.Driver.Linq; +using Volo.Abp.Domain.Repositories.MongoDB; +using Volo.Abp.MongoDB; +using Volo.Docs.MongoDB; + +namespace Volo.Docs.Documents +{ + public class MongoDocumentRepository : MongoDbRepository, IDocumentRepository + { + public MongoDocumentRepository(IMongoDbContextProvider dbContextProvider) + : base(dbContextProvider) + { + } + + public async Task FindAsync(Guid projectId, string name, string languageCode, string version) + { + return await GetMongoQueryable().FirstOrDefaultAsync(x => x.ProjectId == projectId && + x.Name == name && + x.LanguageCode == languageCode && + x.Version == version); + } + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/MongoDB/BloggingMongoDbModule.cs b/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/MongoDB/BloggingMongoDbModule.cs index 68b7827b08..cc9662a1ad 100644 --- a/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/MongoDB/BloggingMongoDbModule.cs +++ b/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/MongoDB/BloggingMongoDbModule.cs @@ -2,6 +2,7 @@ using Volo.Abp.MongoDB; using Volo.Docs.Projects; using Microsoft.Extensions.DependencyInjection; +using Volo.Docs.Documents; namespace Volo.Docs.MongoDB { @@ -16,6 +17,7 @@ namespace Volo.Docs.MongoDB context.Services.AddMongoDbContext(options => { options.AddRepository(); + options.AddRepository(); }); } } diff --git a/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/MongoDB/DocsMongoDbContext.cs b/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/MongoDB/DocsMongoDbContext.cs index cc65e9ab3e..afc430c945 100644 --- a/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/MongoDB/DocsMongoDbContext.cs +++ b/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/MongoDB/DocsMongoDbContext.cs @@ -2,6 +2,7 @@ using Volo.Abp.Data; using Volo.Docs.Projects; using Volo.Abp.MongoDB; +using Volo.Docs.Documents; namespace Volo.Docs.MongoDB { @@ -9,6 +10,7 @@ namespace Volo.Docs.MongoDB public class DocsMongoDbContext : AbpMongoDbContext, IDocsMongoDbContext { public IMongoCollection Projects => Collection(); + public IMongoCollection Documents => Collection(); protected override void CreateModel(IMongoModelBuilder modelBuilder) { diff --git a/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/MongoDB/DocsMongoDbContextExtensions.cs b/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/MongoDB/DocsMongoDbContextExtensions.cs index 456070a645..c1645885d2 100644 --- a/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/MongoDB/DocsMongoDbContextExtensions.cs +++ b/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/MongoDB/DocsMongoDbContextExtensions.cs @@ -1,6 +1,7 @@ using System; using Volo.Abp; using Volo.Abp.MongoDB; +using Volo.Docs.Documents; using Volo.Docs.Projects; namespace Volo.Docs.MongoDB @@ -23,6 +24,11 @@ namespace Volo.Docs.MongoDB { b.CollectionName = options.CollectionPrefix + "Projects"; }); + + builder.Entity(b => + { + b.CollectionName = options.CollectionPrefix + "DocumentS"; + }); } } } diff --git a/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/MongoDB/IDocsMongoDbContext.cs b/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/MongoDB/IDocsMongoDbContext.cs index 78b3be8484..92c86a7c4f 100644 --- a/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/MongoDB/IDocsMongoDbContext.cs +++ b/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/MongoDB/IDocsMongoDbContext.cs @@ -1,6 +1,7 @@ using MongoDB.Driver; using Volo.Abp.Data; using Volo.Abp.MongoDB; +using Volo.Docs.Documents; using Volo.Docs.Projects; namespace Volo.Docs.MongoDB @@ -8,8 +9,8 @@ namespace Volo.Docs.MongoDB [ConnectionStringName(DocsDbProperties.ConnectionStringName)] public interface IDocsMongoDbContext : IAbpMongoDbContext { - IMongoCollection Projects { get; } + IMongoCollection Documents { get; } } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Web/Areas/Documents/TagHelpers/TreeTagHelper.cs b/modules/docs/src/Volo.Docs.Web/Areas/Documents/TagHelpers/TreeTagHelper.cs index afb61eadd3..23be8a8cff 100644 --- a/modules/docs/src/Volo.Docs.Web/Areas/Documents/TagHelpers/TreeTagHelper.cs +++ b/modules/docs/src/Volo.Docs.Web/Areas/Documents/TagHelpers/TreeTagHelper.cs @@ -2,8 +2,10 @@ using System.Linq; using System.Text; using Microsoft.AspNetCore.Razor.TagHelpers; +using Microsoft.Extensions.Localization; using Microsoft.Extensions.Options; using Volo.Docs.Documents; +using Volo.Docs.Localization; using Volo.Docs.Utils; namespace Volo.Docs.Areas.Documents.TagHelpers @@ -15,6 +17,8 @@ namespace Volo.Docs.Areas.Documents.TagHelpers { private readonly DocsUiOptions _uiOptions; + private readonly IStringLocalizer _localizer; + private const string LiItemTemplateWithLink = @"
  • {2}{3}
  • "; private const string ListItemAnchor = @"{2}"; @@ -41,8 +45,9 @@ namespace Volo.Docs.Areas.Documents.TagHelpers [HtmlAttributeName("language")] public string LanguageCode { get; set; } - public TreeTagHelper(IOptions urlOptions) + public TreeTagHelper(IOptions urlOptions, IStringLocalizer localizer) { + _localizer = localizer; _uiOptions = urlOptions.Value; } @@ -118,7 +123,15 @@ namespace Volo.Docs.Areas.Documents.TagHelpers } else { - listInnerItem = string.Format(ListItemAnchor, NormalizePath(node.Path), textCss, node.Text.IsNullOrEmpty() ? "?" : node.Text); + var badge = node.Path.IsNullOrWhiteSpace() + ? "" + : "" + + (node.LastUpdatedTime + TimeSpan.FromDays(30) > DateTime.Now ? (node.UpdatedCount == 1 ? _localizer["New"] : _localizer["Upd"]) : "") + ""; + + listInnerItem = string.Format(ListItemAnchor, NormalizePath(node.Path), textCss, + node.Text.IsNullOrEmpty() + ? "?" + : node.Text + badge); } return string.Format(LiItemTemplateWithLink, diff --git a/modules/docs/src/Volo.Docs.Web/DocsWebAutoMapperProfile.cs b/modules/docs/src/Volo.Docs.Web/DocsWebAutoMapperProfile.cs index 4a25c94370..a4c4c7647e 100644 --- a/modules/docs/src/Volo.Docs.Web/DocsWebAutoMapperProfile.cs +++ b/modules/docs/src/Volo.Docs.Web/DocsWebAutoMapperProfile.cs @@ -8,8 +8,7 @@ namespace Volo.Docs { public DocsWebAutoMapperProfile() { - CreateMap() - .Ignore(x => x.RootNode); + } } } diff --git a/modules/docs/src/Volo.Docs.Web/Models/NavigationWithDetailsDto.cs b/modules/docs/src/Volo.Docs.Web/Models/NavigationWithDetailsDto.cs deleted file mode 100644 index a85c6eeb01..0000000000 --- a/modules/docs/src/Volo.Docs.Web/Models/NavigationWithDetailsDto.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using Newtonsoft.Json; - -namespace Volo.Docs.Documents -{ - public class NavigationWithDetailsDto : DocumentWithDetailsDto - { - [JsonProperty("items")] - public NavigationNode RootNode { get; set; } - - public void ConvertItems() - { - if (Content.IsNullOrEmpty()) - { - RootNode = new NavigationNode(); - return; - } - - try - { - RootNode = JsonConvert.DeserializeObject(Content); - } - catch (JsonException ex) - { - //todo: should log the exception? - RootNode = new NavigationNode(); - } - } - } -} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml index bebf083381..a8d950b1ce 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml @@ -1,4 +1,4 @@ -@page +@page @using Microsoft.AspNetCore.Mvc.Localization @using Volo.Abp.AspNetCore.Mvc.UI.Layout @using Volo.Abp.AspNetCore.Mvc.UI.Packages.Anchor @@ -145,7 +145,7 @@ - @if (Model.Navigation == null || Model.Navigation.Content.IsNullOrEmpty()) + @if (Model.Navigation == null || !Model.Navigation.HasChildItems) {
    @L["NavigationDocumentNotFound"] @@ -153,7 +153,7 @@ } else { -
    diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs index 82b58ad117..6212619971 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs @@ -49,7 +49,7 @@ namespace Volo.Docs.Pages.Documents.Project public List ProjectSelectItems { get; private set; } - public NavigationWithDetailsDto Navigation { get; private set; } + public NavigationNode Navigation { get; private set; } public VersionInfoViewModel LatestVersionInfo { get; private set; } @@ -271,7 +271,7 @@ namespace Volo.Docs.Pages.Documents.Project { try { - var document = await _documentAppService.GetNavigationAsync( + Navigation = await _documentAppService.GetNavigationAsync( new GetNavigationDocumentInput { ProjectId = Project.Id, @@ -279,15 +279,11 @@ namespace Volo.Docs.Pages.Documents.Project Version = Version } ); - - Navigation = ObjectMapper.Map(document); } catch (DocumentNotFoundException) //TODO: What if called on a remote service which may return 404 { return; } - - Navigation.ConvertItems(); } public string CreateVersionLink(VersionInfoViewModel latestVersion, string version, string documentName = null) diff --git a/modules/docs/test/Volo.Docs.Domain.Tests/Volo/Docs/DocumentStoreFactory_Tests.cs b/modules/docs/test/Volo.Docs.Domain.Tests/Volo/Docs/DocumentStoreFactory_Tests.cs index 73e07ec8e2..23d34748a6 100644 --- a/modules/docs/test/Volo.Docs.Domain.Tests/Volo/Docs/DocumentStoreFactory_Tests.cs +++ b/modules/docs/test/Volo.Docs.Domain.Tests/Volo/Docs/DocumentStoreFactory_Tests.cs @@ -8,18 +8,18 @@ namespace Volo.Docs { public class DocumentStoreFactory_Tests : DocsDomainTestBase { - private readonly IDocumentStoreFactory _documentStoreFactory; + private readonly IDocumentSourceFactory _documentStoreFactory; public DocumentStoreFactory_Tests() { - _documentStoreFactory = GetRequiredService(); + _documentStoreFactory = GetRequiredService(); } [Fact] public void Create() { - _documentStoreFactory.Create(GithubDocumentStore.Type).GetType().ShouldBe(typeof(GithubDocumentStore)); - _documentStoreFactory.Create(FileSystemDocumentStore.Type).GetType().ShouldBe(typeof(FileSystemDocumentStore)); + _documentStoreFactory.Create(GithubDocumentSource.Type).GetType().ShouldBe(typeof(GithubDocumentSource)); + _documentStoreFactory.Create(FileSystemDocumentSource.Type).GetType().ShouldBe(typeof(FileSystemDocumentSource)); } } } diff --git a/modules/docs/test/Volo.Docs.Domain.Tests/Volo/Docs/GithubDocumentStore_Tests.cs b/modules/docs/test/Volo.Docs.Domain.Tests/Volo/Docs/GithubDocumentStore_Tests.cs index 76d1f9f68f..6b6bb0565c 100644 --- a/modules/docs/test/Volo.Docs.Domain.Tests/Volo/Docs/GithubDocumentStore_Tests.cs +++ b/modules/docs/test/Volo.Docs.Domain.Tests/Volo/Docs/GithubDocumentStore_Tests.cs @@ -9,13 +9,13 @@ namespace Volo.Docs { public class GithubDocumentStore_Tests : DocsDomainTestBase { - private readonly IDocumentStoreFactory _documentStoreFactory; + private readonly IDocumentSourceFactory _documentStoreFactory; private readonly IProjectRepository _projectRepository; private readonly DocsTestData _testData; public GithubDocumentStore_Tests() { - _documentStoreFactory = GetRequiredService(); + _documentStoreFactory = GetRequiredService(); _projectRepository = GetRequiredService(); _testData = GetRequiredService(); } @@ -23,15 +23,15 @@ namespace Volo.Docs [Fact] public async Task GetDocumentAsync() { - var store = _documentStoreFactory.Create(GithubDocumentStore.Type); + var source = _documentStoreFactory.Create(GithubDocumentSource.Type); var project = await _projectRepository.FindAsync(_testData.PorjectId); project.ShouldNotBeNull(); - var document = await store.GetDocumentAsync(project, "index2", "en", "0.123.0"); + var document = await source.GetDocumentAsync(project, "index2", "en", "0.123.0"); document.ShouldNotBeNull(); - document.Title.ShouldBe("index2"); + document.Name.ShouldBe("index2"); document.FileName.ShouldBe("index2"); document.Version.ShouldBe("0.123.0"); document.Content.ShouldBe("stringContent"); @@ -40,12 +40,12 @@ namespace Volo.Docs [Fact] public async Task GetVersionsAsync() { - var store = _documentStoreFactory.Create(GithubDocumentStore.Type); + var source = _documentStoreFactory.Create(GithubDocumentSource.Type); var project = await _projectRepository.FindAsync(_testData.PorjectId); project.ShouldNotBeNull(); - var document = await store.GetVersionsAsync(project); + var document = await source.GetVersionsAsync(project); document.ShouldNotBeNull(); document.Count.ShouldBe(1); @@ -55,12 +55,12 @@ namespace Volo.Docs [Fact] public async Task GetResource() { - var store = _documentStoreFactory.Create(GithubDocumentStore.Type); + var source = _documentStoreFactory.Create(GithubDocumentSource.Type); var project = await _projectRepository.FindAsync(_testData.PorjectId); project.ShouldNotBeNull(); - var documentResource = await store.GetResource(project, "index.md", "en", "0.123.0"); + var documentResource = await source.GetResource(project, "index.md", "en", "0.123.0"); documentResource.ShouldNotBeNull(); documentResource.Content.ShouldBe(new byte[] diff --git a/modules/docs/test/Volo.Docs.TestBase/Volo/Docs/DocsTestDataBuilder.cs b/modules/docs/test/Volo.Docs.TestBase/Volo/Docs/DocsTestDataBuilder.cs index 121d18b44a..be5bab81bc 100644 --- a/modules/docs/test/Volo.Docs.TestBase/Volo/Docs/DocsTestDataBuilder.cs +++ b/modules/docs/test/Volo.Docs.TestBase/Volo/Docs/DocsTestDataBuilder.cs @@ -25,7 +25,7 @@ namespace Volo.Docs _testData.PorjectId, "ABP vNext", "ABP", - GithubDocumentStore.Type, + GithubDocumentSource.Type, "md", "index", "docs-nav.json",