From 0492e2476d8c91a98745f0cf36ff078f4c764b15 Mon Sep 17 00:00:00 2001 From: Oliver Cooper Date: Sat, 21 Mar 2020 12:21:48 +0000 Subject: [PATCH 001/151] Added virtual to TenantCreateDto. --- .../Volo/Abp/TenantManagement/TenantCreateDto.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/TenantCreateDto.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/TenantCreateDto.cs index 189d7d0f80..7b52a6dd4b 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/TenantCreateDto.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/TenantCreateDto.cs @@ -12,11 +12,11 @@ namespace Volo.Abp.TenantManagement [Required] [EmailAddress] [MaxLength(256)] - public string AdminEmailAddress { get; set; } + public virtual string AdminEmailAddress { get; set; } [Required] [MaxLength(128)] - public string AdminPassword { get; set; } + public virtual string AdminPassword { get; set; } } } \ No newline at end of file From a8d4e7c229d8e76f7a174a30de31a02e475d9fe4 Mon Sep 17 00:00:00 2001 From: maliming Date: Wed, 25 Mar 2020 15:38:37 +0800 Subject: [PATCH 002/151] Use Exists property to determine if the file exists. Resolve #3341 --- .../Mvc/UI/Bundling/TagHelpers/AbpTagHelperResourceService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/TagHelpers/AbpTagHelperResourceService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/TagHelpers/AbpTagHelperResourceService.cs index 73b6e025ea..40fd3e6ea5 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/TagHelpers/AbpTagHelperResourceService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/TagHelpers/AbpTagHelperResourceService.cs @@ -63,7 +63,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling.TagHelpers foreach (var bundleFile in bundleFiles) { var file = WebContentFileProvider.GetFileInfo(bundleFile); - if (file == null) + if (!file.Exists) { throw new AbpException($"Could not find the bundle file from {nameof(IWebContentFileProvider)}"); } From 283da6783b632bf5d00d834dd8f7b10c098a0b6c Mon Sep 17 00:00:00 2001 From: maliming Date: Thu, 26 Mar 2020 14:45:46 +0800 Subject: [PATCH 003/151] Apply Entity Extension System for samples Resolve #3361 --- .../Acme.BookStore.Domain/Users/AppUser.cs | 16 ++++++-- .../Acme.BookStore.Domain/Users/AppUser.cs | 16 ++++++-- .../BookStoreMigrationsDbContext.cs | 7 ---- .../BookStoreMigrationsDbContextFactory.cs | 2 + .../EntityFrameworkCore/BookStoreDbContext.cs | 8 ++-- ...okStoreDbContextModelCreatingExtensions.cs | 8 ---- .../BookStoreEntityExtensions.cs | 33 +++++++++++++++ .../BookStoreEntityFrameworkCoreModule.cs | 5 +++ .../BookManagementEntityExtensions.cs | 32 +++++++++++++++ ...BookManagementEntityFrameworkCoreModule.cs | 5 +++ .../Acme.BookStore.Domain/Users/AppUser.cs | 16 ++++++-- .../BookStoreMigrationsDbContext.cs | 7 ---- .../BookStoreMigrationsDbContextFactory.cs | 2 + .../EntityFrameworkCore/BookStoreDbContext.cs | 8 ++-- ...okStoreDbContextModelCreatingExtensions.cs | 8 ---- .../BookStoreEntityExtensions.cs | 33 +++++++++++++++ .../BookStoreEntityFrameworkCoreModule.cs | 5 +++ .../src/DashboardDemo.Domain/Users/AppUser.cs | 16 ++++++-- .../DashboardDemoMigrationsDbContext.cs | 7 ---- ...DashboardDemoMigrationsDbContextFactory.cs | 2 + .../DashboardDemoDbContext.cs | 8 ++-- ...ardDemoDbContextModelCreatingExtensions.cs | 8 ---- .../DashboardDemoEntityExtensions.cs | 33 +++++++++++++++ .../DashboardDemoEntityFrameworkCoreModule.cs | 5 +++ .../Acme.BookStore.Domain/Users/AppUser.cs | 16 ++++++-- .../BookStoreMigrationsDbContext.cs | 13 ------ .../BookStoreMigrationsDbContextFactory.cs | 2 + .../EntityFrameworkCore/BookStoreDbContext.cs | 8 ++-- ...okStoreDbContextModelCreatingExtensions.cs | 19 +-------- .../BookStoreEntityExtensions.cs | 40 +++++++++++++++++++ .../BookStoreEntityFrameworkCoreModule.cs | 5 +++ 31 files changed, 290 insertions(+), 103 deletions(-) create mode 100644 samples/BookStore-Modular/application/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreEntityExtensions.cs create mode 100644 samples/BookStore-Modular/modules/book-management/src/Acme.BookStore.BookManagement.EntityFrameworkCore/EntityFrameworkCore/BookManagementEntityExtensions.cs create mode 100644 samples/BookStore/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreEntityExtensions.cs create mode 100644 samples/DashboardDemo/src/DashboardDemo.EntityFrameworkCore/EntityFrameworkCore/DashboardDemoEntityExtensions.cs create mode 100644 samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreEntityExtensions.cs diff --git a/samples/BookStore-Angular-MongoDb/aspnet-core/src/Acme.BookStore.Domain/Users/AppUser.cs b/samples/BookStore-Angular-MongoDb/aspnet-core/src/Acme.BookStore.Domain/Users/AppUser.cs index 9068cfbcd5..37f67ba60a 100644 --- a/samples/BookStore-Angular-MongoDb/aspnet-core/src/Acme.BookStore.Domain/Users/AppUser.cs +++ b/samples/BookStore-Angular-MongoDb/aspnet-core/src/Acme.BookStore.Domain/Users/AppUser.cs @@ -41,9 +41,19 @@ namespace Acme.BookStore.Users #endregion /* Add your own properties here. Example: - * - * public virtual string MyProperty { get; set; } - */ + * + * public string MyProperty { get; set; } + * + * If you add a property and using the EF Core, remember these; + * + * 1. update BookStoreDbContext.OnModelCreating + * to configure the mapping for your new property + * 2. Update BookStoreEntityExtensions to extend the IdentityUser entity + * and add your new property to the migration. + * 3. Use the Add-Migration to add a new database migration. + * 4. Run the .DbMigrator project (or use the Update-Database command) to apply + * schema change to the database. + */ private AppUser() { diff --git a/samples/BookStore-Modular/application/src/Acme.BookStore.Domain/Users/AppUser.cs b/samples/BookStore-Modular/application/src/Acme.BookStore.Domain/Users/AppUser.cs index 9068cfbcd5..37f67ba60a 100644 --- a/samples/BookStore-Modular/application/src/Acme.BookStore.Domain/Users/AppUser.cs +++ b/samples/BookStore-Modular/application/src/Acme.BookStore.Domain/Users/AppUser.cs @@ -41,9 +41,19 @@ namespace Acme.BookStore.Users #endregion /* Add your own properties here. Example: - * - * public virtual string MyProperty { get; set; } - */ + * + * public string MyProperty { get; set; } + * + * If you add a property and using the EF Core, remember these; + * + * 1. update BookStoreDbContext.OnModelCreating + * to configure the mapping for your new property + * 2. Update BookStoreEntityExtensions to extend the IdentityUser entity + * and add your new property to the migration. + * 3. Use the Add-Migration to add a new database migration. + * 4. Run the .DbMigrator project (or use the Update-Database command) to apply + * schema change to the database. + */ private AppUser() { diff --git a/samples/BookStore-Modular/application/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContext.cs b/samples/BookStore-Modular/application/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContext.cs index 6a74deef7e..7d7b1cb243 100644 --- a/samples/BookStore-Modular/application/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContext.cs +++ b/samples/BookStore-Modular/application/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContext.cs @@ -42,13 +42,6 @@ namespace Acme.BookStore.EntityFrameworkCore builder.ConfigureTenantManagement(); builder.ConfigureBookManagement(); - /* Configure customizations for entities from the modules included */ - - builder.Entity(b => - { - b.ConfigureCustomUserProperties(); - }); - /* Configure your own tables/entities inside the ConfigureBookStore method */ builder.ConfigureBookStore(); diff --git a/samples/BookStore-Modular/application/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContextFactory.cs b/samples/BookStore-Modular/application/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContextFactory.cs index 7212eb7340..4f285e597e 100644 --- a/samples/BookStore-Modular/application/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContextFactory.cs +++ b/samples/BookStore-Modular/application/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContextFactory.cs @@ -11,6 +11,8 @@ namespace Acme.BookStore.EntityFrameworkCore { public BookStoreMigrationsDbContext CreateDbContext(string[] args) { + BookStoreEntityExtensions.Configure(); + var configuration = BuildConfiguration(); var builder = new DbContextOptionsBuilder() diff --git a/samples/BookStore-Modular/application/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreDbContext.cs b/samples/BookStore-Modular/application/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreDbContext.cs index 85644bf40a..7ddeab7a5f 100644 --- a/samples/BookStore-Modular/application/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreDbContext.cs +++ b/samples/BookStore-Modular/application/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreDbContext.cs @@ -3,6 +3,7 @@ using Acme.BookStore.Users; using Volo.Abp.Data; using Volo.Abp.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore.Modeling; +using Volo.Abp.Identity; using Volo.Abp.Users.EntityFrameworkCore; namespace Acme.BookStore.EntityFrameworkCore @@ -39,12 +40,13 @@ namespace Acme.BookStore.EntityFrameworkCore builder.Entity(b => { - b.ToTable("AbpUsers"); //Sharing the same table "AbpUsers" with the IdentityUser + b.ToTable(AbpIdentityDbProperties.DbTablePrefix + "Users"); //Sharing the same table "AbpUsers" with the IdentityUser b.ConfigureByConvention(); b.ConfigureAbpUser(); - //Moved customization to a method so we can share it with the BookStoreMigrationsDbContext class - b.ConfigureCustomUserProperties(); + /* Configure mappings for your additional properties + * Also see the BookStoreEntityExtensions class + */ }); /* Configure your own tables/entities inside the ConfigureBookStore method */ diff --git a/samples/BookStore-Modular/application/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreDbContextModelCreatingExtensions.cs b/samples/BookStore-Modular/application/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreDbContextModelCreatingExtensions.cs index 1510809d5f..c132d297a4 100644 --- a/samples/BookStore-Modular/application/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreDbContextModelCreatingExtensions.cs +++ b/samples/BookStore-Modular/application/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreDbContextModelCreatingExtensions.cs @@ -1,7 +1,5 @@ using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; using Volo.Abp; -using Volo.Abp.Users; namespace Acme.BookStore.EntityFrameworkCore { @@ -20,11 +18,5 @@ namespace Acme.BookStore.EntityFrameworkCore // //... //}); } - - public static void ConfigureCustomUserProperties(this EntityTypeBuilder b) - where TUser: class, IUser - { - //b.Property(nameof(AppUser.MyProperty))... - } } } \ No newline at end of file diff --git a/samples/BookStore-Modular/application/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreEntityExtensions.cs b/samples/BookStore-Modular/application/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreEntityExtensions.cs new file mode 100644 index 0000000000..771390698f --- /dev/null +++ b/samples/BookStore-Modular/application/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreEntityExtensions.cs @@ -0,0 +1,33 @@ +using Volo.Abp.EntityFrameworkCore.Extensions; +using Volo.Abp.Identity; +using Volo.Abp.Threading; + +namespace Acme.BookStore.EntityFrameworkCore +{ + public static class BookStoreEntityExtensions + { + private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); + + public static void Configure() + { + OneTimeRunner.Run(() => + { + /* You can configure entity extension properties for the + * entities defined in the used modules. + * + * Example: + * + * EntityExtensionManager.AddProperty( + * "MyProperty", + * b => + * { + * b.HasMaxLength(128); + * }); + * + * See the documentation for more: + * https://docs.abp.io/en/abp/latest/Customizing-Application-Modules-Extending-Entities + */ + }); + } + } +} \ No newline at end of file diff --git a/samples/BookStore-Modular/application/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreEntityFrameworkCoreModule.cs b/samples/BookStore-Modular/application/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreEntityFrameworkCoreModule.cs index 5cb2a6dc7e..c8142b8088 100644 --- a/samples/BookStore-Modular/application/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreEntityFrameworkCoreModule.cs +++ b/samples/BookStore-Modular/application/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreEntityFrameworkCoreModule.cs @@ -29,6 +29,11 @@ namespace Acme.BookStore.EntityFrameworkCore )] public class BookStoreEntityFrameworkCoreModule : AbpModule { + public override void PreConfigureServices(ServiceConfigurationContext context) + { + BookStoreEntityExtensions.Configure(); + } + public override void ConfigureServices(ServiceConfigurationContext context) { context.Services.AddAbpDbContext(options => diff --git a/samples/BookStore-Modular/modules/book-management/src/Acme.BookStore.BookManagement.EntityFrameworkCore/EntityFrameworkCore/BookManagementEntityExtensions.cs b/samples/BookStore-Modular/modules/book-management/src/Acme.BookStore.BookManagement.EntityFrameworkCore/EntityFrameworkCore/BookManagementEntityExtensions.cs new file mode 100644 index 0000000000..b7a3871453 --- /dev/null +++ b/samples/BookStore-Modular/modules/book-management/src/Acme.BookStore.BookManagement.EntityFrameworkCore/EntityFrameworkCore/BookManagementEntityExtensions.cs @@ -0,0 +1,32 @@ +using Volo.Abp.EntityFrameworkCore.Extensions; +using Volo.Abp.Threading; + +namespace Acme.BookStore.BookManagement.EntityFrameworkCore +{ + public static class BookManagementEntityExtensions + { + private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); + + public static void Configure() + { + OneTimeRunner.Run(() => + { + /* You can configure entity extension properties for the + * entities defined in the used modules. + * + * Example: + * + * EntityExtensionManager.AddProperty( + * "MyProperty", + * b => + * { + * b.HasMaxLength(128); + * }); + * + * See the documentation for more: + * https://docs.abp.io/en/abp/latest/Customizing-Application-Modules-Extending-Entities + */ + }); + } + } +} \ No newline at end of file diff --git a/samples/BookStore-Modular/modules/book-management/src/Acme.BookStore.BookManagement.EntityFrameworkCore/EntityFrameworkCore/BookManagementEntityFrameworkCoreModule.cs b/samples/BookStore-Modular/modules/book-management/src/Acme.BookStore.BookManagement.EntityFrameworkCore/EntityFrameworkCore/BookManagementEntityFrameworkCoreModule.cs index c2b2867938..3734551e73 100644 --- a/samples/BookStore-Modular/modules/book-management/src/Acme.BookStore.BookManagement.EntityFrameworkCore/EntityFrameworkCore/BookManagementEntityFrameworkCoreModule.cs +++ b/samples/BookStore-Modular/modules/book-management/src/Acme.BookStore.BookManagement.EntityFrameworkCore/EntityFrameworkCore/BookManagementEntityFrameworkCoreModule.cs @@ -10,6 +10,11 @@ namespace Acme.BookStore.BookManagement.EntityFrameworkCore )] public class BookManagementEntityFrameworkCoreModule : AbpModule { + public override void PreConfigureServices(ServiceConfigurationContext context) + { + BookManagementEntityExtensions.Configure(); + } + public override void ConfigureServices(ServiceConfigurationContext context) { context.Services.AddAbpDbContext(options => diff --git a/samples/BookStore/src/Acme.BookStore.Domain/Users/AppUser.cs b/samples/BookStore/src/Acme.BookStore.Domain/Users/AppUser.cs index 9068cfbcd5..37f67ba60a 100644 --- a/samples/BookStore/src/Acme.BookStore.Domain/Users/AppUser.cs +++ b/samples/BookStore/src/Acme.BookStore.Domain/Users/AppUser.cs @@ -41,9 +41,19 @@ namespace Acme.BookStore.Users #endregion /* Add your own properties here. Example: - * - * public virtual string MyProperty { get; set; } - */ + * + * public string MyProperty { get; set; } + * + * If you add a property and using the EF Core, remember these; + * + * 1. update BookStoreDbContext.OnModelCreating + * to configure the mapping for your new property + * 2. Update BookStoreEntityExtensions to extend the IdentityUser entity + * and add your new property to the migration. + * 3. Use the Add-Migration to add a new database migration. + * 4. Run the .DbMigrator project (or use the Update-Database command) to apply + * schema change to the database. + */ private AppUser() { diff --git a/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContext.cs b/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContext.cs index 541a91a0fd..5287d6f535 100644 --- a/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContext.cs +++ b/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContext.cs @@ -40,13 +40,6 @@ namespace Acme.BookStore.EntityFrameworkCore builder.ConfigureFeatureManagement(); builder.ConfigureTenantManagement(); - /* Configure customizations for entities from the modules included */ - - builder.Entity(b => - { - b.ConfigureCustomUserProperties(); - }); - /* Configure your own tables/entities inside the ConfigureBookStore method */ builder.ConfigureBookStore(); diff --git a/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContextFactory.cs b/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContextFactory.cs index da72e6fb21..cf8a18e468 100644 --- a/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContextFactory.cs +++ b/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContextFactory.cs @@ -11,6 +11,8 @@ namespace Acme.BookStore.EntityFrameworkCore { public BookStoreMigrationsDbContext CreateDbContext(string[] args) { + BookStoreEntityExtensions.Configure(); + var configuration = BuildConfiguration(); var builder = new DbContextOptionsBuilder() diff --git a/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreDbContext.cs b/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreDbContext.cs index 386eb2623b..5849e12137 100644 --- a/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreDbContext.cs +++ b/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreDbContext.cs @@ -3,6 +3,7 @@ using Acme.BookStore.Users; using Volo.Abp.Data; using Volo.Abp.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore.Modeling; +using Volo.Abp.Identity; using Volo.Abp.Users.EntityFrameworkCore; namespace Acme.BookStore.EntityFrameworkCore @@ -41,15 +42,16 @@ namespace Acme.BookStore.EntityFrameworkCore builder.Entity(b => { - b.ToTable("AbpUsers"); //Sharing the same table "AbpUsers" with the IdentityUser + b.ToTable(AbpIdentityDbProperties.DbTablePrefix + "Users"); //Sharing the same table "AbpUsers" with the IdentityUser b.ConfigureFullAudited(); b.ConfigureExtraProperties(); b.ConfigureConcurrencyStamp(); b.ConfigureAbpUser(); - //Moved customization to a method so we can share it with the BookStoreMigrationsDbContext class - b.ConfigureCustomUserProperties(); + /* Configure mappings for your additional properties + * Also see the BookStoreEntityExtensions class + */ }); /* Configure your own tables/entities inside the ConfigureBookStore method */ diff --git a/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreDbContextModelCreatingExtensions.cs b/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreDbContextModelCreatingExtensions.cs index 922793e029..f11ec0d00a 100644 --- a/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreDbContextModelCreatingExtensions.cs +++ b/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreDbContextModelCreatingExtensions.cs @@ -1,8 +1,6 @@ using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; using Volo.Abp; using Volo.Abp.EntityFrameworkCore.Modeling; -using Volo.Abp.Users; namespace Acme.BookStore.EntityFrameworkCore { @@ -21,11 +19,5 @@ namespace Acme.BookStore.EntityFrameworkCore b.Property(x => x.Name).IsRequired().HasMaxLength(128); }); } - - public static void ConfigureCustomUserProperties(this EntityTypeBuilder b) - where TUser: class, IUser - { - //b.Property(nameof(AppUser.MyProperty))... - } } } \ No newline at end of file diff --git a/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreEntityExtensions.cs b/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreEntityExtensions.cs new file mode 100644 index 0000000000..771390698f --- /dev/null +++ b/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreEntityExtensions.cs @@ -0,0 +1,33 @@ +using Volo.Abp.EntityFrameworkCore.Extensions; +using Volo.Abp.Identity; +using Volo.Abp.Threading; + +namespace Acme.BookStore.EntityFrameworkCore +{ + public static class BookStoreEntityExtensions + { + private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); + + public static void Configure() + { + OneTimeRunner.Run(() => + { + /* You can configure entity extension properties for the + * entities defined in the used modules. + * + * Example: + * + * EntityExtensionManager.AddProperty( + * "MyProperty", + * b => + * { + * b.HasMaxLength(128); + * }); + * + * See the documentation for more: + * https://docs.abp.io/en/abp/latest/Customizing-Application-Modules-Extending-Entities + */ + }); + } + } +} \ No newline at end of file diff --git a/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreEntityFrameworkCoreModule.cs b/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreEntityFrameworkCoreModule.cs index 156a4207cb..be5f6039b4 100644 --- a/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreEntityFrameworkCoreModule.cs +++ b/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreEntityFrameworkCoreModule.cs @@ -27,6 +27,11 @@ namespace Acme.BookStore.EntityFrameworkCore )] public class BookStoreEntityFrameworkCoreModule : AbpModule { + public override void PreConfigureServices(ServiceConfigurationContext context) + { + BookStoreEntityExtensions.Configure(); + } + public override void ConfigureServices(ServiceConfigurationContext context) { context.Services.AddAbpDbContext(options => diff --git a/samples/DashboardDemo/src/DashboardDemo.Domain/Users/AppUser.cs b/samples/DashboardDemo/src/DashboardDemo.Domain/Users/AppUser.cs index 2f2ba91689..cfad912abe 100644 --- a/samples/DashboardDemo/src/DashboardDemo.Domain/Users/AppUser.cs +++ b/samples/DashboardDemo/src/DashboardDemo.Domain/Users/AppUser.cs @@ -41,9 +41,19 @@ namespace DashboardDemo.Users #endregion /* Add your own properties here. Example: - * - * public virtual string MyProperty { get; set; } - */ + * + * public string MyProperty { get; set; } + * + * If you add a property and using the EF Core, remember these; + * + * 1. update BookStoreDbContext.OnModelCreating + * to configure the mapping for your new property + * 2. Update BookStoreEntityExtensions to extend the IdentityUser entity + * and add your new property to the migration. + * 3. Use the Add-Migration to add a new database migration. + * 4. Run the .DbMigrator project (or use the Update-Database command) to apply + * schema change to the database. + */ private AppUser() { diff --git a/samples/DashboardDemo/src/DashboardDemo.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/DashboardDemoMigrationsDbContext.cs b/samples/DashboardDemo/src/DashboardDemo.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/DashboardDemoMigrationsDbContext.cs index c94d27faf0..ccec84b7e1 100644 --- a/samples/DashboardDemo/src/DashboardDemo.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/DashboardDemoMigrationsDbContext.cs +++ b/samples/DashboardDemo/src/DashboardDemo.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/DashboardDemoMigrationsDbContext.cs @@ -40,13 +40,6 @@ namespace DashboardDemo.EntityFrameworkCore builder.ConfigureFeatureManagement(); builder.ConfigureTenantManagement(); - /* Configure customizations for entities from the modules included */ - - builder.Entity(b => - { - b.ConfigureCustomUserProperties(); - }); - /* Configure your own tables/entities inside the ConfigureDashboardDemo method */ builder.ConfigureDashboardDemo(); diff --git a/samples/DashboardDemo/src/DashboardDemo.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/DashboardDemoMigrationsDbContextFactory.cs b/samples/DashboardDemo/src/DashboardDemo.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/DashboardDemoMigrationsDbContextFactory.cs index 0773892abc..10ce7b7da1 100644 --- a/samples/DashboardDemo/src/DashboardDemo.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/DashboardDemoMigrationsDbContextFactory.cs +++ b/samples/DashboardDemo/src/DashboardDemo.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/DashboardDemoMigrationsDbContextFactory.cs @@ -11,6 +11,8 @@ namespace DashboardDemo.EntityFrameworkCore { public DashboardDemoMigrationsDbContext CreateDbContext(string[] args) { + DashboardDemoEntityExtensions.Configure(); + var configuration = BuildConfiguration(); var builder = new DbContextOptionsBuilder() diff --git a/samples/DashboardDemo/src/DashboardDemo.EntityFrameworkCore/EntityFrameworkCore/DashboardDemoDbContext.cs b/samples/DashboardDemo/src/DashboardDemo.EntityFrameworkCore/EntityFrameworkCore/DashboardDemoDbContext.cs index 94ec22abb3..33c1ddb82d 100644 --- a/samples/DashboardDemo/src/DashboardDemo.EntityFrameworkCore/EntityFrameworkCore/DashboardDemoDbContext.cs +++ b/samples/DashboardDemo/src/DashboardDemo.EntityFrameworkCore/EntityFrameworkCore/DashboardDemoDbContext.cs @@ -3,6 +3,7 @@ using DashboardDemo.Users; using Volo.Abp.Data; using Volo.Abp.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore.Modeling; +using Volo.Abp.Identity; using Volo.Abp.Users.EntityFrameworkCore; namespace DashboardDemo.EntityFrameworkCore @@ -39,15 +40,16 @@ namespace DashboardDemo.EntityFrameworkCore builder.Entity(b => { - b.ToTable("AbpUsers"); //Sharing the same table "AbpUsers" with the IdentityUser + b.ToTable(AbpIdentityDbProperties.DbTablePrefix + "Users"); //Sharing the same table "AbpUsers" with the IdentityUser b.ConfigureFullAudited(); b.ConfigureExtraProperties(); b.ConfigureConcurrencyStamp(); b.ConfigureAbpUser(); - //Moved customization to a method so we can share it with the DashboardDemoMigrationsDbContext class - b.ConfigureCustomUserProperties(); + /* Configure mappings for your additional properties + * Also see the DashboardDemoEntityExtensions class + */ }); /* Configure your own tables/entities inside the ConfigureDashboardDemo method */ diff --git a/samples/DashboardDemo/src/DashboardDemo.EntityFrameworkCore/EntityFrameworkCore/DashboardDemoDbContextModelCreatingExtensions.cs b/samples/DashboardDemo/src/DashboardDemo.EntityFrameworkCore/EntityFrameworkCore/DashboardDemoDbContextModelCreatingExtensions.cs index 60dae7c4cf..0a5d05f6bc 100644 --- a/samples/DashboardDemo/src/DashboardDemo.EntityFrameworkCore/EntityFrameworkCore/DashboardDemoDbContextModelCreatingExtensions.cs +++ b/samples/DashboardDemo/src/DashboardDemo.EntityFrameworkCore/EntityFrameworkCore/DashboardDemoDbContextModelCreatingExtensions.cs @@ -1,7 +1,5 @@ using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; using Volo.Abp; -using Volo.Abp.Users; namespace DashboardDemo.EntityFrameworkCore { @@ -20,11 +18,5 @@ namespace DashboardDemo.EntityFrameworkCore // //... //}); } - - public static void ConfigureCustomUserProperties(this EntityTypeBuilder b) - where TUser: class, IUser - { - //b.Property(nameof(AppUser.MyProperty))... - } } } \ No newline at end of file diff --git a/samples/DashboardDemo/src/DashboardDemo.EntityFrameworkCore/EntityFrameworkCore/DashboardDemoEntityExtensions.cs b/samples/DashboardDemo/src/DashboardDemo.EntityFrameworkCore/EntityFrameworkCore/DashboardDemoEntityExtensions.cs new file mode 100644 index 0000000000..b41ccb8ac8 --- /dev/null +++ b/samples/DashboardDemo/src/DashboardDemo.EntityFrameworkCore/EntityFrameworkCore/DashboardDemoEntityExtensions.cs @@ -0,0 +1,33 @@ +using Volo.Abp.EntityFrameworkCore.Extensions; +using Volo.Abp.Identity; +using Volo.Abp.Threading; + +namespace DashboardDemo.EntityFrameworkCore +{ + public static class DashboardDemoEntityExtensions + { + private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); + + public static void Configure() + { + OneTimeRunner.Run(() => + { + /* You can configure entity extension properties for the + * entities defined in the used modules. + * + * Example: + * + * EntityExtensionManager.AddProperty( + * "MyProperty", + * b => + * { + * b.HasMaxLength(128); + * }); + * + * See the documentation for more: + * https://docs.abp.io/en/abp/latest/Customizing-Application-Modules-Extending-Entities + */ + }); + } + } +} \ No newline at end of file diff --git a/samples/DashboardDemo/src/DashboardDemo.EntityFrameworkCore/EntityFrameworkCore/DashboardDemoEntityFrameworkCoreModule.cs b/samples/DashboardDemo/src/DashboardDemo.EntityFrameworkCore/EntityFrameworkCore/DashboardDemoEntityFrameworkCoreModule.cs index de03726a20..b183c49446 100644 --- a/samples/DashboardDemo/src/DashboardDemo.EntityFrameworkCore/EntityFrameworkCore/DashboardDemoEntityFrameworkCoreModule.cs +++ b/samples/DashboardDemo/src/DashboardDemo.EntityFrameworkCore/EntityFrameworkCore/DashboardDemoEntityFrameworkCoreModule.cs @@ -27,6 +27,11 @@ namespace DashboardDemo.EntityFrameworkCore )] public class DashboardDemoEntityFrameworkCoreModule : AbpModule { + public override void PreConfigureServices(ServiceConfigurationContext context) + { + DashboardDemoEntityExtensions.Configure(); + } + public override void ConfigureServices(ServiceConfigurationContext context) { context.Services.AddAbpDbContext(options => diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain/Users/AppUser.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain/Users/AppUser.cs index 9068cfbcd5..37f67ba60a 100644 --- a/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain/Users/AppUser.cs +++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain/Users/AppUser.cs @@ -41,9 +41,19 @@ namespace Acme.BookStore.Users #endregion /* Add your own properties here. Example: - * - * public virtual string MyProperty { get; set; } - */ + * + * public string MyProperty { get; set; } + * + * If you add a property and using the EF Core, remember these; + * + * 1. update BookStoreDbContext.OnModelCreating + * to configure the mapping for your new property + * 2. Update BookStoreEntityExtensions to extend the IdentityUser entity + * and add your new property to the migration. + * 3. Use the Add-Migration to add a new database migration. + * 4. Run the .DbMigrator project (or use the Update-Database command) to apply + * schema change to the database. + */ private AppUser() { diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContext.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContext.cs index 7a83a323d8..8064243388 100644 --- a/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContext.cs +++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContext.cs @@ -34,19 +34,6 @@ namespace Acme.BookStore.EntityFrameworkCore builder.ConfigureFeatureManagement(); builder.ConfigureTenantManagement(); - /* Configure customizations for entities from the modules included */ - - //CONFIGURE THE CUSTOM ROLE PROPERTIES - builder.Entity(b => - { - b.ConfigureCustomRoleProperties(); - }); - - builder.Entity(b => - { - b.ConfigureCustomUserProperties(); - }); - /* Configure your own tables/entities inside the ConfigureBookStore method */ builder.ConfigureBookStore(); diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContextFactory.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContextFactory.cs index da72e6fb21..cf8a18e468 100644 --- a/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContextFactory.cs +++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContextFactory.cs @@ -11,6 +11,8 @@ namespace Acme.BookStore.EntityFrameworkCore { public BookStoreMigrationsDbContext CreateDbContext(string[] args) { + BookStoreEntityExtensions.Configure(); + var configuration = BuildConfiguration(); var builder = new DbContextOptionsBuilder() diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreDbContext.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreDbContext.cs index 091e5820fc..d3726865cd 100644 --- a/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreDbContext.cs +++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreDbContext.cs @@ -4,6 +4,7 @@ using Acme.BookStore.Users; using Volo.Abp.Data; using Volo.Abp.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore.Modeling; +using Volo.Abp.Identity; using Volo.Abp.Users.EntityFrameworkCore; namespace Acme.BookStore.EntityFrameworkCore @@ -51,12 +52,13 @@ namespace Acme.BookStore.EntityFrameworkCore builder.Entity(b => { - b.ToTable("AbpUsers"); //Sharing the same table "AbpUsers" with the IdentityUser + b.ToTable(AbpIdentityDbProperties.DbTablePrefix + "Users"); //Sharing the same table "AbpUsers" with the IdentityUser b.ConfigureByConvention(); b.ConfigureAbpUser(); - //Moved customization to a method so we can share it with the BookStoreMigrationsDbContext class - b.ConfigureCustomUserProperties(); + /* Configure mappings for your additional properties + * Also see the BookStoreEntityExtensions class + */ }); /* Configure your own tables/entities inside the ConfigureBookStore method */ diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreDbContextModelCreatingExtensions.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreDbContextModelCreatingExtensions.cs index 345bde14a0..c132d297a4 100644 --- a/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreDbContextModelCreatingExtensions.cs +++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreDbContextModelCreatingExtensions.cs @@ -1,10 +1,5 @@ -using System; -using Acme.BookStore.Roles; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; +using Microsoft.EntityFrameworkCore; using Volo.Abp; -using Volo.Abp.Domain.Entities; -using Volo.Abp.Users; namespace Acme.BookStore.EntityFrameworkCore { @@ -23,17 +18,5 @@ namespace Acme.BookStore.EntityFrameworkCore // //... //}); } - - public static void ConfigureCustomUserProperties(this EntityTypeBuilder b) - where TUser: class, IUser - { - //b.Property(nameof(AppUser.MyProperty))... - } - - public static void ConfigureCustomRoleProperties(this EntityTypeBuilder b) - where TRole : class, IEntity - { - b.Property(nameof(AppRole.Title)).HasMaxLength(128); - } } } \ No newline at end of file diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreEntityExtensions.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreEntityExtensions.cs new file mode 100644 index 0000000000..9d59942de8 --- /dev/null +++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreEntityExtensions.cs @@ -0,0 +1,40 @@ +using Volo.Abp.EntityFrameworkCore.Extensions; +using Volo.Abp.Identity; +using Volo.Abp.Threading; + +namespace Acme.BookStore.EntityFrameworkCore +{ + public static class BookStoreEntityExtensions + { + private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); + + public static void Configure() + { + OneTimeRunner.Run(() => + { + /* You can configure entity extension properties for the + * entities defined in the used modules. + * + * Example: + * + * EntityExtensionManager.AddProperty( + * "MyProperty", + * b => + * { + * b.HasMaxLength(128); + * }); + * + * See the documentation for more: + * https://docs.abp.io/en/abp/latest/Customizing-Application-Modules-Extending-Entities + */ + + EntityExtensionManager.AddProperty( + nameof(AppRole.Title), + b => + { + b.HasMaxLength(128); + }); + }); + } + } +} \ No newline at end of file diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreEntityFrameworkCoreModule.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreEntityFrameworkCoreModule.cs index 156a4207cb..be5f6039b4 100644 --- a/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreEntityFrameworkCoreModule.cs +++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreEntityFrameworkCoreModule.cs @@ -27,6 +27,11 @@ namespace Acme.BookStore.EntityFrameworkCore )] public class BookStoreEntityFrameworkCoreModule : AbpModule { + public override void PreConfigureServices(ServiceConfigurationContext context) + { + BookStoreEntityExtensions.Configure(); + } + public override void ConfigureServices(ServiceConfigurationContext context) { context.Services.AddAbpDbContext(options => From 3d85fd01417a5e141c06847b90124e82f78868fc Mon Sep 17 00:00:00 2001 From: maliming Date: Thu, 26 Mar 2020 15:48:30 +0800 Subject: [PATCH 004/151] Undo changes to EfCoreMigrationDemo. --- build/common.ps1 | 1 + .../Acme.BookStore.Domain/Users/AppUser.cs | 16 ++------ .../BookStoreMigrationsDbContext.cs | 13 ++++++ .../BookStoreMigrationsDbContextFactory.cs | 3 +- .../EntityFrameworkCore/BookStoreDbContext.cs | 8 ++-- ...okStoreDbContextModelCreatingExtensions.cs | 19 ++++++++- .../BookStoreEntityExtensions.cs | 40 ------------------- .../BookStoreEntityFrameworkCoreModule.cs | 5 --- ...BookStore.EntityFrameworkCore.Tests.csproj | 1 + .../BookStoreEntityFrameworkCoreTestModule.cs | 12 +++++- .../BookStoreWebTestModule.cs | 8 ++++ 11 files changed, 59 insertions(+), 67 deletions(-) delete mode 100644 samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreEntityExtensions.cs diff --git a/build/common.ps1 b/build/common.ps1 index e4ba6a8adc..06fa20b35e 100644 --- a/build/common.ps1 +++ b/build/common.ps1 @@ -28,6 +28,7 @@ $solutionPaths = ( "../samples/BookStore-Modular/modules/book-management", "../samples/BookStore-Modular/application", "../samples/DashboardDemo", + "../samples/EfCoreMigrationDemo", "../samples/MicroserviceDemo", "../samples/RabbitMqEventBus", "../abp_io/AbpIoLocalization" diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain/Users/AppUser.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain/Users/AppUser.cs index 37f67ba60a..9068cfbcd5 100644 --- a/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain/Users/AppUser.cs +++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain/Users/AppUser.cs @@ -41,19 +41,9 @@ namespace Acme.BookStore.Users #endregion /* Add your own properties here. Example: - * - * public string MyProperty { get; set; } - * - * If you add a property and using the EF Core, remember these; - * - * 1. update BookStoreDbContext.OnModelCreating - * to configure the mapping for your new property - * 2. Update BookStoreEntityExtensions to extend the IdentityUser entity - * and add your new property to the migration. - * 3. Use the Add-Migration to add a new database migration. - * 4. Run the .DbMigrator project (or use the Update-Database command) to apply - * schema change to the database. - */ + * + * public virtual string MyProperty { get; set; } + */ private AppUser() { diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContext.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContext.cs index 8064243388..7a83a323d8 100644 --- a/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContext.cs +++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContext.cs @@ -34,6 +34,19 @@ namespace Acme.BookStore.EntityFrameworkCore builder.ConfigureFeatureManagement(); builder.ConfigureTenantManagement(); + /* Configure customizations for entities from the modules included */ + + //CONFIGURE THE CUSTOM ROLE PROPERTIES + builder.Entity(b => + { + b.ConfigureCustomRoleProperties(); + }); + + builder.Entity(b => + { + b.ConfigureCustomUserProperties(); + }); + /* Configure your own tables/entities inside the ConfigureBookStore method */ builder.ConfigureBookStore(); diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContextFactory.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContextFactory.cs index cf8a18e468..7364cd29ab 100644 --- a/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContextFactory.cs +++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContextFactory.cs @@ -11,8 +11,7 @@ namespace Acme.BookStore.EntityFrameworkCore { public BookStoreMigrationsDbContext CreateDbContext(string[] args) { - BookStoreEntityExtensions.Configure(); - + var configuration = BuildConfiguration(); var builder = new DbContextOptionsBuilder() diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreDbContext.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreDbContext.cs index d3726865cd..091e5820fc 100644 --- a/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreDbContext.cs +++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreDbContext.cs @@ -4,7 +4,6 @@ using Acme.BookStore.Users; using Volo.Abp.Data; using Volo.Abp.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore.Modeling; -using Volo.Abp.Identity; using Volo.Abp.Users.EntityFrameworkCore; namespace Acme.BookStore.EntityFrameworkCore @@ -52,13 +51,12 @@ namespace Acme.BookStore.EntityFrameworkCore builder.Entity(b => { - b.ToTable(AbpIdentityDbProperties.DbTablePrefix + "Users"); //Sharing the same table "AbpUsers" with the IdentityUser + b.ToTable("AbpUsers"); //Sharing the same table "AbpUsers" with the IdentityUser b.ConfigureByConvention(); b.ConfigureAbpUser(); - /* Configure mappings for your additional properties - * Also see the BookStoreEntityExtensions class - */ + //Moved customization to a method so we can share it with the BookStoreMigrationsDbContext class + b.ConfigureCustomUserProperties(); }); /* Configure your own tables/entities inside the ConfigureBookStore method */ diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreDbContextModelCreatingExtensions.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreDbContextModelCreatingExtensions.cs index c132d297a4..345bde14a0 100644 --- a/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreDbContextModelCreatingExtensions.cs +++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreDbContextModelCreatingExtensions.cs @@ -1,5 +1,10 @@ -using Microsoft.EntityFrameworkCore; +using System; +using Acme.BookStore.Roles; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; using Volo.Abp; +using Volo.Abp.Domain.Entities; +using Volo.Abp.Users; namespace Acme.BookStore.EntityFrameworkCore { @@ -18,5 +23,17 @@ namespace Acme.BookStore.EntityFrameworkCore // //... //}); } + + public static void ConfigureCustomUserProperties(this EntityTypeBuilder b) + where TUser: class, IUser + { + //b.Property(nameof(AppUser.MyProperty))... + } + + public static void ConfigureCustomRoleProperties(this EntityTypeBuilder b) + where TRole : class, IEntity + { + b.Property(nameof(AppRole.Title)).HasMaxLength(128); + } } } \ No newline at end of file diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreEntityExtensions.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreEntityExtensions.cs deleted file mode 100644 index 9d59942de8..0000000000 --- a/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreEntityExtensions.cs +++ /dev/null @@ -1,40 +0,0 @@ -using Volo.Abp.EntityFrameworkCore.Extensions; -using Volo.Abp.Identity; -using Volo.Abp.Threading; - -namespace Acme.BookStore.EntityFrameworkCore -{ - public static class BookStoreEntityExtensions - { - private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); - - public static void Configure() - { - OneTimeRunner.Run(() => - { - /* You can configure entity extension properties for the - * entities defined in the used modules. - * - * Example: - * - * EntityExtensionManager.AddProperty( - * "MyProperty", - * b => - * { - * b.HasMaxLength(128); - * }); - * - * See the documentation for more: - * https://docs.abp.io/en/abp/latest/Customizing-Application-Modules-Extending-Entities - */ - - EntityExtensionManager.AddProperty( - nameof(AppRole.Title), - b => - { - b.HasMaxLength(128); - }); - }); - } - } -} \ No newline at end of file diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreEntityFrameworkCoreModule.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreEntityFrameworkCoreModule.cs index be5f6039b4..156a4207cb 100644 --- a/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreEntityFrameworkCoreModule.cs +++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreEntityFrameworkCoreModule.cs @@ -27,11 +27,6 @@ namespace Acme.BookStore.EntityFrameworkCore )] public class BookStoreEntityFrameworkCoreModule : AbpModule { - public override void PreConfigureServices(ServiceConfigurationContext context) - { - BookStoreEntityExtensions.Configure(); - } - public override void ConfigureServices(ServiceConfigurationContext context) { context.Services.AddAbpDbContext(options => diff --git a/samples/EfCoreMigrationDemo/test/Acme.BookStore.EntityFrameworkCore.Tests/Acme.BookStore.EntityFrameworkCore.Tests.csproj b/samples/EfCoreMigrationDemo/test/Acme.BookStore.EntityFrameworkCore.Tests/Acme.BookStore.EntityFrameworkCore.Tests.csproj index dd2137ad06..b03b0ed22d 100644 --- a/samples/EfCoreMigrationDemo/test/Acme.BookStore.EntityFrameworkCore.Tests/Acme.BookStore.EntityFrameworkCore.Tests.csproj +++ b/samples/EfCoreMigrationDemo/test/Acme.BookStore.EntityFrameworkCore.Tests/Acme.BookStore.EntityFrameworkCore.Tests.csproj @@ -9,6 +9,7 @@ + diff --git a/samples/EfCoreMigrationDemo/test/Acme.BookStore.EntityFrameworkCore.Tests/EntityFrameworkCore/BookStoreEntityFrameworkCoreTestModule.cs b/samples/EfCoreMigrationDemo/test/Acme.BookStore.EntityFrameworkCore.Tests/EntityFrameworkCore/BookStoreEntityFrameworkCoreTestModule.cs index e1171d6d90..a3f2bb5aa7 100644 --- a/samples/EfCoreMigrationDemo/test/Acme.BookStore.EntityFrameworkCore.Tests/EntityFrameworkCore/BookStoreEntityFrameworkCoreTestModule.cs +++ b/samples/EfCoreMigrationDemo/test/Acme.BookStore.EntityFrameworkCore.Tests/EntityFrameworkCore/BookStoreEntityFrameworkCoreTestModule.cs @@ -1,4 +1,5 @@ -using Microsoft.Data.Sqlite; +using Acme.BookStore.DbMigrationsForSecondDb.EntityFrameworkCore; +using Microsoft.Data.Sqlite; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage; @@ -51,6 +52,15 @@ namespace Acme.BookStore.EntityFrameworkCore context.GetService().CreateTables(); } + var secondOptions = new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options; + + using (var context = new BookStoreSecondMigrationsDbContext(secondOptions)) + { + context.GetService().CreateTables(); + } + return connection; } } diff --git a/samples/EfCoreMigrationDemo/test/Acme.BookStore.Web.Tests/BookStoreWebTestModule.cs b/samples/EfCoreMigrationDemo/test/Acme.BookStore.Web.Tests/BookStoreWebTestModule.cs index 46e4312035..786015d18b 100644 --- a/samples/EfCoreMigrationDemo/test/Acme.BookStore.Web.Tests/BookStoreWebTestModule.cs +++ b/samples/EfCoreMigrationDemo/test/Acme.BookStore.Web.Tests/BookStoreWebTestModule.cs @@ -12,6 +12,7 @@ using Acme.BookStore.Web; using Acme.BookStore.Web.Menus; using Volo.Abp; using Volo.Abp.AspNetCore.TestBase; +using Volo.Abp.Data; using Volo.Abp.Localization; using Volo.Abp.Modularity; using Volo.Abp.UI.Navigation; @@ -38,6 +39,13 @@ namespace Acme.BookStore { ConfigureLocalizationServices(context.Services); ConfigureNavigationServices(context.Services); + + Configure(options => + { + //SqliteConnection does not support nested transactions. + //So Dbcontext and connectionString need be same. + options.ConnectionStrings.Clear(); + }); } private static void ConfigureLocalizationServices(IServiceCollection services) From 6b07a3a8375da22ceb03c889a65c415762ee5882 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Thu, 26 Mar 2020 11:52:43 +0300 Subject: [PATCH 005/151] refactor(core): add fallback api to getApiUrl selector --- npm/ng-packs/packages/core/src/lib/states/config.state.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/npm/ng-packs/packages/core/src/lib/states/config.state.ts b/npm/ng-packs/packages/core/src/lib/states/config.state.ts index 8ce206dd76..91bcc5d914 100644 --- a/npm/ng-packs/packages/core/src/lib/states/config.state.ts +++ b/npm/ng-packs/packages/core/src/lib/states/config.state.ts @@ -81,7 +81,7 @@ export class ConfigState { static getApiUrl(key?: string) { const selector = createSelector([ConfigState], (state: Config.State): string => { - return state.environment.apis[key || 'default'].url; + return (state.environment.apis[key || 'default'] || state.environment.apis.default).url; }); return selector; From 191d2baa52be49af60b5515618225cd49a9bbfc3 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Thu, 26 Mar 2020 11:53:39 +0300 Subject: [PATCH 006/151] feat: add apiName variables to some services --- .../src/lib/services/account.service.ts | 9 +++-- .../application-configuration.service.ts | 12 +++++-- .../core/src/lib/services/profile.service.ts | 18 +++++++--- .../services/feature-management.service.ts | 8 +++-- .../src/lib/services/identity.service.ts | 34 ++++++++++++------- .../services/permission-management.service.ts | 15 ++++++-- .../lib/services/tenant-management.service.ts | 28 ++++++++++----- 7 files changed, 91 insertions(+), 33 deletions(-) diff --git a/npm/ng-packs/packages/account/src/lib/services/account.service.ts b/npm/ng-packs/packages/account/src/lib/services/account.service.ts index 6c2571a518..ae9fc19d21 100644 --- a/npm/ng-packs/packages/account/src/lib/services/account.service.ts +++ b/npm/ng-packs/packages/account/src/lib/services/account.service.ts @@ -7,6 +7,8 @@ import { RegisterResponse, RegisterRequest, TenantIdResponse } from '../models'; providedIn: 'root', }) export class AccountService { + apiName = 'AbpAccount'; + constructor(private rest: RestService) {} findTenant(tenantName: string): Observable { @@ -15,7 +17,7 @@ export class AccountService { url: `/api/abp/multi-tenancy/tenants/by-name/${tenantName}`, }; - return this.rest.request(request); + return this.rest.request(request, { apiName: this.apiName }); } register(body: RegisterRequest): Observable { @@ -25,6 +27,9 @@ export class AccountService { body, }; - return this.rest.request(request, { skipHandleError: true }); + return this.rest.request(request, { + skipHandleError: true, + apiName: this.apiName, + }); } } diff --git a/npm/ng-packs/packages/core/src/lib/services/application-configuration.service.ts b/npm/ng-packs/packages/core/src/lib/services/application-configuration.service.ts index 5081f94068..39b893501c 100644 --- a/npm/ng-packs/packages/core/src/lib/services/application-configuration.service.ts +++ b/npm/ng-packs/packages/core/src/lib/services/application-configuration.service.ts @@ -3,12 +3,18 @@ import { Observable } from 'rxjs'; import { Rest } from '../models/rest'; import { ApplicationConfiguration } from '../models/application-configuration'; import { RestService } from './rest.service'; +import { Store } from '@ngxs/store'; +import { ConfigState } from '../states/config.state'; @Injectable({ providedIn: 'root', }) export class ApplicationConfigurationService { - constructor(private rest: RestService) {} + get apiName(): string { + return this.store.selectSnapshot(ConfigState.getDeep('environment.application.name')); + } + + constructor(private rest: RestService, private store: Store) {} getConfiguration(): Observable { const request: Rest.Request = { @@ -16,6 +22,8 @@ export class ApplicationConfigurationService { url: '/api/abp/application-configuration', }; - return this.rest.request(request); + return this.rest.request(request, { + apiName: this.apiName, + }); } } diff --git a/npm/ng-packs/packages/core/src/lib/services/profile.service.ts b/npm/ng-packs/packages/core/src/lib/services/profile.service.ts index 38d5fb3a7b..d80caf7e80 100644 --- a/npm/ng-packs/packages/core/src/lib/services/profile.service.ts +++ b/npm/ng-packs/packages/core/src/lib/services/profile.service.ts @@ -7,6 +7,8 @@ import { Profile, Rest } from '../models'; providedIn: 'root', }) export class ProfileService { + apiName = 'AbpIdentity'; + constructor(private rest: RestService) {} get(): Observable { @@ -15,7 +17,7 @@ export class ProfileService { url: '/api/identity/my-profile', }; - return this.rest.request(request); + return this.rest.request(request, { apiName: this.apiName }); } update(body: Profile.Response): Observable { @@ -25,16 +27,24 @@ export class ProfileService { body, }; - return this.rest.request(request); + return this.rest.request(request, { + apiName: this.apiName, + }); } - changePassword(body: Profile.ChangePasswordRequest, skipHandleError: boolean = false): Observable { + changePassword( + body: Profile.ChangePasswordRequest, + skipHandleError: boolean = false, + ): Observable { const request: Rest.Request = { method: 'POST', url: '/api/identity/my-profile/change-password', body, }; - return this.rest.request(request, { skipHandleError }); + return this.rest.request(request, { + skipHandleError, + apiName: this.apiName, + }); } } diff --git a/npm/ng-packs/packages/feature-management/src/lib/services/feature-management.service.ts b/npm/ng-packs/packages/feature-management/src/lib/services/feature-management.service.ts index 5f6c0eed6e..1020e60d4e 100644 --- a/npm/ng-packs/packages/feature-management/src/lib/services/feature-management.service.ts +++ b/npm/ng-packs/packages/feature-management/src/lib/services/feature-management.service.ts @@ -8,6 +8,8 @@ import { FeatureManagement } from '../models'; providedIn: 'root', }) export class FeatureManagementService { + apiName = 'FeatureManagement'; + constructor(private rest: RestService, private store: Store) {} getFeatures(params: FeatureManagement.Provider): Observable { @@ -16,7 +18,9 @@ export class FeatureManagementService { url: '/api/abp/features', params, }; - return this.rest.request(request); + return this.rest.request(request, { + apiName: this.apiName, + }); } updateFeatures({ @@ -30,6 +34,6 @@ export class FeatureManagementService { body: { features }, params: { providerKey, providerName }, }; - return this.rest.request(request); + return this.rest.request(request, { apiName: this.apiName }); } } diff --git a/npm/ng-packs/packages/identity/src/lib/services/identity.service.ts b/npm/ng-packs/packages/identity/src/lib/services/identity.service.ts index ae9ca3a921..51e88557fe 100644 --- a/npm/ng-packs/packages/identity/src/lib/services/identity.service.ts +++ b/npm/ng-packs/packages/identity/src/lib/services/identity.service.ts @@ -7,6 +7,8 @@ import { Identity } from '../models/identity'; providedIn: 'root', }) export class IdentityService { + apiName = 'AbpIdentity'; + constructor(private rest: RestService) {} getRoles(params = {} as ABP.PageQueryParams): Observable { @@ -16,7 +18,7 @@ export class IdentityService { params, }; - return this.rest.request(request); + return this.rest.request(request, { apiName: this.apiName }); } getAllRoles(): Observable { @@ -25,7 +27,7 @@ export class IdentityService { url: '/api/identity/roles/all', }; - return this.rest.request(request); + return this.rest.request(request, { apiName: this.apiName }); } getRoleById(id: string): Observable { @@ -34,7 +36,7 @@ export class IdentityService { url: `/api/identity/roles/${id}`, }; - return this.rest.request(request); + return this.rest.request(request, { apiName: this.apiName }); } deleteRole(id: string): Observable { @@ -43,7 +45,7 @@ export class IdentityService { url: `/api/identity/roles/${id}`, }; - return this.rest.request(request); + return this.rest.request(request, { apiName: this.apiName }); } createRole(body: Identity.RoleSaveRequest): Observable { @@ -53,7 +55,9 @@ export class IdentityService { body, }; - return this.rest.request(request); + return this.rest.request(request, { + apiName: this.apiName, + }); } updateRole(body: Identity.RoleItem): Observable { @@ -66,7 +70,9 @@ export class IdentityService { body, }; - return this.rest.request(request); + return this.rest.request(request, { + apiName: this.apiName, + }); } getUsers(params = {} as ABP.PageQueryParams): Observable { @@ -76,7 +82,7 @@ export class IdentityService { params, }; - return this.rest.request(request); + return this.rest.request(request, { apiName: this.apiName }); } getUserById(id: string): Observable { @@ -85,7 +91,7 @@ export class IdentityService { url: `/api/identity/users/${id}`, }; - return this.rest.request(request); + return this.rest.request(request, { apiName: this.apiName }); } getUserRoles(id: string): Observable { @@ -94,7 +100,7 @@ export class IdentityService { url: `/api/identity/users/${id}/roles`, }; - return this.rest.request(request); + return this.rest.request(request, { apiName: this.apiName }); } deleteUser(id: string): Observable { @@ -103,7 +109,7 @@ export class IdentityService { url: `/api/identity/users/${id}`, }; - return this.rest.request(request); + return this.rest.request(request, { apiName: this.apiName }); } createUser(body: Identity.UserSaveRequest): Observable { @@ -113,7 +119,9 @@ export class IdentityService { body, }; - return this.rest.request(request); + return this.rest.request(request, { + apiName: this.apiName, + }); } updateUser(body: Identity.UserItem): Observable { @@ -126,6 +134,8 @@ export class IdentityService { body, }; - return this.rest.request(request); + return this.rest.request(request, { + apiName: this.apiName, + }); } } diff --git a/npm/ng-packs/packages/permission-management/src/lib/services/permission-management.service.ts b/npm/ng-packs/packages/permission-management/src/lib/services/permission-management.service.ts index e7fdd98ce3..fa6433e952 100644 --- a/npm/ng-packs/packages/permission-management/src/lib/services/permission-management.service.ts +++ b/npm/ng-packs/packages/permission-management/src/lib/services/permission-management.service.ts @@ -7,16 +7,23 @@ import { PermissionManagement } from '../models/permission-management'; providedIn: 'root', }) export class PermissionManagementService { + apiName = 'AbpPermissionManagement'; + constructor(private rest: RestService) {} - getPermissions(params: PermissionManagement.GrantedProvider): Observable { + getPermissions( + params: PermissionManagement.GrantedProvider, + ): Observable { const request: Rest.Request = { method: 'GET', url: '/api/abp/permissions', params, }; - return this.rest.request(request); + return this.rest.request( + request, + { apiName: this.apiName }, + ); } updatePermissions({ @@ -31,6 +38,8 @@ export class PermissionManagementService { params: { providerKey, providerName }, }; - return this.rest.request(request); + return this.rest.request(request, { + apiName: this.apiName, + }); } } diff --git a/npm/ng-packs/packages/tenant-management/src/lib/services/tenant-management.service.ts b/npm/ng-packs/packages/tenant-management/src/lib/services/tenant-management.service.ts index 27ee26b7ed..8678da1332 100644 --- a/npm/ng-packs/packages/tenant-management/src/lib/services/tenant-management.service.ts +++ b/npm/ng-packs/packages/tenant-management/src/lib/services/tenant-management.service.ts @@ -7,6 +7,8 @@ import { TenantManagement } from '../models/tenant-management'; providedIn: 'root', }) export class TenantManagementService { + apiName = 'AbpTenantManagement'; + constructor(private rest: RestService) {} getTenant(params = {} as ABP.PageQueryParams): Observable { @@ -16,7 +18,7 @@ export class TenantManagementService { params, }; - return this.rest.request(request); + return this.rest.request(request, { apiName: this.apiName }); } getTenantById(id: string): Observable { @@ -25,7 +27,7 @@ export class TenantManagementService { url: `/api/multi-tenancy/tenants/${id}`, }; - return this.rest.request(request); + return this.rest.request(request, { apiName: this.apiName }); } deleteTenant(id: string): Observable { @@ -34,7 +36,7 @@ export class TenantManagementService { url: `/api/multi-tenancy/tenants/${id}`, }; - return this.rest.request(request); + return this.rest.request(request, { apiName: this.apiName }); } createTenant(body: TenantManagement.AddRequest): Observable { @@ -44,7 +46,9 @@ export class TenantManagementService { body, }; - return this.rest.request(request); + return this.rest.request(request, { + apiName: this.apiName, + }); } updateTenant(body: TenantManagement.UpdateRequest): Observable { @@ -57,7 +61,9 @@ export class TenantManagementService { body, }; - return this.rest.request(request); + return this.rest.request(request, { + apiName: this.apiName, + }); } getDefaultConnectionString(id: string): Observable { @@ -68,7 +74,9 @@ export class TenantManagementService { responseType: Rest.ResponseType.Text, url, }; - return this.rest.request(request); + return this.rest.request(request, { + apiName: this.apiName, + }); } updateDefaultConnectionString( @@ -81,7 +89,9 @@ export class TenantManagementService { url, params: { defaultConnectionString: payload.defaultConnectionString }, }; - return this.rest.request(request); + return this.rest.request(request, { + apiName: this.apiName, + }); } deleteDefaultConnectionString(id: string): Observable { @@ -91,6 +101,8 @@ export class TenantManagementService { method: 'DELETE', url, }; - return this.rest.request(request); + return this.rest.request(request, { + apiName: this.apiName, + }); } } From 4d93244f06b3f54c3c700b7439ce1ddadf3b4dc9 Mon Sep 17 00:00:00 2001 From: Arman Ozak Date: Thu, 26 Mar 2020 19:06:27 +0300 Subject: [PATCH 007/151] feat(core): add methods to LinkedList for adding and dropping multiple nodes --- .../core/src/lib/tests/linked-list.spec.ts | 870 ++++++++++++++++-- .../core/src/lib/utils/linked-list.ts | 257 ++++-- 2 files changed, 997 insertions(+), 130 deletions(-) diff --git a/npm/ng-packs/packages/core/src/lib/tests/linked-list.spec.ts b/npm/ng-packs/packages/core/src/lib/tests/linked-list.spec.ts index 518956deba..3ad9eeda63 100644 --- a/npm/ng-packs/packages/core/src/lib/tests/linked-list.spec.ts +++ b/npm/ng-packs/packages/core/src/lib/tests/linked-list.spec.ts @@ -1,4 +1,4 @@ -import { LinkedList } from '../utils/linked-list'; +import { LinkedList, ListNode } from '../utils/linked-list'; describe('Linked List (Doubly)', () => { let list: LinkedList; @@ -44,9 +44,11 @@ describe('Linked List (Doubly)', () => { expect(list.length).toBe(3); expect(list.head.value).toBe('c'); expect(list.head.next.value).toBe('b'); + expect(list.head.next.next.value).toBe('a'); expect(list.head.previous).toBeUndefined(); expect(list.tail.value).toBe('a'); expect(list.tail.previous.value).toBe('b'); + expect(list.tail.previous.previous.value).toBe('c'); expect(list.tail.next).toBeUndefined(); }); }); @@ -72,34 +74,49 @@ describe('Linked List (Doubly)', () => { expect(list.length).toBe(3); expect(list.head.value).toBe('a'); expect(list.head.next.value).toBe('b'); + expect(list.head.next.next.value).toBe('c'); expect(list.head.previous).toBeUndefined(); expect(list.tail.value).toBe('c'); expect(list.tail.previous.value).toBe('b'); + expect(list.tail.previous.previous.value).toBe('a'); expect(list.tail.next).toBeUndefined(); }); }); describe('#after', () => { - it('should place a node after node with given value', () => { + it('should add a node after node with given value', () => { list.add('a').tail(); - list.add('b').tail(); - list.add('c').tail(); - // "a" <-> "b" <-> "c" + // "a" - list.add('x').after('b'); + list.add('b').after('a'); + list.add('c').after('b'); - // "a" <-> "b" <-> "x" <-> "c" + // "a" <-> "b" <-> "c" - expect(list.length).toBe(4); + expect(list.length).toBe(3); expect(list.head.value).toBe('a'); expect(list.head.next.value).toBe('b'); - expect(list.head.next.next.value).toBe('x'); - expect(list.head.next.next.next.value).toBe('c'); + expect(list.head.next.next.value).toBe('c'); expect(list.tail.value).toBe('c'); - expect(list.tail.previous.value).toBe('x'); - expect(list.tail.previous.previous.value).toBe('b'); - expect(list.tail.previous.previous.previous.value).toBe('a'); + expect(list.tail.previous.value).toBe('b'); + expect(list.tail.previous.previous.value).toBe('a'); + }); + + it('should add a node to tail if given value is not found', () => { + list.add('a').tail(); + + // "a" + + list.add('b').after('x'); + + // "a" <-> "b" + + expect(list.length).toBe(2); + expect(list.head.value).toBe('a'); + expect(list.head.next.value).toBe('b'); + expect(list.tail.value).toBe('b'); + expect(list.tail.previous.value).toBe('a'); }); it('should be able to receive a custom compareFn', () => { @@ -126,79 +143,516 @@ describe('Linked List (Doubly)', () => { }); describe('#before', () => { - it('should place a node before node with given value', () => { + it('should add a node before node with given value', () => { + list.add('c').tail(); + + // "c" + + list.add('b').before('c'); + list.add('a').before('b'); + + // "a" <-> "b" <-> "c" + + expect(list.length).toBe(3); + expect(list.head.value).toBe('a'); + expect(list.head.next.value).toBe('b'); + expect(list.head.next.next.value).toBe('c'); + expect(list.tail.value).toBe('c'); + expect(list.tail.previous.value).toBe('b'); + expect(list.tail.previous.previous.value).toBe('a'); + }); + + it('should add a node to head if given value is not found', () => { + list.add('b').tail(); + + // "a" + + list.add('a').before('x'); + + // "a" <-> "b" + + expect(list.length).toBe(2); + expect(list.head.value).toBe('a'); + expect(list.head.next.value).toBe('b'); + expect(list.tail.value).toBe('b'); + expect(list.tail.previous.value).toBe('a'); + }); + + it('should be able to receive a custom compareFn', () => { + list.add({ x: 1 }).tail(); + list.add({ x: 2 }).tail(); + list.add({ x: 3 }).tail(); + + // {"x":1} <-> {"x":2} <-> {"x":3} + + list.add({ x: 0 }).before({ x: 2 }, (v1: X, v2: X) => v1.x === v2.x); + + // {"x":1} <-> {"x":0} <-> {"x":2} <-> {"x":3} + + expect(list.length).toBe(4); + expect(list.head.value.x).toBe(1); + expect(list.head.next.value.x).toBe(0); + expect(list.head.next.next.value.x).toBe(2); + expect(list.head.next.next.next.value.x).toBe(3); + expect(list.tail.value.x).toBe(3); + expect(list.tail.previous.value.x).toBe(2); + expect(list.tail.previous.previous.value.x).toBe(0); + expect(list.tail.previous.previous.previous.value.x).toBe(1); + }); + }); + + describe('#byIndex', () => { + it('should add a node at given index', () => { list.add('a').tail(); list.add('b').tail(); list.add('c').tail(); // "a" <-> "b" <-> "c" - list.add('x').before('b'); + list.add('x').byIndex(1); // "a" <-> "x" <-> "b" <-> "c" - expect(list.length).toBe(4); + list.add('y').byIndex(3); + + // "a" <-> "x" <-> "b" <-> "y" <-> "c" + + expect(list.length).toBe(5); expect(list.head.value).toBe('a'); expect(list.head.next.value).toBe('x'); expect(list.head.next.next.value).toBe('b'); + expect(list.head.next.next.next.value).toBe('y'); + expect(list.head.next.next.next.next.value).toBe('c'); + expect(list.tail.value).toBe('c'); + expect(list.tail.previous.value).toBe('y'); + expect(list.tail.previous.previous.value).toBe('b'); + expect(list.tail.previous.previous.previous.value).toBe('x'); + expect(list.tail.previous.previous.previous.previous.value).toBe('a'); + }); + + it('should add a node to head if given index is zero', () => { + list.add('a').tail(); + list.add('b').tail(); + list.add('c').tail(); + + // "a" <-> "b" <-> "c" + + list.add('x').byIndex(0); + + // "x" <-> "a" <-> "b" <-> "c" + + expect(list.length).toBe(4); + expect(list.head.value).toBe('x'); + expect(list.head.next.value).toBe('a'); + expect(list.head.next.next.value).toBe('b'); expect(list.head.next.next.next.value).toBe('c'); expect(list.tail.value).toBe('c'); expect(list.tail.previous.value).toBe('b'); - expect(list.tail.previous.previous.value).toBe('x'); - expect(list.tail.previous.previous.previous.value).toBe('a'); + expect(list.tail.previous.previous.value).toBe('a'); + expect(list.tail.previous.previous.previous.value).toBe('x'); + }); + + it('should add a node to tail if given index more than size', () => { + list.add('a').tail(); + list.add('b').tail(); + list.add('c').tail(); + + // "a" <-> "b" <-> "c" + + list.add('x').byIndex(4); + + // "a" <-> "b" <-> "c" <-> "x" + + expect(list.length).toBe(4); + expect(list.head.value).toBe('a'); + expect(list.head.next.value).toBe('b'); + expect(list.head.next.next.value).toBe('c'); + expect(list.head.next.next.next.value).toBe('x'); + expect(list.tail.value).toBe('x'); + expect(list.tail.previous.value).toBe('c'); + expect(list.tail.previous.previous.value).toBe('b'); + expect(list.tail.previous.previous.previous.value).toBe('a'); + }); + + it('should be able to add a node at given index counting from right to left', () => { + list.add('a').tail(); + list.add('b').tail(); + list.add('c').tail(); + + // "a" <-> "b" <-> "c" + + list.add('x').byIndex(-1); + + // "a" <-> "b" <-> "x" <-> "c" + + expect(list.length).toBe(4); + expect(list.head.value).toBe('a'); + expect(list.head.next.value).toBe('b'); + expect(list.head.next.next.value).toBe('x'); + expect(list.head.next.next.next.value).toBe('c'); + expect(list.tail.value).toBe('c'); + expect(list.tail.previous.value).toBe('x'); + expect(list.tail.previous.previous.value).toBe('b'); + expect(list.tail.previous.previous.previous.value).toBe('a'); + }); + + it('should add a node to head if given index is less than minus size', () => { + list.add('a').tail(); + list.add('b').tail(); + list.add('c').tail(); + + // "a" <-> "b" <-> "c" + + list.add('x').byIndex(-4); + + // "x" <-> "a" <-> "b" <-> "c" + + expect(list.length).toBe(4); + expect(list.head.value).toBe('x'); + expect(list.head.next.value).toBe('a'); + expect(list.head.next.next.value).toBe('b'); + expect(list.head.next.next.next.value).toBe('c'); + expect(list.tail.value).toBe('c'); + expect(list.tail.previous.value).toBe('b'); + expect(list.tail.previous.previous.value).toBe('a'); + expect(list.tail.previous.previous.previous.value).toBe('x'); + }); + }); + }); + + describe('#addMany', () => { + describe('#head', () => { + it('should add multiple nodes to the head of the list', () => { + list.add('x').head(); + + // "x" + + list.addMany(['a', 'b', 'c']).head(); + + // "a" <-> "b" <-> "c" <-> "x" + + expect(list.length).toBe(4); + expect(list.head.value).toBe('a'); + expect(list.head.next.value).toBe('b'); + expect(list.head.next.next.value).toBe('c'); + expect(list.head.next.next.next.value).toBe('x'); + expect(list.head.previous).toBeUndefined(); + expect(list.tail.value).toBe('x'); + expect(list.tail.previous.value).toBe('c'); + expect(list.tail.previous.previous.value).toBe('b'); + expect(list.tail.previous.previous.previous.value).toBe('a'); + expect(list.tail.next).toBeUndefined(); + }); + }); + + describe('#tail', () => { + it('should add multiple nodes to the tail of the list', () => { + list.add('x').tail(); + + // "x" + + list.addMany(['a', 'b', 'c']).tail(); + + // "x" <-> "a" <-> "b" <-> "c" + + expect(list.length).toBe(4); + expect(list.head.value).toBe('x'); + expect(list.head.next.value).toBe('a'); + expect(list.head.next.next.value).toBe('b'); + expect(list.head.next.next.next.value).toBe('c'); + expect(list.head.previous).toBeUndefined(); + expect(list.tail.value).toBe('c'); + expect(list.tail.previous.value).toBe('b'); + expect(list.tail.previous.previous.value).toBe('a'); + expect(list.tail.previous.previous.previous.value).toBe('x'); + expect(list.tail.next).toBeUndefined(); + }); + }); + + describe('#after', () => { + it('should add multiple nodes after node with given value', () => { + list.add('a').tail(); + + // "a" + + list.addMany(['b', 'c']).after('a'); + + // "a" <-> "b" <-> "c" + + list.addMany(['x', 'y', 'z']).after('b'); + + // "a" <-> "b" <-> "x" <-> "y" <-> "z" <-> "c" + + expect(list.length).toBe(6); + expect(list.head.value).toBe('a'); + expect(list.head.next.value).toBe('b'); + expect(list.head.next.next.value).toBe('x'); + expect(list.head.next.next.next.value).toBe('y'); + expect(list.head.next.next.next.next.value).toBe('z'); + expect(list.head.next.next.next.next.next.value).toBe('c'); + expect(list.tail.value).toBe('c'); + expect(list.tail.previous.value).toBe('z'); + expect(list.tail.previous.previous.value).toBe('y'); + expect(list.tail.previous.previous.previous.value).toBe('x'); + expect(list.tail.previous.previous.previous.previous.value).toBe('b'); + expect(list.tail.previous.previous.previous.previous.previous.value).toBe('a'); + }); + + it('should add multiple nodes to tail if given value is not found', () => { + list.add('a').tail(); + + // "a" + + list.addMany(['b', 'c']).after('x'); + + // "a" <-> "b" <-> "c" + + expect(list.length).toBe(3); + expect(list.head.value).toBe('a'); + expect(list.head.next.value).toBe('b'); + expect(list.head.next.next.value).toBe('c'); + expect(list.tail.value).toBe('c'); + expect(list.tail.previous.value).toBe('b'); + expect(list.tail.previous.previous.value).toBe('a'); + }); + + it('should be able to receive a custom compareFn', () => { + list.addMany([{ x: 1 }, { x: 2 }, { x: 3 }]).tail(); + + // {"x":1} <-> {"x":2} <-> {"x":3} + + list.addMany([{ x: 4 }, { x: 5 }]).after({ x: 1 }, (v1: X, v2: X) => v1.x === v2.x); + + // {"x":1} <-> {"x":4} <-> {"x":5} <-> {"x":2} <-> {"x":3} + + expect(list.length).toBe(5); + expect(list.head.value.x).toBe(1); + expect(list.head.next.value.x).toBe(4); + expect(list.head.next.next.value.x).toBe(5); + expect(list.head.next.next.next.value.x).toBe(2); + expect(list.head.next.next.next.next.value.x).toBe(3); + expect(list.tail.value.x).toBe(3); + expect(list.tail.previous.value.x).toBe(2); + expect(list.tail.previous.previous.value.x).toBe(5); + expect(list.tail.previous.previous.previous.value.x).toBe(4); + expect(list.tail.previous.previous.previous.previous.value.x).toBe(1); + }); + + it('should not change the list when empty array given as value', () => { + list.add('a').tail(); + + // "a" + + list.addMany([]).after('a'); + + // "a" + + expect(list.length).toBe(1); + expect(list.head.value).toBe('a'); + expect(list.tail.value).toBe('a'); + }); + }); + + describe('#before', () => { + it('should add multiple nodes before node with given value', () => { + list.add('c').tail(); + + // "c" + + list.addMany(['a', 'b']).before('c'); + + // "a" <-> "b" <-> "c" + + list.addMany(['x', 'y', 'z']).before('b'); + + // "a" <-> "x" <-> "y" <-> "z" <-> "b" <-> "c" + + expect(list.length).toBe(6); + expect(list.head.value).toBe('a'); + expect(list.head.next.value).toBe('x'); + expect(list.head.next.next.value).toBe('y'); + expect(list.head.next.next.next.value).toBe('z'); + expect(list.head.next.next.next.next.value).toBe('b'); + expect(list.head.next.next.next.next.next.value).toBe('c'); + expect(list.tail.value).toBe('c'); + expect(list.tail.previous.value).toBe('b'); + expect(list.tail.previous.previous.value).toBe('z'); + expect(list.tail.previous.previous.previous.value).toBe('y'); + expect(list.tail.previous.previous.previous.previous.value).toBe('x'); + expect(list.tail.previous.previous.previous.previous.previous.value).toBe('a'); + }); + + it('should add multiple nodes to head if given value is not found', () => { + list.add('c').tail(); + + // "c" + + list.addMany(['a', 'b']).before('x'); + + // "a" <-> "b" <-> "c" + + expect(list.length).toBe(3); + expect(list.head.value).toBe('a'); + expect(list.head.next.value).toBe('b'); + expect(list.head.next.next.value).toBe('c'); + expect(list.tail.value).toBe('c'); + expect(list.tail.previous.value).toBe('b'); + expect(list.tail.previous.previous.value).toBe('a'); + }); + + it('should be able to receive a custom compareFn', () => { + list.addMany([{ x: 1 }, { x: 2 }, { x: 3 }]).tail(); + + // {"x":1} <-> {"x":2} <-> {"x":3} + + list.addMany([{ x: 4 }, { x: 5 }]).before({ x: 3 }, (v1: X, v2: X) => v1.x === v2.x); + + // {"x":1} <-> {"x":2} <-> {"x":4} <-> {"x":5} <-> {"x":3} + + expect(list.length).toBe(5); + expect(list.head.value.x).toBe(1); + expect(list.head.next.value.x).toBe(2); + expect(list.head.next.next.value.x).toBe(4); + expect(list.head.next.next.next.value.x).toBe(5); + expect(list.head.next.next.next.next.value.x).toBe(3); + expect(list.tail.value.x).toBe(3); + expect(list.tail.previous.value.x).toBe(5); + expect(list.tail.previous.previous.value.x).toBe(4); + expect(list.tail.previous.previous.previous.value.x).toBe(2); + expect(list.tail.previous.previous.previous.previous.value.x).toBe(1); + }); + + it('should not change the list when empty array given as value', () => { + list.add('a').tail(); + + // "a" + + list.addMany([]).before('a'); + + // "a" + + expect(list.length).toBe(1); + expect(list.head.value).toBe('a'); + expect(list.tail.value).toBe('a'); + }); + }); + + describe('#byIndex', () => { + it('should add multiple nodes starting from given index', () => { + list.addMany(['a', 'b', 'c']).tail(); + + // "a" <-> "b" <-> "c" + + list.addMany(['x', 'y']).byIndex(1); + + // "a" <-> "x" <-> "y" <-> "b" <-> "c" + + list.addMany(['z']).byIndex(4); + + // "a" <-> "x" <-> "y" <-> "b" <-> "z" <-> "c" + + expect(list.length).toBe(6); + expect(list.head.value).toBe('a'); + expect(list.head.next.value).toBe('x'); + expect(list.head.next.next.value).toBe('y'); + expect(list.head.next.next.next.value).toBe('b'); + expect(list.head.next.next.next.next.value).toBe('z'); + expect(list.head.next.next.next.next.next.value).toBe('c'); + expect(list.tail.value).toBe('c'); + expect(list.tail.previous.value).toBe('z'); + expect(list.tail.previous.previous.value).toBe('b'); + expect(list.tail.previous.previous.previous.value).toBe('y'); + expect(list.tail.previous.previous.previous.previous.value).toBe('x'); + expect(list.tail.previous.previous.previous.previous.previous.value).toBe('a'); + }); + + it('should add multiple nodes to head if given index is zero', () => { + list.addMany(['a', 'b', 'c']).tail(); + + // "a" <-> "b" <-> "c" + + list.addMany(['x', 'y']).byIndex(0); + + // "x" <-> "y" <-> "a" <-> "b" <-> "c" + + expect(list.length).toBe(5); + expect(list.head.value).toBe('x'); + expect(list.head.next.value).toBe('y'); + expect(list.head.next.next.value).toBe('a'); + expect(list.head.next.next.next.value).toBe('b'); + expect(list.head.next.next.next.next.value).toBe('c'); + expect(list.tail.value).toBe('c'); + expect(list.tail.previous.value).toBe('b'); + expect(list.tail.previous.previous.value).toBe('a'); + expect(list.tail.previous.previous.previous.value).toBe('y'); + expect(list.tail.previous.previous.previous.previous.value).toBe('x'); }); - it('should be able to receive a custom compareFn', () => { - list.add({ x: 1 }).tail(); - list.add({ x: 2 }).tail(); - list.add({ x: 3 }).tail(); + it('should add multiple nodes to tail if given index more than size', () => { + list.addMany(['a', 'b', 'c']).tail(); - // {"x":1} <-> {"x":2} <-> {"x":3} + // "a" <-> "b" <-> "c" - list.add({ x: 0 }).before({ x: 2 }, (v1: X, v2: X) => v1.x === v2.x); + list.addMany(['x', 'y']).byIndex(4); - // {"x":1} <-> {"x":0} <-> {"x":2} <-> {"x":3} + // "a" <-> "b" <-> "c" <-> "x" <-> "y" - expect(list.length).toBe(4); - expect(list.head.value.x).toBe(1); - expect(list.head.next.value.x).toBe(0); - expect(list.head.next.next.value.x).toBe(2); - expect(list.head.next.next.next.value.x).toBe(3); - expect(list.tail.value.x).toBe(3); - expect(list.tail.previous.value.x).toBe(2); - expect(list.tail.previous.previous.value.x).toBe(0); - expect(list.tail.previous.previous.previous.value.x).toBe(1); + expect(list.length).toBe(5); + expect(list.head.value).toBe('a'); + expect(list.head.next.value).toBe('b'); + expect(list.head.next.next.value).toBe('c'); + expect(list.head.next.next.next.value).toBe('x'); + expect(list.head.next.next.next.next.value).toBe('y'); + expect(list.tail.value).toBe('y'); + expect(list.tail.previous.value).toBe('x'); + expect(list.tail.previous.previous.value).toBe('c'); + expect(list.tail.previous.previous.previous.value).toBe('b'); + expect(list.tail.previous.previous.previous.previous.value).toBe('a'); }); - }); - describe('#byIndex', () => { - it('should place a node at given index', () => { - list.add('a').tail(); - list.add('b').tail(); - list.add('c').tail(); + it('should be able to add multiple nodes at given index counting from right to left', () => { + list.addMany(['a', 'b', 'c']).tail(); // "a" <-> "b" <-> "c" - list.add('x').byIndex(1); - - // "a" <-> "x" <-> "b" <-> "c" - - list.add('y').byIndex(3); + list.addMany(['x', 'y']).byIndex(-1); - // "a" <-> "x" <-> "b" <-> "y" <-> "c" + // "a" <-> "b" <-> "x" <-> "y" <-> "c" expect(list.length).toBe(5); expect(list.head.value).toBe('a'); - expect(list.head.next.value).toBe('x'); - expect(list.head.next.next.value).toBe('b'); + expect(list.head.next.value).toBe('b'); + expect(list.head.next.next.value).toBe('x'); expect(list.head.next.next.next.value).toBe('y'); expect(list.head.next.next.next.next.value).toBe('c'); expect(list.tail.value).toBe('c'); expect(list.tail.previous.value).toBe('y'); - expect(list.tail.previous.previous.value).toBe('b'); - expect(list.tail.previous.previous.previous.value).toBe('x'); + expect(list.tail.previous.previous.value).toBe('x'); + expect(list.tail.previous.previous.previous.value).toBe('b'); expect(list.tail.previous.previous.previous.previous.value).toBe('a'); }); + + it('should add a node to head if given index is less than minus size', () => { + list.addMany(['a', 'b', 'c']).tail(); + + // "a" <-> "b" <-> "c" + + list.addMany(['x', 'y']).byIndex(-4); + + // "x" <-> "y" <-> "a" <-> "b" <-> "c" + + expect(list.length).toBe(5); + expect(list.head.value).toBe('x'); + expect(list.head.next.value).toBe('y'); + expect(list.head.next.next.value).toBe('a'); + expect(list.head.next.next.next.value).toBe('b'); + expect(list.head.next.next.next.next.value).toBe('c'); + expect(list.tail.value).toBe('c'); + expect(list.tail.previous.value).toBe('b'); + expect(list.tail.previous.previous.value).toBe('a'); + expect(list.tail.previous.previous.previous.value).toBe('y'); + expect(list.tail.previous.previous.previous.previous.value).toBe('x'); + }); }); }); @@ -212,19 +666,19 @@ describe('Linked List (Doubly)', () => { // "a" <-> "x" <-> "b" <-> "x" <-> "c" - const node1 = list.find(node => node.previous && node.previous.value === 'a'); + const found1 = list.find(node => node.previous && node.previous.value === 'a'); - expect(node1.value).toBe('x'); - expect(node1.previous.value).toBe('a'); - expect(node1.next.value).toBe('b'); + expect(found1.value).toBe('x'); + expect(found1.previous.value).toBe('a'); + expect(found1.next.value).toBe('b'); // "a" <-> "x" <-> "b" <-> "x" <-> "c" - const node2 = list.find(node => node.next && node.next.value === 'c'); + const found2 = list.find(node => node.next && node.next.value === 'c'); - expect(node2.value).toBe('x'); - expect(node2.previous.value).toBe('b'); - expect(node2.next.value).toBe('c'); + expect(found2.value).toBe('x'); + expect(found2.previous.value).toBe('b'); + expect(found2.next.value).toBe('c'); }); it('should return undefined when list is empty', () => { @@ -329,7 +783,8 @@ describe('Linked List (Doubly)', () => { describe('#drop', () => { describe('#head', () => { it('should return undefined when there is no head', () => { - expect(list.drop().head()).toBeUndefined(); + const dropped = list.drop().head(); + expect(dropped).toBeUndefined(); }); it('should remove the node from the head of the list', () => { @@ -350,12 +805,22 @@ describe('Linked List (Doubly)', () => { expect(list.tail.value).toBe('c'); expect(list.tail.previous.value).toBe('b'); expect(list.tail.next).toBeUndefined(); + + // "b" <-> "c" + + list.drop().head(); + list.drop().head(); + + expect(list.length).toBe(0); + expect(list.head).toBeUndefined(); + expect(list.tail).toBeUndefined(); }); }); - describe('#head', () => { + describe('#tail', () => { it('should return undefined when there is no tail', () => { - expect(list.drop().tail()).toBeUndefined(); + const dropped = list.drop().tail(); + expect(dropped).toBeUndefined(); }); it('should remove the node from the tail of the list', () => { @@ -376,6 +841,15 @@ describe('Linked List (Doubly)', () => { expect(list.tail.value).toBe('b'); expect(list.tail.previous.value).toBe('a'); expect(list.tail.next).toBeUndefined(); + + // "a" <-> "b" + + list.drop().tail(); + list.drop().tail(); + + expect(list.length).toBe(0); + expect(list.head).toBeUndefined(); + expect(list.tail).toBeUndefined(); }); }); @@ -393,7 +867,7 @@ describe('Linked List (Doubly)', () => { // "a" <-> "c" <-> "d" <-> "e" - list.drop().byIndex(2); + list.drop().byIndex(-2); // "a" <-> "c" <-> "e" @@ -404,11 +878,21 @@ describe('Linked List (Doubly)', () => { expect(list.tail.value).toBe('e'); expect(list.tail.previous.value).toBe('c'); expect(list.tail.previous.previous.value).toBe('a'); + + // "a" <-> "c" <-> "e" + + list.drop().byIndex(2); + list.drop().byIndex(1); + list.drop().byIndex(0); + + expect(list.length).toBe(0); + expect(list.head).toBeUndefined(); + expect(list.tail).toBeUndefined(); }); it('should return undefined when list is empty', () => { - const node = list.drop().byIndex(0); - expect(node).toBeUndefined(); + const dropped = list.drop().byIndex(0); + expect(dropped).toBeUndefined(); }); it('should return undefined when given index does not exist', () => { @@ -418,11 +902,11 @@ describe('Linked List (Doubly)', () => { // "a" <-> "b" <-> "c" - const node1 = list.drop().byIndex(4); + const dropped1 = list.drop().byIndex(4); // "a" <-> "b" <-> "c" - expect(node1).toBeUndefined(); + expect(dropped1).toBeUndefined(); expect(list.length).toBe(3); expect(list.head.value).toBe('a'); expect(list.head.next.value).toBe('b'); @@ -433,11 +917,11 @@ describe('Linked List (Doubly)', () => { // "a" <-> "b" <-> "c" - const node2 = list.drop().byIndex(-1); + const dropped2 = list.drop().byIndex(-4); // "a" <-> "b" <-> "c" - expect(node2).toBeUndefined(); + expect(dropped2).toBeUndefined(); expect(list.length).toBe(3); expect(list.head.value).toBe('a'); expect(list.head.next.value).toBe('b'); @@ -506,8 +990,8 @@ describe('Linked List (Doubly)', () => { }); it('should return undefined when list is empty', () => { - const node = list.drop().byValue('x'); - expect(node).toBeUndefined(); + const dropped = list.drop().byValue('x'); + expect(dropped).toBeUndefined(); }); it('should return undefined when given value is not found', () => { @@ -622,6 +1106,214 @@ describe('Linked List (Doubly)', () => { }); }); + describe('#dropMany', () => { + describe('#head', () => { + it('should return empty array when there is no head', () => { + const dropped = list.dropMany(1).head(); + expect(dropped).toEqual([]); + }); + + it('should remove multiple nodes from the head of the list', () => { + list.addMany(['a', 'b', 'c', 'd', 'e']).tail(); + + // "a" <-> "b" <-> "c" <-> "d" <-> "e" + + list.dropMany(3).head(); + + // "d" <-> "e" + + expect(list.length).toBe(2); + expect(list.head.value).toBe('d'); + expect(list.head.next.value).toBe('e'); + expect(list.head.previous).toBeUndefined(); + expect(list.tail.value).toBe('e'); + expect(list.tail.previous.value).toBe('d'); + expect(list.tail.next).toBeUndefined(); + }); + + it('should not change the list when count is less than or equal to zero', () => { + list.add('a').tail(); + + // "a" + + list.dropMany(0).head(); + + // "a" + + list.dropMany(-1).head(); + + // "a" + + expect(list.length).toBe(1); + expect(list.head.value).toBe('a'); + expect(list.tail.value).toBe('a'); + }); + }); + + describe('#tail', () => { + it('should return empty array when there is no tail', () => { + const dropped = list.dropMany(1).tail(); + expect(dropped).toEqual([]); + }); + + it('should remove multiple nodes from the tail of the list', () => { + list.addMany(['a', 'b', 'c', 'd', 'e']).tail(); + + // "a" <-> "b" <-> "c" <-> "d" <-> "e" + + list.dropMany(3).tail(); + + // "a" <-> "b" + + expect(list.length).toBe(2); + expect(list.head.value).toBe('a'); + expect(list.head.next.value).toBe('b'); + expect(list.head.previous).toBeUndefined(); + expect(list.tail.value).toBe('b'); + expect(list.tail.previous.value).toBe('a'); + expect(list.tail.next).toBeUndefined(); + }); + + it('should not change the list when count is less than or equal to zero', () => { + list.add('a').tail(); + + // "a" + + list.dropMany(0).tail(); + + // "a" + + list.dropMany(-1).tail(); + + // "a" + + expect(list.length).toBe(1); + expect(list.head.value).toBe('a'); + expect(list.tail.value).toBe('a'); + }); + }); + + describe('#byIndex', () => { + it('should remove multiple nodes starting from given index', () => { + list.addMany(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']).tail(); + + // "a" <-> "b" <-> "c" <-> "d" <-> "e" <-> "f" <-> "g" <-> "h" + + list.dropMany(2).byIndex(1); + + // "a" <-> "d" <-> "e" <-> "f" <-> "g" <-> "h" + + list.dropMany(2).byIndex(-3); + + // "a" <-> "d" <-> "e" <-> "h" + + expect(list.length).toBe(4); + expect(list.head.value).toBe('a'); + expect(list.head.next.value).toBe('d'); + expect(list.head.next.next.value).toBe('e'); + expect(list.head.next.next.next.value).toBe('h'); + expect(list.tail.value).toBe('h'); + expect(list.tail.previous.value).toBe('e'); + expect(list.tail.previous.previous.value).toBe('d'); + expect(list.tail.previous.previous.previous.value).toBe('a'); + + list.dropMany(4).byIndex(0); + + expect(list.length).toBe(0); + expect(list.head).toBeUndefined(); + expect(list.tail).toBeUndefined(); + }); + + it('should return empty array when list is empty', () => { + const dropped = list.dropMany(1).byIndex(0); + expect(dropped).toEqual([]); + }); + + it('should return empty array when given index does not exist', () => { + list.addMany(['a', 'b', 'c']).tail(); + + // "a" <-> "b" <-> "c" + + const dropped = list.dropMany(3).byIndex(4); + + // "a" <-> "b" <-> "c" + + expect(dropped).toEqual([]); + expect(list.length).toBe(3); + expect(list.head.value).toBe('a'); + expect(list.head.next.value).toBe('b'); + expect(list.head.next.next.value).toBe('c'); + expect(list.tail.value).toBe('c'); + expect(list.tail.previous.value).toBe('b'); + expect(list.tail.previous.previous.value).toBe('a'); + }); + + it('should remove from start when given index is less than minus size', () => { + list.addMany(['a', 'b', 'c', 'd', 'e']).tail(); + + // "a" <-> "b" <-> "c" <-> "d" <-> "e" + + list.dropMany(2).byIndex(-9); + + // "c" <-> "d" <-> "e" + + expect(list.length).toBe(3); + expect(list.head.value).toBe('c'); + expect(list.head.next.value).toBe('d'); + expect(list.head.next.next.value).toBe('e'); + expect(list.tail.value).toBe('e'); + expect(list.tail.previous.value).toBe('d'); + expect(list.tail.previous.previous.value).toBe('c'); + }); + + it('should remove from end when given index + count is larger than or equal to size', () => { + list.addMany(['a', 'b', 'c', 'd', 'e']).tail(); + + // "a" <-> "b" <-> "c" <-> "d" <-> "e" + + list.dropMany(2).byIndex(3); + + // "a" <-> "b" <-> "c" + + expect(list.length).toBe(3); + expect(list.head.value).toBe('a'); + expect(list.head.next.value).toBe('b'); + expect(list.head.next.next.value).toBe('c'); + expect(list.tail.value).toBe('c'); + expect(list.tail.previous.value).toBe('b'); + expect(list.tail.previous.previous.value).toBe('a'); + + // "a" <-> "b" <-> "c" + + list.dropMany(9).byIndex(1); + + // "a" + + expect(list.length).toBe(1); + expect(list.head.value).toBe('a'); + expect(list.tail.value).toBe('a'); + }); + + it('should not change the list when count is less than or equal to zero', () => { + list.add('a').tail(); + + // "a" + + list.dropMany(0).byIndex(0); + + // "a" + + list.dropMany(-1).byIndex(0); + + // "a" + + expect(list.length).toBe(1); + expect(list.head.value).toBe('a'); + expect(list.tail.value).toBe('a'); + }); + }); + }); + describe('#get', () => { it('should return node at given index', () => { list.add('a').tail(); @@ -761,6 +1453,27 @@ describe('Linked List (Doubly)', () => { }); }); + describe('#toNodeArray', () => { + it('should return array of nodes', () => { + list.addTail('a'); + list.addTail(2); + list.addTail('c'); + list.addTail({ k: 4, v: 'd' }); + + // "a" <-> 2 <-> "c" <-> {"k":4,"v":"d"} + + const arr = list.toNodeArray(); + + expect(arr.every(node => node instanceof ListNode)).toBe(true); + expect(arr.map(node => node.value)).toEqual(['a', 2, 'c', { k: 4, v: 'd' }]); + }); + + it('should return empty array when list is empty', () => { + const arr = list.toNodeArray(); + expect(arr).toEqual([]); + }); + }); + describe('#toString', () => { it('should return string representation', () => { list.addTail('a'); @@ -778,6 +1491,23 @@ describe('Linked List (Doubly)', () => { const str = list.toString(); expect(str).toBe(''); }); + + it('should be coercible', () => { + list.addMany(['a', 'b', 'c']).tail(); + + // "a" <-> "b" <-> "c" + + expect('' + list).toBe('"a" <-> "b" <-> "c"'); + }); + + it('should be able to receive a custom mapperFn', () => { + list.addMany([{ x: 1 }, { x: 2 }, { x: 3 }]).tail(); + + // {"x":1} <-> {"x":2} <-> {"x":3} + + const str = list.toString(value => value.x); + expect(str).toBe('1 <-> 2 <-> 3'); + }); }); it('should be iterable', () => { diff --git a/npm/ng-packs/packages/core/src/lib/utils/linked-list.ts b/npm/ng-packs/packages/core/src/lib/utils/linked-list.ts index 42cc5bc941..9bd3e21941 100644 --- a/npm/ng-packs/packages/core/src/lib/utils/linked-list.ts +++ b/npm/ng-packs/packages/core/src/lib/utils/linked-list.ts @@ -27,65 +27,107 @@ export class LinkedList { return this.size; } - private linkWith( + private attach( value: T, previousNode: ListNode | undefined, nextNode: ListNode | undefined, ): ListNode { - const node = new ListNode(value); - if (!previousNode) return this.addHead(value); + if (!nextNode) return this.addTail(value); + const node = new ListNode(value); node.previous = previousNode; previousNode.next = node; node.next = nextNode; nextNode.previous = node; - this.size += 1; + this.size++; + + return node; + } + + private attachMany( + values: T[], + previousNode: ListNode | undefined, + nextNode: ListNode | undefined, + ): ListNode[] { + if (!values.length) return []; + + if (!previousNode) return this.addManyHead(values); + + if (!nextNode) return this.addManyTail(values); + + const list = new LinkedList(); + list.addManyTail(values); + list.first!.previous = previousNode; + previousNode.next = list.first; + list.last!.next = nextNode; + nextNode.previous = list.last; + + this.size += values.length; + + return list.toNodeArray(); + } + + private detach(node: ListNode) { + if (!node.previous) return this.dropHead(); + + if (!node.next) return this.dropTail(); + + node.previous.next = node.next; + node.next.previous = node.previous; + + this.size--; return node; } add(value: T) { return { - after: (previousValue: T, compareFn = compare) => { - return this.addAfter(value, previousValue, compareFn); - }, - before: (nextValue: T, compareFn = compare) => { - return this.addBefore(value, nextValue, compareFn); - }, - byIndex: (position: number): ListNode => { - return this.addByIndex(value, position); - }, - head: (): ListNode => { - return this.addHead(value); - }, - tail: (): ListNode => { - return this.addTail(value); - }, + after: (previousValue: T, compareFn: ListComparisonFn = compare) => + this.addAfter(value, previousValue, compareFn), + before: (nextValue: T, compareFn: ListComparisonFn = compare) => + this.addBefore(value, nextValue, compareFn), + byIndex: (position: number) => this.addByIndex(value, position), + head: () => this.addHead(value), + tail: () => this.addTail(value), + }; + } + + addMany(values: T[]) { + return { + after: (previousValue: T, compareFn: ListComparisonFn = compare) => + this.addManyAfter(values, previousValue, compareFn), + before: (nextValue: T, compareFn: ListComparisonFn = compare) => + this.addManyBefore(values, nextValue, compareFn), + byIndex: (position: number) => this.addManyByIndex(values, position), + head: () => this.addManyHead(values), + tail: () => this.addManyTail(values), }; } - addAfter(value: T, previousValue: T, compareFn = compare): ListNode { + addAfter(value: T, previousValue: T, compareFn: ListComparisonFn = compare): ListNode { const previous = this.find(node => compareFn(node.value, previousValue)); - return previous ? this.linkWith(value, previous, previous.next) : this.addTail(value); + return previous ? this.attach(value, previous, previous.next) : this.addTail(value); } - addBefore(value: T, nextValue: T, compareFn = compare): ListNode { + addBefore(value: T, nextValue: T, compareFn: ListComparisonFn = compare): ListNode { const next = this.find(node => compareFn(node.value, nextValue)); - return next ? this.linkWith(value, next.previous, next) : this.addHead(value); + return next ? this.attach(value, next.previous, next) : this.addHead(value); } addByIndex(value: T, position: number): ListNode { + if (position < 0) position += this.size; + else if (position >= this.size) return this.addTail(value); + if (position <= 0) return this.addHead(value); - if (position >= this.size) return this.addTail(value); const next = this.get(position)!; - return this.linkWith(value, next.previous, next); + return this.attach(value, next.previous, next); } addHead(value: T): ListNode { @@ -97,7 +139,7 @@ export class LinkedList { else this.last = node; this.first = node; - this.size += 1; + this.size++; return node; } @@ -114,51 +156,92 @@ export class LinkedList { this.last = node; } - this.size += 1; + this.size++; return node; } + addManyAfter( + values: T[], + previousValue: T, + compareFn: ListComparisonFn = compare, + ): ListNode[] { + const previous = this.find(node => compareFn(node.value, previousValue)); + + return previous ? this.attachMany(values, previous, previous.next) : this.addManyTail(values); + } + + addManyBefore( + values: T[], + nextValue: T, + compareFn: ListComparisonFn = compare, + ): ListNode[] { + const next = this.find(node => compareFn(node.value, nextValue)); + + return next ? this.attachMany(values, next.previous, next) : this.addManyHead(values); + } + + addManyByIndex(values: T[], position: number): ListNode[] { + if (position < 0) position += this.size; + + if (position <= 0) return this.addManyHead(values); + + if (position >= this.size) return this.addManyTail(values); + + const next = this.get(position)!; + + return this.attachMany(values, next.previous, next); + } + + addManyHead(values: T[]): ListNode[] { + return values.reduceRight[]>((nodes, value) => { + nodes.unshift(this.addHead(value)); + return nodes; + }, []); + } + + addManyTail(values: T[]): ListNode[] { + return values.map(value => this.addTail(value)); + } + drop() { return { byIndex: (position: number) => this.dropByIndex(position), - byValue: (value: T, compareFn = compare) => this.dropByValue(value, compareFn), - byValueAll: (value: T, compareFn = compare) => this.dropByValueAll(value, compareFn), + byValue: (value: T, compareFn: ListComparisonFn = compare) => + this.dropByValue(value, compareFn), + byValueAll: (value: T, compareFn: ListComparisonFn = compare) => + this.dropByValueAll(value, compareFn), head: () => this.dropHead(), tail: () => this.dropTail(), }; } + dropMany(count: number) { + return { + byIndex: (position: number) => this.dropManyByIndex(count, position), + head: () => this.dropManyHead(count), + tail: () => this.dropManyTail(count), + }; + } + dropByIndex(position: number): ListNode | undefined { - if (position === 0) return this.dropHead(); - else if (position === this.size - 1) return this.dropTail(); + if (position < 0) position += this.size; const current = this.get(position); - if (current) { - current.previous!.next = current.next; - current.next!.previous = current.previous; - - this.size -= 1; - - return current; - } - - return undefined; + return current ? this.detach(current) : undefined; } - dropByValue(value: T, compareFn = compare): ListNode | undefined { + dropByValue(value: T, compareFn: ListComparisonFn = compare): ListNode | undefined { const position = this.findIndex(node => compareFn(node.value, value)); - if (position < 0) return undefined; - - return this.dropByIndex(position); + return position < 0 ? undefined : this.dropByIndex(position); } - dropByValueAll(value: T, compareFn = compare): ListNode[] { + dropByValueAll(value: T, compareFn: ListComparisonFn = compare): ListNode[] { const dropped: ListNode[] = []; - for (let current = this.first, position = 0; current; position += 1, current = current.next) { + for (let current = this.first, position = 0; current; position++, current = current.next) { if (compareFn(current.value, value)) { dropped.push(this.dropByIndex(position - dropped.length)!); } @@ -176,7 +259,7 @@ export class LinkedList { if (this.first) this.first.previous = undefined; else this.last = undefined; - this.size -= 1; + this.size--; return head; } @@ -193,7 +276,7 @@ export class LinkedList { if (this.last) this.last.next = undefined; else this.first = undefined; - this.size -= 1; + this.size--; return tail; } @@ -201,24 +284,66 @@ export class LinkedList { return undefined; } - find(predicate: ListIteratorFunction): ListNode | undefined { - for (let current = this.first, position = 0; current; position += 1, current = current.next) { + dropManyByIndex(count: number, position: number): ListNode[] { + if (count <= 0) return []; + + if (position < 0) position = Math.max(position + this.size, 0); + else if (position >= this.size) return []; + + count = Math.min(count, this.size - position); + + const dropped: ListNode[] = []; + + while (count--) { + const current = this.get(position); + dropped.push(this.detach(current!)!); + } + + return dropped; + } + + dropManyHead(count: Exclude): ListNode[] { + if (count <= 0) return []; + + count = Math.min(count, this.size); + + const dropped: ListNode[] = []; + + while (count--) dropped.unshift(this.dropHead()!); + + return dropped; + } + + dropManyTail(count: Exclude): ListNode[] { + if (count <= 0) return []; + + count = Math.min(count, this.size); + + const dropped: ListNode[] = []; + + while (count--) dropped.push(this.dropTail()!); + + return dropped; + } + + find(predicate: ListIteratorFn): ListNode | undefined { + for (let current = this.first, position = 0; current; position++, current = current.next) { if (predicate(current, position, this)) return current; } return undefined; } - findIndex(predicate: ListIteratorFunction): number { - for (let current = this.first, position = 0; current; position += 1, current = current.next) { + findIndex(predicate: ListIteratorFn): number { + for (let current = this.first, position = 0; current; position++, current = current.next) { if (predicate(current, position, this)) return position; } return -1; } - forEach(callback: ListIteratorFunction) { - for (let node = this.first, position = 0; node; position += 1, node = node.next) { + forEach(callback: ListIteratorFn) { + for (let node = this.first, position = 0; node; position++, node = node.next) { callback(node, position, this); } } @@ -227,7 +352,7 @@ export class LinkedList { return this.find((_, index) => position === index); } - indexOf(value: T, compareFn = compare): number { + indexOf(value: T, compareFn: ListComparisonFn = compare): number { return this.findIndex(node => compareFn(node.value, value)); } @@ -239,20 +364,32 @@ export class LinkedList { return array; } - toString(): string { + toNodeArray(): ListNode[] { + const array = new Array(this.size); + + this.forEach((node, index) => (array[index!] = node)); + + return array; + } + + toString(mapperFn: ListMapperFn = JSON.stringify): string { return this.toArray() - .map(value => JSON.stringify(value)) + .map(value => mapperFn(value)) .join(' <-> '); } *[Symbol.iterator]() { - for (let node = this.first, position = 0; node; position += 1, node = node.next) { + for (let node = this.first, position = 0; node; position++, node = node.next) { yield node.value; } } } -export type ListIteratorFunction = ( +export type ListMapperFn = (value: T) => any; + +export type ListComparisonFn = (value1: T, value2: T) => boolean; + +export type ListIteratorFn = ( node: ListNode, index?: number, list?: LinkedList, From 7a22f1a4f24bf1f098723c3c896d177e0d4e4cf9 Mon Sep 17 00:00:00 2001 From: Arman Ozak Date: Thu, 26 Mar 2020 20:08:54 +0300 Subject: [PATCH 008/151] docs(core): add how to add and drop multiple values in LinkedList --- docs/en/UI/Angular/Linked-List.md | 628 +++++++++++++++++++++++++----- 1 file changed, 534 insertions(+), 94 deletions(-) diff --git a/docs/en/UI/Angular/Linked-List.md b/docs/en/UI/Angular/Linked-List.md index c3fb307806..388c5963cd 100644 --- a/docs/en/UI/Angular/Linked-List.md +++ b/docs/en/UI/Angular/Linked-List.md @@ -26,7 +26,7 @@ The constructor does not get any parameters. ### How to Add New Nodes -There are a few methods to create new nodes in a linked list and all of them are separately available as well as revealed from an `add` method. +There are several methods to create new nodes in a linked list and all of them are separately available as well as revealed by `add` and `addMany` methods. @@ -50,6 +50,22 @@ list.addHead('c'); +#### addManyHead(values: T\[\]): ListNode\\[\] + +Adds multiple nodes with given values as the first nodes in list: + +```js +list.addManyHead(['a', 'b', 'c']); + +// "a" <-> "b" <-> "c" + +list.addManyHead(['x', 'y', 'z']); + +// "x" <-> "y" <-> "z" <-> "a" <-> "b" <-> "c" +``` + + + #### addTail(value: T): ListNode\ Adds a node with given value as the last node in list: @@ -70,6 +86,22 @@ list.addTail('c'); +#### addManyTail(values: T\[\]): ListNode\\[\] + +Adds multiple nodes with given values as the last nodes in list: + +```js +list.addManyTail(['a', 'b', 'c']); + +// "a" <-> "b" <-> "c" + +list.addManyTail(['x', 'y', 'z']); + +// "a" <-> "b" <-> "c" <-> "x" <-> "y" <-> "z" +``` + + + #### addAfter(value: T, previousValue: T, compareFn = compare): ListNode\ Adds a node with given value after the first node that has the previous value: @@ -109,6 +141,40 @@ list.addAfter({ x: 0 }, { x: 2 }, (v1, v2) => v1.x === v2.x); +#### addManyAfter(values: T\[\], previousValue: T, compareFn = compare): ListNode\\[\] + +Adds multiple nodes with given values after the first node that has the previous value: + +```js +list.addManyTail(['a', 'b', 'b', 'c']); + +// "a" <-> "b" <-> "b" <-> "c" + +list.addManyAfter(['x', 'y'], 'b'); + +// "a" <-> "b" <-> "x" <-> "y" <-> "b" <-> "c" +``` + + + +You may pass a custom compare function to detect the searched value: + +```js +list.addManyTail([{ x: 1 },{ x: 2 },{ x: 3 }]); + +// {"x":1} <-> {"x":2} <-> {"x":3} + +list.addManyAfter([{ x: 4 }, { x: 5 }], { x: 2 }, (v1, v2) => v1.x === v2.x); + +// {"x":1} <-> {"x":2} <-> {"x":4} <-> {"x":5} <-> {"x":3} +``` + + + +> The default compare function checks deep equality, so you will rarely need to pass that parameter. + + + #### addBefore(value: T, nextValue: T, compareFn = compare): ListNode\ Adds a node with given value before the first node that has the next value: @@ -148,6 +214,40 @@ list.addBefore({ x: 0 }, { x: 2 }, (v1, v2) => v1.x === v2.x); +#### addManyBefore(values: T\[\], nextValue: T, compareFn = compare): ListNode\\[\] + +Adds multiple nodes with given values before the first node that has the next value: + +```js +list.addManyTail(['a', 'b', 'b', 'c']); + +// "a" <-> "b" <-> "b" <-> "c" + +list.addManyBefore(['x', 'y'], 'b'); + +// "a" <-> "x" <-> "y" <-> "b" <-> "b" <-> "c" +``` + + + +You may pass a custom compare function to detect the searched value: + +```js +list.addManyTail([{ x: 1 },{ x: 2 },{ x: 3 }]); + +// {"x":1} <-> {"x":2} <-> {"x":3} + +list.addManyBefore([{ x: 4 }, { x: 5 }], { x: 2 }, (v1, v2) => v1.x === v2.x); + +// {"x":1} <-> {"x":4} <-> {"x":5} <-> {"x":2} <-> {"x":3} +``` + + + +> The default compare function checks deep equality, so you will rarely need to pass that parameter. + + + #### addByIndex(value: T, position: number): ListNode\ Adds a node with given value at the specified position in the list: @@ -166,6 +266,52 @@ list.addByIndex('x', 2); +It works with negative index too: + +```js +list.addTail('a'); +list.addTail('b'); +list.addTail('c'); + +// "a" <-> "b" <-> "c" + +list.addByIndex('x', -1); + +// "a" <-> "b" <-> "x" <-> "c" +``` + + + +#### addManyByIndex(values: T\[\], position: number): ListNode\\[\] + +Adds multiple nodes with given values at the specified position in the list: + +```js +list.addManyTail(['a', 'b', 'c']); + +// "a" <-> "b" <-> "c" + +list.addManyByIndex(['x', 'y'], 2); + +// "a" <-> "b" <-> "x" <-> "y" <-> "c" +``` + + + +It works with negative index too: + +```js +list.addManyTail(['a', 'b', 'c']); + +// "a" <-> "b" <-> "c" + +list.addManyByIndex(['x', 'y'], -1); + +// "a" <-> "b" <-> "x" <-> "y" <-> "c" +``` + + + #### add(value: T).head(): ListNode\ Adds a node with given value as the first node in list: @@ -314,10 +460,172 @@ list.add('x').byIndex(2); +It works with negative index too: + +```js +list.add('a').tail(); +list.add('b').tail(); +list.add('c').tail(); + +// "a" <-> "b" <-> "c" + +list.add('x').byIndex(-1); + +// "a" <-> "b" <-> "x" <-> "c" +``` + + + > This is an alternative API for `addByIndex`. +#### addMany(values: T\[\]).head(): ListNode\\[\] + +Adds multiple nodes with given values as the first nodes in list: + +```js +list.addMany(['a', 'b', 'c']).head(); + +// "a" <-> "b" <-> "c" + +list.addMany(['x', 'y', 'z']).head(); + +// "x" <-> "y" <-> "z" <-> "a" <-> "b" <-> "c" +``` + + + +> This is an alternative API for `addManyHead`. + + + +#### addMany(values: T\[\]).tail(): ListNode\\[\] + +Adds multiple nodes with given values as the last nodes in list: + +```js +list.addMany(['a', 'b', 'c']).tail(); + +// "a" <-> "b" <-> "c" + +list.addMany(['x', 'y', 'z']).tail(); + +// "a" <-> "b" <-> "c" <-> "x" <-> "y" <-> "z" +``` + + + +> This is an alternative API for `addManyTail`. + + + +#### addMany(values: T\[\]).after(previousValue: T, compareFn = compare): ListNode\\[\] + +Adds multiple nodes with given values after the first node that has the previous value: + +```js +list.addMany(['a', 'b', 'b', 'c']).tail(); + +// "a" <-> "b" <-> "b" <-> "c" + +list.addMany(['x', 'y']).after('b'); + +// "a" <-> "b" <-> "x" <-> "y" <-> "b" <-> "c" +``` + + + +You may pass a custom compare function to detect the searched value: + +```js +list.addMany([{ x: 1 }, { x: 2 }, { x: 3 }]).tail(); + +// {"x":1} <-> {"x":2} <-> {"x":3} + +list.addMany([{ x: 4 }, { x: 5 }]).after({ x: 2 }, (v1, v2) => v1.x === v2.x); + +// {"x":1} <-> {"x":2} <-> {"x":4} <-> {"x":5} <-> {"x":3} +``` + + + +> This is an alternative API for `addManyAfter`. +> +> The default compare function checks deep equality, so you will rarely need to pass that parameter. + + + +#### addMany(values: T\[\]).before(nextValue: T, compareFn = compare): ListNode\\[\] + +Adds multiple nodes with given values before the first node that has the next value: + +```js +list.addMany(['a', 'b', 'b', 'c']).tail(); + +// "a" <-> "b" <-> "b" <-> "c" + +list.addMany(['x', 'y']).before('b'); + +// "a" <-> "x" <-> "y" <-> "b" <-> "b" <-> "c" +``` + + + +You may pass a custom compare function to detect the searched value: + +```js +list.addMany([{ x: 1 }, { x: 2 }, { x: 3 }]).tail(); + +// {"x":1} <-> {"x":2} <-> {"x":3} + +list.addMany([{ x: 4 }, { x: 5 }]).before({ x: 2 }, (v1, v2) => v1.x === v2.x); + +// {"x":1} <-> {"x":4} <-> {"x":5} <-> {"x":2} <-> {"x":3} +``` + + + +> This is an alternative API for `addManyBefore`. +> +> The default compare function checks deep equality, so you will rarely need to pass that parameter. + + + +#### addMany(values: T\[\]).byIndex(position: number): ListNode\\[\] + +Adds multiple nodes with given values at the specified position in the list: + +```js +list.addMany(['a', 'b', 'c']).tail(); + +// "a" <-> "b" <-> "c" + +list.addMany(['x', 'y']).byIndex(2); + +// "a" <-> "b" <-> "x" <-> "y" <-> "c" +``` + + + +It works with negative index too: + +```js +list.addMany(['a', 'b', 'c']).tail(); + +// "a" <-> "b" <-> "c" + +list.addMany(['x', 'y']).byIndex(-1); + +// "a" <-> "b" <-> "x" <-> "y" <-> "c" +``` + + + +> This is an alternative API for `addManyByIndex`. + + + ### How to Remove Nodes There are a few methods to remove nodes from a linked list and all of them are separately available as well as revealed from a `drop` method. @@ -329,9 +637,7 @@ There are a few methods to remove nodes from a linked list and all of them are s Removes the first node from the list: ```js -list.addTail('a'); -list.addTail('b'); -list.addTail('c'); +list.addMany(['a', 'b', 'c']).tail(); // "a" <-> "b" <-> "c" @@ -342,14 +648,28 @@ list.dropHead(); +#### dropManyHead(count: number): ListNode\\[\] + +Removes the first nodes from the list based on given count: + +```js +list.addMany(['a', 'b', 'c']).tail(); + +// "a" <-> "b" <-> "c" + +list.dropManyHead(2); + +// "c" +``` + + + #### dropTail(): ListNode\ | undefined Removes the last node from the list: ```js -list.addTail('a'); -list.addTail('b'); -list.addTail('c'); +list.addMany(['a', 'b', 'c']).tail(); // "a" <-> "b" <-> "c" @@ -360,14 +680,28 @@ list.dropTail(); +#### dropManyTail(count: number): ListNode\\[\] + +Removes the last nodes from the list based on given count: + +```js +list.addMany(['a', 'b', 'c']).tail(); + +// "a" <-> "b" <-> "c" + +list.dropManyTail(2); + +// "a" +``` + + + #### dropByIndex(position: number): ListNode\ | undefined Removes the node with the specified position from the list: ```js -list.addTail('a'); -list.addTail('b'); -list.addTail('c'); +list.addMany(['a', 'b', 'c']).tail(); // "a" <-> "b" <-> "c" @@ -378,16 +712,56 @@ list.dropByIndex(1); +It works with negative index too: + +```js +list.addMany(['a', 'b', 'c']).tail(); + +// "a" <-> "b" <-> "c" + +list.dropByIndex(-2); + +// "a" <-> "c" +``` + + + +#### dropManyByIndex(count: number, position: number): ListNode\\[\] + +Removes the nodes starting from the specified position from the list based on given count: + +```js +list.addMany(['a', 'b', 'c', 'd']).tail(); + +// "a" <-> "b" <-> "c" <-> "d + +list.dropManyByIndex(2, 1); + +// "a" <-> "d" +``` + + + +It works with negative index too: + +```js +list.addMany(['a', 'b', 'c', 'd']).tail(); + +// "a" <-> "b" <-> "c" <-> "d + +list.dropManyByIndex(2, -2); + +// "a" <-> "d" +``` + + + #### dropByValue(value: T, compareFn = compare): ListNode\ | undefined Removes the first node with given value from the list: ```js -list.addTail('a'); -list.addTail('x'); -list.addTail('b'); -list.addTail('x'); -list.addTail('c'); +list.addMany(['a', 'x', 'b', 'x', 'c']).tail(); // "a" <-> "x" <-> "b" <-> "x" <-> "c" @@ -401,11 +775,7 @@ list.dropByValue('x'); You may pass a custom compare function to detect the searched value: ```js -list.addTail({ x: 1 }); -list.addTail({ x: 0 }); -list.addTail({ x: 2 }); -list.addTail({ x: 0 }); -list.addTail({ x: 3 }); +list.addMany([{ x: 1 }, { x: 0 }, { x: 2 }, { x: 0 }, { x: 3 }]).tail(); // {"x":1} <-> {"x":0} <-> {"x":2} <-> {"x":0} <-> {"x":3} @@ -425,11 +795,7 @@ list.dropByValue({ x: 0 }, (v1, v2) => v1.x === v2.x); Removes all nodes with given value from the list: ```js -list.addTail('a'); -list.addTail('x'); -list.addTail('b'); -list.addTail('x'); -list.addTail('c'); +list.addMany(['a', 'x', 'b', 'x', 'c']).tail(); // "a" <-> "x" <-> "b" <-> "x" <-> "c" @@ -443,11 +809,7 @@ list.dropByValueAll('x'); You may pass a custom compare function to detect the searched value: ```js -list.addTail({ x: 1 }); -list.addTail({ x: 0 }); -list.addTail({ x: 2 }); -list.addTail({ x: 0 }); -list.addTail({ x: 3 }); +list.addMany([{ x: 1 }, { x: 0 }, { x: 2 }, { x: 0 }, { x: 3 }]).tail(); // {"x":1} <-> {"x":0} <-> {"x":2} <-> {"x":0} <-> {"x":3} @@ -467,9 +829,7 @@ list.dropByValue({ x: 0 }, (v1, v2) => v1.x === v2.x); Removes the first node in list: ```js -list.add('a').tail(); -list.add('b').tail(); -list.add('c').tail(); +list.addMany(['a', 'b', 'c']).tail(); // "a" <-> "b" <-> "c" @@ -489,9 +849,7 @@ list.drop().head(); Removes the last node in list: ```js -list.add('a').tail(); -list.add('b').tail(); -list.add('c').tail(); +list.addMany(['a', 'b', 'c']).tail(); // "a" <-> "b" <-> "c" @@ -511,9 +869,7 @@ list.drop().tail(); Removes the node with the specified position from the list: ```js -list.add('a').tail(); -list.add('b').tail(); -list.add('c').tail(); +list.addMany(['a', 'b', 'c']).tail(); // "a" <-> "b" <-> "c" @@ -524,6 +880,20 @@ list.drop().byIndex(1); +It works with negative index too: + +```js +list.addMany(['a', 'b', 'c']).tail(); + +// "a" <-> "b" <-> "c" + +list.drop().byIndex(-2); + +// "a" <-> "c" +``` + + + > This is an alternative API for `dropByIndex`. @@ -533,11 +903,7 @@ list.drop().byIndex(1); Removes the first node with given value from the list: ```js -list.add('a').tail(); -list.add('x').tail(); -list.add('b').tail(); -list.add('x').tail(); -list.add('c').tail(); +list.addMany(['a', 'x', 'b', 'x', 'c']).tail(); // "a" <-> "x" <-> "b" <-> "x" <-> "c" @@ -551,11 +917,7 @@ list.drop().byValue('x'); You may pass a custom compare function to detect the searched value: ```js -list.add({ x: 1 }).tail(); -list.add({ x: 0 }).tail(); -list.add({ x: 2 }).tail(); -list.add({ x: 0 }).tail(); -list.add({ x: 3 }).tail(); +list.addMany([{ x: 1 }, { x: 0 }, { x: 2 }, { x: 0 }, { x: 3 }]).tail(); // {"x":1} <-> {"x":0} <-> {"x":2} <-> {"x":0} <-> {"x":3} @@ -577,11 +939,7 @@ list.drop().byValue({ x: 0 }, (v1, v2) => v1.x === v2.x); Removes all nodes with given value from the list: ```js -list.add('a').tail(); -list.add('x').tail(); -list.add('b').tail(); -list.add('x').tail(); -list.add('c').tail(); +list.addMany(['a', 'x', 'b', 'x', 'c']).tail(); // "a" <-> "x" <-> "b" <-> "x" <-> "c" @@ -595,11 +953,7 @@ list.drop().byValueAll('x'); You may pass a custom compare function to detect the searched value: ```js -list.add({ x: 1 }).tail(); -list.add({ x: 0 }).tail(); -list.add({ x: 2 }).tail(); -list.add({ x: 0 }).tail(); -list.add({ x: 3 }).tail(); +list.addMany([{ x: 1 }, { x: 0 }, { x: 2 }, { x: 0 }, { x: 3 }]).tail(); // {"x":1} <-> {"x":0} <-> {"x":2} <-> {"x":0} <-> {"x":3} @@ -616,6 +970,80 @@ list.drop().byValueAll({ x: 0 }, (v1, v2) => v1.x === v2.x); +#### dropMany(count: number).head(): ListNode\\[\] + +Removes the first nodes from the list based on given count: + +```js +list.addMany(['a', 'b', 'c']).tail(); + +// "a" <-> "b" <-> "c" + +list.dropMany(2).head(); + +// "c" +``` + + + +> This is an alternative API for `dropManyHead`. + + + +#### dropMany(count: number).tail(): ListNode\\[\] + +Removes the last nodes from the list based on given count: + +```js +list.addMany(['a', 'b', 'c']).tail(); + +// "a" <-> "b" <-> "c" + +list.dropMany(2).tail(); + +// "a" +``` + + + +> This is an alternative API for `dropManyTail`. + + + +#### dropMany(count: number).byIndex(position: number): ListNode\\[\] + +Removes the nodes starting from the specified position from the list based on given count: + +```js +list.addMany(['a', 'b', 'c', 'd']).tail(); + +// "a" <-> "b" <-> "c" <-> "d + +list.dropMany(2).byIndex(1); + +// "a" <-> "d" +``` + + + +It works with negative index too: + +```js +list.addMany(['a', 'b', 'c', 'd']).tail(); + +// "a" <-> "b" <-> "c" <-> "d + +list.dropMany(2).byIndex(-2); + +// "a" <-> "d" +``` + + + +> This is an alternative API for `dropManyByIndex`. + + + ### How to Find Nodes There are a few methods to find specific nodes in a linked list. @@ -627,10 +1055,7 @@ There are a few methods to find specific nodes in a linked list. Finds the first node from the list that matches the given predicate: ```js -list.addTail('a'); -list.addTail('b'); -list.addTail('b'); -list.addTail('c'); +list.addTailMany(['a', 'b', 'b', 'c']); // "a" <-> "b" <-> "b" <-> "c" @@ -650,10 +1075,7 @@ found.next.value === "b" Finds the position of the first node from the list that matches the given predicate: ```js -list.addTail('a'); -list.addTail('b'); -list.addTail('b'); -list.addTail('c'); +list.addTailMany(['a', 'b', 'b', 'c']); // "a" <-> "b" <-> "b" <-> "c" @@ -677,9 +1099,7 @@ i3 === -1 Finds and returns the node with specific position in the list: ```js -list.addTail('a'); -list.addTail('b'); -list.addTail('c'); +list.addTailMany(['a', 'b', 'c']); // "a" <-> "b" <-> "c" @@ -699,10 +1119,7 @@ found.next.value === "c" Finds the position of the first node from the list that has the given value: ```js -list.addTail('a'); -list.addTail('b'); -list.addTail('b'); -list.addTail('c'); +list.addTailMany(['a', 'b', 'b', 'c']); // "a" <-> "b" <-> "b" <-> "c" @@ -724,11 +1141,7 @@ i3 === -1 You may pass a custom compare function to detect the searched value: ```js -list.addTail({ x: 1 }); -list.addTail({ x: 0 }); -list.addTail({ x: 2 }); -list.addTail({ x: 0 }); -list.addTail({ x: 3 }); +list.addTailMany([{ x: 1 }, { x: 0 }, { x: 2 }, { x: 0 }, { x: 3 }]); // {"x":1} <-> {"x":0} <-> {"x":2} <-> {"x":0} <-> {"x":3} @@ -764,9 +1177,7 @@ There are a few ways to iterate over or display a linked list. Runs a callback function on all nodes in a linked list from head to tail: ```js -list.addTail('a'); -list.addTail('b'); -list.addTail('c'); +list.addTailMany(['a', 'b', 'c']); // "a" <-> "b" <-> "c" @@ -784,9 +1195,7 @@ list.forEach((node, index) => console.log(node.value + index)); A linked list is iterable. In other words, you may use methods like `for...of` on it. ```js -list.addTail('a'); -list.addTail('b'); -list.addTail('c'); +list.addTailMany(['a', 'b', 'c']); // "a" <-> "b" <-> "c" @@ -801,14 +1210,12 @@ for(const node of list) { -#### toArray(): T[] +#### toArray(): T\[\] -Converts a linked list to an array: +Converts a linked list to an array of values: ```js -list.addTail('a'); -list.addTail('b'); -list.addTail('c'); +list.addTailMany(['a', 'b', 'c']); // "a" <-> "b" <-> "c" @@ -821,15 +1228,32 @@ arr === ['a', 'b', 'c'] +#### toNodeArray(): T\[\] + +Converts a linked list to an array of nodes: + +```js +list.addTailMany(['a', 'b', 'c']); + +// "a" <-> "b" <-> "c" + +const arr = list.toNodeArray(); + +/* +arr[0].value === 'a' +arr[1].value === 'a' +arr[2].value === 'a' +*/ +``` + + + #### toString(): string Converts a linked list to a string representation of nodes and their relations: ```js -list.addTail('a'); -list.addTail(2); -list.addTail('c'); -list.addTail({ k: 4, v: 'd' }); +list.addTailMany(['a', 2, 'c', { k: 4, v: 'd' }]); // "a" <-> 2 <-> "c" <-> {"k":4,"v":"d"} @@ -842,3 +1266,19 @@ str === '"a" <-> 2 <-> "c" <-> {"k":4,"v":"d"}' +You may pass a custom mapper function to map values before stringifying them: + +```js +list.addMany([{ x: 1 }, { x: 2 }, { x: 3 }, { x: 4 }, { x: 5 }]).tail(); + +// {"x":1} <-> {"x":2} <-> {"x":3} <-> {"x":4} <-> {"x":5} + +const str = list.toString(value => value.x); + +/* +str === '1 <-> 2 <-> 3 <-> 4 <-> 5' +*/ +``` + + + From c4c4cfadccc27dadac817b9d0e96a0df4f6c0cc6 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Fri, 27 Mar 2020 07:29:52 +0300 Subject: [PATCH 009/151] fix: fix lint error --- npm/ng-packs/packages/core/src/lib/states/config.state.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/npm/ng-packs/packages/core/src/lib/states/config.state.ts b/npm/ng-packs/packages/core/src/lib/states/config.state.ts index f8f4d069f6..74e9ee8cd0 100644 --- a/npm/ng-packs/packages/core/src/lib/states/config.state.ts +++ b/npm/ng-packs/packages/core/src/lib/states/config.state.ts @@ -301,7 +301,7 @@ export class ConfigState { } @Action(SetEnvironment) - setEnvironment({ patchState }: StateContext, { environment }:SetEnvironment) { + setEnvironment({ patchState }: StateContext, { environment }: SetEnvironment) { return patchState({ environment, }); From 0a17d721b96d39e8f37819afa4a343459cf1c37d Mon Sep 17 00:00:00 2001 From: Mehmet Erim <34455572+mehmet-erim@users.noreply.github.com> Date: Fri, 27 Mar 2020 07:53:39 +0300 Subject: [PATCH 010/151] Update Service-Proxies.md --- docs/en/UI/Angular/Service-Proxies.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/en/UI/Angular/Service-Proxies.md b/docs/en/UI/Angular/Service-Proxies.md index b1cd9ad500..97b43b7513 100644 --- a/docs/en/UI/Angular/Service-Proxies.md +++ b/docs/en/UI/Angular/Service-Proxies.md @@ -25,9 +25,9 @@ The files generated with the `--module all` option like below: ### Services -Each generated service matches a back-end controller. The services methods call back-end APIs via [RestService](./HTTP-Requests.md#restservice). +Each generated service matches a back-end controller. The services methods call back-end APIs via [RestService](./Http-Requests.md#restservice). -A variable named `apiName` (available as of v2.4) is defined in each service. `apiName` matches the module's RemoteServiceName. This variable passes to the `RestService` as a parameter at each request. If there is no microservice API defined in the environment, `RestService` uses the default. See [getting a specific API endpoint from application config](HTTP-Requests#how-to-get-a-specific-api-endpoint-from-application-config) +A variable named `apiName` (available as of v2.4) is defined in each service. `apiName` matches the module's RemoteServiceName. This variable passes to the `RestService` as a parameter at each request. If there is no microservice API defined in the environment, `RestService` uses the default. See [getting a specific API endpoint from application config](./Http-Requests.md#how-to-get-a-specific-api-endpoint-from-application-config) The `providedIn` property of the services is defined as `'root'`. Therefore no need to add a service as a provider to a module. You can use a service by injecting it into a constructor as shown below: @@ -64,4 +64,4 @@ Initial values ​​can optionally be passed to each class constructor. ## What's Next? -* [Http Requests](./Http-Requests.md) \ No newline at end of file +* [HTTP Requests](./Http-Requests.md) From aab32ad8c5dc6c968f42f4e6ee57953f68eec5a8 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Fri, 27 Mar 2020 09:10:45 +0300 Subject: [PATCH 011/151] chore: set dev-app as default project --- npm/ng-packs/angular.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/npm/ng-packs/angular.json b/npm/ng-packs/angular.json index d0289505fe..af185688b2 100644 --- a/npm/ng-packs/angular.json +++ b/npm/ng-packs/angular.json @@ -526,5 +526,5 @@ } } }, - "defaultProject": "core" + "defaultProject": "dev-app" } From 83645730b9bc38eae238861c9432acb05518189f Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Fri, 27 Mar 2020 09:16:45 +0300 Subject: [PATCH 012/151] refactor: deprecate the requirements obj --- .../apps/dev-app/src/app/app.module.ts | 3 -- .../packages/core/src/lib/models/common.ts | 6 ++- templates/app/angular/src/app/app.module.ts | 6 +-- .../module/angular/src/app/app.module.ts | 46 +++++++++---------- 4 files changed, 27 insertions(+), 34 deletions(-) diff --git a/npm/ng-packs/apps/dev-app/src/app/app.module.ts b/npm/ng-packs/apps/dev-app/src/app/app.module.ts index f1324c233a..64f8150f01 100644 --- a/npm/ng-packs/apps/dev-app/src/app/app.module.ts +++ b/npm/ng-packs/apps/dev-app/src/app/app.module.ts @@ -21,9 +21,6 @@ const LOGGERS = [NgxsLoggerPluginModule.forRoot({ disabled: false })]; imports: [ CoreModule.forRoot({ environment, - requirements: { - layouts: LAYOUTS, - }, }), ThemeSharedModule.forRoot(), AccountConfigModule.forRoot({ redirectUrl: '/' }), diff --git a/npm/ng-packs/packages/core/src/lib/models/common.ts b/npm/ng-packs/packages/core/src/lib/models/common.ts index 8b4fb76cb0..79792a1b61 100644 --- a/npm/ng-packs/packages/core/src/lib/models/common.ts +++ b/npm/ng-packs/packages/core/src/lib/models/common.ts @@ -6,7 +6,11 @@ import { Subject } from 'rxjs'; export namespace ABP { export interface Root { environment: Partial; - requirements: Config.Requirements; + /** + * + * @deprecated To be deleted in v3.0 + */ + requirements?: Config.Requirements; } export type PagedResponse = { diff --git a/templates/app/angular/src/app/app.module.ts b/templates/app/angular/src/app/app.module.ts index 5df354fb38..928dff5172 100644 --- a/templates/app/angular/src/app/app.module.ts +++ b/templates/app/angular/src/app/app.module.ts @@ -3,7 +3,6 @@ import { CoreModule } from '@abp/ng.core'; import { IdentityConfigModule } from '@abp/ng.identity.config'; import { SettingManagementConfigModule } from '@abp/ng.setting-management.config'; import { TenantManagementConfigModule } from '@abp/ng.tenant-management.config'; -import { LAYOUTS } from '@abp/ng.theme.basic'; import { ThemeSharedModule } from '@abp/ng.theme.shared'; import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; @@ -20,10 +19,7 @@ const LOGGERS = [NgxsLoggerPluginModule.forRoot({ disabled: false })]; @NgModule({ imports: [ CoreModule.forRoot({ - environment, - requirements: { - layouts: LAYOUTS - } + environment }), ThemeSharedModule.forRoot(), AccountConfigModule.forRoot({ redirectUrl: '/' }), diff --git a/templates/module/angular/src/app/app.module.ts b/templates/module/angular/src/app/app.module.ts index c0fef36c9a..2705a3318b 100644 --- a/templates/module/angular/src/app/app.module.ts +++ b/templates/module/angular/src/app/app.module.ts @@ -1,21 +1,20 @@ -import { AccountConfigModule } from '@abp/ng.account.config'; -import { CoreModule } from '@abp/ng.core'; -import { IdentityConfigModule } from '@abp/ng.identity.config'; -import { SettingManagementConfigModule } from '@abp/ng.setting-management.config'; -import { TenantManagementConfigModule } from '@abp/ng.tenant-management.config'; -import { LAYOUTS } from '@abp/ng.theme.basic'; -import { ThemeSharedModule } from '@abp/ng.theme.shared'; -import { NgModule } from '@angular/core'; -import { BrowserModule } from '@angular/platform-browser'; -import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; -import { NgxsLoggerPluginModule } from '@ngxs/logger-plugin'; -import { NgxsModule } from '@ngxs/store'; -import { OAuthModule } from 'angular-oauth2-oidc'; -import { environment } from '../environments/environment'; -import { AppRoutingModule } from './app-routing.module'; -import { AppComponent } from './app.component'; -import { SharedModule } from './shared/shared.module'; -import { MyProjectNameConfigModule } from '../../projects/my-project-name-config/src/public-api'; +import { AccountConfigModule } from "@abp/ng.account.config"; +import { CoreModule } from "@abp/ng.core"; +import { IdentityConfigModule } from "@abp/ng.identity.config"; +import { SettingManagementConfigModule } from "@abp/ng.setting-management.config"; +import { TenantManagementConfigModule } from "@abp/ng.tenant-management.config"; +import { ThemeSharedModule } from "@abp/ng.theme.shared"; +import { NgModule } from "@angular/core"; +import { BrowserModule } from "@angular/platform-browser"; +import { BrowserAnimationsModule } from "@angular/platform-browser/animations"; +import { NgxsLoggerPluginModule } from "@ngxs/logger-plugin"; +import { NgxsModule } from "@ngxs/store"; +import { OAuthModule } from "angular-oauth2-oidc"; +import { environment } from "../environments/environment"; +import { AppRoutingModule } from "./app-routing.module"; +import { AppComponent } from "./app.component"; +import { SharedModule } from "./shared/shared.module"; +import { MyProjectNameConfigModule } from "../../projects/my-project-name-config/src/public-api"; const LOGGERS = [NgxsLoggerPluginModule.forRoot({ disabled: false })]; @@ -24,14 +23,11 @@ const LOGGERS = [NgxsLoggerPluginModule.forRoot({ disabled: false })]; imports: [ ThemeSharedModule.forRoot(), CoreModule.forRoot({ - environment, - requirements: { - layouts: LAYOUTS, - }, + environment }), OAuthModule.forRoot(), NgxsModule.forRoot([]), - AccountConfigModule.forRoot({ redirectUrl: '/' }), + AccountConfigModule.forRoot({ redirectUrl: "/" }), IdentityConfigModule, TenantManagementConfigModule, SettingManagementConfigModule, @@ -41,8 +37,8 @@ const LOGGERS = [NgxsLoggerPluginModule.forRoot({ disabled: false })]; AppRoutingModule, SharedModule, - ...(environment.production ? [] : LOGGERS), + ...(environment.production ? [] : LOGGERS) ], - bootstrap: [AppComponent], + bootstrap: [AppComponent] }) export class AppModule {} From 97c3a6fce04210fdadfb526ce83c4e7ab7e1a59d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0smail=20=C3=87A=C4=9EDA=C5=9E?= Date: Fri, 27 Mar 2020 10:02:49 +0300 Subject: [PATCH 013/151] added missing comma to docs-nav.json --- docs/en/docs-nav.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/docs-nav.json b/docs/en/docs-nav.json index 71641bf2a8..d46e16bfe5 100644 --- a/docs/en/docs-nav.json +++ b/docs/en/docs-nav.json @@ -5,7 +5,7 @@ "items": [ { "text": "From Startup Templates", - "path": "Getting-Started-With-Startup-Templates.md" + "path": "Getting-Started-With-Startup-Templates.md", "items": [ { "text": "Application with MVC (Razor Pages) UI", From 4ad19ebf84a7af0d68dcd9968bf13e510c6b77ee Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Fri, 27 Mar 2020 10:21:56 +0300 Subject: [PATCH 014/151] feat(theme-basic): add layouts to replaceable components state --- .../src/lib/services/initial.service.ts | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/npm/ng-packs/packages/theme-basic/src/lib/services/initial.service.ts b/npm/ng-packs/packages/theme-basic/src/lib/services/initial.service.ts index 33c7c18770..21fb1756bc 100644 --- a/npm/ng-packs/packages/theme-basic/src/lib/services/initial.service.ts +++ b/npm/ng-packs/packages/theme-basic/src/lib/services/initial.service.ts @@ -1,12 +1,29 @@ +import { LazyLoadService, AddReplaceableComponent } from '@abp/ng.core'; import { Injectable } from '@angular/core'; -import { Router } from '@angular/router'; -import { LazyLoadService } from '@abp/ng.core'; +import { Store } from '@ngxs/store'; import styles from '../constants/styles'; +import { ApplicationLayoutComponent } from '../components/application-layout/application-layout.component'; +import { AccountLayoutComponent } from '../components/account-layout/account-layout.component'; +import { EmptyLayoutComponent } from '../components/empty-layout/empty-layout.component'; @Injectable({ providedIn: 'root' }) export class InitialService { - constructor(private lazyLoadService: LazyLoadService) { + constructor(private lazyLoadService: LazyLoadService, private store: Store) { this.appendStyle().subscribe(); + this.store.dispatch([ + new AddReplaceableComponent({ + key: 'Theme.ApplicationLayoutComponent', + component: ApplicationLayoutComponent, + }), + new AddReplaceableComponent({ + key: 'Theme.AccountLayoutComponent', + component: AccountLayoutComponent, + }), + new AddReplaceableComponent({ + key: 'Theme.EmptyLayoutComponent', + component: EmptyLayoutComponent, + }), + ]); } appendStyle() { From 857ee6b9ef82376c42229c613764feaee7896a95 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Fri, 27 Mar 2020 10:22:45 +0300 Subject: [PATCH 015/151] feat(core): get layouts from store in dynamic-layout.component --- .../components/dynamic-layout.component.ts | 49 +++++---- .../tests/dynamic-layout.component.spec.ts | 102 +++++++++++------- 2 files changed, 93 insertions(+), 58 deletions(-) diff --git a/npm/ng-packs/packages/core/src/lib/components/dynamic-layout.component.ts b/npm/ng-packs/packages/core/src/lib/components/dynamic-layout.component.ts index 7fc1826efe..fc3926a1ea 100644 --- a/npm/ng-packs/packages/core/src/lib/components/dynamic-layout.component.ts +++ b/npm/ng-packs/packages/core/src/lib/components/dynamic-layout.component.ts @@ -1,13 +1,15 @@ import { Component, Input, OnDestroy, Type, Injector } from '@angular/core'; import { ActivatedRoute, NavigationEnd, Router, UrlSegment } from '@angular/router'; import { Select, Store } from '@ngxs/store'; -import { Observable } from 'rxjs'; +import { Observable, combineLatest } from 'rxjs'; import snq from 'snq'; import { eLayoutType } from '../enums/common'; import { Config } from '../models/config'; import { ABP } from '../models/common'; import { ConfigState } from '../states/config.state'; import { takeUntilDestroy } from '../utils/rxjs-utils'; +import { ReplaceableComponentsState } from '../states/replaceable-components.state'; +import { ReplaceableComponents } from '../models/replaceable-components'; @Component({ selector: 'abp-dynamic-layout', @@ -20,24 +22,24 @@ import { takeUntilDestroy } from '../utils/rxjs-utils'; `, }) export class DynamicLayoutComponent implements OnDestroy { - @Select(ConfigState.getOne('requirements')) requirements$: Observable; + @Select(ReplaceableComponentsState.getComponent('Theme.ApplicationLayoutComponent')) + applicationLayout$: Observable; + + @Select(ReplaceableComponentsState.getComponent('Theme.AccountLayoutComponent')) + accountLayout$: Observable; + + @Select(ReplaceableComponentsState.getComponent('Theme.EmptyLayoutComponent')) + emptyLayout$: Observable; layout: Type; + layouts = {} as { [key in eLayoutType]: Type }; + + expectedLayout: eLayoutType = eLayoutType.empty; + constructor(private router: Router, private route: ActivatedRoute, private store: Store) { - const { - requirements: { layouts }, - routes, - } = this.store.selectSnapshot(ConfigState.getAll); - - if ((this.route.snapshot.data || {}).layout) { - this.layout = layouts - .filter(l => !!l) - .find( - (l: any) => - snq(() => l.type.toLowerCase().indexOf(this.route.snapshot.data.layout), -1) > -1, - ); - } + this.listenToLayouts(); + const { routes } = this.store.selectSnapshot(ConfigState.getAll); router.events.pipe(takeUntilDestroy(this)).subscribe(event => { if (event instanceof NavigationEnd) { @@ -45,16 +47,25 @@ export class DynamicLayoutComponent implements OnDestroy { { path: router.url.replace('/', '') }, ] as any); - const layout = (this.route.snapshot.data || {}).layout || findLayout(segments, routes); + this.expectedLayout = + (this.route.snapshot.data || {}).layout || findLayout(segments, routes); - this.layout = layouts - .filter(l => !!l) - .find((l: any) => snq(() => l.type.toLowerCase().indexOf(layout), -1) > -1); + this.layout = this.layouts[this.expectedLayout]; } }); } ngOnDestroy() {} + + listenToLayouts() { + combineLatest(this.applicationLayout$, this.accountLayout$, this.emptyLayout$) + .pipe(takeUntilDestroy(this)) + .subscribe(([application, account, empty]) => { + this.layouts.application = application.component; + this.layouts.account = account.component; + this.layouts.empty = empty.component; + }); + } } function findLayout(segments: UrlSegment[], routes: ABP.FullRoute[]): eLayoutType { diff --git a/npm/ng-packs/packages/core/src/lib/tests/dynamic-layout.component.spec.ts b/npm/ng-packs/packages/core/src/lib/tests/dynamic-layout.component.spec.ts index 54a602b84a..0a123b6a4f 100644 --- a/npm/ng-packs/packages/core/src/lib/tests/dynamic-layout.component.spec.ts +++ b/npm/ng-packs/packages/core/src/lib/tests/dynamic-layout.component.spec.ts @@ -1,36 +1,36 @@ import { Component, NgModule } from '@angular/core'; import { ActivatedRoute, RouterModule } from '@angular/router'; -import { createRoutingFactory, SpectatorRouting, SpyObject } from '@ngneat/spectator/jest'; -import { Store } from '@ngxs/store'; +import { createRoutingFactory, SpectatorRouting } from '@ngneat/spectator/jest'; +import { NgxsModule, Store } from '@ngxs/store'; +import { DynamicLayoutComponent, RouterOutletComponent } from '../components'; import { eLayoutType } from '../enums'; import { ABP } from '../models'; -import { DynamicLayoutComponent, RouterOutletComponent } from '../components'; +import { ConfigState, ReplaceableComponentsState } from '../states'; +import { ApplicationConfigurationService } from '../services'; @Component({ selector: 'abp-layout-application', template: '', }) -class DummyApplicationLayoutComponent { - static type = eLayoutType.application; -} +class DummyApplicationLayoutComponent {} @Component({ selector: 'abp-layout-account', template: '', }) -class DummyAccountLayoutComponent { - static type = eLayoutType.account; -} +class DummyAccountLayoutComponent {} @Component({ selector: 'abp-layout-empty', template: '', }) -class DummyEmptyLayoutComponent { - static type = eLayoutType.empty; -} +class DummyEmptyLayoutComponent {} -const LAYOUTS = [DummyApplicationLayoutComponent, DummyAccountLayoutComponent, DummyEmptyLayoutComponent]; +const LAYOUTS = [ + DummyApplicationLayoutComponent, + DummyAccountLayoutComponent, + DummyEmptyLayoutComponent, +]; @NgModule({ imports: [RouterModule], @@ -47,13 +47,57 @@ class DummyComponent { constructor(public route: ActivatedRoute) {} } +const storeData = { + ConfigState: { + routes: [ + { + path: '', + wrapper: true, + children: [ + { + path: 'parentWithLayout', + layout: eLayoutType.application, + children: [ + { path: 'childWithoutLayout' }, + { path: 'childWithLayout', layout: eLayoutType.account }, + ], + }, + ], + }, + { path: 'withData', layout: eLayoutType.application }, + , + ] as ABP.FullRoute[], + environment: { application: {} }, + }, + ReplaceableComponentsState: { + replaceableComponents: [ + { + key: 'Theme.ApplicationLayoutComponent', + component: DummyApplicationLayoutComponent, + }, + { + key: 'Theme.AccountLayoutComponent', + component: DummyAccountLayoutComponent, + }, + { + key: 'Theme.EmptyLayoutComponent', + component: DummyEmptyLayoutComponent, + }, + ], + }, +}; + describe('DynamicLayoutComponent', () => { const createComponent = createRoutingFactory({ component: RouterOutletComponent, stubsEnabled: false, - mocks: [Store], declarations: [DummyComponent, DynamicLayoutComponent], - imports: [RouterModule, DummyLayoutModule], + mocks: [ApplicationConfigurationService], + imports: [ + RouterModule, + DummyLayoutModule, + NgxsModule.forRoot([ConfigState, ReplaceableComponentsState]), + ], routes: [ { path: '', component: RouterOutletComponent }, { @@ -100,33 +144,13 @@ describe('DynamicLayoutComponent', () => { }); let spectator: SpectatorRouting; - let store: SpyObject; - const mockStoreData = { - requirements: { layouts: LAYOUTS }, - routes: [ - { - path: '', - wrapper: true, - children: [ - { - path: 'parentWithLayout', - layout: eLayoutType.application, - children: [{ path: 'childWithoutLayout' }, { path: 'childWithLayout', layout: eLayoutType.account }], - }, - ], - }, - { path: 'withData', layout: eLayoutType.application }, - , - ] as ABP.FullRoute[], - environment: { application: {} }, - }; - let storeSpy: jest.SpyInstance; + let store: Store; beforeEach(async () => { spectator = createComponent(); store = spectator.get(Store); - storeSpy = jest.spyOn(store, 'selectSnapshot'); - storeSpy.mockReturnValue(mockStoreData); + + store.reset(storeData); }); it('should handle application layout from parent abp route and display it', async () => { @@ -159,7 +183,7 @@ describe('DynamicLayoutComponent', () => { }); it('should not display any layout when layouts are empty', async () => { - storeSpy.mockReturnValue({ ...mockStoreData, requirements: { layouts: [] } }); + store.reset({ ...storeData, ReplaceableComponentsState: {} }); spectator.detectChanges(); From 84890bb91958cc4666a23ef559c62757cb8c9442 Mon Sep 17 00:00:00 2001 From: Alper Ebicoglu Date: Fri, 27 Mar 2020 11:58:12 +0300 Subject: [PATCH 016/151] #closes 3381 --- .../Controllers/HomeController.cs | 7 + .../docs/app/VoloDocs.Web/Pages/Index.cshtml | 5 - .../app/VoloDocs.Web/Pages/Index.cshtml.cs | 29 - .../docs/app/VoloDocs.Web/package-lock.json | 2796 +++++++++++------ modules/docs/app/VoloDocs.Web/package.json | 2 +- .../Documents/DocumentAdminAppService.cs | 12 +- .../Volo/Docs/Documents/DocumentAppService.cs | 20 +- .../Volo/Docs/DocsDomainConsts.cs | 7 + .../Documents/FileSystemDocumentSource.cs | 15 +- .../GitHub/Documents/GithubDocumentSource.cs | 15 +- .../Extensions/NewtonsoftJsonExtensions.cs | 22 + .../ScribanDocumentSectionRenderer.cs | 109 +- .../src/Volo.Docs.Web/Volo.Docs.Web.csproj | 1 + 13 files changed, 2068 insertions(+), 972 deletions(-) delete mode 100644 modules/docs/app/VoloDocs.Web/Pages/Index.cshtml delete mode 100644 modules/docs/app/VoloDocs.Web/Pages/Index.cshtml.cs create mode 100644 modules/docs/src/Volo.Docs.Domain/Volo/Docs/DocsDomainConsts.cs create mode 100644 modules/docs/src/Volo.Docs.Domain/Volo/Extensions/NewtonsoftJsonExtensions.cs diff --git a/modules/docs/app/VoloDocs.Web/Controllers/HomeController.cs b/modules/docs/app/VoloDocs.Web/Controllers/HomeController.cs index 5594306229..17c6550502 100644 --- a/modules/docs/app/VoloDocs.Web/Controllers/HomeController.cs +++ b/modules/docs/app/VoloDocs.Web/Controllers/HomeController.cs @@ -6,7 +6,14 @@ namespace VoloDocs.Web.Controllers { public void Index() { + //if (!_urlUiOptions.RoutePrefix.IsNullOrWhiteSpace()) + //{ + // return Redirect("." + _urlUiOptions.RoutePrefix); + //} + //return Page(); + + //return Redirect("/en/abp/latest"); } } } diff --git a/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml b/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml deleted file mode 100644 index 0d75012326..0000000000 --- a/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml +++ /dev/null @@ -1,5 +0,0 @@ -@page -@model VoloDocs.Web.Pages.IndexModel -@{ -} - diff --git a/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml.cs b/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml.cs deleted file mode 100644 index b127db4b3f..0000000000 --- a/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.RazorPages; -using Microsoft.Extensions.Options; -using Volo.Docs; - -namespace VoloDocs.Web.Pages -{ - public class IndexModel : PageModel - { - private readonly DocsUiOptions _urlUiOptions; - - public IndexModel(IOptions urlOptions) - { - _urlUiOptions = urlOptions.Value; - } - - public IActionResult OnGet() - { - //TODO: Create HomeController & Index instead of Page. Otherwise, we have an empty Index.cshtml file. - if (!_urlUiOptions.RoutePrefix.IsNullOrWhiteSpace()) - { - return Redirect("." + _urlUiOptions.RoutePrefix); - } - - return Page(); - } - } -} \ No newline at end of file diff --git a/modules/docs/app/VoloDocs.Web/package-lock.json b/modules/docs/app/VoloDocs.Web/package-lock.json index a666d3cc7c..e764349469 100644 --- a/modules/docs/app/VoloDocs.Web/package-lock.json +++ b/modules/docs/app/VoloDocs.Web/package-lock.json @@ -5,247 +5,256 @@ "requires": true, "dependencies": { "@abp/anchor-js": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@abp/anchor-js/-/anchor-js-0.5.1.tgz", - "integrity": "sha512-9N/iPP9tDdq9lKRNFQuqRL+QYSv5fq789KgHHGG1/MqExJ6KTPcqUDHvQ53kz96pUgJA+Fyn3dpwgPqLVYI3Yg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@abp/anchor-js/-/anchor-js-1.1.1.tgz", + "integrity": "sha512-hHyYYJ09hhT5xeQJUsBN43yT+y49FKcigq4Wrx8448TrW7r2NJD5i3Xy3BGEstNSlfcQPTsmciQnbkcU2rX1HQ==", "requires": { - "@abp/core": "^0.4.9", - "anchor-js": "^4.1.1" + "@abp/core": "^1.1.1", + "anchor-js": "^4.2.2" } }, "@abp/aspnetcore.mvc.ui": { - "version": "0.4.9", - "resolved": "https://registry.npmjs.org/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-0.4.9.tgz", - "integrity": "sha512-AveMEi6WRQmD1tM9yVNLAe6ffcbtoL3ZGQKTPA95Q+dy5xBXVg4Y8jdhxawNPK64KYArhfrVkQDfa4mq3pW5Qw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-1.1.1.tgz", + "integrity": "sha512-wZbptVCSxZzEjkJx+/sWrH9Pikp9nOy7V8Htz+L+S7/qAzfXu5PRVV8ahddfAcDHRk30buRhdbJlCVdt6hkZ6g==", "requires": { - "ansi-colors": "^1.1.0", + "ansi-colors": "^4.1.1", "extend-object": "^1.0.0", - "gulp": "^3.9.1", - "merge-stream": "^1.0.1", + "gulp": "^4.0.2", + "merge-stream": "^2.0.0", "path": "^0.12.7", - "rimraf": "^2.6.2" + "rimraf": "^3.0.0" } }, "@abp/aspnetcore.mvc.ui.theme.basic": { - "version": "0.4.9", - "resolved": "https://registry.npmjs.org/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-0.4.9.tgz", - "integrity": "sha512-g3Zby8x8+vWw3oTJsSPasjm4tv7BG4270PEf7jK9w925+lIyKYHn6UxOcFbSU2pi9mJTnaF+Fk/rScIcdxwZZw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-1.1.1.tgz", + "integrity": "sha512-ooXtCM3TWN69RU7xs6avnzOQBXzsiHY5BEIogzSBialZC4uG5H56qrIr4MbsFNae+PQM23Mw2tnJ/Z7dutURCQ==", "requires": { - "@abp/aspnetcore.mvc.ui.theme.shared": "^0.4.9" + "@abp/aspnetcore.mvc.ui.theme.shared": "^1.1.1" } }, "@abp/aspnetcore.mvc.ui.theme.shared": { - "version": "0.4.9", - "resolved": "https://registry.npmjs.org/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-0.4.9.tgz", - "integrity": "sha512-Fe4UfQ215Pz2V6D5HUYhDJFeJWjKLcv2gsZfOheWLlOBgYh274pdnUIwceoZ4Btpa9aPECLG+LAH4dTbs8vjRg==", - "requires": { - "@abp/aspnetcore.mvc.ui": "^0.4.9", - "@abp/bootstrap": "^0.4.9", - "@abp/datatables.net-bs4": "^0.4.9", - "@abp/font-awesome": "^0.4.9", - "@abp/jquery-form": "^0.4.9", - "@abp/jquery-validation-unobtrusive": "^0.4.9", - "@abp/lodash": "^0.4.9", - "@abp/select2": "^0.4.9", - "@abp/sweetalert": "^0.4.9", - "@abp/timeago": "^0.4.9", - "@abp/toastr": "^0.4.9" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-1.1.1.tgz", + "integrity": "sha512-LilSyefzT1+rcTU7vbWxcO8TwBgGZIx6QbMUrDicSTH6LLJ9S5+yNaGNJbbZKDG6qx0BEoC1u8dE8KCUshwxoQ==", + "requires": { + "@abp/aspnetcore.mvc.ui": "^1.1.1", + "@abp/bootstrap": "^1.1.1", + "@abp/bootstrap-datepicker": "^1.1.1", + "@abp/datatables.net-bs4": "^1.1.1", + "@abp/font-awesome": "^1.1.1", + "@abp/jquery-form": "^1.1.1", + "@abp/jquery-validation-unobtrusive": "^1.1.1", + "@abp/lodash": "^1.1.1", + "@abp/luxon": "^1.1.1", + "@abp/malihu-custom-scrollbar-plugin": "^1.1.1", + "@abp/select2": "^1.1.1", + "@abp/sweetalert": "^1.1.1", + "@abp/timeago": "^1.1.1", + "@abp/toastr": "^1.1.1" } }, "@abp/bootstrap": { - "version": "0.4.9", - "resolved": "https://registry.npmjs.org/@abp/bootstrap/-/bootstrap-0.4.9.tgz", - "integrity": "sha512-A7lDHo43KnqjINo0xWECx/WzNQe3vqvE3GPv6uXq3KDi+gStQLAFBq3bVcVW/kSxiquDQ/tuCLRpE0qlhoobag==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@abp/bootstrap/-/bootstrap-1.1.1.tgz", + "integrity": "sha512-OIaGJaizhI8UNfy4bnw2xT2Z0QG7BJJrjxOPGepfd4jn/AUi/vFdOpJFWvu2P9PwSzRmn/LuSlr2WONDOdPVWQ==", + "requires": { + "@abp/core": "^1.1.1", + "bootstrap": "^4.3.1" + } + }, + "@abp/bootstrap-datepicker": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@abp/bootstrap-datepicker/-/bootstrap-datepicker-1.1.1.tgz", + "integrity": "sha512-RIQLSrKBu/cTAU2lFenSAoKcMp7wgF4e3nP4/iOu5ZtCgti5vUjMEcqEvBxtlwKTHMXsTG4GtNKqjTwjXMjONQ==", "requires": { - "@abp/core": "^0.4.9", - "bootstrap": "^4.1.1" + "bootstrap-datepicker": "^1.9.0" } }, "@abp/clipboard": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@abp/clipboard/-/clipboard-0.5.1.tgz", - "integrity": "sha512-efOPloVL0moRqGpAMA7DU5o+vzzu7ipGOFcG9nOfDD6uGY9AsOztFc71GwIFrtwADvJSiJHD6OfEIfR++dCT0w==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@abp/clipboard/-/clipboard-1.1.1.tgz", + "integrity": "sha512-O6b7VCAh2mxjkPhgUZYQBhXf0u+dWRECBOYN4KxYiKfk+2xL8X+34Ls7hVLbyuD+4xCcNirMZIG5CnS8auHC/A==", "requires": { - "@abp/core": "^0.4.9", + "@abp/core": "^1.1.1", "clipboard": "^2.0.4" } }, "@abp/core": { - "version": "0.4.9", - "resolved": "https://registry.npmjs.org/@abp/core/-/core-0.4.9.tgz", - "integrity": "sha512-JbibIPDz0w/C9YhexNagMD763qbZCclcHLVlTpKEZUcxzp6rZXwPR6ekh/PnvzD0R7wmHOh+bHl0hs5JSdy3oA==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@abp/core/-/core-1.1.1.tgz", + "integrity": "sha512-OvUG7xRvk8nSqwC1s45YPnTuhC2OWe1AVa1nnC6FVHMH/g1Je7UJwnbu47K7uNS+lDRJUIktNbufYKiwutEjRg==" }, "@abp/datatables.net": { - "version": "0.4.9", - "resolved": "https://registry.npmjs.org/@abp/datatables.net/-/datatables.net-0.4.9.tgz", - "integrity": "sha512-URimiGMFBusEMo9aAadLFCossbYyrN2R6+6YrQ+heqxdheCPmm2wupsXSFoUBHBhD0tzF4rY+OL//oOg3Wtg4g==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@abp/datatables.net/-/datatables.net-1.1.1.tgz", + "integrity": "sha512-y76IDBlgc0n1YgQqJ+9cfzXpLwr2arhdIfSmqX+qRXz6GfVNY7e3JijkFSgDKUzKGYo1HZMzgJmDmeNIRwMZsQ==", "requires": { - "@abp/core": "^0.4.9", - "datatables.net": "^1.10.16" + "@abp/core": "^1.1.1", + "datatables.net": "^1.10.20" } }, "@abp/datatables.net-bs4": { - "version": "0.4.9", - "resolved": "https://registry.npmjs.org/@abp/datatables.net-bs4/-/datatables.net-bs4-0.4.9.tgz", - "integrity": "sha512-Dsz0fy2haBz3dl2MLXWjW2bhDBzp1cpWXSXj8TEEzYazjhyoqBy6AiFlEnRCqO49KZD6Ps1cONSRxx4c4On9Lg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@abp/datatables.net-bs4/-/datatables.net-bs4-1.1.1.tgz", + "integrity": "sha512-t40xQIGBMLPZiSbcZHW3AwE8uk+xcl7OitBT1jym0XPKVtgJsHez3ynDE5v/PjHe+ColCG8lTRjRnNoXo5dzDw==", "requires": { - "@abp/datatables.net": "^0.4.9", - "datatables.net-bs4": "^1.10.16" + "@abp/datatables.net": "^1.1.1", + "datatables.net-bs4": "^1.10.20" } }, "@abp/docs": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@abp/docs/-/docs-0.5.1.tgz", - "integrity": "sha512-3pGYnxZxm2kYPfu2EwDF0QinsNTym2cWlYAo7mVUBuReTPMhwHYtgrE7AX3nCVv1iAo6ltW+mebonGt1s5yXzA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@abp/docs/-/docs-1.1.1.tgz", + "integrity": "sha512-z2Dk7EOhBdFo6BYbgccD91PIg37L2ehkgRT4RWf61dRyjPAQgPwwwyVSqApFmKveWPCzreHoTPKbnrU7EzAssw==", "requires": { - "@abp/anchor-js": "^0.5.1", - "@abp/clipboard": "^0.5.1", - "@abp/malihu-custom-scrollbar-plugin": "^0.5.1", - "@abp/popper.js": "^0.5.1", - "@abp/prismjs": "^0.5.1" + "@abp/anchor-js": "^1.1.1", + "@abp/clipboard": "^1.1.1", + "@abp/malihu-custom-scrollbar-plugin": "^1.1.1", + "@abp/popper.js": "^1.1.1", + "@abp/prismjs": "^1.1.1" } }, "@abp/font-awesome": { - "version": "0.4.9", - "resolved": "https://registry.npmjs.org/@abp/font-awesome/-/font-awesome-0.4.9.tgz", - "integrity": "sha512-H4H/PJeSypoq++jP7eqS3y5jpbPIglUByPymHnho7U84gO06tZBUIoK00zyLACUVLzNztWANhmVqyA6OaHQ6xQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@abp/font-awesome/-/font-awesome-1.1.1.tgz", + "integrity": "sha512-6RHbixi7IVWAb3JCHrUmEYD3HmAH4R75Nuo54LvFzATrh4G6gdBONIeDuTo79OTxe4Zhp+WLxeA49Y21kt77mg==", "requires": { - "@abp/core": "^0.4.9", - "font-awesome": "^4.7.0" + "@abp/core": "^1.1.1", + "@fortawesome/fontawesome-free": "^5.11.2" } }, "@abp/jquery": { - "version": "0.4.9", - "resolved": "https://registry.npmjs.org/@abp/jquery/-/jquery-0.4.9.tgz", - "integrity": "sha512-Lte2rfDhcVXRA18mJMyPs0oFoiX/7x10F9cwMyX4+8e9QulA0dg+MjJZ4HIbxRoKvaYPz0AdE5VZ511folFeTg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@abp/jquery/-/jquery-1.1.1.tgz", + "integrity": "sha512-kj4BTtXF0VbCzCqRXnRVEbGndR3F8NlbBhVQN6BQktOuZta3fvx7f2+pSok8vQv0ddmqUFY7FTT2Ei3l4363LQ==", "requires": { - "@abp/core": "^0.4.9", - "jquery": "^3.3.1" + "@abp/core": "^1.1.1", + "jquery": "^3.4.1" } }, "@abp/jquery-form": { - "version": "0.4.9", - "resolved": "https://registry.npmjs.org/@abp/jquery-form/-/jquery-form-0.4.9.tgz", - "integrity": "sha512-T1LzHNO+L/ATSfsaSu9H5rq9oUGjjBrwcJBVQhWRuGbB/Nsv1t4CdCPZHqbYBsn3ji/6T9C80FMdL+s4iOfy8A==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@abp/jquery-form/-/jquery-form-1.1.1.tgz", + "integrity": "sha512-AIIdN36f8xwr4LgiNnBHohJ5tlxh/r+DuDtXcScpZN6GWBE+XgUotN0pZIIva82IxCyUNdDudzgluX9IjI+00w==", "requires": { - "@abp/jquery": "^0.4.9", + "@abp/jquery": "^1.1.1", "jquery-form": "^4.2.2" } }, "@abp/jquery-validation": { - "version": "0.4.9", - "resolved": "https://registry.npmjs.org/@abp/jquery-validation/-/jquery-validation-0.4.9.tgz", - "integrity": "sha512-8C58G9BTYszW6E0EO6NYqXLEbABXt/yGlOqAFCkPiLVfUcoC6uARqkgIgNVnE99ZUeSmluNsYeCczP0Qb0yNzg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@abp/jquery-validation/-/jquery-validation-1.1.1.tgz", + "integrity": "sha512-YvAjIW8epp+ddu01BTUkZWPfEADAvNPJeUrrZ6OpcPWM15Tf+ddr4ATgJ1LCg0Bh5F09iQC855osow3lt8sc7g==", "requires": { - "@abp/jquery": "^0.4.9", - "jquery-validation": "^1.17.0" + "@abp/jquery": "^1.1.1", + "jquery-validation": "^1.19.1" } }, "@abp/jquery-validation-unobtrusive": { - "version": "0.4.9", - "resolved": "https://registry.npmjs.org/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-0.4.9.tgz", - "integrity": "sha512-GR62QEPexX4uLcqF3y72V39nlx/70C7ubeaIxS1ZEq+0wGklwAiyq1p19qpB5Cuj2GJL+vFrIig5w+B79P2iAw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-1.1.1.tgz", + "integrity": "sha512-q1b0KG8l3DXUiW8JXdq9l1jR/CwgzrZdxwdKGLB2J/oxHlywQIb7yrjR6WGCshjPpcx2SkOL0j/ZXMIMh533hQ==", "requires": { - "@abp/jquery-validation": "^0.4.9", - "jquery-validation-unobtrusive": "^3.2.9" + "@abp/jquery-validation": "^1.1.1", + "jquery-validation-unobtrusive": "^3.2.11" } }, "@abp/lodash": { - "version": "0.4.9", - "resolved": "https://registry.npmjs.org/@abp/lodash/-/lodash-0.4.9.tgz", - "integrity": "sha512-/itYbXQL145WigKIGpnyWgARml7QGie7xqhC1WZG5iUkdqLx+4YBXesdzGFykthDewiQNz8mB2gPk64d376AAw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@abp/lodash/-/lodash-1.1.1.tgz", + "integrity": "sha512-nH7bRS28Tf4hEXcpKHd1IM+MzYTqX8t3htGmsLX4UESQd52eODYOIldtX6gm3OW1O6ECwW6si/o0M2pTEpQqvg==", "requires": { - "@abp/core": "^0.4.9", - "lodash": "^4.17.10" - }, - "dependencies": { - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" - } + "@abp/core": "^1.1.1", + "lodash": "^4.17.15" + } + }, + "@abp/luxon": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@abp/luxon/-/luxon-1.1.1.tgz", + "integrity": "sha512-WNu8JRSb5FDXfcDwjMYyeYeUN48uuDc/I2cdo3xd1rcY+lbmbzxoG9IYOlE8cRHdgX3z82qsZXFs2lcAy0Le2g==", + "requires": { + "luxon": "^1.21.3" } }, "@abp/malihu-custom-scrollbar-plugin": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-0.5.1.tgz", - "integrity": "sha512-i9XorWsWcqb3tbbiwvE4OQCfXXJO38HlkQgvlwzxshB8xDcS9v/JL5fAAvM/Cr66fB2zybsrCseq9QcBXL+yCQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-1.1.1.tgz", + "integrity": "sha512-n4b4QK/L1Czdx0oOpUR/bWjK9VENexfUSV/aMjwzHhDmEFABAmEfhIpudCYDwewGswrd7C9agmBvakv2rwPQeA==", "requires": { - "@abp/core": "^0.4.9", + "@abp/core": "^1.1.1", "malihu-custom-scrollbar-plugin": "^3.1.5" } }, "@abp/popper.js": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@abp/popper.js/-/popper.js-0.5.1.tgz", - "integrity": "sha512-qS97hQQtG78mVPRvmZZtBb7Vu905NpThl9PN3jPWWDiVbOV2/d+BXCTRhTRbfdup3C5cmGdntjaGxfcxlxHt1Q==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@abp/popper.js/-/popper.js-1.1.1.tgz", + "integrity": "sha512-heR73cqmMsVPNgsPxBYbkvc842R3hEEuDAj4oaXZwVTeWXayU6TdDcGdIrfwMZwW2eWivYNnO0bMOVmuhZKTTQ==", "requires": { - "@abp/core": "^0.4.9", - "popper.js": "^1.14.6" + "@abp/core": "^1.1.1", + "popper.js": "^1.16.0" } }, "@abp/prismjs": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@abp/prismjs/-/prismjs-0.5.1.tgz", - "integrity": "sha512-DxoidAVV8LmtgFonbzGJEfszQDUaHEQc+/bcJtyQCuv5l+uflVnpAH+6W8IAErt5N96a0RJbeV9ZBXjIhqOzpA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@abp/prismjs/-/prismjs-1.1.1.tgz", + "integrity": "sha512-kZh2imqVTMDWmE2v+S4wMsigu/hSyVaz3VvZzGctFNctzC17LeD6z6ymfrtQ5BPJbCxGSpHwOt4/Y8bycPTEuQ==", "requires": { - "@abp/core": "^0.4.9", - "prismjs": "^1.15.0" + "@abp/core": "^1.1.1", + "prismjs": "^1.17.1" } }, "@abp/select2": { - "version": "0.4.9", - "resolved": "https://registry.npmjs.org/@abp/select2/-/select2-0.4.9.tgz", - "integrity": "sha512-AaJHWy9fkP/LqVkruZGfvzgdZXyT96/FpnflUpoNPXjuvVRptkJpd/BQiWjpyjS+qzuZ+m3X9dms0d0lAyFKYA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@abp/select2/-/select2-1.1.1.tgz", + "integrity": "sha512-t0qcJhD+uo2+XWr4nmMQLAx7MRGQUBdZ81YmGty045ReoSaEKQf4haLkzBcMzpBRusiyMQO/PbxjtwMw/xJQTQ==", "requires": { - "@abp/core": "^0.4.9", - "select2": "^4.0.5" + "@abp/core": "^1.1.1", + "select2": "^4.0.12" } }, "@abp/sweetalert": { - "version": "0.4.9", - "resolved": "https://registry.npmjs.org/@abp/sweetalert/-/sweetalert-0.4.9.tgz", - "integrity": "sha512-FaxtELo7Um/uasasbOGi1j1XuBtZ819mUo7+6pMSWj2CSAkg2A/RyT9NhYcX8oyGpv188W5CjZfJ1DM0bRH+pQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@abp/sweetalert/-/sweetalert-1.1.1.tgz", + "integrity": "sha512-V6K/qg7J/bdFmom2kaXYeiLvcmLHFl+MacPX4yYAK2biZdb2pWOkUdmcAzZdOT+UruKfLRhvraVC2uXDySi9NA==", "requires": { - "@abp/core": "^0.4.9", - "sweetalert": "^2.1.0" + "@abp/core": "^1.1.1", + "sweetalert": "^2.1.2" } }, "@abp/timeago": { - "version": "0.4.9", - "resolved": "https://registry.npmjs.org/@abp/timeago/-/timeago-0.4.9.tgz", - "integrity": "sha512-RsAyJCl+rEWQL0q0Nx/ijy+iOBYm5IC5Re6y4SQ1jYF/B4n88GM2PFy6kLrE+HHGl5Z5hkWr5OGXmFem50Y3Wg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@abp/timeago/-/timeago-1.1.1.tgz", + "integrity": "sha512-QYYih/4n6XhCqkRw7fBfyg58T5CHqJHyz7SAfq86RiKAJ4jVtjdSVxj3XKxz8eCb56wZGsO1xXXStI3vdLwwNw==", "requires": { - "@abp/jquery": "^0.4.9", - "timeago": "^1.6.3" + "@abp/jquery": "^1.1.1", + "timeago": "^1.6.7" } }, "@abp/toastr": { - "version": "0.4.9", - "resolved": "https://registry.npmjs.org/@abp/toastr/-/toastr-0.4.9.tgz", - "integrity": "sha512-KjnETa1Og5EIMDw/pIxPoKLTABBcsxBN8BqwIG33ya2+BIRfAI7b0lEMoKK+qmwVwI5dkXZlKFGIUmPtb+zVCw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@abp/toastr/-/toastr-1.1.1.tgz", + "integrity": "sha512-GDewBppm+0FO6kTTy0huczoH9P5q6lFicHFAoEawAMkuWJFW/Ihv/YnEvKGDQwGftuVSWexfqBMN/RZ5YSOiGQ==", "requires": { - "@abp/jquery": "^0.4.9", + "@abp/jquery": "^1.1.1", "toastr": "^2.1.4" } }, - "almond": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/almond/-/almond-0.3.3.tgz", - "integrity": "sha1-oOfJWsdiTWQXtElLHmi/9pMWiiA=" + "@fortawesome/fontawesome-free": { + "version": "5.13.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.13.0.tgz", + "integrity": "sha512-xKOeQEl5O47GPZYIMToj6uuA2syyFlq9EMSl2ui0uytjY9xbe8XS0pexNWmxrdcCyNGyDmLyYw5FtKsalBUeOg==" }, "anchor-js": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/anchor-js/-/anchor-js-4.1.1.tgz", - "integrity": "sha512-c2Wl9F1X0C4jkYKLla1SNE2uI6xJrSKsRC7HCCg4yLNQ5sL5D+tDEWrjRaoTuTlMTqBCnF6kOuR3dx59Erxpvw==" + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/anchor-js/-/anchor-js-4.2.2.tgz", + "integrity": "sha512-Rg1tGaG4K3avYqDh7rOYCE/odWxpUiHStnlKL/bGOt9cl6NjR06zhPGVQcCAjE5PT48oQeHVgqNmLzxh0Kuk4A==" }, "ansi-colors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", - "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "requires": { - "ansi-wrap": "^0.1.0" - } + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==" }, "ansi-gray": { "version": "0.1.1", @@ -260,16 +269,28 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" - }, "ansi-wrap": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=" }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "append-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", + "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", + "requires": { + "buffer-equal": "^1.0.0" + } + }, "archy": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", @@ -280,35 +301,89 @@ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" }, + "arr-filter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", + "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", + "requires": { + "make-iterator": "^1.0.0" + } + }, "arr-flatten": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" }, + "arr-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", + "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", + "requires": { + "make-iterator": "^1.0.0" + } + }, "arr-union": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" }, - "array-differ": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", - "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=" - }, "array-each": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=" }, + "array-initial": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", + "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", + "requires": { + "array-slice": "^1.0.0", + "is-number": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==" + } + } + }, + "array-last": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", + "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", + "requires": { + "is-number": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==" + } + } + }, "array-slice": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==" }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" + "array-sort": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", + "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", + "requires": { + "default-compare": "^1.0.0", + "get-value": "^2.0.6", + "kind-of": "^5.0.2" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } }, "array-unique": { "version": "0.3.2", @@ -320,11 +395,51 @@ "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" }, + "async-done": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", + "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.2", + "process-nextick-args": "^2.0.0", + "stream-exhaust": "^1.0.1" + } + }, + "async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==" + }, + "async-settle": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", + "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", + "requires": { + "async-done": "^1.2.2" + } + }, "atob": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" }, + "bach": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", + "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", + "requires": { + "arr-filter": "^1.1.1", + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "array-each": "^1.0.0", + "array-initial": "^1.0.0", + "array-last": "^1.1.1", + "async-done": "^1.2.2", + "async-settle": "^1.0.0", + "now-and-later": "^2.0.0" + } + }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -380,15 +495,32 @@ } } }, - "beeper": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", - "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=" + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==" + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "optional": true, + "requires": { + "file-uri-to-path": "1.0.0" + } }, "bootstrap": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.1.3.tgz", - "integrity": "sha512-rDFIzgXcof0jDyjNosjv4Sno77X4KuPeFxG2XZZv1/Kc8DRVGVADdoQyyOVDwPqL36DDmtCQbrpMCqvpPLJQ0w==" + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.4.1.tgz", + "integrity": "sha512-tbx5cHubwE6e2ZG7nqM3g/FZ5PQEDMWmMGNrCUBVRPHXTJaH7CBDdsLeu3eCh3B1tzAxTnAbtmrzvWEvT2NNEA==" + }, + "bootstrap-datepicker": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/bootstrap-datepicker/-/bootstrap-datepicker-1.9.0.tgz", + "integrity": "sha512-9rYYbaVOheGYxjOr/+bJCmRPihfy+LkLSg4fIFMT9Od8WwWB/MB50w0JO1eBgKUMbb7PFHQD5uAfI3ArAxZRXA==", + "requires": { + "jquery": ">=1.7.1 <4.0.0" + } }, "brace-expansion": { "version": "1.1.11", @@ -426,6 +558,16 @@ } } }, + "buffer-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", + "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=" + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", @@ -442,16 +584,35 @@ "unset-value": "^1.0.0" } }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=" + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + } } }, "class-utils": { @@ -476,24 +637,64 @@ } }, "clipboard": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.4.tgz", - "integrity": "sha512-Vw26VSLRpJfBofiVaFb/I8PVfdI1OxKcYShe6fm0sP/DtmiWQNCjhM/okTvdCo0G+lMMm1rMYbk4IK4x1X+kgQ==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.6.tgz", + "integrity": "sha512-g5zbiixBRk/wyKakSwCKd7vQXDjFnAMGHoEyBogG/bw9kTD9GvdAvaoRR1ALcEzt3pVKxZR0pViekPMIS0QyGg==", "requires": { "good-listener": "^1.2.2", "select": "^1.1.2", "tiny-emitter": "^2.0.0" } }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=" + }, + "clone-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=" }, "clone-stats": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=" + }, + "cloneable-readable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", + "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", + "requires": { + "inherits": "^2.0.1", + "process-nextick-args": "^2.0.0", + "readable-stream": "^2.3.5" + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "collection-map": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", + "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", + "requires": { + "arr-map": "^2.0.2", + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } }, "collection-visit": { "version": "1.0.0", @@ -510,47 +711,79 @@ "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" }, "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "requires": { + "safe-buffer": "~5.1.1" + } + }, "copy-descriptor": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" }, + "copy-props": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.4.tgz", + "integrity": "sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A==", + "requires": { + "each-props": "^1.3.0", + "is-plain-object": "^2.0.1" + } + }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, + "d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, "datatables.net": { - "version": "1.10.19", - "resolved": "https://registry.npmjs.org/datatables.net/-/datatables.net-1.10.19.tgz", - "integrity": "sha512-+ljXcI6Pj3PTGy5pesp3E5Dr3x3AV45EZe0o1r0gKENN2gafBKXodVnk2ypKwl2tTmivjxbkiqoWnipTefyBTA==", + "version": "1.10.20", + "resolved": "https://registry.npmjs.org/datatables.net/-/datatables.net-1.10.20.tgz", + "integrity": "sha512-4E4S7tTU607N3h0fZPkGmAtr9mwy462u+VJ6gxYZ8MxcRIjZqHy3Dv1GNry7i3zQCktTdWbULVKBbkAJkuHEnQ==", "requires": { "jquery": ">=1.7" } }, "datatables.net-bs4": { - "version": "1.10.19", - "resolved": "https://registry.npmjs.org/datatables.net-bs4/-/datatables.net-bs4-1.10.19.tgz", - "integrity": "sha512-pgeP17w4aPR7HIxIwuJghfqXULjdg1K6xMUUKDyCERJRSNNK4MRToFfELtIsluLNN555YBK4Kx8nihX5/ZT1Fw==", + "version": "1.10.20", + "resolved": "https://registry.npmjs.org/datatables.net-bs4/-/datatables.net-bs4-1.10.20.tgz", + "integrity": "sha512-kQmMUMsHMOlAW96ztdoFqjSbLnlGZQ63iIM82kHbmldsfYdzuyhbb4hTx6YNBi481WCO3iPSvI6YodNec46ZAw==", "requires": { - "datatables.net": "1.10.19", + "datatables.net": "1.10.20", "jquery": ">=1.7" } }, - "dateformat": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", - "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=" - }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -559,17 +792,42 @@ "ms": "2.0.0" } }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, "decode-uri-component": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" }, - "defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "default-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", + "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", + "requires": { + "kind-of": "^5.0.2" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "default-resolution": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", + "integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=" + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", "requires": { - "clone": "^1.0.2" + "object-keys": "^1.0.12" } }, "define-property": { @@ -614,30 +872,65 @@ "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==" }, - "deprecated": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", - "integrity": "sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=" - }, "detect-file": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=" }, - "duplexer2": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", - "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "each-props": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", + "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", "requires": { - "readable-stream": "~1.1.9" + "is-plain-object": "^2.0.1", + "object.defaults": "^1.1.0" } }, "end-of-stream": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", - "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es5-ext": { + "version": "0.10.53", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", + "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.3", + "next-tick": "~1.0.0" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", "requires": { - "once": "~1.3.0" + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" } }, "es6-object-assign": { @@ -645,10 +938,25 @@ "resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz", "integrity": "sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw=" }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + "es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "requires": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "requires": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } }, "expand-brackets": { "version": "2.1.4", @@ -690,6 +998,21 @@ "homedir-polyfill": "^1.0.1" } }, + "ext": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", + "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", + "requires": { + "type": "^2.0.0" + }, + "dependencies": { + "type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.0.0.tgz", + "integrity": "sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==" + } + } + }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -779,15 +1102,22 @@ } }, "fancy-log": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", - "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", + "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", "requires": { "ansi-gray": "^0.1.1", "color-support": "^1.1.3", + "parse-node-version": "^1.0.0", "time-stamp": "^1.0.0" } }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "optional": true + }, "fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", @@ -809,26 +1139,30 @@ } } }, - "find-index": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", - "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=" + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } }, "findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", + "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", "requires": { "detect-file": "^1.0.0", - "is-glob": "^3.1.0", + "is-glob": "^4.0.0", "micromatch": "^3.0.4", "resolve-dir": "^1.0.1" } }, "fined": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", - "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", + "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", "requires": { "expand-tilde": "^2.0.2", "is-plain-object": "^2.0.3", @@ -837,20 +1171,19 @@ "parse-filepath": "^1.0.1" } }, - "first-chunk-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", - "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=" - }, "flagged-respawn": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.0.tgz", - "integrity": "sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c=" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", + "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==" }, - "font-awesome": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/font-awesome/-/font-awesome-4.7.0.tgz", - "integrity": "sha1-j6jPBBGhoxr9B7BtKQK7n8gVoTM=" + "flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } }, "for-in": { "version": "1.0.2", @@ -873,84 +1206,579 @@ "map-cache": "^0.2.2" } }, - "fs.realpath": { + "fs-mkdirp-stream": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "gaze": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", - "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", + "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", + "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", "requires": { - "globule": "~0.1.0" + "graceful-fs": "^4.1.11", + "through2": "^2.0.3" } }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, - "glob": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", - "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", + "fsevents": { + "version": "1.2.12", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.12.tgz", + "integrity": "sha512-Ggd/Ktt7E7I8pxZRbGIs7vwqAPscSESMrCSkx2FtWeqmheJgCo2R74fTsZFCifr0VTPwqRpPv17+6b8Zp7th0Q==", + "optional": true, "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^2.0.1", - "once": "^1.3.0" - } - }, - "glob-stream": { - "version": "3.1.18", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", - "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", - "requires": { - "glob": "^4.3.1", - "glob2base": "^0.0.12", - "minimatch": "^2.0.1", - "ordered-read-streams": "^0.1.0", - "through2": "^0.6.1", - "unique-stream": "^1.0.0" + "bindings": "^1.5.0", + "nan": "^2.12.1", + "node-pre-gyp": "*" }, "dependencies": { - "readable-stream": { - "version": "1.0.34", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "abbrev": { + "version": "1.1.1", + "bundled": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "optional": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "optional": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" } }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "optional": true, "requires": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } - } + }, + "chownr": { + "version": "1.1.4", + "bundled": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "optional": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "optional": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "optional": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "debug": { + "version": "3.2.6", + "bundled": true, + "optional": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.7", + "bundled": true, + "optional": true, + "requires": { + "minipass": "^2.6.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.6", + "bundled": true, + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.24", + "bundled": true, + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.3", + "bundled": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "bundled": true, + "optional": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "optional": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "optional": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "bundled": true, + "optional": true + }, + "minipass": { + "version": "2.9.0", + "bundled": true, + "optional": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.3.3", + "bundled": true, + "optional": true, + "requires": { + "minipass": "^2.9.0" + } + }, + "mkdirp": { + "version": "0.5.3", + "bundled": true, + "optional": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "ms": { + "version": "2.1.2", + "bundled": true, + "optional": true + }, + "needle": { + "version": "2.3.3", + "bundled": true, + "optional": true, + "requires": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.14.0", + "bundled": true, + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4.4.2" + } + }, + "nopt": { + "version": "4.0.3", + "bundled": true, + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.1.1", + "bundled": true, + "optional": true, + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-normalize-package-bin": { + "version": "1.0.1", + "bundled": true, + "optional": true + }, + "npm-packlist": { + "version": "1.4.8", + "bundled": true, + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1", + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "optional": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.1", + "bundled": true, + "optional": true + }, + "rc": { + "version": "1.2.8", + "bundled": true, + "optional": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "bundled": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.7.1", + "bundled": true, + "optional": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true, + "optional": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "optional": true + }, + "semver": { + "version": "5.7.1", + "bundled": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "optional": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "optional": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "optional": true + }, + "tar": { + "version": "4.4.13", + "bundled": true, + "optional": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "optional": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "yallist": { + "version": "3.1.1", + "bundled": true, + "optional": true + } } }, - "glob-watcher": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", - "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "glob-stream": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", + "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", "requires": { - "gaze": "^0.5.1" + "extend": "^3.0.0", + "glob": "^7.1.1", + "glob-parent": "^3.1.0", + "is-negated-glob": "^1.0.0", + "ordered-read-streams": "^1.0.0", + "pumpify": "^1.3.5", + "readable-stream": "^2.1.5", + "remove-trailing-separator": "^1.0.1", + "to-absolute-glob": "^2.0.0", + "unique-stream": "^2.0.2" } }, - "glob2base": { - "version": "0.0.12", - "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", - "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", + "glob-watcher": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.3.tgz", + "integrity": "sha512-8tWsULNEPHKQ2MR4zXuzSmqbdyV5PtwwCaWSGQ1WwHsJ07ilNeN1JB8ntxhckbnpSHaf9dXFUHzIWvm1I13dsg==", "requires": { - "find-index": "^0.1.1" + "anymatch": "^2.0.0", + "async-done": "^1.2.0", + "chokidar": "^2.0.0", + "is-negated-glob": "^1.0.0", + "just-debounce": "^1.0.0", + "object.defaults": "^1.1.0" } }, "global-modules": { @@ -975,51 +1803,10 @@ "which": "^1.2.14" } }, - "globule": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", - "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", - "requires": { - "glob": "~3.1.21", - "lodash": "~1.0.1", - "minimatch": "~0.2.11" - }, - "dependencies": { - "glob": { - "version": "3.1.21", - "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", - "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", - "requires": { - "graceful-fs": "~1.2.0", - "inherits": "1", - "minimatch": "~0.2.11" - } - }, - "graceful-fs": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", - "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=" - }, - "inherits": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", - "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=" - }, - "minimatch": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", - "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", - "requires": { - "lru-cache": "2", - "sigmund": "~1.0.0" - } - } - } - }, "glogg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.1.tgz", - "integrity": "sha512-ynYqXLoluBKf9XGR1gA59yEJisIL7YHEH4xr3ZziHB5/yl4qWfaK8Js9jGe6gBGCSCKVqiyO30WnRZADvemUNw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", + "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", "requires": { "sparkles": "^1.0.0" } @@ -1033,56 +1820,54 @@ } }, "graceful-fs": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", - "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", - "requires": { - "natives": "^1.1.0" - } + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==" }, "gulp": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", - "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", - "requires": { - "archy": "^1.0.0", - "chalk": "^1.0.0", - "deprecated": "^0.0.1", - "gulp-util": "^3.0.0", - "interpret": "^1.0.0", - "liftoff": "^2.1.0", - "minimist": "^1.1.0", - "orchestrator": "^0.3.0", - "pretty-hrtime": "^1.0.0", - "semver": "^4.1.0", - "tildify": "^1.0.0", - "v8flags": "^2.0.2", - "vinyl-fs": "^0.3.0" - } - }, - "gulp-util": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", - "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", - "requires": { - "array-differ": "^1.0.0", - "array-uniq": "^1.0.2", - "beeper": "^1.0.0", - "chalk": "^1.0.0", - "dateformat": "^2.0.0", - "fancy-log": "^1.1.0", - "gulplog": "^1.0.0", - "has-gulplog": "^0.1.0", - "lodash._reescape": "^3.0.0", - "lodash._reevaluate": "^3.0.0", - "lodash._reinterpolate": "^3.0.0", - "lodash.template": "^3.0.0", - "minimist": "^1.1.0", - "multipipe": "^0.1.2", - "object-assign": "^3.0.0", - "replace-ext": "0.0.1", - "through2": "^2.0.0", - "vinyl": "^0.5.0" + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", + "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", + "requires": { + "glob-watcher": "^5.0.3", + "gulp-cli": "^2.2.0", + "undertaker": "^1.2.1", + "vinyl-fs": "^3.0.0" + }, + "dependencies": { + "ansi-colors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", + "requires": { + "ansi-wrap": "^0.1.0" + } + }, + "gulp-cli": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.2.0.tgz", + "integrity": "sha512-rGs3bVYHdyJpLqR0TUBnlcZ1O5O++Zs4bA0ajm+zr3WFCfiSLjGwoCBqFs18wzN+ZxahT9DkOK5nDf26iDsWjA==", + "requires": { + "ansi-colors": "^1.0.1", + "archy": "^1.0.0", + "array-sort": "^1.0.0", + "color-support": "^1.1.3", + "concat-stream": "^1.6.0", + "copy-props": "^2.0.1", + "fancy-log": "^1.3.2", + "gulplog": "^1.0.0", + "interpret": "^1.1.0", + "isobject": "^3.0.1", + "liftoff": "^3.1.0", + "matchdep": "^2.0.0", + "mute-stdout": "^1.0.0", + "pretty-hrtime": "^1.0.0", + "replace-homedir": "^1.0.0", + "semver-greatest-satisfied-range": "^1.1.0", + "v8flags": "^3.0.1", + "yargs": "^7.1.0" + } + } } }, "gulplog": { @@ -1093,21 +1878,10 @@ "glogg": "^1.0.0" } }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "has-gulplog": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", - "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", - "requires": { - "sparkles": "^1.0.0" - } + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" }, "has-value": { "version": "1.0.0", @@ -1139,13 +1913,18 @@ } }, "homedir-polyfill": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", - "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", "requires": { "parse-passwd": "^1.0.0" } }, + "hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==" + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -1156,9 +1935,9 @@ } }, "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "ini": { "version": "1.3.5", @@ -1166,9 +1945,14 @@ "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" }, "interpret": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", - "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", + "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==" + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" }, "is-absolute": { "version": "1.0.0", @@ -1197,6 +1981,19 @@ } } }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "requires": { + "binary-extensions": "^1.0.0" + } + }, "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", @@ -1247,14 +2044,27 @@ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", "requires": { - "is-extglob": "^2.1.0" + "is-extglob": "^2.1.1" } }, + "is-negated-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", + "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=" + }, "is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", @@ -1302,15 +2112,20 @@ "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" }, + "is-valid-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", + "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=" + }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" }, "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "isexe": { "version": "2.0.0", @@ -1323,9 +2138,9 @@ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" }, "jquery": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.3.1.tgz", - "integrity": "sha512-Ubldcmxp5np52/ENotGxlLe6aGMvmF4R8S6tZjsP6Knsaxd/xp3Zrh50cG93lR6nPXyUFwzN3ZSOQI0wRJNdGg==" + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.4.1.tgz", + "integrity": "sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw==" }, "jquery-form": { "version": "4.2.2", @@ -1341,154 +2156,103 @@ "integrity": "sha1-BvAzXxbjU6aV5yBr9QUDy1I6buU=" }, "jquery-validation": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/jquery-validation/-/jquery-validation-1.18.0.tgz", - "integrity": "sha512-+MK0pvoegfLrJnwtCU6tx305Vgp9HWevpmdVwDf5TthmINkn0wqqLD0bpa75EERlHsBBjMmza//ppx5ZQPnW3Q==", - "requires": { - "jquery": "^1.7 || ^2.0 || ^3.1" - } + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/jquery-validation/-/jquery-validation-1.19.1.tgz", + "integrity": "sha512-QNnrZBqSltWUEJx+shOY5WtfrIb0gWmDjFfQP8rZKqMMSfpRSwEkSqhfHPvDfkObD8Hnv5KHSYI8yg73sVFdqA==" }, "jquery-validation-unobtrusive": { - "version": "3.2.10", - "resolved": "https://registry.npmjs.org/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-3.2.10.tgz", - "integrity": "sha512-z9ZBP/HslaGNKzFSpfLNJoFm2iqPJfE6CKM0H5e9LmKnYTFxErvCFQZomOLiTmLmZi8Wi/otW38cEXExVDha0w==", + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-3.2.11.tgz", + "integrity": "sha512-3FQPllaWdD+Aq55zJLGSW39+eXPDz1HhwAvrSwYi8zHQ8DVcu5IJ1HVeTiCl0BnCnrIBvfFU3zEB/DrGdcoRIQ==", "requires": { "jquery": ">=1.8", "jquery-validation": ">=1.16" } }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=" + }, + "just-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.0.0.tgz", + "integrity": "sha1-h/zPrv/AtozRnVX2cilD+SnqNeo=" + }, "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" }, - "liftoff": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", - "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", + "last-run": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", + "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", "requires": { - "extend": "^3.0.0", - "findup-sync": "^2.0.0", - "fined": "^1.0.1", - "flagged-respawn": "^1.0.0", - "is-plain-object": "^2.0.4", - "object.map": "^1.0.0", - "rechoir": "^0.6.2", - "resolve": "^1.1.7" + "default-resolution": "^2.0.0", + "es6-weak-map": "^2.0.1" } }, - "lodash": { - "version": "1.0.2", - "resolved": "http://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", - "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=" - }, - "lodash._basecopy": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", - "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=" - }, - "lodash._basetostring": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", - "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=" - }, - "lodash._basevalues": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", - "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=" - }, - "lodash._getnative": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", - "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=" - }, - "lodash._isiterateecall": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", - "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=" - }, - "lodash._reescape": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", - "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=" - }, - "lodash._reevaluate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", - "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=" - }, - "lodash._reinterpolate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=" - }, - "lodash._root": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", - "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=" - }, - "lodash.escape": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", - "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", + "lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", "requires": { - "lodash._root": "^3.0.0" + "readable-stream": "^2.0.5" } }, - "lodash.isarguments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=" - }, - "lodash.isarray": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", - "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=" - }, - "lodash.keys": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", - "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", "requires": { - "lodash._getnative": "^3.0.0", - "lodash.isarguments": "^3.0.0", - "lodash.isarray": "^3.0.0" + "invert-kv": "^1.0.0" } }, - "lodash.restparam": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", - "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=" + "lead": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", + "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", + "requires": { + "flush-write-stream": "^1.0.2" + } }, - "lodash.template": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", - "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", + "liftoff": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", + "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", "requires": { - "lodash._basecopy": "^3.0.0", - "lodash._basetostring": "^3.0.0", - "lodash._basevalues": "^3.0.0", - "lodash._isiterateecall": "^3.0.0", - "lodash._reinterpolate": "^3.0.0", - "lodash.escape": "^3.0.0", - "lodash.keys": "^3.0.0", - "lodash.restparam": "^3.0.0", - "lodash.templatesettings": "^3.0.0" + "extend": "^3.0.0", + "findup-sync": "^3.0.0", + "fined": "^1.0.1", + "flagged-respawn": "^1.0.0", + "is-plain-object": "^2.0.4", + "object.map": "^1.0.0", + "rechoir": "^0.6.2", + "resolve": "^1.1.7" } }, - "lodash.templatesettings": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", - "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "requires": { - "lodash._reinterpolate": "^3.0.0", - "lodash.escape": "^3.0.0" + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" } }, - "lru-cache": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", - "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=" + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" + }, + "luxon": { + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-1.22.2.tgz", + "integrity": "sha512-vq6eSaOOw1fKob+JXwfu0e3/UFUT4G4HTFRJab7dch8J1OdOGW/vXqCiJsY7rm2In+5gKNYx0EtnYT0Tc5V4Qw==" }, "make-iterator": { "version": "1.0.1", @@ -1519,43 +2283,43 @@ "object-visit": "^1.0.0" } }, - "merge-stream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", - "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", + "matchdep": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", + "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", "requires": { - "readable-stream": "^2.0.1" + "findup-sync": "^2.0.0", + "micromatch": "^3.0.4", + "resolve": "^1.4.0", + "stack-trace": "0.0.10" }, "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "findup-sync": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "detect-file": "^1.0.0", + "is-glob": "^3.1.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" } }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", "requires": { - "safe-buffer": "~5.1.0" + "is-extglob": "^2.1.0" } } } }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, "micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", @@ -1577,22 +2341,17 @@ } }, "minimatch": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", - "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "requires": { - "brace-expansion": "^1.0.0" + "brace-expansion": "^1.1.7" } }, - "minimist": { - "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" - }, "mixin-deep": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", - "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", "requires": { "for-in": "^1.0.2", "is-extendable": "^1.0.1" @@ -1608,33 +2367,21 @@ } } }, - "mkdirp": { - "version": "0.5.1", - "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "requires": { - "minimist": "0.0.8" - }, - "dependencies": { - "minimist": { - "version": "0.0.8", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" - } - } - }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, - "multipipe": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", - "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", - "requires": { - "duplexer2": "0.0.2" - } + "mute-stdout": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", + "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==" + }, + "nan": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", + "optional": true }, "nanomatch": { "version": "1.2.13", @@ -1654,15 +2401,42 @@ "to-regex": "^3.0.1" } }, - "natives": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.5.tgz", - "integrity": "sha512-1pJ+02gl2KJgCPFtpZGtuD4lGSJnIZvvFHCQTOeDRMSXjfu2GmYWuhI8NFMA4W2I5NNFRbfy/YCiVt4CgNpP8A==" + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" }, - "object-assign": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", - "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=" + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "now-and-later": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", + "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", + "requires": { + "once": "^1.3.2" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" }, "object-copy": { "version": "0.1.0", @@ -1692,12 +2466,28 @@ } } }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + }, "object-visit": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", "requires": { - "isobject": "^3.0.0" + "isobject": "^3.0.0" + } + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" } }, "object.defaults": { @@ -1728,33 +2518,38 @@ "isobject": "^3.0.1" } }, - "once": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", - "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", + "object.reduce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", + "integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=", "requires": { - "wrappy": "1" + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" } }, - "orchestrator": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", - "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "requires": { - "end-of-stream": "~0.1.5", - "sequencify": "~0.0.7", - "stream-consume": "~0.1.0" + "wrappy": "1" } }, "ordered-read-streams": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", - "integrity": "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", + "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", + "requires": { + "readable-stream": "^2.0.1" + } }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "requires": { + "lcid": "^1.0.0" + } }, "parse-filepath": { "version": "1.0.2", @@ -1766,6 +2561,19 @@ "path-root": "^0.1.1" } }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "requires": { + "error-ex": "^1.2.0" + } + }, + "parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==" + }, "parse-passwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", @@ -1785,6 +2593,19 @@ "util": "^0.10.3" } }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "requires": { + "pinkie-promise": "^2.0.0" + } + }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -1808,10 +2629,38 @@ "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=" }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "requires": { + "pinkie": "^2.0.0" + } + }, "popper.js": { - "version": "1.14.6", - "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.14.6.tgz", - "integrity": "sha512-AGwHGQBKumlk/MDfrSOf0JHhJCImdDMcGNoqKmKkU+68GFazv3CQ6q9r7Ja1sKDZmYWTckY/uLyEznheTDycnA==" + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz", + "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==" }, "posix-character-classes": { "version": "0.1.1", @@ -1824,9 +2673,9 @@ "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=" }, "prismjs": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.15.0.tgz", - "integrity": "sha512-Lf2JrFYx8FanHrjoV5oL8YHCclLQgbJcVZR+gikGGMqz6ub5QVWDTM6YIwm3BuPxM/LOV+rKns3LssXNLIf+DA==", + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.19.0.tgz", + "integrity": "sha512-IVFtbW9mCWm9eOIaEkNyo2Vl4NnEifis2GQ7/MLRG5TQe6t+4Sj9J5QWI9i3v+SS43uZBlCAOn+zYTVYQcPXJw==", "requires": { "clipboard": "^2.0.0" } @@ -1837,24 +2686,75 @@ "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" }, "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, "promise-polyfill": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-6.1.0.tgz", "integrity": "sha1-36lpQ+qcEh/KTem1hoyznTRy4Fc=" }, + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, "readable-stream": { - "version": "1.1.14", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "requires": { "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" } }, "rechoir": { @@ -1874,6 +2774,30 @@ "safe-regex": "^1.1.0" } }, + "remove-bom-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", + "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", + "requires": { + "is-buffer": "^1.1.5", + "is-utf8": "^0.2.1" + } + }, + "remove-bom-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", + "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", + "requires": { + "remove-bom-buffer": "^3.0.0", + "safe-buffer": "^5.1.0", + "through2": "^2.0.3" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" + }, "repeat-element": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", @@ -1885,16 +2809,36 @@ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" }, "replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=" + }, + "replace-homedir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", + "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", + "requires": { + "homedir-polyfill": "^1.0.1", + "is-absolute": "^1.0.0", + "remove-trailing-separator": "^1.1.0" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" }, "resolve": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", - "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", "requires": { - "path-parse": "^1.0.5" + "path-parse": "^1.0.6" } }, "resolve-dir": { @@ -1906,6 +2850,14 @@ "global-modules": "^1.0.0" } }, + "resolve-options": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", + "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", + "requires": { + "value-or-function": "^3.0.0" + } + }, "resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", @@ -1917,34 +2869,11 @@ "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" }, "rimraf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "requires": { - "glob": "^7.0.5" - }, - "dependencies": { - "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "requires": { - "brace-expansion": "^1.1.7" - } - } + "glob": "^7.1.3" } }, "safe-buffer": { @@ -1966,28 +2895,32 @@ "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=" }, "select2": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/select2/-/select2-4.0.5.tgz", - "integrity": "sha1-eqxQaSVhmFs007guxV4ib4lg1Ao=", - "requires": { - "almond": "~0.3.1", - "jquery-mousewheel": "~3.1.13" - } + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/select2/-/select2-4.0.13.tgz", + "integrity": "sha512-1JeB87s6oN/TDxQQYCvS5EFoQyvV6eYMZZ0AeA4tdFDYWN3BAGZ8npr17UBFddU0lgAt3H0yjX3X6/ekOj1yjw==" }, "semver": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", - "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=" + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, + "semver-greatest-satisfied-range": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", + "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", + "requires": { + "sver-compat": "^1.5.0" + } }, - "sequencify": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", - "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=" + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, "set-value": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", - "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", "requires": { "extend-shallow": "^2.0.1", "is-extendable": "^0.1.1", @@ -2005,11 +2938,6 @@ } } }, - "sigmund": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", - "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=" - }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", @@ -2113,11 +3041,11 @@ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" }, "source-map-resolve": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", - "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", "requires": { - "atob": "^2.1.1", + "atob": "^2.1.2", "decode-uri-component": "^0.2.0", "resolve-url": "^0.2.1", "source-map-url": "^0.4.0", @@ -2134,6 +3062,34 @@ "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==" }, + "spdx-correct": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==" + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==" + }, "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", @@ -2142,6 +3098,11 @@ "extend-shallow": "^3.0.0" } }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" + }, "static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", @@ -2161,15 +3122,33 @@ } } }, - "stream-consume": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.1.tgz", - "integrity": "sha512-tNa3hzgkjEP7XbCkbRXe1jpg+ievoa0O4SCFlMOYEscGSS4JJsckGL8swUyAa/ApGU3Ae4t6Honor4HhL+tRyg==" + "stream-exhaust": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", + "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==" + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } }, "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } }, "strip-ansi": { "version": "3.0.1", @@ -2180,72 +3159,47 @@ } }, "strip-bom": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", - "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", "requires": { - "first-chunk-stream": "^1.0.0", "is-utf8": "^0.2.0" } }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + "sver-compat": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", + "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", + "requires": { + "es6-iterator": "^2.0.1", + "es6-symbol": "^3.1.1" + } }, "sweetalert": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/sweetalert/-/sweetalert-2.1.0.tgz", - "integrity": "sha512-9YKj0SvjKyBfRWco50UOsIbXVeifYbxzT9Qda7EsqC01eafHGCSG0IR7g942ufjzt7lnwO8ZZBwr6emXv2fQrg==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/sweetalert/-/sweetalert-2.1.2.tgz", + "integrity": "sha512-iWx7X4anRBNDa/a+AdTmvAzQtkN1+s4j/JJRWlHpYE8Qimkohs8/XnFcWeYHH2lMA8LRCa5tj2d244If3S/hzA==", "requires": { "es6-object-assign": "^1.1.0", "promise-polyfill": "^6.0.2" } }, "through2": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", "requires": { - "readable-stream": "^2.1.5", + "readable-stream": "~2.3.6", "xtend": "~4.0.1" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, - "tildify": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", - "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", + "through2-filter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", + "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", "requires": { - "os-homedir": "^1.0.0" + "through2": "~2.0.0", + "xtend": "~4.0.0" } }, "time-stamp": { @@ -2254,17 +3208,26 @@ "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=" }, "timeago": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/timeago/-/timeago-1.6.3.tgz", - "integrity": "sha512-x97d1X1KsNapWJTgCOOAy/59XagYu2WsDTAH/yvPsWi5bqtGbLPaVZBv3HZ3jTpakHR+JGGyrI9qC0yuvIAvnQ==", + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/timeago/-/timeago-1.6.7.tgz", + "integrity": "sha512-FikcjN98+ij0siKH4VO4dZ358PR3oDDq4Vdl1+sN9gWz1/+JXGr3uZbUShYH/hL7bMhcTpPbplJU5Tej4b4jbQ==", "requires": { - "jquery": ">=1.2.3" + "jquery": ">=1.5.0 <4.0" } }, "tiny-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", + "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==" + }, + "to-absolute-glob": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.0.2.tgz", - "integrity": "sha512-2NM0auVBGft5tee/OxP4PI3d8WItkDM+fPnaRAVo6xTDI2knbz9eC5ArWGqtGlYqiH3RU5yMpdyTTO7MguC4ow==" + "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", + "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", + "requires": { + "is-absolute": "^1.0.0", + "is-negated-glob": "^1.0.0" + } }, "to-object-path": { "version": "0.3.0", @@ -2304,6 +3267,14 @@ "repeat-string": "^1.6.1" } }, + "to-through": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", + "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", + "requires": { + "through2": "^2.0.3" + } + }, "toastr": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/toastr/-/toastr-2.1.4.tgz", @@ -2312,47 +3283,61 @@ "jquery": ">=1.12.0" } }, + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, "unc-path-regex": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=" }, + "undertaker": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.2.1.tgz", + "integrity": "sha512-71WxIzDkgYk9ZS+spIB8iZXchFhAdEo2YU8xYqBYJ39DIUIqziK78ftm26eecoIY49X0J2MLhG4hr18Yp6/CMA==", + "requires": { + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "bach": "^1.0.0", + "collection-map": "^1.0.0", + "es6-weak-map": "^2.0.1", + "last-run": "^1.1.0", + "object.defaults": "^1.0.0", + "object.reduce": "^1.0.0", + "undertaker-registry": "^1.0.0" + } + }, + "undertaker-registry": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", + "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=" + }, "union-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", - "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", "requires": { "arr-union": "^3.1.0", "get-value": "^2.0.6", "is-extendable": "^0.1.1", - "set-value": "^0.4.3" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - }, - "set-value": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", - "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.1", - "to-object-path": "^0.3.0" - } - } + "set-value": "^2.0.1" } }, "unique-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", - "integrity": "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=" + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", + "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", + "requires": { + "json-stable-stringify-without-jsonify": "^1.0.1", + "through2-filter": "^3.0.0" + } }, "unset-value": { "version": "1.0.0", @@ -2387,14 +3372,14 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" } } }, + "upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==" + }, "urix": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", @@ -2405,17 +3390,19 @@ "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" }, - "user-home": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", - "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=" - }, "util": { "version": "0.10.4", "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", "requires": { "inherits": "2.0.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + } } }, "util-deprecate": { @@ -2424,72 +3411,76 @@ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "v8flags": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", - "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.3.tgz", + "integrity": "sha512-amh9CCg3ZxkzQ48Mhcb8iX7xpAfYJgePHxWMQCBWECpOSqJUXgY26ncA61UTV0BkPqfhcy6mzwCIoP4ygxpW8w==", + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "requires": { - "user-home": "^1.1.1" + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" } }, + "value-or-function": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", + "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=" + }, "vinyl": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", - "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", + "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", - "replace-ext": "0.0.1" + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" } }, "vinyl-fs": { - "version": "0.3.14", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", - "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", - "requires": { - "defaults": "^1.0.0", - "glob-stream": "^3.1.5", - "glob-watcher": "^0.0.6", - "graceful-fs": "^3.0.0", - "mkdirp": "^0.5.0", - "strip-bom": "^1.0.0", - "through2": "^0.6.1", - "vinyl": "^0.4.0" - }, - "dependencies": { - "clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=" - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "requires": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" - } - }, - "vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "requires": { - "clone": "^0.2.0", - "clone-stats": "^0.0.1" - } - } + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", + "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", + "requires": { + "fs-mkdirp-stream": "^1.0.0", + "glob-stream": "^6.1.0", + "graceful-fs": "^4.0.0", + "is-valid-glob": "^1.0.0", + "lazystream": "^1.0.0", + "lead": "^1.0.0", + "object.assign": "^4.0.4", + "pumpify": "^1.3.5", + "readable-stream": "^2.3.3", + "remove-bom-buffer": "^3.0.0", + "remove-bom-stream": "^1.2.0", + "resolve-options": "^1.1.0", + "through2": "^2.0.0", + "to-through": "^2.0.0", + "value-or-function": "^3.0.0", + "vinyl": "^2.0.0", + "vinyl-sourcemap": "^1.1.0" + } + }, + "vinyl-sourcemap": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", + "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", + "requires": { + "append-buffer": "^1.0.2", + "convert-source-map": "^1.5.0", + "graceful-fs": "^4.1.6", + "normalize-path": "^2.1.1", + "now-and-later": "^2.0.0", + "remove-bom-buffer": "^3.0.0", + "vinyl": "^2.0.0" } }, "which": { @@ -2500,15 +3491,62 @@ "isexe": "^2.0.0" } }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=" + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + }, + "yargs": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", + "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", + "requires": { + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^5.0.0" + } + }, + "yargs-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", + "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", + "requires": { + "camelcase": "^3.0.0" + } } } } diff --git a/modules/docs/app/VoloDocs.Web/package.json b/modules/docs/app/VoloDocs.Web/package.json index fca480e355..b711db27ba 100644 --- a/modules/docs/app/VoloDocs.Web/package.json +++ b/modules/docs/app/VoloDocs.Web/package.json @@ -6,4 +6,4 @@ "@abp/aspnetcore.mvc.ui.theme.basic": "^1.0.2", "@abp/docs": "^1.0.2" } -} \ 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 index 57ade1bb4b..1000091b65 100644 --- 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 @@ -4,11 +4,13 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Newtonsoft.Json; +using Volo.Abp; using Volo.Abp.Application.Services; using Volo.Abp.Caching; using Volo.Docs.Documents; using Volo.Docs.Documents.FullSearch.Elastic; using Volo.Docs.Projects; +using Volo.Extensions; namespace Volo.Docs.Admin.Documents { @@ -38,15 +40,19 @@ namespace Volo.Docs.Admin.Documents { var project = await _projectRepository.GetAsync(input.ProjectId); - var navigationFile = await GetDocumentAsync( + var navigationDocument = await GetDocumentAsync( project, project.NavigationDocumentName, input.LanguageCode, input.Version ); - var nav = JsonConvert.DeserializeObject(navigationFile.Content); - var leafs = nav.Items.GetAllNodes(x => x.Items) + if (!JsonConvertExtensions.TryDeserializeObject(navigationDocument.Content, out var navigation)) + { + throw new UserFriendlyException($"Cannot validate navigation file '{project.NavigationDocumentName}' for the project {project.Name}."); + } + + var leafs = navigation.Items.GetAllNodes(x => x.Items) .Where(x => x.IsLeaf && !x.Path.IsNullOrWhiteSpace()) .ToList(); 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 9863995d15..4e6138d260 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 @@ -7,9 +7,11 @@ using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Newtonsoft.Json; +using Volo.Abp; using Volo.Abp.Caching; using Volo.Docs.Documents.FullSearch.Elastic; using Volo.Docs.Projects; +using Volo.Extensions; namespace Volo.Docs.Documents { @@ -32,8 +34,8 @@ namespace Volo.Docs.Documents IDistributedCache languageCache, IDistributedCache resourceCache, IDistributedCache documentUpdateCache, - IHostEnvironment hostEnvironment, - IDocumentFullSearch documentFullSearch, + IHostEnvironment hostEnvironment, + IDocumentFullSearch documentFullSearch, IOptions docsElasticSearchOptions) { _projectRepository = projectRepository; @@ -82,7 +84,10 @@ namespace Volo.Docs.Documents input.Version ); - var navigationNode = JsonConvert.DeserializeObject(navigationDocument.Content); + if (!JsonConvertExtensions.TryDeserializeObject(navigationDocument.Content, out var navigationNode)) + { + throw new UserFriendlyException($"Cannot validate navigation file '{project.NavigationDocumentName}' for the project {project.Name}."); + } var leafs = navigationNode.Items.GetAllNodes(x => x.Items) .Where(x => !x.Path.IsNullOrWhiteSpace()) @@ -173,11 +178,16 @@ namespace Volo.Docs.Documents input.Version ); - return JsonConvert.DeserializeObject(document.Content); + if (!JsonConvertExtensions.TryDeserializeObject(document.Content, out var documentParameters)) + { + throw new UserFriendlyException($"Cannot validate document parameters file '{project.ParametersDocumentName}' for the project {project.Name}."); + } + + return documentParameters; } catch (DocumentNotFoundException) { - Logger.LogWarning($"Parameter file ({project.ParametersDocumentName}) not found."); + Logger.LogWarning($"Parameter file ({project.ParametersDocumentName}) not found!"); return new DocumentParametersDto(); } } diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/DocsDomainConsts.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/DocsDomainConsts.cs new file mode 100644 index 0000000000..ff6bd56ee4 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/DocsDomainConsts.cs @@ -0,0 +1,7 @@ +namespace Volo.Docs +{ + public class DocsDomainConsts + { + public static string LanguageConfigFileName = "docs-langs.json"; + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/FileSystem/Documents/FileSystemDocumentSource.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/FileSystem/Documents/FileSystemDocumentSource.cs index 3fa341a848..cc0f03a60a 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/FileSystem/Documents/FileSystemDocumentSource.cs +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/FileSystem/Documents/FileSystemDocumentSource.cs @@ -4,11 +4,13 @@ using System.IO; using System.Security; using System.Threading.Tasks; using Newtonsoft.Json; +using Volo.Abp; using Volo.Abp.Domain.Services; using Volo.Abp.IO; using Volo.Docs.Documents; using Volo.Docs.FileSystem.Projects; using Volo.Docs.Projects; +using Volo.Extensions; namespace Volo.Docs.FileSystem.Documents { @@ -22,7 +24,7 @@ namespace Volo.Docs.FileSystem.Documents var path = Path.Combine(projectFolder, languageCode, documentName); CheckDirectorySecurity(projectFolder, path); - + var content = await FileHelper.ReadAllTextAsync(path); var localDirectory = ""; @@ -55,10 +57,15 @@ namespace Volo.Docs.FileSystem.Documents public async Task GetLanguageListAsync(Project project, string version) { - var path = Path.Combine(project.GetFileSystemPath(), "docs-langs.json"); - var configAsJson = await FileHelper.ReadAllTextAsync(path); + var path = Path.Combine(project.GetFileSystemPath(), DocsDomainConsts.LanguageConfigFileName); + var configJsonContent = await FileHelper.ReadAllTextAsync(path); + + if (!JsonConvertExtensions.TryDeserializeObject(configJsonContent, out var languageConfig)) + { + throw new UserFriendlyException($"Cannot validate language config file '{DocsDomainConsts.LanguageConfigFileName}' for the project {project.Name}."); + } - return JsonConvert.DeserializeObject(configAsJson); + return languageConfig; } public async Task GetResource(Project project, string resourceName, string languageCode, string version) diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/GithubDocumentSource.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/GithubDocumentSource.cs index 3e287789e9..012fc7aed9 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/GithubDocumentSource.cs +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/GithubDocumentSource.cs @@ -10,6 +10,8 @@ using Volo.Docs.GitHub.Projects; using Volo.Docs.Projects; using Newtonsoft.Json.Linq; using Octokit; +using Volo.Abp; +using Volo.Extensions; using Project = Volo.Docs.Projects.Project; namespace Volo.Docs.GitHub.Documents @@ -55,11 +57,11 @@ namespace Volo.Docs.GitHub.Documents var lastSignificantUpdateTime = !isNavigationDocument && !isParameterDocument && version == project.LatestVersionBranchName ? await GetLastSignificantUpdateTime( fileCommits, - project, + project, project.GetGitHubInnerUrl(languageCode, documentName), lastKnownSignificantUpdateTime, documentCreationTime - ) ?? lastKnownSignificantUpdateTime + ) ?? lastKnownSignificantUpdateTime : null; var document = new Document(GuidGenerator.Create(), @@ -179,11 +181,16 @@ namespace Volo.Docs.GitHub.Documents var rootUrl = project.GetGitHubUrl(version); var userAgent = project.GetGithubUserAgentOrNull(); - var url = CalculateRawRootUrl(rootUrl) + "docs-langs.json"; + var url = CalculateRawRootUrl(rootUrl) + DocsDomainConsts.LanguageConfigFileName; var configAsJson = await DownloadWebContentAsStringAsync(url, token, userAgent); - return JsonConvert.DeserializeObject(configAsJson); + if (!JsonConvertExtensions.TryDeserializeObject(configAsJson, out var languageConfig)) + { + throw new UserFriendlyException($"Cannot validate language config file '{DocsDomainConsts.LanguageConfigFileName}' for the project {project.Name} - v{version}."); + } + + return languageConfig; } private async Task> GetReleasesAsync(Project project) diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Extensions/NewtonsoftJsonExtensions.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Extensions/NewtonsoftJsonExtensions.cs new file mode 100644 index 0000000000..200baa9c2c --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Extensions/NewtonsoftJsonExtensions.cs @@ -0,0 +1,22 @@ +using System; +using Newtonsoft.Json; + +namespace Volo.Extensions +{ + public static class JsonConvertExtensions + { + public static bool TryDeserializeObject(string jsonContent, out T result) + { + try + { + result = JsonConvert.DeserializeObject(jsonContent); + return true; + } + catch + { + result = default; + return false; + } + } + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Web/HtmlConverting/ScribanDocumentSectionRenderer.cs b/modules/docs/src/Volo.Docs.Web/HtmlConverting/ScribanDocumentSectionRenderer.cs index 4a4f3b2142..990f2a0dec 100644 --- a/modules/docs/src/Volo.Docs.Web/HtmlConverting/ScribanDocumentSectionRenderer.cs +++ b/modules/docs/src/Volo.Docs.Web/HtmlConverting/ScribanDocumentSectionRenderer.cs @@ -7,16 +7,17 @@ using Newtonsoft.Json; using Scriban; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; -using Volo.Docs.Documents; +using Volo.Abp; +using Volo.Extensions; namespace Volo.Docs.HtmlConverting { public class ScribanDocumentSectionRenderer : IDocumentSectionRenderer { - private const string jsonOpener = "````json"; - private const string jsonCloser = "````"; - private const string docs_param = "//[doc-params]"; - private const string docs_templates = "//[doc-template]"; + private const string JsonOpener = "````json"; + private const string JsonCloser = "````"; + private const string DocsParam = "//[doc-params]"; + private const string DocsTemplates = "//[doc-template]"; public ILogger Logger { get; set; } @@ -40,6 +41,7 @@ namespace Volo.Docs.HtmlConverting } var result = await scribanTemplate.RenderAsync(parameters); + return RemoveOptionsJson(result); } @@ -47,7 +49,7 @@ namespace Volo.Docs.HtmlConverting { try { - if (!document.Contains(jsonOpener) || !document.Contains(docs_param)) + if (!document.Contains(JsonOpener) || !document.Contains(DocsParam)) { return new Dictionary>(); } @@ -59,9 +61,14 @@ namespace Volo.Docs.HtmlConverting return new Dictionary>(); } - var pureJson = insideJsonSection.Replace(docs_param, "").Trim(); + var pureJson = insideJsonSection.Replace(DocsParam, "").Trim(); + + if (!JsonConvertExtensions.TryDeserializeObject>>(pureJson, out var availableParameters)) + { + throw new UserFriendlyException("ERROR-20200327: Cannot validate JSON content for `AvailableParameters`!"); + } - return JsonConvert.DeserializeObject>>(pureJson); + return await Task.FromResult(availableParameters); } catch (Exception) { @@ -70,12 +77,13 @@ namespace Volo.Docs.HtmlConverting } } - private string RemoveOptionsJson(string document) + private static string RemoveOptionsJson(string document) { var orgDocument = document; + try { - if (!document.Contains(jsonOpener) || !document.Contains(docs_param)) + if (!document.Contains(JsonOpener) || !document.Contains(DocsParam)) { return orgDocument; } @@ -88,8 +96,9 @@ namespace Volo.Docs.HtmlConverting } return document.Remove( - jsonBeginningIndex - jsonOpener.Length, (jsonEndingIndex + jsonCloser.Length) - (jsonBeginningIndex - jsonOpener.Length) - ); + jsonBeginningIndex - JsonOpener.Length, + (jsonEndingIndex + JsonCloser.Length) - (jsonBeginningIndex - JsonOpener.Length) + ); } catch (Exception) { @@ -97,25 +106,25 @@ namespace Volo.Docs.HtmlConverting } } - private (int, int, string) GetJsonBeginEndIndexesAndPureJson(string document) + private static (int, int, string) GetJsonBeginEndIndexesAndPureJson(string document) { var searchedIndex = 0; while (searchedIndex < document.Length) { - var jsonBeginningIndex = document.Substring(searchedIndex).IndexOf(jsonOpener, StringComparison.Ordinal) + jsonOpener.Length + searchedIndex; + var jsonBeginningIndex = document.Substring(searchedIndex).IndexOf(JsonOpener, StringComparison.Ordinal) + JsonOpener.Length + searchedIndex; if (jsonBeginningIndex < 0) { return (-1, -1, ""); } - var jsonEndingIndex = document.Substring(jsonBeginningIndex).IndexOf(jsonCloser, StringComparison.Ordinal) + jsonBeginningIndex; + var jsonEndingIndex = document.Substring(jsonBeginningIndex).IndexOf(JsonCloser, StringComparison.Ordinal) + jsonBeginningIndex; var insideJsonSection = document[jsonBeginningIndex..jsonEndingIndex]; - if (insideJsonSection.IndexOf(docs_param) < 0) + if (insideJsonSection.IndexOf(DocsParam, StringComparison.Ordinal) < 0) { - searchedIndex = jsonEndingIndex + jsonCloser.Length; + searchedIndex = jsonEndingIndex + JsonCloser.Length; continue; } @@ -129,68 +138,84 @@ namespace Volo.Docs.HtmlConverting { var templates = new List(); - while (documentContent.Contains(jsonOpener)) + while (documentContent.Contains(JsonOpener)) { var afterJsonOpener = documentContent.Substring( - documentContent.IndexOf(jsonOpener, StringComparison.Ordinal) + jsonOpener.Length); + documentContent.IndexOf(JsonOpener, StringComparison.Ordinal) + JsonOpener.Length + ); var betweenJsonOpenerAndCloser = afterJsonOpener.Substring(0, - afterJsonOpener.IndexOf(jsonCloser, StringComparison.Ordinal)); + afterJsonOpener.IndexOf(JsonCloser, StringComparison.Ordinal) + ); documentContent = afterJsonOpener.Substring( - afterJsonOpener.IndexOf(jsonCloser, StringComparison.Ordinal) + jsonCloser.Length); + afterJsonOpener.IndexOf(JsonCloser, StringComparison.Ordinal) + JsonCloser.Length + ); - if (!betweenJsonOpenerAndCloser.Contains(docs_templates)) + if (!betweenJsonOpenerAndCloser.Contains(DocsTemplates)) { continue; } - var json = betweenJsonOpenerAndCloser.Substring(betweenJsonOpenerAndCloser.IndexOf(docs_templates, StringComparison.Ordinal) + docs_templates.Length); + var json = betweenJsonOpenerAndCloser.Substring(betweenJsonOpenerAndCloser.IndexOf(DocsTemplates, StringComparison.Ordinal) + DocsTemplates.Length); - var template = JsonConvert.DeserializeObject(json); + if (!JsonConvertExtensions.TryDeserializeObject(json, out var template)) + { + throw new UserFriendlyException($"ERROR-20200327: Cannot validate JSON content for `AvailableParameters`!"); + } templates.Add(template); } - return templates; + return await Task.FromResult(templates); } - private string SetPartialTemplates(string document, List templates) + private static string SetPartialTemplates(string document, IReadOnlyCollection templates) { var newDocument = new StringBuilder(); - while (document.Contains(jsonOpener)) + while (document.Contains(JsonOpener)) { var beforeJson = document.Substring(0, - document.IndexOf(jsonOpener, StringComparison.Ordinal) + jsonOpener.Length); + document.IndexOf(JsonOpener, StringComparison.Ordinal) + JsonOpener.Length + ); var afterJsonOpener = document.Substring( - document.IndexOf(jsonOpener, StringComparison.Ordinal) + jsonOpener.Length); + document.IndexOf(JsonOpener, StringComparison.Ordinal) + JsonOpener.Length + ); var betweenJsonOpenerAndCloser = afterJsonOpener.Substring(0, - afterJsonOpener.IndexOf(jsonCloser, StringComparison.Ordinal)); + afterJsonOpener.IndexOf(JsonCloser, StringComparison.Ordinal) + ); - if (!betweenJsonOpenerAndCloser.Contains(docs_templates)) + if (!betweenJsonOpenerAndCloser.Contains(DocsTemplates)) { document = afterJsonOpener.Substring( - afterJsonOpener.IndexOf(jsonCloser, StringComparison.Ordinal) + jsonCloser.Length); - newDocument.Append(beforeJson + betweenJsonOpenerAndCloser + jsonCloser); + afterJsonOpener.IndexOf(JsonCloser, StringComparison.Ordinal) + JsonCloser.Length + ); + + newDocument.Append(beforeJson + betweenJsonOpenerAndCloser + JsonCloser); continue; } - var json = betweenJsonOpenerAndCloser.Substring(betweenJsonOpenerAndCloser.IndexOf(docs_templates, StringComparison.Ordinal) + docs_templates.Length); - - var templatePath = JsonConvert.DeserializeObject(json)?.Path; + var json = betweenJsonOpenerAndCloser.Substring( + betweenJsonOpenerAndCloser.IndexOf(DocsTemplates, StringComparison.Ordinal) + DocsTemplates.Length + ); - var template = templates.FirstOrDefault(t => t.Path == templatePath); + if (JsonConvertExtensions.TryDeserializeObject(json, out var documentPartialTemplateWithValuesDto)) + { + var template = templates.FirstOrDefault(t => t.Path == documentPartialTemplateWithValuesDto.Path); - var beforeTemplate = document.Substring(0, - document.IndexOf(jsonOpener, StringComparison.Ordinal)); + var beforeTemplate = document.Substring(0, + document.IndexOf(JsonOpener, StringComparison.Ordinal) + ); - newDocument.Append(beforeTemplate + template?.Content + jsonCloser); + newDocument.Append(beforeTemplate + template?.Content + JsonCloser); - document = afterJsonOpener.Substring( - afterJsonOpener.IndexOf(jsonCloser, StringComparison.Ordinal) + jsonCloser.Length); + document = afterJsonOpener.Substring( + afterJsonOpener.IndexOf(JsonCloser, StringComparison.Ordinal) + JsonCloser.Length + ); + } } newDocument.Append(document); diff --git a/modules/docs/src/Volo.Docs.Web/Volo.Docs.Web.csproj b/modules/docs/src/Volo.Docs.Web/Volo.Docs.Web.csproj index ed9cf98af8..afec611259 100644 --- a/modules/docs/src/Volo.Docs.Web/Volo.Docs.Web.csproj +++ b/modules/docs/src/Volo.Docs.Web/Volo.Docs.Web.csproj @@ -19,6 +19,7 @@ + From 5c541897808bd96f08a21beac8247b2dbfe61587 Mon Sep 17 00:00:00 2001 From: Alper Ebicoglu Date: Fri, 27 Mar 2020 12:34:18 +0300 Subject: [PATCH 017/151] add home page #3381 --- .../Controllers/HomeController.cs | 19 ------ .../docs/app/VoloDocs.Web/Pages/Index.cshtml | 23 ++++++++ .../app/VoloDocs.Web/Pages/Index.cshtml.cs | 59 +++++++++++++++++++ 3 files changed, 82 insertions(+), 19 deletions(-) delete mode 100644 modules/docs/app/VoloDocs.Web/Controllers/HomeController.cs create mode 100644 modules/docs/app/VoloDocs.Web/Pages/Index.cshtml create mode 100644 modules/docs/app/VoloDocs.Web/Pages/Index.cshtml.cs diff --git a/modules/docs/app/VoloDocs.Web/Controllers/HomeController.cs b/modules/docs/app/VoloDocs.Web/Controllers/HomeController.cs deleted file mode 100644 index 17c6550502..0000000000 --- a/modules/docs/app/VoloDocs.Web/Controllers/HomeController.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Volo.Abp.AspNetCore.Mvc; - -namespace VoloDocs.Web.Controllers -{ - public class HomeController : AbpController - { - public void Index() - { - //if (!_urlUiOptions.RoutePrefix.IsNullOrWhiteSpace()) - //{ - // return Redirect("." + _urlUiOptions.RoutePrefix); - //} - - //return Page(); - - //return Redirect("/en/abp/latest"); - } - } -} diff --git a/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml b/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml new file mode 100644 index 0000000000..0a212f1499 --- /dev/null +++ b/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml @@ -0,0 +1,23 @@ +@page +@model VoloDocs.Web.Pages.IndexModel +@{ +} + +@if (!Model.Projects.Any()) +{ + + No projects found!
+ See documentation to see how you can create a new one. +
+} +else +{ +

Projects

+ + + @foreach (var project in Model.Projects) + { + @project.Name + } + +} \ No newline at end of file diff --git a/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml.cs b/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml.cs new file mode 100644 index 0000000000..537d650f83 --- /dev/null +++ b/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; +using Microsoft.Extensions.Options; +using Volo.Docs; +using Volo.Docs.Projects; + +namespace VoloDocs.Web.Pages +{ + public class IndexModel : PageModel + { + public IReadOnlyList Projects { get; set; } + + private readonly DocsUiOptions _urlUiOptions; + + private readonly IProjectAppService _projectAppService; + + public IndexModel(IOptions urlOptions, IProjectAppService projectAppService) + { + _projectAppService = projectAppService; + _urlUiOptions = urlOptions.Value; + } + + public async Task OnGetAsync() + { + var projects = await _projectAppService.GetListAsync(); + + if (projects.Items.Count == 1) + { + return await RedirectToProjectAsync(projects.Items.First()); + } + else if (projects.Items.Count > 1) + { + Projects = projects.Items; + } + + return Page(); + } + + private async Task RedirectToProjectAsync(ProjectDto project, string language = "en", string version = null) + { + var path = GetUrlForProject(project, language, version); + return await Task.FromResult(Redirect(path)); + } + + //Eg: "/en/abp/latest" + public string GetUrlForProject(ProjectDto project, string language = "en", string version = null) + { + return "." + + _urlUiOptions.RoutePrefix.EnsureStartsWith('/').EnsureEndsWith('/') + + language.EnsureEndsWith('/') + + project.ShortName.EnsureEndsWith('/') + + (version ?? DocsAppConsts.Latest); + } + } +} From e08290b1c5ac4456c21c6cb6760427d50579a0a3 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Fri, 27 Mar 2020 13:52:01 +0300 Subject: [PATCH 018/151] docs: add how to replace a layout section to component-replacement.md --- docs/en/UI/Angular/Component-Replacement.md | 53 +++++++++++++++++++-- 1 file changed, 50 insertions(+), 3 deletions(-) diff --git a/docs/en/UI/Angular/Component-Replacement.md b/docs/en/UI/Angular/Component-Replacement.md index b17c61ae73..d718b46117 100644 --- a/docs/en/UI/Angular/Component-Replacement.md +++ b/docs/en/UI/Angular/Component-Replacement.md @@ -1,10 +1,10 @@ -# Component Replacement +## Component Replacement You can replace some ABP components with your custom components. The reason that you **can replace** but **cannot customize** default ABP components is disabling or changing a part of that component can cause problems. So we named those components as _Replaceable Components_. -## How to Replace a Component +### How to Replace a Component Create a new component that you want to use instead of an ABP component. Add that component to `declarations` and `entryComponents` in the `AppModule`. @@ -29,7 +29,54 @@ export class AppComponent { ![Example Usage](./images/component-replacement.gif) -## Available Replaceable Components + +### How to Replace a Layout + +Each ABP theme module has 3 layouts named `ApplicationLayoutComponent`, `AccountLayoutComponent`, `EmptyLayoutComponent`. These layouts can be replaced with the same way. + +> A layout component template should contain `` element. + +The below example describes how to replace the `ApplicationLayoutComponent`: + +Run the following command to generate a layout in `angular` folder: + +```bash +yarn ng generate component shared/my-application-layout --export --entryComponent + +# You don't need the --entryComponent option in Angular 9 +``` + +Add the following code in your layout template (`my-layout.component.html`) where you want the page to be loaded. + +```html + +``` + +Open the `app.component.ts` and add the below content: + +```js +import { ..., AddReplaceableComponent } from '@abp/ng.core'; // imported AddReplaceableComponent +import { MyApplicationLayoutComponent } from './shared/my-application-layout/my-application-layout.component'; // imported MyApplicationLayoutComponent +import { Store } from '@ngxs/store'; // imported Store +//... +export class AppComponent { + constructor(..., private store: Store) {} // injected Store + + ngOnInit() { + // added below content + this.store.dispatch( + new AddReplaceableComponent({ + component: MyApplicationLayoutComponent, + key: 'Theme.ApplicationLayoutComponent', + }), + ); + + //... + } +} +``` + +### Available Replaceable Components | Component key | Description | | -------------------------------------------------- | --------------------------------------------- | From 0ccce0bbf999b95ff224e8c8ca78046c937bf0c5 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Fri, 27 Mar 2020 13:52:17 +0300 Subject: [PATCH 019/151] docs: fix the links --- docs/en/UI/Angular/Service-Proxies.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/en/UI/Angular/Service-Proxies.md b/docs/en/UI/Angular/Service-Proxies.md index 97b43b7513..6209350349 100644 --- a/docs/en/UI/Angular/Service-Proxies.md +++ b/docs/en/UI/Angular/Service-Proxies.md @@ -25,9 +25,9 @@ The files generated with the `--module all` option like below: ### Services -Each generated service matches a back-end controller. The services methods call back-end APIs via [RestService](./Http-Requests.md#restservice). +Each generated service matches a back-end controller. The services methods call back-end APIs via [RestService](./Http-Requests#restservice). -A variable named `apiName` (available as of v2.4) is defined in each service. `apiName` matches the module's RemoteServiceName. This variable passes to the `RestService` as a parameter at each request. If there is no microservice API defined in the environment, `RestService` uses the default. See [getting a specific API endpoint from application config](./Http-Requests.md#how-to-get-a-specific-api-endpoint-from-application-config) +A variable named `apiName` (available as of v2.4) is defined in each service. `apiName` matches the module's RemoteServiceName. This variable passes to the `RestService` as a parameter at each request. If there is no microservice API defined in the environment, `RestService` uses the default. See [getting a specific API endpoint from application config](./Http-Requests#how-to-get-a-specific-api-endpoint-from-application-config) The `providedIn` property of the services is defined as `'root'`. Therefore no need to add a service as a provider to a module. You can use a service by injecting it into a constructor as shown below: @@ -64,4 +64,4 @@ Initial values ​​can optionally be passed to each class constructor. ## What's Next? -* [HTTP Requests](./Http-Requests.md) +* [HTTP Requests](./Http-Requests) From 8d71b74281dd6fac4279970d14c47806c86e50ba Mon Sep 17 00:00:00 2001 From: Arman Ozak Date: Fri, 27 Mar 2020 14:31:09 +0300 Subject: [PATCH 020/151] style: add prettierrc and rules matching other angular projects --- templates/module/angular/.prettierrc | 5 +++ .../module/angular/src/app/app.module.ts | 42 +++++++++---------- 2 files changed, 26 insertions(+), 21 deletions(-) create mode 100644 templates/module/angular/.prettierrc diff --git a/templates/module/angular/.prettierrc b/templates/module/angular/.prettierrc new file mode 100644 index 0000000000..5e2863a11f --- /dev/null +++ b/templates/module/angular/.prettierrc @@ -0,0 +1,5 @@ +{ + "printWidth": 100, + "singleQuote": true, + "trailingComma": "all" +} diff --git a/templates/module/angular/src/app/app.module.ts b/templates/module/angular/src/app/app.module.ts index 2705a3318b..93e09321ec 100644 --- a/templates/module/angular/src/app/app.module.ts +++ b/templates/module/angular/src/app/app.module.ts @@ -1,20 +1,20 @@ -import { AccountConfigModule } from "@abp/ng.account.config"; -import { CoreModule } from "@abp/ng.core"; -import { IdentityConfigModule } from "@abp/ng.identity.config"; -import { SettingManagementConfigModule } from "@abp/ng.setting-management.config"; -import { TenantManagementConfigModule } from "@abp/ng.tenant-management.config"; -import { ThemeSharedModule } from "@abp/ng.theme.shared"; -import { NgModule } from "@angular/core"; -import { BrowserModule } from "@angular/platform-browser"; -import { BrowserAnimationsModule } from "@angular/platform-browser/animations"; -import { NgxsLoggerPluginModule } from "@ngxs/logger-plugin"; -import { NgxsModule } from "@ngxs/store"; -import { OAuthModule } from "angular-oauth2-oidc"; -import { environment } from "../environments/environment"; -import { AppRoutingModule } from "./app-routing.module"; -import { AppComponent } from "./app.component"; -import { SharedModule } from "./shared/shared.module"; -import { MyProjectNameConfigModule } from "../../projects/my-project-name-config/src/public-api"; +import { AccountConfigModule } from '@abp/ng.account.config'; +import { CoreModule } from '@abp/ng.core'; +import { IdentityConfigModule } from '@abp/ng.identity.config'; +import { SettingManagementConfigModule } from '@abp/ng.setting-management.config'; +import { TenantManagementConfigModule } from '@abp/ng.tenant-management.config'; +import { ThemeSharedModule } from '@abp/ng.theme.shared'; +import { NgModule } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { NgxsLoggerPluginModule } from '@ngxs/logger-plugin'; +import { NgxsModule } from '@ngxs/store'; +import { OAuthModule } from 'angular-oauth2-oidc'; +import { MyProjectNameConfigModule } from '../../projects/my-project-name-config/src/public-api'; +import { environment } from '../environments/environment'; +import { AppRoutingModule } from './app-routing.module'; +import { AppComponent } from './app.component'; +import { SharedModule } from './shared/shared.module'; const LOGGERS = [NgxsLoggerPluginModule.forRoot({ disabled: false })]; @@ -23,11 +23,11 @@ const LOGGERS = [NgxsLoggerPluginModule.forRoot({ disabled: false })]; imports: [ ThemeSharedModule.forRoot(), CoreModule.forRoot({ - environment + environment, }), OAuthModule.forRoot(), NgxsModule.forRoot([]), - AccountConfigModule.forRoot({ redirectUrl: "/" }), + AccountConfigModule.forRoot({ redirectUrl: '/' }), IdentityConfigModule, TenantManagementConfigModule, SettingManagementConfigModule, @@ -37,8 +37,8 @@ const LOGGERS = [NgxsLoggerPluginModule.forRoot({ disabled: false })]; AppRoutingModule, SharedModule, - ...(environment.production ? [] : LOGGERS) + ...(environment.production ? [] : LOGGERS), ], - bootstrap: [AppComponent] + bootstrap: [AppComponent], }) export class AppModule {} From d72aada3b5bcfe05e9c33f60e1658d83c740bf9f Mon Sep 17 00:00:00 2001 From: Alper Ebicoglu Date: Fri, 27 Mar 2020 15:02:18 +0300 Subject: [PATCH 021/151] refactor GithubRepositoryManager #3381 --- .../Documents/GithubRepositoryManager.cs | 68 +++++++++---------- 1 file changed, 32 insertions(+), 36 deletions(-) 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 4627800832..754263989f 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 @@ -23,54 +23,30 @@ namespace Volo.Docs.GitHub.Documents public async Task GetFileRawStringContentAsync(string rawUrl, string token, string userAgent) { - var httpClient = _clientFactory.CreateClient(HttpClientName); - if (!token.IsNullOrWhiteSpace()) - { - httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Token", token); - } - - if (!userAgent.IsNullOrWhiteSpace()) - { - httpClient.DefaultRequestHeaders.Add("User-Agent", userAgent); - } + using var httpClient = CreateHttpClient(token, userAgent); return await httpClient.GetStringAsync(new Uri(rawUrl)); } public async Task GetFileRawByteArrayContentAsync(string rawUrl, string token, string userAgent) { - var httpClient = _clientFactory.CreateClient(HttpClientName); - if (!token.IsNullOrWhiteSpace()) - { - httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Token", token); - } - - if (!userAgent.IsNullOrWhiteSpace()) - { - httpClient.DefaultRequestHeaders.Add("User-Agent", userAgent); - } + using var httpClient = CreateHttpClient(token, userAgent); return await httpClient.GetByteArrayAsync(new Uri(rawUrl)); } - + public async Task> GetReleasesAsync(string name, string repositoryName, string token) { - var client = token.IsNullOrWhiteSpace() - ? new GitHubClient(new ProductHeaderValue(name)) - : new GitHubClient(new ProductHeaderValue(name), new InMemoryCredentialStore(new Credentials(token))); + var client = GetGitHubClient(name, token); + + var releases = await client.Repository.Release.GetAll(name, repositoryName); - return (await client - .Repository - .Release - .GetAll(name, repositoryName)).ToList(); + return releases.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 client = GetGitHubClient(name, 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); @@ -78,12 +54,32 @@ namespace Volo.Docs.GitHub.Documents public async Task GetSingleCommitsAsync(string name, string repositoryName, string sha, string token) { - var client = token.IsNullOrWhiteSpace() - ? new GitHubClient(new ProductHeaderValue(name)) - : new GitHubClient(new ProductHeaderValue(name), new InMemoryCredentialStore(new Credentials(token))); - + var client = GetGitHubClient(name, token); var repo = await client.Repository.Get(name, repositoryName); return await client.Repository.Commit.Get(repo.Id, sha); } + + private HttpClient CreateHttpClient(string token, string userAgent) + { + var httpClient = _clientFactory.CreateClient(HttpClientName); + if (!token.IsNullOrWhiteSpace()) + { + httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Token", token); + } + + if (!userAgent.IsNullOrWhiteSpace()) + { + httpClient.DefaultRequestHeaders.Add("User-Agent", userAgent); + } + + return httpClient; + } + + private static GitHubClient GetGitHubClient(string name, string token) + { + return token.IsNullOrWhiteSpace() + ? new GitHubClient(new ProductHeaderValue(name)) + : new GitHubClient(new ProductHeaderValue(name), new InMemoryCredentialStore(new Credentials(token))); + } } } From bb226783c5bda77bb08af71e65de49f73b77f466 Mon Sep 17 00:00:00 2001 From: Alper Ebicoglu Date: Fri, 27 Mar 2020 15:03:22 +0300 Subject: [PATCH 022/151] #3381 --- .../Volo/Docs/GitHub/Documents/GithubRepositoryManager.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) 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 754263989f..ef21353236 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 @@ -24,24 +24,19 @@ namespace Volo.Docs.GitHub.Documents public async Task GetFileRawStringContentAsync(string rawUrl, string token, string userAgent) { using var httpClient = CreateHttpClient(token, userAgent); - return await httpClient.GetStringAsync(new Uri(rawUrl)); } public async Task GetFileRawByteArrayContentAsync(string rawUrl, string token, string userAgent) { using var httpClient = CreateHttpClient(token, userAgent); - return await httpClient.GetByteArrayAsync(new Uri(rawUrl)); } public async Task> GetReleasesAsync(string name, string repositoryName, string token) { var client = GetGitHubClient(name, token); - - var releases = await client.Repository.Release.GetAll(name, repositoryName); - - return releases.ToList(); + return await client.Repository.Release.GetAll(name, repositoryName); } public async Task> GetFileCommitsAsync(string name, string repositoryName, string version, string filename, string token) From 2f7e69e1a27f2dc1732e4a55ef98d752b6f86f20 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Fri, 27 Mar 2020 15:06:07 +0300 Subject: [PATCH 023/151] refactor: reduce codes and increase readability --- .../components/dynamic-layout.component.ts | 48 +++++++------------ 1 file changed, 16 insertions(+), 32 deletions(-) diff --git a/npm/ng-packs/packages/core/src/lib/components/dynamic-layout.component.ts b/npm/ng-packs/packages/core/src/lib/components/dynamic-layout.component.ts index fc3926a1ea..e835dd777d 100644 --- a/npm/ng-packs/packages/core/src/lib/components/dynamic-layout.component.ts +++ b/npm/ng-packs/packages/core/src/lib/components/dynamic-layout.component.ts @@ -1,15 +1,13 @@ -import { Component, Input, OnDestroy, Type, Injector } from '@angular/core'; +import { Component, OnDestroy, Type } from '@angular/core'; import { ActivatedRoute, NavigationEnd, Router, UrlSegment } from '@angular/router'; -import { Select, Store } from '@ngxs/store'; -import { Observable, combineLatest } from 'rxjs'; +import { Store } from '@ngxs/store'; import snq from 'snq'; import { eLayoutType } from '../enums/common'; -import { Config } from '../models/config'; import { ABP } from '../models/common'; +import { ReplaceableComponents } from '../models/replaceable-components'; import { ConfigState } from '../states/config.state'; -import { takeUntilDestroy } from '../utils/rxjs-utils'; import { ReplaceableComponentsState } from '../states/replaceable-components.state'; -import { ReplaceableComponents } from '../models/replaceable-components'; +import { takeUntilDestroy } from '../utils/rxjs-utils'; @Component({ selector: 'abp-dynamic-layout', @@ -22,23 +20,9 @@ import { ReplaceableComponents } from '../models/replaceable-components'; `, }) export class DynamicLayoutComponent implements OnDestroy { - @Select(ReplaceableComponentsState.getComponent('Theme.ApplicationLayoutComponent')) - applicationLayout$: Observable; - - @Select(ReplaceableComponentsState.getComponent('Theme.AccountLayoutComponent')) - accountLayout$: Observable; - - @Select(ReplaceableComponentsState.getComponent('Theme.EmptyLayoutComponent')) - emptyLayout$: Observable; - layout: Type; - layouts = {} as { [key in eLayoutType]: Type }; - - expectedLayout: eLayoutType = eLayoutType.empty; - constructor(private router: Router, private route: ActivatedRoute, private store: Store) { - this.listenToLayouts(); const { routes } = this.store.selectSnapshot(ConfigState.getAll); router.events.pipe(takeUntilDestroy(this)).subscribe(event => { @@ -47,25 +31,25 @@ export class DynamicLayoutComponent implements OnDestroy { { path: router.url.replace('/', '') }, ] as any); - this.expectedLayout = + const layouts = { + application: this.getComponent('Theme.ApplicationLayoutComponent'), + account: this.getComponent('Theme.AccountLayoutComponent'), + empty: this.getComponent('Theme.EmptyApplicationLayoutComponent'), + }; + + const expectedLayout = (this.route.snapshot.data || {}).layout || findLayout(segments, routes); - this.layout = this.layouts[this.expectedLayout]; + this.layout = layouts[expectedLayout].component; } }); } - ngOnDestroy() {} - - listenToLayouts() { - combineLatest(this.applicationLayout$, this.accountLayout$, this.emptyLayout$) - .pipe(takeUntilDestroy(this)) - .subscribe(([application, account, empty]) => { - this.layouts.application = application.component; - this.layouts.account = account.component; - this.layouts.empty = empty.component; - }); + getComponent(key: string): ReplaceableComponents.ReplaceableComponent { + return this.store.selectSnapshot(ReplaceableComponentsState.getComponent(key)); } + + ngOnDestroy() {} } function findLayout(segments: UrlSegment[], routes: ABP.FullRoute[]): eLayoutType { From 91668b35f423dcca63be06f972e23a8a9e6bfb22 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Fri, 27 Mar 2020 15:14:00 +0300 Subject: [PATCH 024/151] =?UTF-8?q?refactor(core):=20make=20getComponent?= =?UTF-8?q?=20method=20in=20DynamicCompo=C4=B1nent=20private?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/src/lib/components/dynamic-layout.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/npm/ng-packs/packages/core/src/lib/components/dynamic-layout.component.ts b/npm/ng-packs/packages/core/src/lib/components/dynamic-layout.component.ts index e835dd777d..71dd0f3fdf 100644 --- a/npm/ng-packs/packages/core/src/lib/components/dynamic-layout.component.ts +++ b/npm/ng-packs/packages/core/src/lib/components/dynamic-layout.component.ts @@ -45,7 +45,7 @@ export class DynamicLayoutComponent implements OnDestroy { }); } - getComponent(key: string): ReplaceableComponents.ReplaceableComponent { + private getComponent(key: string): ReplaceableComponents.ReplaceableComponent { return this.store.selectSnapshot(ReplaceableComponentsState.getComponent(key)); } From 1f2418b8721e0d991f2289bc4c57ca666de14c60 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Fri, 27 Mar 2020 15:48:37 +0300 Subject: [PATCH 025/151] fix(core): fix component key in dynamic layout --- .../core/src/lib/components/dynamic-layout.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/npm/ng-packs/packages/core/src/lib/components/dynamic-layout.component.ts b/npm/ng-packs/packages/core/src/lib/components/dynamic-layout.component.ts index 71dd0f3fdf..c07f11580f 100644 --- a/npm/ng-packs/packages/core/src/lib/components/dynamic-layout.component.ts +++ b/npm/ng-packs/packages/core/src/lib/components/dynamic-layout.component.ts @@ -34,7 +34,7 @@ export class DynamicLayoutComponent implements OnDestroy { const layouts = { application: this.getComponent('Theme.ApplicationLayoutComponent'), account: this.getComponent('Theme.AccountLayoutComponent'), - empty: this.getComponent('Theme.EmptyApplicationLayoutComponent'), + empty: this.getComponent('Theme.EmptyLayoutComponent'), }; const expectedLayout = From 4c17ed4180c33d457436426ab557fd0ccfb30c8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ahmet=20=C3=87otur?= Date: Fri, 27 Mar 2020 16:07:00 +0300 Subject: [PATCH 026/151] entitychanges ef core implemented --- .../Abp/AuditLogging/IAuditLogRepository.cs | 23 ++++++++ ...bpAuditLoggingEfCoreQueryableExtensions.cs | 12 ++++ .../EfCoreAuditLogRepository.cs | 56 ++++++++++++++++++ .../IAuditLoggingDbContext.cs | 2 + .../MongoDB/MongoAuditLogRepository.cs | 58 +++++++++++++++++++ 5 files changed, 151 insertions(+) diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/IAuditLogRepository.cs b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/IAuditLogRepository.cs index fb676fe288..dbf3692b29 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/IAuditLogRepository.cs +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/IAuditLogRepository.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Net; using System.Threading; using System.Threading.Tasks; +using Volo.Abp.Auditing; using Volo.Abp.Domain.Repositories; namespace Volo.Abp.AuditLogging @@ -44,5 +45,27 @@ namespace Volo.Abp.AuditLogging Task> GetAverageExecutionDurationPerDayAsync( DateTime startDate, DateTime endDate); + + Task> GetEntityChangeListAsync( + string sorting = null, + int maxResultCount = 50, + int skipCount = 0, + Guid? auditLogId = null, + DateTime? startTime = null, + DateTime? endTime = null, + EntityChangeType? changeType = null, + string entityId = null, + string entityTypeFullName = null, + bool includeDetails = false, + CancellationToken cancellationToken = default); + + Task GetEntityChangeCountAsync( + Guid? auditLogId = null, + DateTime? startTime = null, + DateTime? endTime = null, + EntityChangeType? changeType = null, + string entityId = null, + string entityTypeFullName = null, + CancellationToken cancellationToken = default); } } diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/AbpAuditLoggingEfCoreQueryableExtensions.cs b/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/AbpAuditLoggingEfCoreQueryableExtensions.cs index 27445045e7..6dc4bfadb8 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/AbpAuditLoggingEfCoreQueryableExtensions.cs +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/AbpAuditLoggingEfCoreQueryableExtensions.cs @@ -18,5 +18,17 @@ namespace Volo.Abp.AuditLogging .Include(x => x.Actions) .Include(x => x.EntityChanges).ThenInclude(ec=>ec.PropertyChanges); } + + public static IQueryable IncludeDetails( + this IQueryable queryable, + bool include = true) + { + if (!include) + { + return queryable; + } + + return queryable.Include(x => x.PropertyChanges); + } } } diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/EfCoreAuditLogRepository.cs b/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/EfCoreAuditLogRepository.cs index 1fabbcbe7c..ece526d869 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/EfCoreAuditLogRepository.cs +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/EfCoreAuditLogRepository.cs @@ -6,6 +6,7 @@ using System.Net; using System.Threading; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; +using Volo.Abp.Auditing; using Volo.Abp.Domain.Repositories.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore; @@ -139,5 +140,60 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore { return GetQueryable().IncludeDetails(); } + + public virtual async Task> GetEntityChangeListAsync( + string sorting = null, + int maxResultCount = 50, + int skipCount = 0, + Guid? auditLogId = null, + DateTime? startTime = null, + DateTime? endTime = null, + EntityChangeType? changeType = null, + string entityId = null, + string entityTypeFullName = null, + bool includeDetails = false, + CancellationToken cancellationToken = default) + { + var query = GetEntityChangeListQuery(auditLogId, startTime, endTime, changeType, entityId, entityTypeFullName, includeDetails); + + return await query.OrderBy(sorting ?? "changeTime desc") + .PageBy(skipCount, maxResultCount) + .ToListAsync(GetCancellationToken(cancellationToken)); + } + + public virtual async Task GetEntityChangeCountAsync( + Guid? auditLogId = null, + DateTime? startTime = null, + DateTime? endTime = null, + EntityChangeType? changeType = null, + string entityId = null, + string entityTypeFullName = null, + CancellationToken cancellationToken = default) + { + var query = GetEntityChangeListQuery(auditLogId, startTime, endTime, changeType, entityId, entityTypeFullName, false); + + var totalCount = await query.LongCountAsync(GetCancellationToken(cancellationToken)); + + return totalCount; + } + + protected virtual IQueryable GetEntityChangeListQuery( + Guid? auditLogId = null, + DateTime? startTime = null, + DateTime? endTime = null, + EntityChangeType? changeType = null, + string entityId = null, + string entityTypeFullName = null, + bool includeDetails = false) + { + return DbContext.EntityChanges.AsNoTracking().IncludeDetails(includeDetails) + .WhereIf(auditLogId.HasValue, e => e.AuditLogId == auditLogId) + .WhereIf(startTime.HasValue, e => e.ChangeTime >= startTime) + .WhereIf(endTime.HasValue, e => e.ChangeTime <= endTime) + .WhereIf(changeType.HasValue, e => e.ChangeType == changeType) + .WhereIf(!string.IsNullOrWhiteSpace(entityId), e => e.EntityId == entityId) + .WhereIf(!string.IsNullOrWhiteSpace(entityTypeFullName), + e => e.EntityTypeFullName == entityTypeFullName); + } } } diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/IAuditLoggingDbContext.cs b/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/IAuditLoggingDbContext.cs index 684c5fc55f..a74c20bd68 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/IAuditLoggingDbContext.cs +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/IAuditLoggingDbContext.cs @@ -8,5 +8,7 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore public interface IAuditLoggingDbContext : IEfCoreDbContext { DbSet AuditLogs { get; set; } + + DbSet EntityChanges { get; set; } } } \ No newline at end of file diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/MongoAuditLogRepository.cs b/modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/MongoAuditLogRepository.cs index fdb9bca387..a813ada669 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/MongoAuditLogRepository.cs +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/MongoAuditLogRepository.cs @@ -7,6 +7,7 @@ using System.Threading; using System.Threading.Tasks; using MongoDB.Driver; using MongoDB.Driver.Linq; +using Volo.Abp.Auditing; using Volo.Abp.Domain.Repositories.MongoDB; using Volo.Abp.MongoDB; @@ -138,5 +139,62 @@ namespace Volo.Abp.AuditLogging.MongoDB return result.ToDictionary(element => element.Day.ClearTime(), element => element.avgExecutionTime); } + + public virtual async Task> GetEntityChangeListAsync( + string sorting = null, + int maxResultCount = 50, + int skipCount = 0, + Guid? auditLogId = null, + DateTime? startTime = null, + DateTime? endTime = null, + EntityChangeType? changeType = null, + string entityId = null, + string entityTypeFullName = null, + bool includeDetails = false, + CancellationToken cancellationToken = default) + { + var query = GetEntityChangeListQuery(auditLogId, startTime, endTime, changeType, entityId, entityTypeFullName, includeDetails); + + return await query.OrderBy(sorting ?? "changeTime desc").As>() + .PageBy>(skipCount, maxResultCount) + .ToListAsync(GetCancellationToken(cancellationToken)); + } + + public virtual async Task GetEntityChangeCountAsync( + Guid? auditLogId = null, + DateTime? startTime = null, + DateTime? endTime = null, + EntityChangeType? changeType = null, + string entityId = null, + string entityTypeFullName = null, + CancellationToken cancellationToken = default) + { + var query = GetEntityChangeListQuery(auditLogId, startTime, endTime, changeType, entityId, entityTypeFullName); + var count = await query.As>() + .LongCountAsync(GetCancellationToken(cancellationToken)); + + return count; + } + + protected virtual IQueryable GetEntityChangeListQuery( + Guid? auditLogId = null, + DateTime? startTime = null, + DateTime? endTime = null, + EntityChangeType? changeType = null, + string entityId = null, + string entityTypeFullName = null, + bool includeDetails = false) + { + return null; + // TODO: Learn How to? + return GetMongoQueryable() + .WhereIf(auditLogId.HasValue, e => e.AuditLogId == auditLogId) + .WhereIf(startTime.HasValue, e => e.ChangeTime >= startTime) + .WhereIf(endTime.HasValue, e => e.ChangeTime <= endTime) + .WhereIf(changeType.HasValue, e => e.ChangeType == changeType) + .WhereIf(!string.IsNullOrWhiteSpace(entityId), e => e.EntityId == entityId) + .WhereIf(!string.IsNullOrWhiteSpace(entityTypeFullName), + e => e.EntityTypeFullName == entityTypeFullName); + } } } From 6239fcd585958de01da89725d3d3cbc9b244ef5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arma=C4=9Fan=20=C3=9Cnl=C3=BC?= <36102404+armgnunlu@users.noreply.github.com> Date: Fri, 27 Mar 2020 17:40:04 +0300 Subject: [PATCH 027/151] Resolved #3238 --- .../Pages/Documents/Project/Index.cshtml | 31 +- .../Pages/Documents/Search.cshtml | 88 +++-- .../Pages/Documents/Shared/Styles/vs.css | 240 ++++++------ .../Pages/Documents/Shared/Styles/vs.min.css | 2 +- .../Pages/Documents/Shared/Styles/vs.scss | 349 ++++++++++-------- 5 files changed, 384 insertions(+), 326 deletions(-) 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 67e5352e22..6fcf402d70 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 @@ -68,7 +68,7 @@ }
-