From fffa9f92376a964d58e03cc60e079c4b37fd3783 Mon Sep 17 00:00:00 2001 From: maliming <6908465+maliming@users.noreply.github.com> Date: Wed, 3 Jun 2020 15:11:33 +0800 Subject: [PATCH 01/81] Add Volo.Abp.BlobStoring.Azure project. --- framework/Volo.Abp.sln | 7 +++++ .../FodyWeavers.xml | 3 ++ .../FodyWeavers.xsd | 30 +++++++++++++++++++ .../Volo.Abp.BlobStoring.Azure.csproj | 21 +++++++++++++ .../Azure/AbpBlobStoringAzureModule.cs | 12 ++++++++ ...ureBlobContainerConfigurationExtensions.cs | 24 +++++++++++++++ .../BlobStoring/Azure/AzureBlobProvider.cs | 29 ++++++++++++++++++ .../Azure/AzureBlobProviderConfiguration.cs | 12 ++++++++ .../AzureBlobProviderConfigurationNames.cs | 8 +++++ 9 files changed, 146 insertions(+) create mode 100644 framework/src/Volo.Abp.BlobStoring.Azure/FodyWeavers.xml create mode 100644 framework/src/Volo.Abp.BlobStoring.Azure/FodyWeavers.xsd create mode 100644 framework/src/Volo.Abp.BlobStoring.Azure/Volo.Abp.BlobStoring.Azure.csproj create mode 100644 framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureModule.cs create mode 100644 framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobContainerConfigurationExtensions.cs create mode 100644 framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProvider.cs create mode 100644 framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProviderConfiguration.cs create mode 100644 framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProviderConfigurationNames.cs diff --git a/framework/Volo.Abp.sln b/framework/Volo.Abp.sln index 135afaf4d9..d488b3d5b0 100644 --- a/framework/Volo.Abp.sln +++ b/framework/Volo.Abp.sln @@ -301,6 +301,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.BlobStoring.FileSy EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.EntityFrameworkCore.Oracle.Devart", "src\Volo.Abp.EntityFrameworkCore.Oracle.Devart\Volo.Abp.EntityFrameworkCore.Oracle.Devart.csproj", "{75E5C841-5F36-4C44-A532-57CB8E7FFE15}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.BlobStoring.Azure", "src\Volo.Abp.BlobStoring.Azure\Volo.Abp.BlobStoring.Azure.csproj", "{C44242F7-D55D-4867-AAF4-A786E404312E}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -895,6 +897,10 @@ Global {75E5C841-5F36-4C44-A532-57CB8E7FFE15}.Debug|Any CPU.Build.0 = Debug|Any CPU {75E5C841-5F36-4C44-A532-57CB8E7FFE15}.Release|Any CPU.ActiveCfg = Release|Any CPU {75E5C841-5F36-4C44-A532-57CB8E7FFE15}.Release|Any CPU.Build.0 = Release|Any CPU + {C44242F7-D55D-4867-AAF4-A786E404312E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C44242F7-D55D-4867-AAF4-A786E404312E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C44242F7-D55D-4867-AAF4-A786E404312E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C44242F7-D55D-4867-AAF4-A786E404312E}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1047,6 +1053,7 @@ Global {02B1FBE2-850E-4612-ABC6-DD62BCF2DD6B} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {68443D4A-1608-4039-B995-7AF4CF82E9F8} = {447C8A77-E5F0-4538-8687-7383196D04EA} {75E5C841-5F36-4C44-A532-57CB8E7FFE15} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} + {C44242F7-D55D-4867-AAF4-A786E404312E} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5} diff --git a/framework/src/Volo.Abp.BlobStoring.Azure/FodyWeavers.xml b/framework/src/Volo.Abp.BlobStoring.Azure/FodyWeavers.xml new file mode 100644 index 0000000000..bc5a74a236 --- /dev/null +++ b/framework/src/Volo.Abp.BlobStoring.Azure/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + diff --git a/framework/src/Volo.Abp.BlobStoring.Azure/FodyWeavers.xsd b/framework/src/Volo.Abp.BlobStoring.Azure/FodyWeavers.xsd new file mode 100644 index 0000000000..3f3946e282 --- /dev/null +++ b/framework/src/Volo.Abp.BlobStoring.Azure/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/framework/src/Volo.Abp.BlobStoring.Azure/Volo.Abp.BlobStoring.Azure.csproj b/framework/src/Volo.Abp.BlobStoring.Azure/Volo.Abp.BlobStoring.Azure.csproj new file mode 100644 index 0000000000..f7e004cfc8 --- /dev/null +++ b/framework/src/Volo.Abp.BlobStoring.Azure/Volo.Abp.BlobStoring.Azure.csproj @@ -0,0 +1,21 @@ + + + + + + + netstandard2.0 + Volo.Abp.BlobStoring.Azure + Volo.Abp.BlobStoring.Azure + $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; + false + false + false + + + + + + + + diff --git a/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureModule.cs b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureModule.cs new file mode 100644 index 0000000000..a7a935abf5 --- /dev/null +++ b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureModule.cs @@ -0,0 +1,12 @@ +using Volo.Abp.Modularity; + +namespace Volo.Abp.BlobStoring.Azure +{ + [DependsOn( + typeof(AbpBlobStoringModule) + )] + public class AbpBlobStoringAzureModule : AbpModule + { + + } +} diff --git a/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobContainerConfigurationExtensions.cs b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobContainerConfigurationExtensions.cs new file mode 100644 index 0000000000..917870aa9d --- /dev/null +++ b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobContainerConfigurationExtensions.cs @@ -0,0 +1,24 @@ +using System; + +namespace Volo.Abp.BlobStoring.Azure +{ + public static class AzureBlobContainerConfigurationExtensions + { + public static AzureBlobProviderConfiguration GetAzureConfiguration( + this BlobContainerConfiguration containerConfiguration) + { + return new AzureBlobProviderConfiguration(containerConfiguration); + } + + public static BlobContainerConfiguration UseAzure( + this BlobContainerConfiguration containerConfiguration, + Action fileSystemConfigureAction) + { + containerConfiguration.ProviderType = typeof(AzureBlobProvider); + + fileSystemConfigureAction(new AzureBlobProviderConfiguration(containerConfiguration)); + + return containerConfiguration; + } + } +} diff --git a/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProvider.cs b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProvider.cs new file mode 100644 index 0000000000..895fa5c72f --- /dev/null +++ b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProvider.cs @@ -0,0 +1,29 @@ +using System.IO; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.BlobStoring.Azure +{ + public class AzureBlobProvider : BlobProviderBase, ITransientDependency + { + public override Task SaveAsync(BlobProviderSaveArgs args) + { + throw new System.NotImplementedException(); + } + + public override Task DeleteAsync(BlobProviderDeleteArgs args) + { + throw new System.NotImplementedException(); + } + + public override Task ExistsAsync(BlobProviderExistsArgs args) + { + throw new System.NotImplementedException(); + } + + public override Task GetOrNullAsync(BlobProviderGetArgs args) + { + throw new System.NotImplementedException(); + } + } +} diff --git a/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProviderConfiguration.cs b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProviderConfiguration.cs new file mode 100644 index 0000000000..53352661f9 --- /dev/null +++ b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProviderConfiguration.cs @@ -0,0 +1,12 @@ +namespace Volo.Abp.BlobStoring.Azure +{ + public class AzureBlobProviderConfiguration + { + private readonly BlobContainerConfiguration _containerConfiguration; + + public AzureBlobProviderConfiguration(BlobContainerConfiguration containerConfiguration) + { + _containerConfiguration = containerConfiguration; + } + } +} diff --git a/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProviderConfigurationNames.cs b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProviderConfigurationNames.cs new file mode 100644 index 0000000000..8452b0531f --- /dev/null +++ b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProviderConfigurationNames.cs @@ -0,0 +1,8 @@ +namespace Volo.Abp.BlobStoring.Azure +{ + public class AzureBlobProviderConfigurationNames + { + + + } +} From 44521a6bd30ba1e6385ab79017665ffa93c40d1a Mon Sep 17 00:00:00 2001 From: maliming <6908465+maliming@users.noreply.github.com> Date: Wed, 3 Jun 2020 18:25:38 +0800 Subject: [PATCH 02/81] Implement azure blob storage. --- framework/Volo.Abp.sln | 7 +++ .../Volo.Abp.BlobStoring.Azure.csproj | 1 + .../BlobStoring/Azure/AzureBlobProvider.cs | 59 ++++++++++++++++--- .../Azure/AzureBlobProviderConfiguration.cs | 12 ++++ .../AzureBlobProviderConfigurationNames.cs | 6 +- .../Volo/Abp/BlobStoring/BlobProviderArgs.cs | 2 +- .../System/IO/AbpStreamExtensions.cs | 3 + .../Volo.Abp.BlobStoring.Azure.Tests.csproj | 19 ++++++ .../Azure/AbpBlobStoringAzureTestBase.cs | 12 ++++ .../Azure/AbpBlobStoringAzureTestModule.cs | 49 +++++++++++++++ .../Azure/AzureBlobContainer_Tests.cs | 12 ++++ 11 files changed, 170 insertions(+), 12 deletions(-) create mode 100644 framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo.Abp.BlobStoring.Azure.Tests.csproj create mode 100644 framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureTestBase.cs create mode 100644 framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureTestModule.cs create mode 100644 framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AzureBlobContainer_Tests.cs diff --git a/framework/Volo.Abp.sln b/framework/Volo.Abp.sln index d488b3d5b0..e02d40b1e0 100644 --- a/framework/Volo.Abp.sln +++ b/framework/Volo.Abp.sln @@ -303,6 +303,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.EntityFrameworkCor EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.BlobStoring.Azure", "src\Volo.Abp.BlobStoring.Azure\Volo.Abp.BlobStoring.Azure.csproj", "{C44242F7-D55D-4867-AAF4-A786E404312E}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.BlobStoring.Azure.Tests", "test\Volo.Abp.BlobStoring.Azure.Tests\Volo.Abp.BlobStoring.Azure.Tests.csproj", "{A80E9A0B-8932-4B5D-83FB-6751708FD484}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -901,6 +903,10 @@ Global {C44242F7-D55D-4867-AAF4-A786E404312E}.Debug|Any CPU.Build.0 = Debug|Any CPU {C44242F7-D55D-4867-AAF4-A786E404312E}.Release|Any CPU.ActiveCfg = Release|Any CPU {C44242F7-D55D-4867-AAF4-A786E404312E}.Release|Any CPU.Build.0 = Release|Any CPU + {A80E9A0B-8932-4B5D-83FB-6751708FD484}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A80E9A0B-8932-4B5D-83FB-6751708FD484}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A80E9A0B-8932-4B5D-83FB-6751708FD484}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A80E9A0B-8932-4B5D-83FB-6751708FD484}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1054,6 +1060,7 @@ Global {68443D4A-1608-4039-B995-7AF4CF82E9F8} = {447C8A77-E5F0-4538-8687-7383196D04EA} {75E5C841-5F36-4C44-A532-57CB8E7FFE15} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {C44242F7-D55D-4867-AAF4-A786E404312E} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} + {A80E9A0B-8932-4B5D-83FB-6751708FD484} = {447C8A77-E5F0-4538-8687-7383196D04EA} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5} diff --git a/framework/src/Volo.Abp.BlobStoring.Azure/Volo.Abp.BlobStoring.Azure.csproj b/framework/src/Volo.Abp.BlobStoring.Azure/Volo.Abp.BlobStoring.Azure.csproj index f7e004cfc8..1e7c51f4fc 100644 --- a/framework/src/Volo.Abp.BlobStoring.Azure/Volo.Abp.BlobStoring.Azure.csproj +++ b/framework/src/Volo.Abp.BlobStoring.Azure/Volo.Abp.BlobStoring.Azure.csproj @@ -16,6 +16,7 @@ + diff --git a/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProvider.cs b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProvider.cs index 895fa5c72f..d43fbb2158 100644 --- a/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProvider.cs +++ b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProvider.cs @@ -1,29 +1,72 @@ using System.IO; using System.Threading.Tasks; +using Azure.Storage.Blobs; using Volo.Abp.DependencyInjection; namespace Volo.Abp.BlobStoring.Azure { public class AzureBlobProvider : BlobProviderBase, ITransientDependency { - public override Task SaveAsync(BlobProviderSaveArgs args) + public override async Task SaveAsync(BlobProviderSaveArgs args) { - throw new System.NotImplementedException(); + var blobClient = GetBlobClient(args.Configuration.GetAzureConfiguration(), args.BlobName); + + if (!args.OverrideExisting && await BlobExistsAsync(blobClient)) + { + throw new BlobAlreadyExistsException($"Saving BLOB '{args.BlobName}' does already exists in the container '{args.ContainerName}'! Set {nameof(args.OverrideExisting)} if it should be overwritten."); + } + + await blobClient.UploadAsync(args.BlobStream, true); + } + + public override async Task DeleteAsync(BlobProviderDeleteArgs args) + { + var blobClient = GetBlobClient(args.Configuration.GetAzureConfiguration(), args.BlobName); + if (await BlobExistsAsync(blobClient)) + { + return (await blobClient.DeleteAsync()).Status == 200; + } + + return false; + } + + public override async Task ExistsAsync(BlobProviderExistsArgs args) + { + var blobClient = GetBlobClient(args.Configuration.GetAzureConfiguration(), args.BlobName); + return await BlobExistsAsync(blobClient); + } + + public override async Task GetOrNullAsync(BlobProviderGetArgs args) + { + var blobClient = GetBlobClient(args.Configuration.GetAzureConfiguration(), args.BlobName); + if (!await BlobExistsAsync(blobClient)) + { + return null; + } + + var download = await blobClient.DownloadAsync(); + + var memoryStream = new MemoryStream(); + await download.Value.Content.CopyToAsync(memoryStream); + return memoryStream; } - public override Task DeleteAsync(BlobProviderDeleteArgs args) + protected virtual BlobClient GetBlobClient(AzureBlobProviderConfiguration configuration, string blobName) { - throw new System.NotImplementedException(); + var blobContainerClient = GetBlobContainerClient(configuration); + return blobContainerClient.GetBlobClient(blobName); } - public override Task ExistsAsync(BlobProviderExistsArgs args) + protected virtual BlobContainerClient GetBlobContainerClient(AzureBlobProviderConfiguration configuration) { - throw new System.NotImplementedException(); + var blobServiceClient = new BlobServiceClient(configuration.ConnectionString); + return blobServiceClient.GetBlobContainerClient(configuration.ContainerName); } - public override Task GetOrNullAsync(BlobProviderGetArgs args) + private static async Task BlobExistsAsync(BlobClient blobClient) { - throw new System.NotImplementedException(); + var response = await blobClient.ExistsAsync(); + return response.Value; } } } diff --git a/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProviderConfiguration.cs b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProviderConfiguration.cs index 53352661f9..67f6eca307 100644 --- a/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProviderConfiguration.cs +++ b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProviderConfiguration.cs @@ -2,6 +2,18 @@ { public class AzureBlobProviderConfiguration { + public string ConnectionString + { + get => _containerConfiguration.GetConfiguration(AzureBlobProviderConfigurationNames.ConnectionString); + set => _containerConfiguration.SetConfiguration(AzureBlobProviderConfigurationNames.ConnectionString, Check.NotNullOrWhiteSpace(value, nameof(value))); + } + + public string ContainerName + { + get => _containerConfiguration.GetConfiguration(AzureBlobProviderConfigurationNames.ContainerName); + set => _containerConfiguration.SetConfiguration(AzureBlobProviderConfigurationNames.ContainerName, Check.NotNullOrWhiteSpace(value, nameof(value))); + } + private readonly BlobContainerConfiguration _containerConfiguration; public AzureBlobProviderConfiguration(BlobContainerConfiguration containerConfiguration) diff --git a/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProviderConfigurationNames.cs b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProviderConfigurationNames.cs index 8452b0531f..f90f037046 100644 --- a/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProviderConfigurationNames.cs +++ b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProviderConfigurationNames.cs @@ -1,8 +1,8 @@ namespace Volo.Abp.BlobStoring.Azure { - public class AzureBlobProviderConfigurationNames + public static class AzureBlobProviderConfigurationNames { - - + public const string ConnectionString = "Azure.ConnectionString"; + public const string ContainerName = "Azure.ContainerName"; } } diff --git a/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobProviderArgs.cs b/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobProviderArgs.cs index fcc264977a..0170409a16 100644 --- a/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobProviderArgs.cs +++ b/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobProviderArgs.cs @@ -28,4 +28,4 @@ namespace Volo.Abp.BlobStoring CancellationToken = cancellationToken; } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Core/System/IO/AbpStreamExtensions.cs b/framework/src/Volo.Abp.Core/System/IO/AbpStreamExtensions.cs index 466d73b2a7..bd85773a9b 100644 --- a/framework/src/Volo.Abp.Core/System/IO/AbpStreamExtensions.cs +++ b/framework/src/Volo.Abp.Core/System/IO/AbpStreamExtensions.cs @@ -9,6 +9,7 @@ namespace System.IO { using (var memoryStream = new MemoryStream()) { + stream.Position = 0; stream.CopyTo(memoryStream); return memoryStream.ToArray(); } @@ -18,6 +19,7 @@ namespace System.IO { using (var memoryStream = new MemoryStream()) { + stream.Position = 0; await stream.CopyToAsync(memoryStream, cancellationToken); return memoryStream.ToArray(); } @@ -25,6 +27,7 @@ namespace System.IO public static Task CopyToAsync(this Stream stream, Stream destination, CancellationToken cancellationToken) { + stream.Position = 0; return stream.CopyToAsync( destination, 81920, //this is already the default value, but needed to set to be able to pass the cancellationToken diff --git a/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo.Abp.BlobStoring.Azure.Tests.csproj b/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo.Abp.BlobStoring.Azure.Tests.csproj new file mode 100644 index 0000000000..ff97ea97d3 --- /dev/null +++ b/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo.Abp.BlobStoring.Azure.Tests.csproj @@ -0,0 +1,19 @@ + + + + + + netcoreapp3.1 + + 9f0d2c00-80c1-435b-bfab-2c39c8249091 + + + + + + + + + + + diff --git a/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureTestBase.cs b/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureTestBase.cs new file mode 100644 index 0000000000..7213c8eb78 --- /dev/null +++ b/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureTestBase.cs @@ -0,0 +1,12 @@ +using Volo.Abp.Testing; + +namespace Volo.Abp.BlobStoring.Azure +{ + public class AbpBlobStoringAzureTestBase : AbpIntegratedTest + { + protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) + { + options.UseAutofac(); + } + } +} diff --git a/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureTestModule.cs b/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureTestModule.cs new file mode 100644 index 0000000000..354b8b93b6 --- /dev/null +++ b/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureTestModule.cs @@ -0,0 +1,49 @@ +using System; +using Azure.Storage.Blobs; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Modularity; + +namespace Volo.Abp.BlobStoring.Azure +{ + [DependsOn( + typeof(AbpBlobStoringAzureModule), + typeof(AbpBlobStoringTestModule) + )] + public class AbpBlobStoringAzureTestModule : AbpModule + { + private readonly string _randomContainerName = "abp-azure-test-container-" + Guid.NewGuid().ToString("N"); + + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.ReplaceConfiguration(ConfigurationHelper.BuildConfiguration(builderAction: builder => + { + builder.AddUserSecrets("9f0d2c00-80c1-435b-bfab-2c39c8249091"); + })); + + var configuration = context.Services.GetConfiguration(); + + var blobServiceClient = new BlobServiceClient(configuration["Azure:ConnectionString"]); + blobServiceClient.CreateBlobContainer(_randomContainerName); + + Configure(options => + { + options.Containers.ConfigureAll((containerName, containerConfiguration) => + { + containerConfiguration.UseAzure(azure => + { + azure.ConnectionString = configuration["Azure:ConnectionString"]; + azure.ContainerName = _randomContainerName; + }); + }); + }); + } + + public override void OnApplicationShutdown(ApplicationShutdownContext context) + { + var configuration = context.ServiceProvider.GetRequiredService(); + var blobServiceClient = new BlobServiceClient(configuration["Azure:ConnectionString"]); + blobServiceClient.DeleteBlobContainer(_randomContainerName); + } + } +} diff --git a/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AzureBlobContainer_Tests.cs b/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AzureBlobContainer_Tests.cs new file mode 100644 index 0000000000..f4e820d46f --- /dev/null +++ b/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AzureBlobContainer_Tests.cs @@ -0,0 +1,12 @@ +using Xunit; + +namespace Volo.Abp.BlobStoring.Azure +{ + public class AzureBlobContainer_Tests : BlobContainer_Tests + { + public AzureBlobContainer_Tests() + { + + } + } +} From 0e2e5629aa9370c5f548fdacf1bcba1d4c70f17e Mon Sep 17 00:00:00 2001 From: maliming <6908465+maliming@users.noreply.github.com> Date: Wed, 3 Jun 2020 18:44:39 +0800 Subject: [PATCH 03/81] Skip azure unit testing. --- .../Abp/BlobStoring/Azure/AbpBlobStoringAzureTestModule.cs | 4 +++- .../Volo/Abp/BlobStoring/Azure/AzureBlobContainer_Tests.cs | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureTestModule.cs b/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureTestModule.cs index 354b8b93b6..4a1b0f8114 100644 --- a/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureTestModule.cs +++ b/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureTestModule.cs @@ -12,13 +12,15 @@ namespace Volo.Abp.BlobStoring.Azure )] public class AbpBlobStoringAzureTestModule : AbpModule { + public static string UserSecretsId = "9f0d2c00-80c1-435b-bfab-2c39c8249091"; + private readonly string _randomContainerName = "abp-azure-test-container-" + Guid.NewGuid().ToString("N"); public override void ConfigureServices(ServiceConfigurationContext context) { context.Services.ReplaceConfiguration(ConfigurationHelper.BuildConfiguration(builderAction: builder => { - builder.AddUserSecrets("9f0d2c00-80c1-435b-bfab-2c39c8249091"); + builder.AddUserSecrets(UserSecretsId); })); var configuration = context.Services.GetConfiguration(); diff --git a/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AzureBlobContainer_Tests.cs b/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AzureBlobContainer_Tests.cs index f4e820d46f..75070d2cac 100644 --- a/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AzureBlobContainer_Tests.cs +++ b/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AzureBlobContainer_Tests.cs @@ -1,7 +1,9 @@ using Xunit; +//#define I_HAVE_SET_THE_CORRECT_CONNECTIONSTRING_IN_THE_USERSECRETS_FILE namespace Volo.Abp.BlobStoring.Azure { +#if I_HAVE_SET_THE_CORRECT_CONNECTION_STRING_IN_THE_USERSECRETS_FILE public class AzureBlobContainer_Tests : BlobContainer_Tests { public AzureBlobContainer_Tests() @@ -9,4 +11,5 @@ namespace Volo.Abp.BlobStoring.Azure } } +#endif } From 3acc5c8c85eb3c60a56d6bf01ed018e8abf8cfb4 Mon Sep 17 00:00:00 2001 From: maliming <6908465+maliming@users.noreply.github.com> Date: Wed, 3 Jun 2020 19:05:23 +0800 Subject: [PATCH 04/81] Small refactoring. --- .../BlobStoring/Azure/AbpBlobStoringAzureModule.cs | 4 +--- .../Volo/Abp/BlobStoring/Azure/AzureBlobProvider.cs | 4 +--- .../Azure/AbpBlobStoringAzureTestModule.cs | 12 ++++++++---- .../BlobStoring/Azure/AzureBlobContainer_Tests.cs | 7 ++++--- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureModule.cs b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureModule.cs index a7a935abf5..0b386fbec1 100644 --- a/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureModule.cs +++ b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureModule.cs @@ -2,9 +2,7 @@ namespace Volo.Abp.BlobStoring.Azure { - [DependsOn( - typeof(AbpBlobStoringModule) - )] + [DependsOn(typeof(AbpBlobStoringModule))] public class AbpBlobStoringAzureModule : AbpModule { diff --git a/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProvider.cs b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProvider.cs index d43fbb2158..eb69bb802a 100644 --- a/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProvider.cs +++ b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProvider.cs @@ -45,7 +45,6 @@ namespace Volo.Abp.BlobStoring.Azure } var download = await blobClient.DownloadAsync(); - var memoryStream = new MemoryStream(); await download.Value.Content.CopyToAsync(memoryStream); return memoryStream; @@ -65,8 +64,7 @@ namespace Volo.Abp.BlobStoring.Azure private static async Task BlobExistsAsync(BlobClient blobClient) { - var response = await blobClient.ExistsAsync(); - return response.Value; + return (await blobClient.ExistsAsync()).Value; } } } diff --git a/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureTestModule.cs b/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureTestModule.cs index 4a1b0f8114..4711699726 100644 --- a/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureTestModule.cs +++ b/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureTestModule.cs @@ -12,7 +12,9 @@ namespace Volo.Abp.BlobStoring.Azure )] public class AbpBlobStoringAzureTestModule : AbpModule { - public static string UserSecretsId = "9f0d2c00-80c1-435b-bfab-2c39c8249091"; + private const string UserSecretsId = "9f0d2c00-80c1-435b-bfab-2c39c8249091"; + + private string _connectionString; private readonly string _randomContainerName = "abp-azure-test-container-" + Guid.NewGuid().ToString("N"); @@ -25,7 +27,9 @@ namespace Volo.Abp.BlobStoring.Azure var configuration = context.Services.GetConfiguration(); - var blobServiceClient = new BlobServiceClient(configuration["Azure:ConnectionString"]); + _connectionString = configuration["Azure:ConnectionString"]; + + var blobServiceClient = new BlobServiceClient(_connectionString); blobServiceClient.CreateBlobContainer(_randomContainerName); Configure(options => @@ -34,7 +38,7 @@ namespace Volo.Abp.BlobStoring.Azure { containerConfiguration.UseAzure(azure => { - azure.ConnectionString = configuration["Azure:ConnectionString"]; + azure.ConnectionString = _connectionString; azure.ContainerName = _randomContainerName; }); }); @@ -44,7 +48,7 @@ namespace Volo.Abp.BlobStoring.Azure public override void OnApplicationShutdown(ApplicationShutdownContext context) { var configuration = context.ServiceProvider.GetRequiredService(); - var blobServiceClient = new BlobServiceClient(configuration["Azure:ConnectionString"]); + var blobServiceClient = new BlobServiceClient(_connectionString); blobServiceClient.DeleteBlobContainer(_randomContainerName); } } diff --git a/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AzureBlobContainer_Tests.cs b/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AzureBlobContainer_Tests.cs index 75070d2cac..751918be85 100644 --- a/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AzureBlobContainer_Tests.cs +++ b/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AzureBlobContainer_Tests.cs @@ -1,9 +1,10 @@ using Xunit; -//#define I_HAVE_SET_THE_CORRECT_CONNECTIONSTRING_IN_THE_USERSECRETS_FILE namespace Volo.Abp.BlobStoring.Azure { -#if I_HAVE_SET_THE_CORRECT_CONNECTION_STRING_IN_THE_USERSECRETS_FILE + /* + //Please set the correct connection string in secrets.json and continue the test. + public class AzureBlobContainer_Tests : BlobContainer_Tests { public AzureBlobContainer_Tests() @@ -11,5 +12,5 @@ namespace Volo.Abp.BlobStoring.Azure } } -#endif + */ } From 9d2097ca0c6d33e9a6adc276ef2e75e5bdd139c2 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Thu, 4 Jun 2020 03:38:10 +0300 Subject: [PATCH 05/81] feat(theme-shared): add ngx-datatable as dependency --- npm/ng-packs/angular.json | 15 + npm/ng-packs/package.json | 3 +- .../packages/theme-shared/ng-package.json | 1 + .../packages/theme-shared/package.json | 3 +- .../theme-shared/src/lib/constants/styles.ts | 3 + .../src/lib/theme-shared.module.ts | 4 +- npm/ng-packs/scripts/yarn.lock | 1275 +++++++++++++++++ npm/ng-packs/yarn.lock | 7 + 8 files changed, 1308 insertions(+), 3 deletions(-) create mode 100644 npm/ng-packs/scripts/yarn.lock diff --git a/npm/ng-packs/angular.json b/npm/ng-packs/angular.json index 2b876fe21c..fccbd32996 100644 --- a/npm/ng-packs/angular.json +++ b/npm/ng-packs/angular.json @@ -460,6 +460,21 @@ "inject": true, "bundleName": "fontawesome-v4-shims.min" }, + { + "input": "node_modules/@swimlane/ngx-datatable/index.css", + "inject": true, + "bundleName": "ngx-datatable-index" + }, + { + "input": "node_modules/@swimlane/ngx-datatable/assets/icons.css", + "inject": true, + "bundleName": "ngx-datatable-icons" + }, + { + "input": "node_modules/@swimlane/ngx-datatable/themes/material.css", + "inject": true, + "bundleName": "ngx-datatable-material" + }, "apps/dev-app/src/styles.scss" ], "scripts": [] diff --git a/npm/ng-packs/package.json b/npm/ng-packs/package.json index dedee9d8fc..f6ae01cf5b 100644 --- a/npm/ng-packs/package.json +++ b/npm/ng-packs/package.json @@ -54,12 +54,13 @@ "@fortawesome/fontawesome-free": "^5.12.1", "@ng-bootstrap/ng-bootstrap": "^5.3.0", "@ngneat/spectator": "^4.5.0", - "@ngx-validate/core": "^0.0.7", + "@ngx-validate/core": "^0.0.8", "@ngxs/devtools-plugin": "^3.5.1", "@ngxs/logger-plugin": "^3.5.1", "@ngxs/router-plugin": "^3.6.2", "@ngxs/storage-plugin": "^3.6.2", "@ngxs/store": "^3.6.2", + "@swimlane/ngx-datatable": "^16.0.0", "@types/jest": "^24.0.18", "@types/node": "~8.9.4", "angular-oauth2-oidc": "^8.0.4", diff --git a/npm/ng-packs/packages/theme-shared/ng-package.json b/npm/ng-packs/packages/theme-shared/ng-package.json index 58d74cba48..0c3b5e300f 100644 --- a/npm/ng-packs/packages/theme-shared/ng-package.json +++ b/npm/ng-packs/packages/theme-shared/ng-package.json @@ -10,6 +10,7 @@ "@fortawesome/fontawesome-free", "@ng-bootstrap/ng-bootstrap", "@ngx-validate/core", + "@swimlane/ngx-datatable", "bootstrap", "font-awesome", "chart.js" diff --git a/npm/ng-packs/packages/theme-shared/package.json b/npm/ng-packs/packages/theme-shared/package.json index 8d3d2b3b39..8e27a70039 100644 --- a/npm/ng-packs/packages/theme-shared/package.json +++ b/npm/ng-packs/packages/theme-shared/package.json @@ -10,7 +10,8 @@ "@abp/ng.core": "~2.8.0", "@fortawesome/fontawesome-free": "^5.12.1", "@ng-bootstrap/ng-bootstrap": "^5.3.0", - "@ngx-validate/core": "^0.0.7", + "@ngx-validate/core": "^0.0.8", + "@swimlane/ngx-datatable": "^16.0.0", "bootstrap": "^4.4.1", "chart.js": "^2.9.3" }, diff --git a/npm/ng-packs/packages/theme-shared/src/lib/constants/styles.ts b/npm/ng-packs/packages/theme-shared/src/lib/constants/styles.ts index a691f96ead..a1a3b7afe5 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/constants/styles.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/constants/styles.ts @@ -136,6 +136,9 @@ export default ` .sorting_asc:after { opacity: .3; } +.ngx-datatable.material { +box-shadow: none; +} @keyframes fadeInTop { from { diff --git a/npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts b/npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts index 72ec96f569..dd7803e459 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts @@ -3,6 +3,7 @@ import { DatePipe } from '@angular/common'; import { APP_INITIALIZER, Injector, ModuleWithProviders, NgModule } from '@angular/core'; import { NgbDateParserFormatter, NgbPaginationModule } from '@ng-bootstrap/ng-bootstrap'; import { NgxValidateCoreModule } from '@ngx-validate/core'; +import { NgxDatatableModule } from '@swimlane/ngx-datatable'; import { BreadcrumbComponent } from './components/breadcrumb/breadcrumb.component'; import { ButtonComponent } from './components/button/button.component'; import { ChartComponent } from './components/chart/chart.component'; @@ -46,7 +47,7 @@ export function appendScript(injector: Injector) { } @NgModule({ - imports: [CoreModule, NgxValidateCoreModule, NgbPaginationModule], + imports: [CoreModule, NgxDatatableModule, NgxValidateCoreModule, NgbPaginationModule], declarations: [ BreadcrumbComponent, ButtonComponent, @@ -67,6 +68,7 @@ export function appendScript(injector: Injector) { TableSortDirective, ], exports: [ + NgxDatatableModule, BreadcrumbComponent, ButtonComponent, ChartComponent, diff --git a/npm/ng-packs/scripts/yarn.lock b/npm/ng-packs/scripts/yarn.lock new file mode 100644 index 0000000000..17801cf3f4 --- /dev/null +++ b/npm/ng-packs/scripts/yarn.lock @@ -0,0 +1,1275 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@types/fs-extra@^8.0.1": + version "8.1.1" + resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-8.1.1.tgz#1e49f22d09aa46e19b51c0b013cb63d0d923a068" + integrity sha512-TcUlBem321DFQzBNuz8p0CLLKp0VvF/XH9E4KHNmgwyp4E3AfgI5cjiIVZWlbfThBop2qxFIh4+LeY6hVWWZ2w== + dependencies: + "@types/node" "*" + +"@types/json5@^0.0.29": + version "0.0.29" + resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" + integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= + +"@types/node@*": + version "14.0.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.9.tgz#43896ab87fc82bda1dfd600cdf44a0c8a64e11d2" + integrity sha512-0sCTiXKXELOBxvZLN4krQ0FPOAA7ij+6WwvD0k/PHd9/KAkr4dXel5J9fh6F4x1FwAQILqAWkmpeuS6mjf1iKA== + +"@types/node@^13.1.2": + version "13.13.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-13.13.9.tgz#79df4ae965fb76d31943b54a6419599307a21394" + integrity sha512-EPZBIGed5gNnfWCiwEIwTE2Jdg4813odnG8iNPMQGrqVxrI+wL68SPtPeCX+ZxGBaA6pKAVc6jaKgP/Q0QzfdQ== + +ansi-bgblack@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-bgblack/-/ansi-bgblack-0.1.1.tgz#a68ba5007887701b6aafbe3fa0dadfdfa8ee3ca2" + integrity sha1-poulAHiHcBtqr74/oNrf36juPKI= + dependencies: + ansi-wrap "0.1.0" + +ansi-bgblue@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-bgblue/-/ansi-bgblue-0.1.1.tgz#67bdc04edc9b9b5278969da196dea3d75c8c3613" + integrity sha1-Z73ATtybm1J4lp2hlt6j11yMNhM= + dependencies: + ansi-wrap "0.1.0" + +ansi-bgcyan@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-bgcyan/-/ansi-bgcyan-0.1.1.tgz#58489425600bde9f5507068dd969ebfdb50fe768" + integrity sha1-WEiUJWAL3p9VBwaN2Wnr/bUP52g= + dependencies: + ansi-wrap "0.1.0" + +ansi-bggreen@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-bggreen/-/ansi-bggreen-0.1.1.tgz#4e3191248529943f4321e96bf131d1c13816af49" + integrity sha1-TjGRJIUplD9DIelr8THRwTgWr0k= + dependencies: + ansi-wrap "0.1.0" + +ansi-bgmagenta@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-bgmagenta/-/ansi-bgmagenta-0.1.1.tgz#9b28432c076eaa999418672a3efbe19391c2c7a1" + integrity sha1-myhDLAduqpmUGGcqPvvhk5HCx6E= + dependencies: + ansi-wrap "0.1.0" + +ansi-bgred@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-bgred/-/ansi-bgred-0.1.1.tgz#a76f92838382ba43290a6c1778424f984d6f1041" + integrity sha1-p2+Sg4OCukMpCmwXeEJPmE1vEEE= + dependencies: + ansi-wrap "0.1.0" + +ansi-bgwhite@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-bgwhite/-/ansi-bgwhite-0.1.1.tgz#6504651377a58a6ececd0331994e480258e11ba8" + integrity sha1-ZQRlE3elim7OzQMxmU5IAljhG6g= + dependencies: + ansi-wrap "0.1.0" + +ansi-bgyellow@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-bgyellow/-/ansi-bgyellow-0.1.1.tgz#c3fe2eb08cd476648029e6874d15a0b38f61d44f" + integrity sha1-w/4usIzUdmSAKeaHTRWgs49h1E8= + dependencies: + ansi-wrap "0.1.0" + +ansi-black@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-black/-/ansi-black-0.1.1.tgz#f6185e889360b2545a1ec50c0bf063fc43032453" + integrity sha1-9hheiJNgslRaHsUMC/Bj/EMDJFM= + dependencies: + ansi-wrap "0.1.0" + +ansi-blue@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-blue/-/ansi-blue-0.1.1.tgz#15b804990e92fc9ca8c5476ce8f699777c21edbf" + integrity sha1-FbgEmQ6S/JyoxUds6PaZd3wh7b8= + dependencies: + ansi-wrap "0.1.0" + +ansi-bold@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-bold/-/ansi-bold-0.1.1.tgz#3e63950af5acc2ae2e670e6f67deb115d1a5f505" + integrity sha1-PmOVCvWswq4uZw5vZ96xFdGl9QU= + dependencies: + ansi-wrap "0.1.0" + +ansi-colors@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-0.2.0.tgz#72c31de2a0d9a2ccd0cac30cc9823eeb2f6434b5" + integrity sha1-csMd4qDZoszQysMMyYI+6y9kNLU= + dependencies: + ansi-bgblack "^0.1.1" + ansi-bgblue "^0.1.1" + ansi-bgcyan "^0.1.1" + ansi-bggreen "^0.1.1" + ansi-bgmagenta "^0.1.1" + ansi-bgred "^0.1.1" + ansi-bgwhite "^0.1.1" + ansi-bgyellow "^0.1.1" + ansi-black "^0.1.1" + ansi-blue "^0.1.1" + ansi-bold "^0.1.1" + ansi-cyan "^0.1.1" + ansi-dim "^0.1.1" + ansi-gray "^0.1.1" + ansi-green "^0.1.1" + ansi-grey "^0.1.1" + ansi-hidden "^0.1.1" + ansi-inverse "^0.1.1" + ansi-italic "^0.1.1" + ansi-magenta "^0.1.1" + ansi-red "^0.1.1" + ansi-reset "^0.1.1" + ansi-strikethrough "^0.1.1" + ansi-underline "^0.1.1" + ansi-white "^0.1.1" + ansi-yellow "^0.1.1" + lazy-cache "^2.0.1" + +ansi-cyan@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-cyan/-/ansi-cyan-0.1.1.tgz#538ae528af8982f28ae30d86f2f17456d2609873" + integrity sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM= + dependencies: + ansi-wrap "0.1.0" + +ansi-dim@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-dim/-/ansi-dim-0.1.1.tgz#40de4c603aa8086d8e7a86b8ff998d5c36eefd6c" + integrity sha1-QN5MYDqoCG2Oeoa4/5mNXDbu/Ww= + dependencies: + ansi-wrap "0.1.0" + +ansi-gray@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-gray/-/ansi-gray-0.1.1.tgz#2962cf54ec9792c48510a3deb524436861ef7251" + integrity sha1-KWLPVOyXksSFEKPetSRDaGHvclE= + dependencies: + ansi-wrap "0.1.0" + +ansi-green@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-green/-/ansi-green-0.1.1.tgz#8a5d9a979e458d57c40e33580b37390b8e10d0f7" + integrity sha1-il2al55FjVfEDjNYCzc5C44Q0Pc= + dependencies: + ansi-wrap "0.1.0" + +ansi-grey@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-grey/-/ansi-grey-0.1.1.tgz#59d98b6ac2ba19f8a51798e9853fba78339a33c1" + integrity sha1-WdmLasK6GfilF5jphT+6eDOaM8E= + dependencies: + ansi-wrap "0.1.0" + +ansi-hidden@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-hidden/-/ansi-hidden-0.1.1.tgz#ed6a4c498d2bb7cbb289dbf2a8d1dcc8567fae0f" + integrity sha1-7WpMSY0rt8uyidvyqNHcyFZ/rg8= + dependencies: + ansi-wrap "0.1.0" + +ansi-inverse@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-inverse/-/ansi-inverse-0.1.1.tgz#b6af45826fe826bfb528a6c79885794355ccd269" + integrity sha1-tq9Fgm/oJr+1KKbHmIV5Q1XM0mk= + dependencies: + ansi-wrap "0.1.0" + +ansi-italic@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-italic/-/ansi-italic-0.1.1.tgz#104743463f625c142a036739cf85eda688986f23" + integrity sha1-EEdDRj9iXBQqA2c5z4XtpoiYbyM= + dependencies: + ansi-wrap "0.1.0" + +ansi-magenta@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-magenta/-/ansi-magenta-0.1.1.tgz#063b5ba16fb3f23e1cfda2b07c0a89de11e430ae" + integrity sha1-BjtboW+z8j4c/aKwfAqJ3hHkMK4= + dependencies: + ansi-wrap "0.1.0" + +ansi-red@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-red/-/ansi-red-0.1.1.tgz#8c638f9d1080800a353c9c28c8a81ca4705d946c" + integrity sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw= + dependencies: + ansi-wrap "0.1.0" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= + +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + +ansi-reset@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-reset/-/ansi-reset-0.1.1.tgz#e7e71292c3c7ddcd4d62ef4a6c7c05980911c3b7" + integrity sha1-5+cSksPH3c1NYu9KbHwFmAkRw7c= + dependencies: + ansi-wrap "0.1.0" + +ansi-strikethrough@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-strikethrough/-/ansi-strikethrough-0.1.1.tgz#d84877140b2cff07d1c93ebce69904f68885e568" + integrity sha1-2Eh3FAss/wfRyT685pkE9oiF5Wg= + dependencies: + ansi-wrap "0.1.0" + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= + +ansi-underline@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-underline/-/ansi-underline-0.1.1.tgz#dfc920f4c97b5977ea162df8ffb988308aaa71a4" + integrity sha1-38kg9Ml7WXfqFi34/7mIMIqqcaQ= + dependencies: + ansi-wrap "0.1.0" + +ansi-white@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-white/-/ansi-white-0.1.1.tgz#9c77b7c193c5ee992e6011d36ec4c921b4578944" + integrity sha1-nHe3wZPF7pkuYBHTbsTJIbRXiUQ= + dependencies: + ansi-wrap "0.1.0" + +ansi-wrap@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" + integrity sha1-qCJQ3bABXponyoLoLqYDu/pF768= + +ansi-yellow@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-yellow/-/ansi-yellow-0.1.1.tgz#cb9356f2f46c732f0e3199e6102955a77da83c1d" + integrity sha1-y5NW8vRscy8OMZnmEClVp32oPB0= + dependencies: + ansi-wrap "0.1.0" + +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + +arr-flatten@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== + +arr-swap@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arr-swap/-/arr-swap-1.0.1.tgz#147590ed65fc815bc07fef0997c2e5823d643534" + integrity sha1-FHWQ7WX8gVvAf+8Jl8Llgj1kNTQ= + dependencies: + is-number "^3.0.0" + +babel-code-frame@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" + integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s= + dependencies: + chalk "^1.1.3" + esutils "^2.0.2" + js-tokens "^3.0.2" + +babel-messages@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" + integrity sha1-8830cDhYA1sqKVHG7F7fbGLyYw4= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-syntax-trailing-function-commas@^6.5.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" + integrity sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM= + +babel-plugin-transform-es2015-modules-commonjs@^6.7.4: + version "6.26.2" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz#58a793863a9e7ca870bdc5a881117ffac27db6f3" + integrity sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q== + dependencies: + babel-plugin-transform-strict-mode "^6.24.1" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-types "^6.26.0" + +babel-plugin-transform-strict-mode@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" + integrity sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g= + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-preset-node6@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/babel-preset-node6/-/babel-preset-node6-11.0.0.tgz#0835994517248985a29d18f6d465dab16bb8a7d8" + integrity sha1-CDWZRRckiYWinRj21GXasWu4p9g= + dependencies: + babel-plugin-syntax-trailing-function-commas "^6.5.0" + babel-plugin-transform-es2015-modules-commonjs "^6.7.4" + +babel-runtime@^6.22.0, babel-runtime@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" + integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.11.0" + +babel-template@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" + integrity sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI= + dependencies: + babel-runtime "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + lodash "^4.17.4" + +babel-traverse@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" + integrity sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4= + dependencies: + babel-code-frame "^6.26.0" + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + debug "^2.6.8" + globals "^9.18.0" + invariant "^2.2.2" + lodash "^4.17.4" + +babel-types@^6.24.1, babel-types@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" + integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc= + dependencies: + babel-runtime "^6.26.0" + esutils "^2.0.2" + lodash "^4.17.4" + to-fast-properties "^1.0.3" + +babylon@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" + integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +buffer-from@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== + +chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= + dependencies: + 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" + +choices-separator@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/choices-separator/-/choices-separator-2.0.0.tgz#92fd1763182d79033f5c5c51d0ba352e5567c696" + integrity sha1-kv0XYxgteQM/XFxR0Lo1LlVnxpY= + dependencies: + ansi-dim "^0.1.1" + debug "^2.6.6" + strip-color "^0.1.0" + +clone-deep@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-1.0.0.tgz#b2f354444b5d4a0ce58faca337ef34da2b14a6c7" + integrity sha512-hmJRX8x1QOJVV+GUjOBzi6iauhPqc9hIF6xitWRBbiPZOBb6vGo/mDRIK9P74RTKSQK7AE8B0DDWY/vpRrPmQw== + dependencies: + for-own "^1.0.0" + is-plain-object "^2.0.4" + kind-of "^5.0.0" + shallow-clone "^1.0.0" + +clone-deep@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" + integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== + dependencies: + is-plain-object "^2.0.4" + kind-of "^6.0.2" + shallow-clone "^3.0.0" + +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= + dependencies: + map-visit "^1.0.0" + object-visit "^1.0.0" + +commander@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" + integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== + +component-emitter@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" + integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= + +core-js@^2.4.0: + version "2.6.11" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c" + integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg== + +cross-spawn@^7.0.0: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +debug@^2.6.6, debug@^2.6.8: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@^3.0.1: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + dependencies: + ms "^2.1.1" + +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= + dependencies: + is-descriptor "^0.1.0" + +define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= + dependencies: + is-descriptor "^1.0.0" + +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + +end-of-stream@^1.1.0: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + +error-symbol@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/error-symbol/-/error-symbol-0.1.0.tgz#0a4dae37d600d15a29ba453d8ef920f1844333f6" + integrity sha1-Ck2uN9YA0VopukU9jvkg8YRDM/Y= + +escape-string-regexp@^1.0.2: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +esm@^3.2.25: + version "3.2.25" + resolved "https://registry.yarnpkg.com/esm/-/esm-3.2.25.tgz#342c18c29d56157688ba5ce31f8431fbb795cc10" + integrity sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +execa@^2.0.3: + version "2.1.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-2.1.0.tgz#e5d3ecd837d2a60ec50f3da78fd39767747bbe99" + integrity sha512-Y/URAVapfbYy2Xp/gb6A0E7iR8xeqOCXsuuaoMn7A5PzrXUK84E1gyiEfq0wQd/GHA6GsoHWwhNq8anb0mleIw== + dependencies: + cross-spawn "^7.0.0" + get-stream "^5.0.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^3.0.0" + onetime "^5.1.0" + p-finally "^2.0.0" + signal-exit "^3.0.2" + strip-final-newline "^2.0.0" + +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= + dependencies: + is-extendable "^0.1.0" + +for-in@^0.1.3: + version "0.1.8" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-0.1.8.tgz#d8773908e31256109952b1fdb9b3fa867d2775e1" + integrity sha1-2Hc5COMSVhCZUrH9ubP6hn0ndeE= + +for-in@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= + +for-own@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/for-own/-/for-own-1.0.0.tgz#c63332f415cedc4b04dbfe70cf836494c53cb44b" + integrity sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs= + dependencies: + for-in "^1.0.1" + +fs-extra@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" + integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +get-stream@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.1.0.tgz#01203cdc92597f9b909067c3e656cc1f4d3c4dc9" + integrity sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw== + dependencies: + pump "^3.0.0" + +glob@^7.1.6: + version "7.1.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== + dependencies: + 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" + +globals@^9.18.0: + version "9.18.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" + integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== + +graceful-fs@^4.1.6, graceful-fs@^4.2.0: + version "4.2.4" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" + integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= + dependencies: + ansi-regex "^2.0.0" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +info-symbol@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/info-symbol/-/info-symbol-0.1.0.tgz#27841d72867ddb4242cd612d79c10633881c6a78" + integrity sha1-J4QdcoZ920JCzWEtecEGM4gcang= + +inherits@2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +invariant@^2.2.2: + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== + dependencies: + loose-envify "^1.0.0" + +is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= + dependencies: + kind-of "^3.0.2" + +is-accessor-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== + dependencies: + kind-of "^6.0.0" + +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + +is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= + dependencies: + kind-of "^3.0.2" + +is-data-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== + dependencies: + kind-of "^6.0.0" + +is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" + +is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== + dependencies: + is-accessor-descriptor "^1.0.0" + is-data-descriptor "^1.0.0" + kind-of "^6.0.2" + +is-extendable@^0.1.0, is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= + dependencies: + kind-of "^3.0.2" + +is-number@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-6.0.0.tgz#e6d15ad31fc262887cccf217ae5f9316f81b1995" + integrity sha512-Wu1VHeILBK8KAWJUAiSZQX94GmOE45Rg6/538fKwiloUu21KncEkYGPqob2oSZ5mUT73vLGrHQjKw3KMPwfDzg== + +is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +is-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" + integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== + +is-windows@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + +isobject@^3.0.0, isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= + +"js-tokens@^3.0.0 || ^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-tokens@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" + integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= + +json5@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" + integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== + dependencies: + minimist "^1.2.0" + +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= + optionalDependencies: + graceful-fs "^4.1.6" + +kind-of@^3.0.2, kind-of@^3.0.3: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= + dependencies: + is-buffer "^1.1.5" + +kind-of@^5.0.0, kind-of@^5.0.2: + version "5.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== + +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +koalas@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/koalas/-/koalas-1.0.2.tgz#318433f074235db78fae5661a02a8ca53ee295cd" + integrity sha1-MYQz8HQjXbePrlZhoCqMpT7ilc0= + +lazy-cache@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-2.0.2.tgz#b9190a4f913354694840859f8a8f7084d8822264" + integrity sha1-uRkKT5EzVGlIQIWfio9whNiCImQ= + dependencies: + set-getter "^0.1.0" + +lodash@^4.17.4: + version "4.17.15" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" + integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== + +log-ok@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/log-ok/-/log-ok-0.1.1.tgz#bea3dd36acd0b8a7240d78736b5b97c65444a334" + integrity sha1-vqPdNqzQuKckDXhza1uXxlREozQ= + dependencies: + ansi-green "^0.1.1" + success-symbol "^0.1.0" + +log-utils@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/log-utils/-/log-utils-0.2.1.tgz#a4c217a0dd9a50515d9b920206091ab3d4e031cf" + integrity sha1-pMIXoN2aUFFdm5ICBgkas9TgMc8= + dependencies: + ansi-colors "^0.2.0" + error-symbol "^0.1.0" + info-symbol "^0.1.0" + log-ok "^0.1.1" + success-symbol "^0.1.0" + time-stamp "^1.0.1" + warning-symbol "^0.1.0" + +loose-envify@^1.0.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +make-error@^1.1.1: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= + dependencies: + object-visit "^1.0.0" + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +minimist@^1.2.0: + version "1.2.5" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + +mixin-object@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/mixin-object/-/mixin-object-2.0.1.tgz#4fb949441dab182540f1fe035ba60e1947a5e57e" + integrity sha1-T7lJRB2rGCVA8f4DW6YOGUel5X4= + dependencies: + for-in "^0.1.3" + is-extendable "^0.1.1" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + +ms@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +mute-stream@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" + integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= + +npm-run-path@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-3.1.0.tgz#7f91be317f6a466efed3c9f2980ad8a4ee8b0fa5" + integrity sha512-Dbl4A/VfiVGLgQv29URL9xshU8XDY1GeLy+fsaZ1AA8JDSfjvr5P5+pzRbWqRSBxk6/DW7MIh8lTM/PaGnP2kg== + dependencies: + path-key "^3.0.0" + +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= + dependencies: + isobject "^3.0.0" + +once@^1.3.0, once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +onetime@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5" + integrity sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q== + dependencies: + mimic-fn "^2.1.0" + +p-finally@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-2.0.1.tgz#bd6fcaa9c559a096b680806f4d657b3f0f240561" + integrity sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +pointer-symbol@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/pointer-symbol/-/pointer-symbol-1.0.0.tgz#60f9110204ea7a929b62644a21315543cbb3d447" + integrity sha1-YPkRAgTqepKbYmRKITFVQ8uz1Ec= + +prompt-actions@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/prompt-actions/-/prompt-actions-3.0.2.tgz#537eee52241c940379f354a06eae8528e44ceeba" + integrity sha512-dhz2Fl7vK+LPpmnQ/S/eSut4BnH4NZDLyddHKi5uTU/2PDn3grEMGkgsll16V5RpVUh/yxdiam0xsM0RD4xvtg== + dependencies: + debug "^2.6.8" + +prompt-base@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/prompt-base/-/prompt-base-4.1.0.tgz#7b88e4c01b096c83d2f4e501a7e85f0d369ecd1f" + integrity sha512-svGzgLUKZoqomz9SGMkf1hBG8Wl3K7JGuRCXc/Pv7xw8239hhaTBXrmjt7EXA9P/QZzdyT8uNWt9F/iJTXq75g== + dependencies: + component-emitter "^1.2.1" + debug "^3.0.1" + koalas "^1.0.2" + log-utils "^0.2.1" + prompt-actions "^3.0.2" + prompt-question "^5.0.1" + readline-ui "^2.2.3" + readline-utils "^2.2.3" + static-extend "^0.1.2" + +prompt-choices@^4.0.5: + version "4.1.0" + resolved "https://registry.yarnpkg.com/prompt-choices/-/prompt-choices-4.1.0.tgz#6094202c4e55d0762e49c1e53735727e53fd484f" + integrity sha512-ZNYLv6rW9z9n0WdwCkEuS+w5nUAGzRgtRt6GQ5aFNFz6MIcU7nHFlHOwZtzy7RQBk80KzUGPSRQphvMiQzB8pg== + dependencies: + arr-flatten "^1.1.0" + arr-swap "^1.0.1" + choices-separator "^2.0.0" + clone-deep "^4.0.0" + collection-visit "^1.0.0" + define-property "^2.0.2" + is-number "^6.0.0" + kind-of "^6.0.2" + koalas "^1.0.2" + log-utils "^0.2.1" + pointer-symbol "^1.0.0" + radio-symbol "^2.0.0" + set-value "^3.0.0" + strip-color "^0.1.0" + terminal-paginator "^2.0.2" + toggle-array "^1.0.1" + +prompt-confirm@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/prompt-confirm/-/prompt-confirm-2.0.4.tgz#42c06907333e876f2ae8867281e0b9521a4796ca" + integrity sha512-X5lzbC8/kMNHdPOqQPfMKpH4VV2f7v2OTRJoN69ZYBirSwTeQaf9ZhmzPEO9ybMA0YV2Pha5MV27u2/U4ahWfg== + dependencies: + ansi-cyan "^0.1.1" + prompt-base "^4.0.1" + +prompt-question@^5.0.1: + version "5.0.2" + resolved "https://registry.yarnpkg.com/prompt-question/-/prompt-question-5.0.2.tgz#81a479f38f0bafecc758e5d6f7bc586e599610b3" + integrity sha512-wreaLbbu8f5+7zXds199uiT11Ojp59Z4iBi6hONlSLtsKGTvL2UY8VglcxQ3t/X4qWIxsNCg6aT4O8keO65v6Q== + dependencies: + clone-deep "^1.0.0" + debug "^3.0.1" + define-property "^1.0.0" + isobject "^3.0.1" + kind-of "^5.0.2" + koalas "^1.0.2" + prompt-choices "^4.0.5" + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +radio-symbol@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/radio-symbol/-/radio-symbol-2.0.0.tgz#7aa9bfc50485636d52dd76d6a8e631b290799ae1" + integrity sha1-eqm/xQSFY21S3XbWqOYxspB5muE= + dependencies: + ansi-gray "^0.1.1" + ansi-green "^0.1.1" + is-windows "^1.0.1" + +readline-ui@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/readline-ui/-/readline-ui-2.2.3.tgz#9e873a7668bbd8ca8a5573ce810a6bafb70a5089" + integrity sha512-ix7jz0PxqQqcIuq3yQTHv1TOhlD2IHO74aNO+lSuXsRYm1d+pdyup1yF3zKyLK1wWZrVNGjkzw5tUegO2IDy+A== + dependencies: + component-emitter "^1.2.1" + debug "^2.6.8" + readline-utils "^2.2.1" + string-width "^2.0.0" + +readline-utils@^2.2.1, readline-utils@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/readline-utils/-/readline-utils-2.2.3.tgz#6f847d6b8f1915c391b581c367cd47873862351a" + integrity sha1-b4R9a48ZFcORtYHDZ81HhzhiNRo= + dependencies: + arr-flatten "^1.1.0" + extend-shallow "^2.0.1" + is-buffer "^1.1.5" + is-number "^3.0.0" + is-windows "^1.0.1" + koalas "^1.0.2" + mute-stream "0.0.7" + strip-color "^0.1.0" + window-size "^1.1.0" + +regenerator-runtime@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" + integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== + +set-getter@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/set-getter/-/set-getter-0.1.0.tgz#d769c182c9d5a51f409145f2fba82e5e86e80376" + integrity sha1-12nBgsnVpR9AkUXy+6guXoboA3Y= + dependencies: + to-object-path "^0.3.0" + +set-value@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-3.0.2.tgz#74e8ecd023c33d0f77199d415409a40f21e61b90" + integrity sha512-npjkVoz+ank0zjlV9F47Fdbjfj/PfXyVhZvGALWsyIYU/qrMzpi6avjKW3/7KeSU2Df3I46BrN1xOI1+6vW0hA== + dependencies: + is-plain-object "^2.0.4" + +shallow-clone@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-1.0.0.tgz#4480cd06e882ef68b2ad88a3ea54832e2c48b571" + integrity sha512-oeXreoKR/SyNJtRJMAKPDSvd28OqEwG4eR/xc856cRGBII7gX9lvAqDxusPm0846z/w/hWYjI1NpKwJ00NHzRA== + dependencies: + is-extendable "^0.1.1" + kind-of "^5.0.0" + mixin-object "^2.0.1" + +shallow-clone@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" + integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== + dependencies: + kind-of "^6.0.2" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +signal-exit@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" + integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== + +source-map-support@^0.5.17: + version "0.5.19" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" + integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +static-extend@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" + +string-width@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +strip-ansi@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= + dependencies: + ansi-regex "^3.0.0" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= + +strip-color@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/strip-color/-/strip-color-0.1.0.tgz#106f65d3d3e6a2d9401cac0eb0ce8b8a702b4f7b" + integrity sha1-EG9l09PmotlAHKwOsM6LinArT3s= + +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + +success-symbol@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/success-symbol/-/success-symbol-0.1.0.tgz#24022e486f3bf1cdca094283b769c472d3b72897" + integrity sha1-JAIuSG878c3KCUKDt2nEctO3KJc= + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= + +terminal-paginator@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/terminal-paginator/-/terminal-paginator-2.0.2.tgz#967e66056f28fe8f55ba7c1eebfb7c3ef371c1d3" + integrity sha512-IZMT5ECF9p4s+sNCV8uvZSW9E1+9zy9Ji9xz2oee8Jfo7hUFpauyjxkhfRcIH6Lu3Wdepv5D1kVRc8Hx74/LfQ== + dependencies: + debug "^2.6.6" + extend-shallow "^2.0.1" + log-utils "^0.2.1" + +time-stamp@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3" + integrity sha1-dkpaEa9QVhkhsTPztE5hhofg9cM= + +to-fast-properties@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" + integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc= + +to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= + dependencies: + kind-of "^3.0.2" + +toggle-array@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toggle-array/-/toggle-array-1.0.1.tgz#cbf5840792bd5097f33117ae824c932affe87d58" + integrity sha1-y/WEB5K9UJfzMReugkyTKv/ofVg= + dependencies: + isobject "^3.0.0" + +ts-node@^8.5.4: + version "8.10.2" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.10.2.tgz#eee03764633b1234ddd37f8db9ec10b75ec7fb8d" + integrity sha512-ISJJGgkIpDdBhWVu3jufsWpK3Rzo7bdiIXJjQc0ynKxVOVcg2oIrf2H2cejminGrptVc6q6/uynAHNCuWGbpVA== + dependencies: + arg "^4.1.0" + diff "^4.0.1" + make-error "^1.1.1" + source-map-support "^0.5.17" + yn "3.1.1" + +tsconfig-paths@^3.9.0: + version "3.9.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz#098547a6c4448807e8fcb8eae081064ee9a3c90b" + integrity sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw== + dependencies: + "@types/json5" "^0.0.29" + json5 "^1.0.1" + minimist "^1.2.0" + strip-bom "^3.0.0" + +typescript@^3.7.4: + version "3.9.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.3.tgz#d3ac8883a97c26139e42df5e93eeece33d610b8a" + integrity sha512-D/wqnB2xzNFIcoBG9FG8cXRDjiqSTbG2wd8DMZeQyJlP1vfTkIxH4GKveWaEBYySKIg+USu+E+EDIR47SqnaMQ== + +universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + +warning-symbol@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/warning-symbol/-/warning-symbol-0.1.0.tgz#bb31dd11b7a0f9d67ab2ed95f457b65825bbad21" + integrity sha1-uzHdEbeg+dZ6su2V9Fe2WCW7rSE= + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +window-size@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/window-size/-/window-size-1.1.1.tgz#9858586580ada78ab26ecd6978a6e03115c1af20" + integrity sha512-5D/9vujkmVQ7pSmc0SCBmHXbkv6eaHwXEx65MywhmUMsI8sGqJ972APq1lotfcwMKPFLuCFfL8xGHLIp7jaBmA== + dependencies: + define-property "^1.0.0" + is-number "^3.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== diff --git a/npm/ng-packs/yarn.lock b/npm/ng-packs/yarn.lock index f288eac2f1..e19659640b 100644 --- a/npm/ng-packs/yarn.lock +++ b/npm/ng-packs/yarn.lock @@ -2350,6 +2350,13 @@ resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== +"@swimlane/ngx-datatable@^16.0.0": + version "16.1.1" + resolved "https://registry.yarnpkg.com/@swimlane/ngx-datatable/-/ngx-datatable-16.1.1.tgz#1215e81f51400314ba6899f66acdbd4e3bde2915" + integrity sha512-h2A9xC/jo314eC/CzA19aoY/YadhdTupolCwpgB9Cbw3sDRi3x/LeGsdLSV0bj3XBKQUB3DA/gPuASKYuhm8iA== + dependencies: + tslib "^1.9.0" + "@szmarczak/http-timer@^1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" From f96b8028dfc0495fc05524d41c9965919e6820d8 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Thu, 4 Jun 2020 03:39:40 +0300 Subject: [PATCH 06/81] feat(identity): implement ngx-datatable and list service to roles.component --- .../lib/components/roles/roles.component.html | 138 ++++++++---------- .../lib/components/roles/roles.component.ts | 32 ++-- 2 files changed, 71 insertions(+), 99 deletions(-) diff --git a/npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.html b/npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.html index 9962d8dbb4..d71f6cce5e 100644 --- a/npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.html +++ b/npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.html @@ -19,90 +19,70 @@ -
- + - - - - - - - - {{ 'AbpIdentity::Actions' | abpLocalization }} - - {{ 'AbpIdentity::RoleName' | abpLocalization }} - - - - - - - -
+ + +
+ +
+ + -
- - - -
- - - {{ data.name - }}{{ - 'AbpIdentity::DisplayName:IsDefault' | abpLocalization - }} - {{ - 'AbpIdentity::DisplayName:IsPublic' | abpLocalization - }} - - - - +
+
+
+ +
diff --git a/npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.ts b/npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.ts index 5e0f64e811..e2dc5fa59d 100644 --- a/npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.ts +++ b/npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.ts @@ -1,5 +1,6 @@ -import { ABP } from '@abp/ng.core'; -import { ConfirmationService, Confirmation } from '@abp/ng.theme.shared'; +import { ListService } from '@abp/ng.core'; +import { ePermissionManagementComponents } from '@abp/ng.permission-management'; +import { Confirmation, ConfirmationService } from '@abp/ng.theme.shared'; import { Component, ElementRef, OnInit, ViewChild } from '@angular/core'; import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms'; import { Select, Store } from '@ngxs/store'; @@ -14,11 +15,11 @@ import { } from '../../actions/identity.actions'; import { Identity } from '../../models/identity'; import { IdentityState } from '../../states/identity.state'; -import { ePermissionManagementComponents } from '@abp/ng.permission-management'; @Component({ selector: 'abp-roles', templateUrl: './roles.component.html', + providers: [ListService], }) export class RolesComponent implements OnInit { @Select(IdentityState.getRoles) @@ -37,16 +38,10 @@ export class RolesComponent implements OnInit { providerKey: string; - pageQuery: ABP.PageQueryParams = { maxResultCount: 10 }; - loading = false; modalBusy = false; - sortOrder = ''; - - sortKey = ''; - permissionManagementKey = ePermissionManagementComponents.PermissionManagement; @ViewChild('formRef', { static: false, read: ElementRef }) @@ -57,6 +52,7 @@ export class RolesComponent implements OnInit { }; constructor( + public readonly list: ListService, private confirmationService: ConfirmationService, private fb: FormBuilder, private store: Store, @@ -126,18 +122,8 @@ export class RolesComponent implements OnInit { }); } - onPageChange(page: number) { - this.pageQuery.skipCount = (page - 1) * this.pageQuery.maxResultCount; - - this.get(); - } - get() { - this.loading = true; - this.store - .dispatch(new GetRoles(this.pageQuery)) - .pipe(finalize(() => (this.loading = false))) - .subscribe(); + this.list.hookToQuery(query => this.store.dispatch(new GetRoles(query))).subscribe(); } onClickSaveButton() { @@ -152,4 +138,10 @@ export class RolesComponent implements OnInit { this.visiblePermissions = true; }, 0); } + + onSort(event) { + const { prop, dir } = event.sorts[0]; + this.list.sortKey = prop; + this.list.sortOrder = dir; + } } From 057c4c1a250c3d14471ef87a6b9b9db1ce04b46f Mon Sep 17 00:00:00 2001 From: maliming <6908465+maliming@users.noreply.github.com> Date: Thu, 4 Jun 2020 15:35:43 +0800 Subject: [PATCH 07/81] Compatible with multi-tenancy. --- ...ureBlobContainerConfigurationExtensions.cs | 4 +- .../BlobStoring/Azure/AzureBlobProvider.cs | 29 ++++++---- .../Azure/DefaultAzureBlobNameCalculator.cs | 22 +++++++ .../Azure/IAzureBlobNameCalculator.cs | 7 +++ .../Azure/AbpBlobStoringAzureTestBase.cs | 8 +++ .../Azure/AbpBlobStoringAzureTestModule.cs | 14 ++++- .../Azure/AzureBlobNameCalculator_Tests.cs | 57 +++++++++++++++++++ 7 files changed, 127 insertions(+), 14 deletions(-) create mode 100644 framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/DefaultAzureBlobNameCalculator.cs create mode 100644 framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/IAzureBlobNameCalculator.cs create mode 100644 framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AzureBlobNameCalculator_Tests.cs diff --git a/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobContainerConfigurationExtensions.cs b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobContainerConfigurationExtensions.cs index 917870aa9d..945c930175 100644 --- a/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobContainerConfigurationExtensions.cs +++ b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobContainerConfigurationExtensions.cs @@ -12,11 +12,11 @@ namespace Volo.Abp.BlobStoring.Azure public static BlobContainerConfiguration UseAzure( this BlobContainerConfiguration containerConfiguration, - Action fileSystemConfigureAction) + Action azureConfigureAction) { containerConfiguration.ProviderType = typeof(AzureBlobProvider); - fileSystemConfigureAction(new AzureBlobProviderConfiguration(containerConfiguration)); + azureConfigureAction(new AzureBlobProviderConfiguration(containerConfiguration)); return containerConfiguration; } diff --git a/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProvider.cs b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProvider.cs index eb69bb802a..e0b70dc66c 100644 --- a/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProvider.cs +++ b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProvider.cs @@ -1,15 +1,24 @@ using System.IO; using System.Threading.Tasks; using Azure.Storage.Blobs; +using Azure.Storage.Blobs.Specialized; using Volo.Abp.DependencyInjection; namespace Volo.Abp.BlobStoring.Azure { public class AzureBlobProvider : BlobProviderBase, ITransientDependency { + protected IAzureBlobNameCalculator AzureBlobNameCalculator { get; } + + public AzureBlobProvider(IAzureBlobNameCalculator azureBlobNameCalculator) + { + AzureBlobNameCalculator = azureBlobNameCalculator; + } + public override async Task SaveAsync(BlobProviderSaveArgs args) { - var blobClient = GetBlobClient(args.Configuration.GetAzureConfiguration(), args.BlobName); + var blobName = AzureBlobNameCalculator.Calculate(args); + var blobClient = GetBlobClient(args.Configuration.GetAzureConfiguration(), blobName); if (!args.OverrideExisting && await BlobExistsAsync(blobClient)) { @@ -21,24 +30,22 @@ namespace Volo.Abp.BlobStoring.Azure public override async Task DeleteAsync(BlobProviderDeleteArgs args) { - var blobClient = GetBlobClient(args.Configuration.GetAzureConfiguration(), args.BlobName); - if (await BlobExistsAsync(blobClient)) - { - return (await blobClient.DeleteAsync()).Status == 200; - } - - return false; + var blobName = AzureBlobNameCalculator.Calculate(args); + var blobClient = GetBlobClient(args.Configuration.GetAzureConfiguration(), blobName); + return await blobClient.DeleteIfExistsAsync(); } public override async Task ExistsAsync(BlobProviderExistsArgs args) { - var blobClient = GetBlobClient(args.Configuration.GetAzureConfiguration(), args.BlobName); + var blobName = AzureBlobNameCalculator.Calculate(args); + var blobClient = GetBlobClient(args.Configuration.GetAzureConfiguration(), blobName); return await BlobExistsAsync(blobClient); } public override async Task GetOrNullAsync(BlobProviderGetArgs args) { - var blobClient = GetBlobClient(args.Configuration.GetAzureConfiguration(), args.BlobName); + var blobName = AzureBlobNameCalculator.Calculate(args); + var blobClient = GetBlobClient(args.Configuration.GetAzureConfiguration(), blobName); if (!await BlobExistsAsync(blobClient)) { return null; @@ -62,7 +69,7 @@ namespace Volo.Abp.BlobStoring.Azure return blobServiceClient.GetBlobContainerClient(configuration.ContainerName); } - private static async Task BlobExistsAsync(BlobClient blobClient) + private static async Task BlobExistsAsync(BlobBaseClient blobClient) { return (await blobClient.ExistsAsync()).Value; } diff --git a/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/DefaultAzureBlobNameCalculator.cs b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/DefaultAzureBlobNameCalculator.cs new file mode 100644 index 0000000000..0c6cd481c9 --- /dev/null +++ b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/DefaultAzureBlobNameCalculator.cs @@ -0,0 +1,22 @@ +using Volo.Abp.DependencyInjection; +using Volo.Abp.MultiTenancy; + +namespace Volo.Abp.BlobStoring.Azure +{ + public class DefaultAzureBlobNameCalculator : IAzureBlobNameCalculator, ITransientDependency + { + protected ICurrentTenant CurrentTenant { get; } + + public DefaultAzureBlobNameCalculator(ICurrentTenant currentTenant) + { + CurrentTenant = currentTenant; + } + + public virtual string Calculate(BlobProviderArgs args) + { + return CurrentTenant.Id == null + ? $"host/{args.BlobName}" + : $"tenants/{CurrentTenant.Id.Value.ToString("D")}/{args.BlobName}"; + } + } +} diff --git a/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/IAzureBlobNameCalculator.cs b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/IAzureBlobNameCalculator.cs new file mode 100644 index 0000000000..5985a9278d --- /dev/null +++ b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/IAzureBlobNameCalculator.cs @@ -0,0 +1,7 @@ +namespace Volo.Abp.BlobStoring.Azure +{ + public interface IAzureBlobNameCalculator + { + string Calculate(BlobProviderArgs args); + } +} diff --git a/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureTestBase.cs b/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureTestBase.cs index 7213c8eb78..8941234cbf 100644 --- a/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureTestBase.cs +++ b/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureTestBase.cs @@ -2,6 +2,14 @@ namespace Volo.Abp.BlobStoring.Azure { + public class AbpBlobStoringAzureTestCommonBase : AbpIntegratedTest + { + protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) + { + options.UseAutofac(); + } + } + public class AbpBlobStoringAzureTestBase : AbpIntegratedTest { protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) diff --git a/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureTestModule.cs b/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureTestModule.cs index 4711699726..a45d209b32 100644 --- a/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureTestModule.cs +++ b/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureTestModule.cs @@ -6,10 +6,22 @@ using Volo.Abp.Modularity; namespace Volo.Abp.BlobStoring.Azure { + + /// + /// This module will not try to connect to azure. + /// [DependsOn( typeof(AbpBlobStoringAzureModule), typeof(AbpBlobStoringTestModule) )] + public class AbpBlobStoringAzureTestCommonModule : AbpModule + { + + } + + [DependsOn( + typeof(AbpBlobStoringAzureTestCommonModule) + )] public class AbpBlobStoringAzureTestModule : AbpModule { private const string UserSecretsId = "9f0d2c00-80c1-435b-bfab-2c39c8249091"; @@ -47,9 +59,9 @@ namespace Volo.Abp.BlobStoring.Azure public override void OnApplicationShutdown(ApplicationShutdownContext context) { - var configuration = context.ServiceProvider.GetRequiredService(); var blobServiceClient = new BlobServiceClient(_connectionString); blobServiceClient.DeleteBlobContainer(_randomContainerName); } } + } diff --git a/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AzureBlobNameCalculator_Tests.cs b/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AzureBlobNameCalculator_Tests.cs new file mode 100644 index 0000000000..4540d208ae --- /dev/null +++ b/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AzureBlobNameCalculator_Tests.cs @@ -0,0 +1,57 @@ +using System; +using Shouldly; +using Volo.Abp.MultiTenancy; +using Xunit; + +namespace Volo.Abp.BlobStoring.Azure +{ + public class AzureBlobNameCalculator_Tests : AbpBlobStoringAzureTestCommonBase + { + private readonly IAzureBlobNameCalculator _calculator; + private readonly ICurrentTenant _currentTenant; + + private const string AzureContainerName = "/"; + private const string AzureSeparator = "/"; + + public AzureBlobNameCalculator_Tests() + { + _calculator = GetRequiredService(); + _currentTenant = GetRequiredService(); + } + + [Fact] + public void Default_Settings() + { + _calculator.Calculate( + GetArgs("my-container", "my-blob") + ).ShouldBe($"host{AzureSeparator}my-blob"); + } + + [Fact] + public void Default_Settings_With_TenantId() + { + var tenantId = Guid.NewGuid(); + + using (_currentTenant.Change(tenantId)) + { + _calculator.Calculate( + GetArgs("my-container", "my-blob") + ).ShouldBe($"tenants{AzureSeparator}{tenantId:D}{AzureSeparator}my-blob"); + } + } + + private static BlobProviderArgs GetArgs( + string containerName, + string blobName) + { + return new BlobProviderGetArgs( + containerName, + new BlobContainerConfiguration().UseAzure(x => + { + x.ContainerName = containerName; + }), + blobName + ); + } + } +} From 43836880deffb31062490c0da420a8442eef147a Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Thu, 4 Jun 2020 15:12:10 +0300 Subject: [PATCH 08/81] feat(theme-shared): replace ngx-datatable messages with localized texts resolves #4197 --- .../Localization/Resources/AbpUi/en.json | 4 ++- .../Localization/Resources/AbpUi/tr.json | 4 ++- .../src/lib/theme-shared.module.ts | 36 +++++++++++-------- 3 files changed, 27 insertions(+), 17 deletions(-) diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json index 2bd4bc7352..a4fdf7afbd 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json @@ -47,6 +47,8 @@ "PagerInfoEmpty": "Showing 0 to 0 of 0 entries", "PagerInfoFiltered": "(filtered from _MAX_ total entries)", "NoDataAvailableInDatatable": "No data available", + "Total": "total", + "Selected": "selected", "PagerShowMenuEntries": "Show _MENU_ entries", "DatatableActionDropdownDefaultText": "Actions", "ChangePassword": "Change password", @@ -59,6 +61,6 @@ "500Message": "Internal Server Error", "GoHomePage": "Go to the homepage", "GoBack": "Go back", - "Search" : "Search" + "Search": "Search" } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/tr.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/tr.json index ddf8760fa9..bf558bb763 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/tr.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/tr.json @@ -47,6 +47,8 @@ "PagerInfoEmpty": "0 kayıttan 0 ile 0 arası gösteriliyor.", "PagerInfoFiltered": "(_MAX_ kayıt arasından filtrelendi)", "NoDataAvailableInDatatable": "Tabloda kayıt mevcut değil.", + "Total": "toplam", + "Selected": "seçilen", "PagerShowMenuEntries": "Sayfada _MENU_ kayıt göster.", "DatatableActionDropdownDefaultText": "İşlemler", "ChangePassword": "Şifre değiştir", @@ -61,4 +63,4 @@ "GoBack": "Geri dön", "Search": "Arama" } -} \ No newline at end of file +} diff --git a/npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts b/npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts index dd7803e459..10e112ffed 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts @@ -1,9 +1,9 @@ -import { CoreModule, LazyLoadService, noop } from '@abp/ng.core'; +import { CoreModule, LazyLoadService, noop, ConfigState } from '@abp/ng.core'; import { DatePipe } from '@angular/common'; import { APP_INITIALIZER, Injector, ModuleWithProviders, NgModule } from '@angular/core'; import { NgbDateParserFormatter, NgbPaginationModule } from '@ng-bootstrap/ng-bootstrap'; import { NgxValidateCoreModule } from '@ngx-validate/core'; -import { NgxDatatableModule } from '@swimlane/ngx-datatable'; +import { NgxDatatableModule, INgxDatatableConfig } from '@swimlane/ngx-datatable'; import { BreadcrumbComponent } from './components/breadcrumb/breadcrumb.component'; import { ButtonComponent } from './components/button/button.component'; import { ChartComponent } from './components/chart/chart.component'; @@ -29,21 +29,22 @@ import { THEME_SHARED_APPEND_CONTENT } from './tokens/append-content.token'; import { httpErrorConfigFactory, HTTP_ERROR_CONFIG } from './tokens/http-error.token'; import { DateParserFormatter } from './utils/date-parser-formatter'; import { chartJsLoaded$ } from './utils/widget-utils'; +import { Store } from '@ngxs/store'; -/** - * - * @deprecated To be deleted in v2.6 - * - */ -export function appendScript(injector: Injector) { - const fn = () => { - import('chart.js').then(() => chartJsLoaded$.next(true)); +export function ngxDatatableMessageFactory(store: Store) { + const emptyMessage = store.selectSnapshot( + ConfigState.getLocalization('AbpUi::NoDataAvailableInDatatable'), + ); + const totalMessage = store.selectSnapshot(ConfigState.getLocalization('AbpUi::Total')); + const selectedMessage = store.selectSnapshot(ConfigState.getLocalization('AbpUi::Selected')); - const lazyLoadService: LazyLoadService = injector.get(LazyLoadService); - return lazyLoadService.load(null, 'style', styles, 'head', 'beforeend').toPromise(); - }; - - return fn; + return { + messages: { + emptyMessage, + totalMessage, + selectedMessage, + }, + } as INgxDatatableConfig; } @NgModule({ @@ -120,6 +121,11 @@ export class ThemeSharedModule { deps: [HTTP_ERROR_CONFIG], }, { provide: NgbDateParserFormatter, useClass: DateParserFormatter }, + { + provide: 'configuration', + useFactory: ngxDatatableMessageFactory, + deps: [Store], + }, ], }; } From bc2c5057ff73fe480fb0adad861b6849fbb9c812 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Thu, 4 Jun 2020 15:37:49 +0300 Subject: [PATCH 09/81] fix(identity): ngx-datatable variable mistake in roles.component --- .../src/lib/components/roles/roles.component.html | 14 +++++++------- .../src/lib/components/roles/roles.component.ts | 6 ++---- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.html b/npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.html index d71f6cce5e..eb45a485a8 100644 --- a/npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.html +++ b/npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.html @@ -19,12 +19,12 @@ -
+
- +
diff --git a/npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.ts b/npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.ts index e2dc5fa59d..09582f4e9f 100644 --- a/npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.ts +++ b/npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.ts @@ -38,8 +38,6 @@ export class RolesComponent implements OnInit { providerKey: string; - loading = false; - modalBusy = false; permissionManagementKey = ePermissionManagementComponents.PermissionManagement; @@ -139,8 +137,8 @@ export class RolesComponent implements OnInit { }, 0); } - onSort(event) { - const { prop, dir } = event.sorts[0]; + sort(data) { + const { prop, dir } = data.sorts[0]; this.list.sortKey = prop; this.list.sortOrder = dir; } From 247eea7e6031c0dfe25238bf0dd2751d929febbc Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Thu, 4 Jun 2020 15:38:21 +0300 Subject: [PATCH 10/81] feat(identity): replace abp-table in users.component with ngx-datatable --- .../lib/components/users/users.component.html | 164 ++++++++---------- .../lib/components/users/users.component.ts | 31 +--- 2 files changed, 79 insertions(+), 116 deletions(-) diff --git a/npm/ng-packs/packages/identity/src/lib/components/users/users.component.html b/npm/ng-packs/packages/identity/src/lib/components/users/users.component.html index e00dbfe866..68012b3d90 100644 --- a/npm/ng-packs/packages/identity/src/lib/components/users/users.component.html +++ b/npm/ng-packs/packages/identity/src/lib/components/users/users.component.html @@ -20,108 +20,86 @@
- + [(ngModel)]="list.filter" + /> +
- - - - - - - - - {{ 'AbpIdentity::Actions' | abpLocalization }} - - {{ 'AbpIdentity::UserName' | abpLocalization }} - - - - - {{ 'AbpIdentity::EmailAddress' | abpLocalization }} - - - - {{ 'AbpIdentity::PhoneNumber' | abpLocalization }} - + +
+ +
+ + -
- - - -
- - {{ data.userName }} - {{ data.email }} - {{ data.phoneNumber }} - - - +
+
+ + + + +
diff --git a/npm/ng-packs/packages/identity/src/lib/components/users/users.component.ts b/npm/ng-packs/packages/identity/src/lib/components/users/users.component.ts index e208f9ffec..33aa8ee40d 100644 --- a/npm/ng-packs/packages/identity/src/lib/components/users/users.component.ts +++ b/npm/ng-packs/packages/identity/src/lib/components/users/users.component.ts @@ -1,4 +1,4 @@ -import { ABP } from '@abp/ng.core'; +import { ABP, ListService } from '@abp/ng.core'; import { Confirmation, ConfirmationService, getPasswordValidators } from '@abp/ng.theme.shared'; import { Component, OnInit, TemplateRef, TrackByFunction, ViewChild } from '@angular/core'; import { @@ -28,6 +28,7 @@ import { ePermissionManagementComponents } from '@abp/ng.permission-management'; @Component({ selector: 'abp-users', templateUrl: './users.component.html', + providers: [ListService], }) export class UsersComponent implements OnInit { @Select(IdentityState.getUsers) @@ -51,18 +52,10 @@ export class UsersComponent implements OnInit { providerKey: string; - pageQuery: ABP.PageQueryParams = { maxResultCount: 10 }; - isModalVisible: boolean; - loading = false; - modalBusy = false; - sortOrder = ''; - - sortKey = ''; - permissionManagementKey = ePermissionManagementComponents.PermissionManagement; trackByFn: TrackByFunction = (index, item) => Object.keys(item)[0] || index; @@ -76,6 +69,7 @@ export class UsersComponent implements OnInit { } constructor( + public readonly list: ListService, private confirmationService: ConfirmationService, private fb: FormBuilder, private store: Store, @@ -86,11 +80,6 @@ export class UsersComponent implements OnInit { this.get(); } - onSearch(value: string) { - this.pageQuery.filter = value; - this.get(); - } - buildForm() { this.identityService.getAllRoles().subscribe(({ items }) => { this.roles = items; @@ -199,18 +188,14 @@ export class UsersComponent implements OnInit { }); } - onPageChange(page: number) { - this.pageQuery.skipCount = (page - 1) * this.pageQuery.maxResultCount; - - this.get(); + sort(data) { + const { prop, dir } = data.sorts[0]; + this.list.sortKey = prop; + this.list.sortOrder = dir; } get() { - this.loading = true; - this.store - .dispatch(new GetUsers(this.pageQuery)) - .pipe(finalize(() => (this.loading = false))) - .subscribe(); + this.list.hookToQuery(query => this.store.dispatch(new GetUsers(query))).subscribe(); } openPermissionsModal(providerKey: string) { From 1fae3a9d58310d54a2e319256b4edf4bb74e265e Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Thu, 4 Jun 2020 15:38:36 +0300 Subject: [PATCH 11/81] feat(tenant-management): replace abp-table in tenants.component with ngx-datatable --- .../components/tenants/tenants.component.html | 153 ++++++++---------- .../components/tenants/tenants.component.ts | 41 ++--- 2 files changed, 84 insertions(+), 110 deletions(-) diff --git a/npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.html b/npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.html index 10761a3618..5508166f7a 100644 --- a/npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.html +++ b/npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.html @@ -18,99 +18,88 @@ +
- + [(ngModel)]="list.filter" + /> +
- - - - - - - - - {{ 'AbpTenantManagement::Actions' | abpLocalization }} - - {{ 'AbpTenantManagement::TenantName' | abpLocalization }} - + +
+ +
+ + + -
- - - - -
- - {{ data.name }} - - - +
+
+ + + diff --git a/npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.ts b/npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.ts index d04f384a79..7eb40e53e8 100644 --- a/npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.ts +++ b/npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.ts @@ -1,6 +1,7 @@ -import { ABP } from '@abp/ng.core'; -import { ConfirmationService, Confirmation, getPasswordValidators } from '@abp/ng.theme.shared'; -import { Component, OnInit, TemplateRef, ViewChild, ChangeDetectorRef } from '@angular/core'; +import { ABP, ListService } from '@abp/ng.core'; +import { eFeatureManagementComponents } from '@abp/ng.feature-management'; +import { Confirmation, ConfirmationService, getPasswordValidators } from '@abp/ng.theme.shared'; +import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { Select, Store } from '@ngxs/store'; import { Observable } from 'rxjs'; @@ -14,7 +15,6 @@ import { } from '../../actions/tenant-management.actions'; import { TenantManagementService } from '../../services/tenant-management.service'; import { TenantManagementState } from '../../states/tenant-management.state'; -import { eFeatureManagementComponents } from '@abp/ng.feature-management'; interface SelectedModalContent { type: 'saveConnStr' | 'saveTenant'; @@ -25,6 +25,7 @@ interface SelectedModalContent { @Component({ selector: 'abp-tenants', templateUrl: './tenants.component.html', + providers: [ListService], }) export class TenantsComponent implements OnInit { @Select(TenantManagementState.get) @@ -51,16 +52,8 @@ export class TenantsComponent implements OnInit { _useSharedDatabase: boolean; - pageQuery: ABP.PageQueryParams = { maxResultCount: 10 }; - - loading = false; - modalBusy = false; - sortOrder = ''; - - sortKey = ''; - featureManagementKey = eFeatureManagementComponents.FeatureManagement; get hasSelectedTenant(): boolean { @@ -106,6 +99,7 @@ export class TenantsComponent implements OnInit { }; constructor( + public readonly list: ListService, private confirmationService: ConfirmationService, private tenantService: TenantManagementService, private fb: FormBuilder, @@ -116,11 +110,6 @@ export class TenantsComponent implements OnInit { this.get(); } - onSearch(value: string) { - this.pageQuery.filter = value; - this.get(); - } - private createTenantForm() { const tenantForm = this.fb.group({ name: [this.selected.name || '', [Validators.required, Validators.maxLength(256)]], @@ -262,18 +251,8 @@ export class TenantsComponent implements OnInit { }); } - onPageChange(page: number) { - this.pageQuery.skipCount = (page - 1) * this.pageQuery.maxResultCount; - - this.get(); - } - get() { - this.loading = true; - this.store - .dispatch(new GetTenants(this.pageQuery)) - .pipe(finalize(() => (this.loading = false))) - .subscribe(); + this.list.hookToQuery(query => this.store.dispatch(new GetTenants(query))).subscribe(); } onSharedDatabaseChange(value: boolean) { @@ -295,4 +274,10 @@ export class TenantsComponent implements OnInit { this.visibleFeatures = true; }, 0); } + + sort(data) { + const { prop, dir } = data.sorts[0]; + this.list.sortKey = prop; + this.list.sortOrder = dir; + } } From f5dd09128ad56f8805b483a1292e86b049d27f35 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Thu, 4 Jun 2020 15:41:22 +0300 Subject: [PATCH 12/81] chore: add ngx-datatable styles to app template --- templates/app/angular/angular.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/templates/app/angular/angular.json b/templates/app/angular/angular.json index dfcaa5b9d3..9177a6d86c 100644 --- a/templates/app/angular/angular.json +++ b/templates/app/angular/angular.json @@ -46,6 +46,21 @@ "inject": true, "bundleName": "fontawesome-v4-shims.min" }, + { + "input": "node_modules/@swimlane/ngx-datatable/index.css", + "inject": true, + "bundleName": "ngx-datatable-index" + }, + { + "input": "node_modules/@swimlane/ngx-datatable/assets/icons.css", + "inject": true, + "bundleName": "ngx-datatable-icons" + }, + { + "input": "node_modules/@swimlane/ngx-datatable/themes/material.css", + "inject": true, + "bundleName": "ngx-datatable-material" + }, "src/styles.scss" ], "scripts": [] From b990b2babe25c93aaa598d8f9d359b3736eb3f9d Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Thu, 4 Jun 2020 15:43:05 +0300 Subject: [PATCH 13/81] chore: add ngx-datatable styles to module template --- templates/module/angular/angular.json | 60 ++++++++++--------- .../module/angular/src/app/app.component.ts | 19 +----- 2 files changed, 34 insertions(+), 45 deletions(-) diff --git a/templates/module/angular/angular.json b/templates/module/angular/angular.json index 7120592c4d..642e441e81 100644 --- a/templates/module/angular/angular.json +++ b/templates/module/angular/angular.json @@ -24,27 +24,44 @@ "tsConfig": "tsconfig.app.json", "aot": true, "extractCss": true, - "assets": [ - "src/favicon.ico", - "src/assets" - ], + "assets": ["src/favicon.ico", "src/assets"], "styles": [ + { + "input": "node_modules/@abp/ng.theme.shared/styles/bootstrap-rtl.min.css", + "inject": false, + "bundleName": "bootstrap-rtl.min" + }, { "input": "node_modules/bootstrap/dist/css/bootstrap.min.css", "inject": true, - "bundleName": "bootstrap.min" + "bundleName": "bootstrap-ltr.min" }, - "src/styles.scss", { "input": "node_modules/@fortawesome/fontawesome-free/css/all.min.css", - "inject": false, + "inject": true, "bundleName": "fontawesome-all.min" }, { "input": "node_modules/@fortawesome/fontawesome-free/css/v4-shims.min.css", - "inject": false, + "inject": true, "bundleName": "fontawesome-v4-shims.min" - } + }, + { + "input": "node_modules/@swimlane/ngx-datatable/index.css", + "inject": true, + "bundleName": "ngx-datatable-index" + }, + { + "input": "node_modules/@swimlane/ngx-datatable/assets/icons.css", + "inject": true, + "bundleName": "ngx-datatable-icons" + }, + { + "input": "node_modules/@swimlane/ngx-datatable/themes/material.css", + "inject": true, + "bundleName": "ngx-datatable-material" + }, + "src/styles.scss" ], "scripts": [] }, @@ -102,10 +119,7 @@ "polyfills": "src/polyfills.ts", "tsConfig": "tsconfig.spec.json", "karmaConfig": "karma.conf.js", - "assets": [ - "src/favicon.ico", - "src/assets" - ], + "assets": ["src/favicon.ico", "src/assets"], "styles": [ { "input": "node_modules/bootstrap/dist/css/bootstrap.min.css", @@ -130,14 +144,8 @@ "lint": { "builder": "@angular-devkit/build-angular:tslint", "options": { - "tsConfig": [ - "tsconfig.app.json", - "tsconfig.spec.json", - "e2e/tsconfig.json" - ], - "exclude": [ - "**/node_modules/**" - ] + "tsConfig": ["tsconfig.app.json", "tsconfig.spec.json", "e2e/tsconfig.json"], + "exclude": ["**/node_modules/**"] } }, "e2e": { @@ -187,9 +195,7 @@ "projects/my-project-name/tsconfig.lib.json", "projects/my-project-name/tsconfig.spec.json" ], - "exclude": [ - "**/node_modules/**" - ] + "exclude": ["**/node_modules/**"] } } } @@ -227,9 +233,7 @@ "projects/my-project-name-config/tsconfig.lib.json", "projects/my-project-name-config/tsconfig.spec.json" ], - "exclude": [ - "**/node_modules/**" - ] + "exclude": ["**/node_modules/**"] } } } @@ -239,4 +243,4 @@ "cli": { "analytics": false } -} \ No newline at end of file +} diff --git a/templates/module/angular/src/app/app.component.ts b/templates/module/angular/src/app/app.component.ts index 1cf17b8116..bf2a27962a 100644 --- a/templates/module/angular/src/app/app.component.ts +++ b/templates/module/angular/src/app/app.component.ts @@ -1,6 +1,4 @@ -import { LazyLoadService, LOADING_STRATEGY } from '@abp/ng.core'; -import { Component, OnInit } from '@angular/core'; -import { forkJoin } from 'rxjs'; +import { Component } from '@angular/core'; @Component({ selector: 'app-root', @@ -9,17 +7,4 @@ import { forkJoin } from 'rxjs'; `, }) -export class AppComponent implements OnInit { - constructor(private lazyLoadService: LazyLoadService) {} - - ngOnInit() { - forkJoin([ - this.lazyLoadService.load( - LOADING_STRATEGY.PrependAnonymousStyleToHead('fontawesome-v4-shims.min.css'), - ), - this.lazyLoadService.load( - LOADING_STRATEGY.PrependAnonymousStyleToHead('fontawesome-all.min.css'), - ), - ]).subscribe(); - } -} +export class AppComponent {} From bd155182346b0698299de99e96b122e4ea3d8f54 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Thu, 4 Jun 2020 16:09:28 +0300 Subject: [PATCH 14/81] fix: lint errors --- npm/ng-packs/tslint.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/npm/ng-packs/tslint.json b/npm/ng-packs/tslint.json index d75b6a274b..5a5d15bc35 100644 --- a/npm/ng-packs/tslint.json +++ b/npm/ng-packs/tslint.json @@ -37,7 +37,7 @@ "import-blacklist": [true, "rxjs/Rx"], "interface-over-type-literal": true, "interface-name": [true, "never-prefix"], - "member-access": [true, "no-public"], + "member-access": [false], "member-ordering": [ true, { From f3fa7be78140a362d497be1c34b40e912a0f5489 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Thu, 4 Jun 2020 16:31:33 +0300 Subject: [PATCH 15/81] fix(ci): fix prod build error --- npm/ng-packs/scripts/prod-build.ts | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/npm/ng-packs/scripts/prod-build.ts b/npm/ng-packs/scripts/prod-build.ts index 03a1432b99..0923601529 100644 --- a/npm/ng-packs/scripts/prod-build.ts +++ b/npm/ng-packs/scripts/prod-build.ts @@ -2,10 +2,10 @@ import execa from 'execa'; import fse from 'fs-extra'; (async () => { - await execa('yarn', ['ng', 'build', '--prod'], { - stdout: 'inherit', - cwd: '..', - }); + // await execa('yarn', ['ng', 'build', '--prod'], { + // stdout: 'inherit', + // cwd: '..', + // }); await execa('yarn', ['install', '--ignore-scripts'], { stdout: 'inherit', @@ -13,11 +13,19 @@ import fse from 'fs-extra'; }); await fse.remove('../../../templates/app/angular/node_modules/@abp'); - await fse.copy('../node_modules/@abp', '../../../templates/app/angular/node_modules/@abp', { overwrite: true, }); + // TODO: Will be removed in v3.1, it is added to fix the prod build error + await fse.copy( + '../node_modules/@swimlane', + '../../../templates/app/angular/node_modules/@swimlane', + { + overwrite: true, + }, + ); + await execa('yarn', ['ng', 'build', '--prod'], { stdout: 'inherit', cwd: '../../../templates/app/angular', From d7b5ca5bbf8fb987bb8f993483b90f227c6c0d9f Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Thu, 4 Jun 2020 16:31:59 +0300 Subject: [PATCH 16/81] chore: uncomment --- npm/ng-packs/scripts/prod-build.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/npm/ng-packs/scripts/prod-build.ts b/npm/ng-packs/scripts/prod-build.ts index 0923601529..33f2aa2c44 100644 --- a/npm/ng-packs/scripts/prod-build.ts +++ b/npm/ng-packs/scripts/prod-build.ts @@ -2,10 +2,10 @@ import execa from 'execa'; import fse from 'fs-extra'; (async () => { - // await execa('yarn', ['ng', 'build', '--prod'], { - // stdout: 'inherit', - // cwd: '..', - // }); + await execa('yarn', ['ng', 'build', '--prod'], { + stdout: 'inherit', + cwd: '..', + }); await execa('yarn', ['install', '--ignore-scripts'], { stdout: 'inherit', From 5990965b383d08432c5c5f25a7627e560d7765a8 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Thu, 4 Jun 2020 17:25:22 +0300 Subject: [PATCH 17/81] chore: change localization sources --- .../src/lib/components/tenants/tenants.component.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.html b/npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.html index 5508166f7a..3a391133b2 100644 --- a/npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.html +++ b/npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.html @@ -48,7 +48,7 @@ class="material" > @@ -117,7 +117,7 @@ {{ 'AbpTenantManagement::Cancel' | abpLocalization }} {{ - 'AbpIdentity::Save' | abpLocalization + 'AbpTenantManagement::Save' | abpLocalization }}
From 832cfc64bfd8a5829d874fdec0e2d5a8c6b3a7a8 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Fri, 5 Jun 2020 01:16:50 +0300 Subject: [PATCH 18/81] refactor(core): set _page variable initial value to 0 resolves #4224 --- npm/ng-packs/packages/core/src/lib/services/list.service.ts | 4 ++-- .../identity/src/lib/components/roles/roles.component.html | 4 ++-- .../identity/src/lib/components/users/users.component.html | 4 ++-- .../src/lib/components/tenants/tenants.component.html | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/npm/ng-packs/packages/core/src/lib/services/list.service.ts b/npm/ng-packs/packages/core/src/lib/services/list.service.ts index 944368ad88..ae166a5243 100644 --- a/npm/ng-packs/packages/core/src/lib/services/list.service.ts +++ b/npm/ng-packs/packages/core/src/lib/services/list.service.ts @@ -26,7 +26,7 @@ export class ListService implements OnDestroy { return this._maxResultCount; } - private _page = 1; + private _page = 0; set page(value: number) { this._page = value; this.get(); @@ -71,7 +71,7 @@ export class ListService implements OnDestroy { this._query$.next({ filter: this._filter || undefined, maxResultCount: this._maxResultCount, - skipCount: (this._page - 1) * this._maxResultCount, + skipCount: this._page * this._maxResultCount, sorting: this._sortOrder ? `${this._sortKey} ${this._sortOrder}` : undefined, }); }; diff --git a/npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.html b/npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.html index eb45a485a8..3ecc6413ea 100644 --- a/npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.html +++ b/npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.html @@ -27,9 +27,9 @@ (sort)="sort($event)" [externalPaging]="true" [count]="totalCount$ | async" - [offset]="list.page - 1" + [offset]="list.page" [limit]="list.maxResultCount" - (page)="list.page = $event.offset + 1" + (page)="list.page = $event.offset" [headerHeight]="50" [footerHeight]="50" columnMode="force" diff --git a/npm/ng-packs/packages/identity/src/lib/components/users/users.component.html b/npm/ng-packs/packages/identity/src/lib/components/users/users.component.html index 68012b3d90..e87a1e2634 100644 --- a/npm/ng-packs/packages/identity/src/lib/components/users/users.component.html +++ b/npm/ng-packs/packages/identity/src/lib/components/users/users.component.html @@ -37,9 +37,9 @@ (sort)="sort($event)" [externalPaging]="true" [count]="totalCount$ | async" - [offset]="list.page - 1" + [offset]="list.page" [limit]="list.maxResultCount" - (page)="list.page = $event.offset + 1" + (page)="list.page = $event.offset" [headerHeight]="50" [footerHeight]="50" columnMode="force" diff --git a/npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.html b/npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.html index 3a391133b2..a73ccef949 100644 --- a/npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.html +++ b/npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.html @@ -38,9 +38,9 @@ (sort)="sort($event)" [externalPaging]="true" [count]="totalCount$ | async" - [offset]="list.page - 1" + [offset]="list.page" [limit]="list.maxResultCount" - (page)="list.page = $event.offset + 1" + (page)="list.page = $event.offset" [headerHeight]="50" [footerHeight]="50" columnMode="force" From 934077586c80e7a27550ce2f991b0baa8ad71e38 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Fri, 5 Jun 2020 01:31:30 +0300 Subject: [PATCH 19/81] refactor: make users table responsive --- .../identity/src/lib/components/users/users.component.html | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/npm/ng-packs/packages/identity/src/lib/components/users/users.component.html b/npm/ng-packs/packages/identity/src/lib/components/users/users.component.html index e87a1e2634..e17ad21ce0 100644 --- a/npm/ng-packs/packages/identity/src/lib/components/users/users.component.html +++ b/npm/ng-packs/packages/identity/src/lib/components/users/users.component.html @@ -42,6 +42,7 @@ (page)="list.page = $event.offset" [headerHeight]="50" [footerHeight]="50" + [scrollbarH]="true" columnMode="force" rowHeight="auto" class="material" @@ -88,14 +89,17 @@ From 6247f4d098be051848cfc45636969e110a90c9a6 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Fri, 5 Jun 2020 01:41:54 +0300 Subject: [PATCH 20/81] refactor(core): add a generic type to list service --- .../core/src/lib/services/list.service.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/npm/ng-packs/packages/core/src/lib/services/list.service.ts b/npm/ng-packs/packages/core/src/lib/services/list.service.ts index ae166a5243..fec8c44ab1 100644 --- a/npm/ng-packs/packages/core/src/lib/services/list.service.ts +++ b/npm/ng-packs/packages/core/src/lib/services/list.service.ts @@ -7,7 +7,7 @@ import { LIST_QUERY_DEBOUNCE_TIME } from '../tokens/list.token'; import { takeUntilDestroy } from '../utils/rxjs-utils'; @Injectable() -export class ListService implements OnDestroy { +export class ListService implements OnDestroy { private _filter = ''; set filter(value: string) { this._filter = value; @@ -53,9 +53,9 @@ export class ListService implements OnDestroy { return this._sortOrder; } - private _query$ = new ReplaySubject(1); + private _query$ = new ReplaySubject(1); - get query$(): Observable { + get query$(): Observable { return this._query$ .asObservable() .pipe(debounceTime(this.delay || 300), shareReplay({ bufferSize: 1, refCount: true })); @@ -68,12 +68,12 @@ export class ListService implements OnDestroy { } get = () => { - this._query$.next({ + this._query$.next(({ filter: this._filter || undefined, maxResultCount: this._maxResultCount, skipCount: this._page * this._maxResultCount, sorting: this._sortOrder ? `${this._sortKey} ${this._sortOrder}` : undefined, - }); + } as any) as QueryParamsType); }; constructor(@Optional() @Inject(LIST_QUERY_DEBOUNCE_TIME) private delay: number) { @@ -81,7 +81,7 @@ export class ListService implements OnDestroy { } hookToQuery( - streamCreatorCallback: QueryStreamCreatorCallback, + streamCreatorCallback: QueryStreamCreatorCallback, ): Observable> { this._isLoading$.next(true); @@ -96,6 +96,6 @@ export class ListService implements OnDestroy { ngOnDestroy() {} } -export type QueryStreamCreatorCallback = ( - query: ABP.PageQueryParams, +export type QueryStreamCreatorCallback = ( + query: QueryParamsType, ) => Observable>; From a64fbde7997d433707befa10027b9c85e54fcd1c Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Fri, 5 Jun 2020 02:53:58 +0300 Subject: [PATCH 21/81] fix: memory leak problem --- .../identity/src/lib/components/roles/roles.component.ts | 8 ++++---- .../identity/src/lib/components/users/users.component.ts | 8 ++++---- .../src/lib/components/tenants/tenants.component.ts | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.ts b/npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.ts index 09582f4e9f..73a9a64dfb 100644 --- a/npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.ts +++ b/npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.ts @@ -57,7 +57,7 @@ export class RolesComponent implements OnInit { ) {} ngOnInit() { - this.get(); + this.hookToQuery(); } buildForm() { @@ -104,7 +104,7 @@ export class RolesComponent implements OnInit { .pipe(finalize(() => (this.modalBusy = false))) .subscribe(() => { this.isModalVisible = false; - this.get(); + this.list.get(); }); } @@ -115,12 +115,12 @@ export class RolesComponent implements OnInit { }) .subscribe((status: Confirmation.Status) => { if (status === Confirmation.Status.confirm) { - this.store.dispatch(new DeleteRole(id)).subscribe(() => this.get()); + this.store.dispatch(new DeleteRole(id)).subscribe(() => this.list.get()); } }); } - get() { + private hookToQuery() { this.list.hookToQuery(query => this.store.dispatch(new GetRoles(query))).subscribe(); } diff --git a/npm/ng-packs/packages/identity/src/lib/components/users/users.component.ts b/npm/ng-packs/packages/identity/src/lib/components/users/users.component.ts index 33aa8ee40d..5a55c8f51f 100644 --- a/npm/ng-packs/packages/identity/src/lib/components/users/users.component.ts +++ b/npm/ng-packs/packages/identity/src/lib/components/users/users.component.ts @@ -77,7 +77,7 @@ export class UsersComponent implements OnInit { ) {} ngOnInit() { - this.get(); + this.hookToQuery(); } buildForm() { @@ -172,7 +172,7 @@ export class UsersComponent implements OnInit { .pipe(finalize(() => (this.modalBusy = false))) .subscribe(() => { this.isModalVisible = false; - this.get(); + this.list.get(); }); } @@ -183,7 +183,7 @@ export class UsersComponent implements OnInit { }) .subscribe((status: Confirmation.Status) => { if (status === Confirmation.Status.confirm) { - this.store.dispatch(new DeleteUser(id)).subscribe(() => this.get()); + this.store.dispatch(new DeleteUser(id)).subscribe(() => this.list.get()); } }); } @@ -194,7 +194,7 @@ export class UsersComponent implements OnInit { this.list.sortOrder = dir; } - get() { + private hookToQuery() { this.list.hookToQuery(query => this.store.dispatch(new GetUsers(query))).subscribe(); } diff --git a/npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.ts b/npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.ts index 7eb40e53e8..c0a431bbb5 100644 --- a/npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.ts +++ b/npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.ts @@ -107,7 +107,7 @@ export class TenantsComponent implements OnInit { ) {} ngOnInit() { - this.get(); + this.hookToQuery(); } private createTenantForm() { @@ -231,7 +231,7 @@ export class TenantsComponent implements OnInit { .pipe(finalize(() => (this.modalBusy = false))) .subscribe(() => { this.isModalVisible = false; - this.get(); + this.list.get(); }); } @@ -246,12 +246,12 @@ export class TenantsComponent implements OnInit { ) .subscribe((status: Confirmation.Status) => { if (status === Confirmation.Status.confirm) { - this.store.dispatch(new DeleteTenant(id)).subscribe(() => this.get()); + this.store.dispatch(new DeleteTenant(id)).subscribe(() => this.list.get()); } }); } - get() { + hookToQuery() { this.list.hookToQuery(query => this.store.dispatch(new GetTenants(query))).subscribe(); } From b6b47703b22cad9b982ce3ffc8d6c087b0d30ab2 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Fri, 5 Jun 2020 10:16:44 +0300 Subject: [PATCH 22/81] refactor(core): add same value control to list.service --- npm/ng-packs/packages/core/src/lib/services/list.service.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/npm/ng-packs/packages/core/src/lib/services/list.service.ts b/npm/ng-packs/packages/core/src/lib/services/list.service.ts index fec8c44ab1..3aff601f7a 100644 --- a/npm/ng-packs/packages/core/src/lib/services/list.service.ts +++ b/npm/ng-packs/packages/core/src/lib/services/list.service.ts @@ -28,6 +28,8 @@ export class ListService implements OnDes private _page = 0; set page(value: number) { + if (value === this._page) return; + this._page = value; this.get(); } From 3932ea3709a8a404ba365fe617492da39b9c2a08 Mon Sep 17 00:00:00 2001 From: maliming <6908465+maliming@users.noreply.github.com> Date: Fri, 5 Jun 2020 18:37:56 +0800 Subject: [PATCH 23/81] Support CreateContainerIfNotExists. --- .../BlobStoring/Azure/AzureBlobProvider.cs | 45 ++++++++++++++----- .../Azure/AzureBlobProviderConfiguration.cs | 9 ++++ .../AzureBlobProviderConfigurationNames.cs | 1 + .../Azure/AbpBlobStoringAzureTestModule.cs | 7 +-- 4 files changed, 46 insertions(+), 16 deletions(-) diff --git a/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProvider.cs b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProvider.cs index e0b70dc66c..ec854b7be3 100644 --- a/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProvider.cs +++ b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProvider.cs @@ -18,39 +18,49 @@ namespace Volo.Abp.BlobStoring.Azure public override async Task SaveAsync(BlobProviderSaveArgs args) { var blobName = AzureBlobNameCalculator.Calculate(args); - var blobClient = GetBlobClient(args.Configuration.GetAzureConfiguration(), blobName); + var configuration = args.Configuration.GetAzureConfiguration(); - if (!args.OverrideExisting && await BlobExistsAsync(blobClient)) + if (!args.OverrideExisting && await BlobExistsAsync(configuration, blobName)) { throw new BlobAlreadyExistsException($"Saving BLOB '{args.BlobName}' does already exists in the container '{args.ContainerName}'! Set {nameof(args.OverrideExisting)} if it should be overwritten."); } - await blobClient.UploadAsync(args.BlobStream, true); + if (configuration.CreateContainerIfNotExists) + { + await CreateContainerIfNotExists(args.Configuration.GetAzureConfiguration()); + } + + await GetBlobClient(configuration, blobName).UploadAsync(args.BlobStream, true); } public override async Task DeleteAsync(BlobProviderDeleteArgs args) { var blobName = AzureBlobNameCalculator.Calculate(args); - var blobClient = GetBlobClient(args.Configuration.GetAzureConfiguration(), blobName); - return await blobClient.DeleteIfExistsAsync(); + + if (await BlobExistsAsync(args.Configuration.GetAzureConfiguration(), blobName)) + { + return await GetBlobClient(args.Configuration.GetAzureConfiguration(), blobName).DeleteIfExistsAsync(); + } + + return false; } public override async Task ExistsAsync(BlobProviderExistsArgs args) { var blobName = AzureBlobNameCalculator.Calculate(args); - var blobClient = GetBlobClient(args.Configuration.GetAzureConfiguration(), blobName); - return await BlobExistsAsync(blobClient); + return await BlobExistsAsync(args.Configuration.GetAzureConfiguration(), blobName); } public override async Task GetOrNullAsync(BlobProviderGetArgs args) { var blobName = AzureBlobNameCalculator.Calculate(args); - var blobClient = GetBlobClient(args.Configuration.GetAzureConfiguration(), blobName); - if (!await BlobExistsAsync(blobClient)) + + if (!await BlobExistsAsync(args.Configuration.GetAzureConfiguration(), blobName)) { return null; } + var blobClient = GetBlobClient(args.Configuration.GetAzureConfiguration(), blobName); var download = await blobClient.DownloadAsync(); var memoryStream = new MemoryStream(); await download.Value.Content.CopyToAsync(memoryStream); @@ -69,9 +79,22 @@ namespace Volo.Abp.BlobStoring.Azure return blobServiceClient.GetBlobContainerClient(configuration.ContainerName); } - private static async Task BlobExistsAsync(BlobBaseClient blobClient) + protected virtual async Task CreateContainerIfNotExists(AzureBlobProviderConfiguration configuration) + { + var blobContainerClient = GetBlobContainerClient(configuration); + await blobContainerClient.CreateIfNotExistsAsync(); + } + + private async Task BlobExistsAsync(AzureBlobProviderConfiguration configuration, string blobName) + { + // Make sure Blob Container exists. + return await ContainerExistsAsync(GetBlobContainerClient(configuration)) && + (await GetBlobClient(configuration, blobName).ExistsAsync()).Value; + } + + private static async Task ContainerExistsAsync(BlobContainerClient blobContainerClient) { - return (await blobClient.ExistsAsync()).Value; + return (await blobContainerClient.ExistsAsync()).Value; } } } diff --git a/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProviderConfiguration.cs b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProviderConfiguration.cs index 67f6eca307..a0906ed31f 100644 --- a/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProviderConfiguration.cs +++ b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProviderConfiguration.cs @@ -14,6 +14,15 @@ set => _containerConfiguration.SetConfiguration(AzureBlobProviderConfigurationNames.ContainerName, Check.NotNullOrWhiteSpace(value, nameof(value))); } + /// + /// Default value: false. + /// + public bool CreateContainerIfNotExists + { + get => _containerConfiguration.GetConfigurationOrDefault(AzureBlobProviderConfigurationNames.CreateContainerIfNotExists, false); + set => _containerConfiguration.SetConfiguration(AzureBlobProviderConfigurationNames.CreateContainerIfNotExists, value); + } + private readonly BlobContainerConfiguration _containerConfiguration; public AzureBlobProviderConfiguration(BlobContainerConfiguration containerConfiguration) diff --git a/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProviderConfigurationNames.cs b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProviderConfigurationNames.cs index f90f037046..b8fbff19d2 100644 --- a/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProviderConfigurationNames.cs +++ b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProviderConfigurationNames.cs @@ -4,5 +4,6 @@ { public const string ConnectionString = "Azure.ConnectionString"; public const string ContainerName = "Azure.ContainerName"; + public const string CreateContainerIfNotExists = "Azure.CreateContainerIfNotExists"; } } diff --git a/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureTestModule.cs b/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureTestModule.cs index a45d209b32..5e66be4e19 100644 --- a/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureTestModule.cs +++ b/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureTestModule.cs @@ -38,12 +38,8 @@ namespace Volo.Abp.BlobStoring.Azure })); var configuration = context.Services.GetConfiguration(); - _connectionString = configuration["Azure:ConnectionString"]; - var blobServiceClient = new BlobServiceClient(_connectionString); - blobServiceClient.CreateBlobContainer(_randomContainerName); - Configure(options => { options.Containers.ConfigureAll((containerName, containerConfiguration) => @@ -52,6 +48,7 @@ namespace Volo.Abp.BlobStoring.Azure { azure.ConnectionString = _connectionString; azure.ContainerName = _randomContainerName; + azure.CreateContainerIfNotExists = true; }); }); }); @@ -60,7 +57,7 @@ namespace Volo.Abp.BlobStoring.Azure public override void OnApplicationShutdown(ApplicationShutdownContext context) { var blobServiceClient = new BlobServiceClient(_connectionString); - blobServiceClient.DeleteBlobContainer(_randomContainerName); + blobServiceClient.GetBlobContainerClient(_randomContainerName).DeleteIfExists(); } } From 8b44b99b73ce25ba563ccfb98b6205795c35c4c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Levent=20Arman=20=C3=96zak?= Date: Fri, 5 Jun 2020 17:11:57 +0300 Subject: [PATCH 24/81] style: add spaces before box-shadow property --- npm/ng-packs/packages/theme-shared/src/lib/constants/styles.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/npm/ng-packs/packages/theme-shared/src/lib/constants/styles.ts b/npm/ng-packs/packages/theme-shared/src/lib/constants/styles.ts index a1a3b7afe5..a3698f2164 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/constants/styles.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/constants/styles.ts @@ -137,7 +137,7 @@ export default ` opacity: .3; } .ngx-datatable.material { -box-shadow: none; + box-shadow: none; } @keyframes fadeInTop { From 51116d56e1ed0b6e43f32a7990f2fb73c80cfd21 Mon Sep 17 00:00:00 2001 From: Arman Ozak Date: Mon, 8 Jun 2020 17:40:49 +0300 Subject: [PATCH 25/81] build: update abp packages --- npm/ng-packs/package.json | 26 +++---- npm/ng-packs/yarn.lock | 141 ++++++++++++++++++-------------------- 2 files changed, 80 insertions(+), 87 deletions(-) diff --git a/npm/ng-packs/package.json b/npm/ng-packs/package.json index f6ae01cf5b..1961458c97 100644 --- a/npm/ng-packs/package.json +++ b/npm/ng-packs/package.json @@ -22,19 +22,19 @@ "generate:changelog": "conventional-changelog -p angular -i CHANGELOG.md -s" }, "devDependencies": { - "@abp/ng.account": "~2.8.0", - "@abp/ng.account.config": "~2.8.0", - "@abp/ng.core": "~2.8.0", - "@abp/ng.feature-management": "~2.8.0", - "@abp/ng.identity": "~2.8.0", - "@abp/ng.identity.config": "~2.8.0", - "@abp/ng.permission-management": "~2.8.0", - "@abp/ng.setting-management": "~2.8.0", - "@abp/ng.setting-management.config": "~2.8.0", - "@abp/ng.tenant-management": "~2.8.0", - "@abp/ng.tenant-management.config": "~2.8.0", - "@abp/ng.theme.basic": "~2.8.0", - "@abp/ng.theme.shared": "~2.8.0", + "@abp/ng.account": "~2.9.0", + "@abp/ng.account.config": "~2.9.0", + "@abp/ng.core": "~2.9.0", + "@abp/ng.feature-management": "~2.9.0", + "@abp/ng.identity": "~2.9.0", + "@abp/ng.identity.config": "~2.9.0", + "@abp/ng.permission-management": "~2.9.0", + "@abp/ng.setting-management": "~2.9.0", + "@abp/ng.setting-management.config": "~2.9.0", + "@abp/ng.tenant-management": "~2.9.0", + "@abp/ng.tenant-management.config": "~2.9.0", + "@abp/ng.theme.basic": "~2.9.0", + "@abp/ng.theme.shared": "~2.9.0", "@abp/utils": "^2.7.0", "@angular-builders/jest": "^8.2.0", "@angular-devkit/build-angular": "~0.803.21", diff --git a/npm/ng-packs/yarn.lock b/npm/ng-packs/yarn.lock index 99d06d1e20..073f1b1b34 100644 --- a/npm/ng-packs/yarn.lock +++ b/npm/ng-packs/yarn.lock @@ -2,26 +2,26 @@ # yarn lockfile v1 -"@abp/ng.account.config@~2.8.0": - version "2.8.0" - resolved "https://registry.yarnpkg.com/@abp/ng.account.config/-/ng.account.config-2.8.0.tgz#c641a2d07c3a4ffc9fd4638b7000918791fe01d1" - integrity sha512-1MDOdrvaFuv5jW95bOcstfV2buN5PFwYfW6PSxP6DIqrpVLvDvyvtkX+VptVL3q/grufiI8g1Yed02hERAzo6g== +"@abp/ng.account.config@~2.9.0": + version "2.9.0" + resolved "https://registry.yarnpkg.com/@abp/ng.account.config/-/ng.account.config-2.9.0.tgz#fdb930db942def047823a6e891ebeeae7f8a19a4" + integrity sha512-lC/wpb4HeVf6eJiZjKJKtLEBQhR2x364Cs51cIHA8vEs8bJjZX/oodLYeItT3SuDii7MkREiv9uc12pMLK96IA== dependencies: tslib "^1.9.0" -"@abp/ng.account@~2.8.0": - version "2.8.0" - resolved "https://registry.yarnpkg.com/@abp/ng.account/-/ng.account-2.8.0.tgz#ee9cf3570d4f69264756e472043d217a5f8fa46f" - integrity sha512-E4BMEwSWnvYm5A82+U+slVR4ecccq1Z3wJb5rmm1+ExQBbaadM2qrn8rrak0n+rSI0qcQkDncDIsbp7fb7AYJA== +"@abp/ng.account@~2.9.0": + version "2.9.0" + resolved "https://registry.yarnpkg.com/@abp/ng.account/-/ng.account-2.9.0.tgz#a863b0bdf9f7027738e4da40a8bcce867fef52bc" + integrity sha512-NnSKdCMbx87lIxyB8oYGYAAk4jYmmqIUElfNIC5D5pI76ekQrBVFD2ebimDgOyHl7oMS/k6byHNG3RhXln6pXg== dependencies: - "@abp/ng.account.config" "~2.8.0" - "@abp/ng.theme.shared" "~2.8.0" + "@abp/ng.account.config" "~2.9.0" + "@abp/ng.theme.shared" "~2.9.0" tslib "^1.9.0" -"@abp/ng.core@~2.8.0": - version "2.8.0" - resolved "https://registry.yarnpkg.com/@abp/ng.core/-/ng.core-2.8.0.tgz#1b4940a7d37f56eb7ec3f99275d32d43f68b600d" - integrity sha512-LxUPm+gQGake9/CMvx2ZukcAsDExziTNqTf5vQLWN2Ggx85wPbajqJc0zP08i8ST2LRP/3DCjRS/Cg6QVp+I2A== +"@abp/ng.core@~2.9.0": + version "2.9.0" + resolved "https://registry.yarnpkg.com/@abp/ng.core/-/ng.core-2.9.0.tgz#7fd64163355ebb9e43b63ff3fbbc7f4d4470033f" + integrity sha512-hZ7u5imE7PCzinvdeFQA4kaNAiUaY+CpuiFTAHmxVNzNtv7SNqLXw1VmltklFJTj98ZXQOWCSiliBWZSYwKGPA== dependencies: "@abp/utils" "^2.7.0" "@angular/localize" "~9.1.0" @@ -35,86 +35,86 @@ ts-toolbelt "^6.3.6" tslib "^1.9.0" -"@abp/ng.feature-management@~2.8.0": - version "2.8.0" - resolved "https://registry.yarnpkg.com/@abp/ng.feature-management/-/ng.feature-management-2.8.0.tgz#8fed791071142f2980ccbb60b362c042c6fcdbea" - integrity sha512-4FHR43vf0AlQqbIZjRVBYZPORPe8sW0DXraChuuhskMOliDqqXVSk5rx+72qnxvUZhS0eo40nd5Ns/rA34RMNw== +"@abp/ng.feature-management@~2.9.0": + version "2.9.0" + resolved "https://registry.yarnpkg.com/@abp/ng.feature-management/-/ng.feature-management-2.9.0.tgz#a3d1fdb7df081cb7d56819107c3d4db5628a6191" + integrity sha512-tQDq3I1IvrJA4VarY3nqdR0n9/s7bcZidAFPb2VdnqVb2Ri/iNThu8oYQ7zx9lhT+UarCvJYmGwAkNAzd+9NQQ== dependencies: - "@abp/ng.theme.shared" "~2.8.0" + "@abp/ng.theme.shared" "~2.9.0" tslib "^1.9.0" -"@abp/ng.identity.config@~2.8.0": - version "2.8.0" - resolved "https://registry.yarnpkg.com/@abp/ng.identity.config/-/ng.identity.config-2.8.0.tgz#32372ddf784c2a92ff979435faa255b6c277db0a" - integrity sha512-8SGXu435KdY0TsFCupEKmlI37aPgGGANglv16j90013BTDQVGSPpdTGawN1I0En3r6ODZKHP3rNble+fFiCJ+A== +"@abp/ng.identity.config@~2.9.0": + version "2.9.0" + resolved "https://registry.yarnpkg.com/@abp/ng.identity.config/-/ng.identity.config-2.9.0.tgz#c8c5a30817b8d953d91288f67325e2ddb3edb922" + integrity sha512-aHi/7PvSomHUNWOk2sWw/W/IqJK2icFHsqtrsS0Op9HtVK6ORW5DSroWTU7CrY39Tnv93sRPBW+hTq0pA92yVw== dependencies: tslib "^1.9.0" -"@abp/ng.identity@~2.8.0": - version "2.8.0" - resolved "https://registry.yarnpkg.com/@abp/ng.identity/-/ng.identity-2.8.0.tgz#b77cfe08b72f69fc9f8c2d74dd8cf1f85358c4c9" - integrity sha512-LvzTfyrzLAcHeYivDHZJkSLYk7ZtTKp218eBjKuav2HSrvKUlBHKL50croldDguFNnq1uVRCYIBS7Vpj8lH1Fg== +"@abp/ng.identity@~2.9.0": + version "2.9.0" + resolved "https://registry.yarnpkg.com/@abp/ng.identity/-/ng.identity-2.9.0.tgz#d0343122cf47191f49d35b291ad548f07a47630e" + integrity sha512-o/BMi3MfF+h7bFS12tfaqldFGS/dDUKSGU89ufygUKEyAFFpTZTVOc5aI+8/FxVEx5ag5ibSeS943BHhCp0WEg== dependencies: - "@abp/ng.identity.config" "~2.8.0" - "@abp/ng.permission-management" "~2.8.0" - "@abp/ng.theme.shared" "~2.8.0" + "@abp/ng.identity.config" "~2.9.0" + "@abp/ng.permission-management" "~2.9.0" + "@abp/ng.theme.shared" "~2.9.0" tslib "^1.9.0" -"@abp/ng.permission-management@~2.8.0": - version "2.8.0" - resolved "https://registry.yarnpkg.com/@abp/ng.permission-management/-/ng.permission-management-2.8.0.tgz#832c71b2f91392493d9390751227dcede5406612" - integrity sha512-T4DMTQe0YA2JtKA5Avb41vBVB1rjjIDZO2ykCq1FqSIbXKHLUliZ1CSnOWMWqOzc7LfsdT0qyReQtoRGGiTFGg== +"@abp/ng.permission-management@~2.9.0": + version "2.9.0" + resolved "https://registry.yarnpkg.com/@abp/ng.permission-management/-/ng.permission-management-2.9.0.tgz#9ddbc23ea4948c57ff30286d32b7216fbfeb059c" + integrity sha512-fRENj1l0ZsUK/pEutY+i0G+Hwuel5K6PKVpBxUYmZIO1KQ2KvMA9Hj/sDsxI/zpM0GUIha7TksMFr5NCwKcLjg== dependencies: - "@abp/ng.theme.shared" "~2.8.0" + "@abp/ng.theme.shared" "~2.9.0" tslib "^1.9.0" -"@abp/ng.setting-management.config@~2.8.0": - version "2.8.0" - resolved "https://registry.yarnpkg.com/@abp/ng.setting-management.config/-/ng.setting-management.config-2.8.0.tgz#7ce2ad4f428bd3d66810c3c868702b72001b79e5" - integrity sha512-EVtgpCa3ApYZhPpctex3KwLBuJ14jxVMie4xUEg+txxKIhcV2aTAS8pFT4D9erJvW5wAXMNY/h34eZo0eFhS/g== +"@abp/ng.setting-management.config@~2.9.0": + version "2.9.0" + resolved "https://registry.yarnpkg.com/@abp/ng.setting-management.config/-/ng.setting-management.config-2.9.0.tgz#fce1a8a264f201961ba8a1daf92a4ca74cf24c4a" + integrity sha512-9BUGmCQFYZ8TZhN6enenHgu/Cenpey95pEHsXXqdBdNy2vKQmcOuOMMRZtB3H5OxqqXMAzVCxbGQP3loihgx8g== dependencies: tslib "^1.9.0" -"@abp/ng.setting-management@~2.8.0": - version "2.8.0" - resolved "https://registry.yarnpkg.com/@abp/ng.setting-management/-/ng.setting-management-2.8.0.tgz#6676e5b0aaf9c5c80bc2d630611dd1b635948637" - integrity sha512-CBlP4h/1/zgS7r2iKQlV8aDvnlmGH+4uGlNM8c1Usprisap8A9yfLc56UOkeU26os/dwitxwDFV6yJDPKiPa0g== +"@abp/ng.setting-management@~2.9.0": + version "2.9.0" + resolved "https://registry.yarnpkg.com/@abp/ng.setting-management/-/ng.setting-management-2.9.0.tgz#43fad32df23c4c31e49cbc86b45bdb071720392b" + integrity sha512-4vZVMPMxFbM5h2IKSQE23VWQledKI0EDIpkzNDw/zlhOadWOJ9z5jmHT7DOf1qSETJ5cNJsHhZgDwMyzsOzjeA== dependencies: - "@abp/ng.setting-management.config" "~2.8.0" - "@abp/ng.theme.shared" "~2.8.0" + "@abp/ng.setting-management.config" "~2.9.0" + "@abp/ng.theme.shared" "~2.9.0" tslib "^1.9.0" -"@abp/ng.tenant-management.config@~2.8.0": - version "2.8.0" - resolved "https://registry.yarnpkg.com/@abp/ng.tenant-management.config/-/ng.tenant-management.config-2.8.0.tgz#9e09101f07ee91005f41a79d87028c091855b48c" - integrity sha512-Z/9kzlHqt6bsmLqoSTPt3MDl11wlxQfWcDty7/zI4alx27omCiXUp+pEvw3TYTg9yhyIf6mehfQkknwzrxvYew== +"@abp/ng.tenant-management.config@~2.9.0": + version "2.9.0" + resolved "https://registry.yarnpkg.com/@abp/ng.tenant-management.config/-/ng.tenant-management.config-2.9.0.tgz#79e0ee917e5006f893a83b27d2af2c8e1fdeaf41" + integrity sha512-yVF+8NEE+6EzSedhxt6Zf89NhOHVysSyu62sLNOzgmqngKQ/oxs08tAEb7vcCkHNYnBisOhQvTg0aqdP7Ax2Jw== dependencies: tslib "^1.9.0" -"@abp/ng.tenant-management@~2.8.0": - version "2.8.0" - resolved "https://registry.yarnpkg.com/@abp/ng.tenant-management/-/ng.tenant-management-2.8.0.tgz#44b51b2d76d7c2a118a3e2ff2c871751bb05a75d" - integrity sha512-pm8uhmalEhLMHx1mdj+Fua8wt+V7brw6s4mi7wnISuqKcfIB77hUI4MvTTZhS0GfS4T+EL81V2Yt0Y/DRTX8xQ== +"@abp/ng.tenant-management@~2.9.0": + version "2.9.0" + resolved "https://registry.yarnpkg.com/@abp/ng.tenant-management/-/ng.tenant-management-2.9.0.tgz#5ec9c092d95051e6c5077ed55999e0f3cf254765" + integrity sha512-Y7hP1akqo0IqcaTiZKXjUtUZtCnsROZ/pps/BzisBukIgtYvdRsqc/UeQ9YC32lL+O0xwQPyjcJ4/mir0KPS4Q== dependencies: - "@abp/ng.feature-management" "~2.8.0" - "@abp/ng.tenant-management.config" "~2.8.0" - "@abp/ng.theme.shared" "~2.8.0" + "@abp/ng.feature-management" "~2.9.0" + "@abp/ng.tenant-management.config" "~2.9.0" + "@abp/ng.theme.shared" "~2.9.0" tslib "^1.9.0" -"@abp/ng.theme.basic@~2.8.0": - version "2.8.0" - resolved "https://registry.yarnpkg.com/@abp/ng.theme.basic/-/ng.theme.basic-2.8.0.tgz#9ecd23e75b264a851b8665e3e08d99306a44ec7b" - integrity sha512-5o3+Vbz9bA2IEe2IcDbUFHsfxMEcfe8rs2/A2o6Z4BQaqus+JtrQhxd1BExXb39NO8gdUBQ8fkyZVkOuyL7e6g== +"@abp/ng.theme.basic@~2.9.0": + version "2.9.0" + resolved "https://registry.yarnpkg.com/@abp/ng.theme.basic/-/ng.theme.basic-2.9.0.tgz#aa0351de9ec8237136f2f2ef014077cc330cefcf" + integrity sha512-TS3Ikeg+HPdBLXbzNcKbA2Ewi2zUbvCkOiF2aZxYCMrKOXDax6d0sN8m64X+vWuL4+cPtzcNg5bWsiDtUYRE2A== dependencies: - "@abp/ng.theme.shared" "~2.8.0" + "@abp/ng.theme.shared" "~2.9.0" tslib "^1.9.0" -"@abp/ng.theme.shared@~2.8.0": - version "2.8.0" - resolved "https://registry.yarnpkg.com/@abp/ng.theme.shared/-/ng.theme.shared-2.8.0.tgz#feb4ce0908b99e72fb230b1830bef6a6321cc4bd" - integrity sha512-0iVpvpLcpwMBLQk2VIKWxz6FktpJIbgxpgT+ypEUy6zDmaTT3TZuTeApleGJVLbEz2jkdEj2ApZH2asNaT1bPA== +"@abp/ng.theme.shared@~2.9.0": + version "2.9.0" + resolved "https://registry.yarnpkg.com/@abp/ng.theme.shared/-/ng.theme.shared-2.9.0.tgz#aaf97cf94ff798b3695cbb1b0dec33d20996fbda" + integrity sha512-04xlt3aKiDVyE+6NpxA0KGHGuupJWhXTjPWwlzVtfNiPqYjx0rG2FbTGgNWMW4K1qTlRRVjPA5a/MDhZtZHZIw== dependencies: - "@abp/ng.core" "~2.8.0" + "@abp/ng.core" "~2.9.0" "@fortawesome/fontawesome-free" "^5.12.1" "@ng-bootstrap/ng-bootstrap" "^5.3.0" "@ngx-validate/core" "^0.0.7" @@ -2129,14 +2129,7 @@ tree-kill "1.2.2" webpack-sources "1.4.3" -"@ngx-validate/core@^0.0.7": - version "0.0.7" - resolved "https://registry.yarnpkg.com/@ngx-validate/core/-/core-0.0.7.tgz#35a4364e8c8bb43ce1731e8d681ce1ab307c5955" - integrity sha512-APT7kstDaJ0JkC6cDkypbVSXAOAEyPTQ9P8DjEI1szi+Xzuz69XLASK3NdTYjFwogWevhYXoYRaR2Bq9iWzl+g== - dependencies: - tslib "^1.9.0" - -"@ngx-validate/core@^0.0.8": +"@ngx-validate/core@^0.0.7", "@ngx-validate/core@^0.0.8": version "0.0.8" resolved "https://registry.yarnpkg.com/@ngx-validate/core/-/core-0.0.8.tgz#8577405eb1af0f5002cdda7a86fbcda56280f116" integrity sha512-caIG5ao76Xhf7T+pNA8crnpAwK0yqj3i0OAUGZRUq1W+kNgz+ZnrSd4F9an/W4g+38u/8gfUVvsfsm07ju6qYA== From 490c08ff5b03cdbd7c22bcd72cbda3ce0acbed60 Mon Sep 17 00:00:00 2001 From: Arman Ozak Date: Mon, 8 Jun 2020 17:41:38 +0300 Subject: [PATCH 26/81] feat: add abpList directive to ThemeSharedModule --- .../theme-shared/src/lib/directives/index.ts | 1 + .../ngx-datatable-list.directive.ts | 74 +++++++++++++++++++ .../src/lib/theme-shared.module.ts | 11 +-- 3 files changed, 81 insertions(+), 5 deletions(-) create mode 100644 npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-list.directive.ts diff --git a/npm/ng-packs/packages/theme-shared/src/lib/directives/index.ts b/npm/ng-packs/packages/theme-shared/src/lib/directives/index.ts index aa2725e328..32b97c163a 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/directives/index.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/directives/index.ts @@ -1,2 +1,3 @@ export * from './loading.directive'; +export * from './ngx-datatable-list.directive'; export * from './table-sort.directive'; diff --git a/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-list.directive.ts b/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-list.directive.ts new file mode 100644 index 0000000000..0f603e0eaa --- /dev/null +++ b/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-list.directive.ts @@ -0,0 +1,74 @@ +import { ListService } from '@abp/ng.core'; +import { + ChangeDetectorRef, + Directive, + Host, + HostBinding, + Input, + OnChanges, + OnDestroy, + OnInit, + SimpleChanges, +} from '@angular/core'; +import { DatatableComponent } from '@swimlane/ngx-datatable'; +import { Subscription } from 'rxjs'; + +@Directive({ + exportAs: 'abpList', + selector: 'ngx-datatable[abpList]', +}) +export class NgxDatatableListDirective implements OnChanges, OnDestroy, OnInit { + private subscription = new Subscription(); + + /* tslint:disable-next-line:no-input-rename */ + @Input('abpList') list: ListService; + @Input() columnMode: 'standard' | 'flex' | 'force' = 'force'; + @Input() externalPaging = true; + @Input() externalSorting = true; + @Input() footerHeight = 50; + @Input() headerHeight = 50; + @Input() rowHeight: Function | number | 'auto' | undefined = 'auto'; + + @HostBinding() @Input() class = 'ngx-datatable material bordered'; + + constructor( + @Host() private cdRef: ChangeDetectorRef, + @Host() private table: DatatableComponent, + ) {} + + ngOnChanges({ list, ...changes }: SimpleChanges) { + if (!(list && list.firstChange)) return; + + ['columnMode', 'externalPaging', 'externalSorting', 'footerHeight', 'headerHeight', 'rowHeight'] + .filter(key => Object.keys(changes).indexOf(key) < 0) + .forEach(key => (this.table[key] = this[key])); + + const { maxResultCount, page } = list.currentValue; + this.table.limit = maxResultCount; + this.table.offset = page; + } + + ngOnDestroy() { + this.subscription.unsubscribe(); + } + + ngOnInit() { + const subPage = this.table.page.subscribe(({ offset }) => { + this.list.page = offset; + this.table.offset = offset; + }); + this.subscription.add(subPage); + + const subSort = this.table.sort.subscribe(({ sorts: [{ prop, dir }] }) => { + this.list.sortKey = prop; + this.list.sortOrder = dir; + }); + this.subscription.add(subSort); + + const subIsLoading = this.list.isLoading$.subscribe(loading => { + this.table.loadingIndicator = loading; + this.cdRef.markForCheck(); + }); + this.subscription.add(subIsLoading); + } +} diff --git a/npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts b/npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts index 10e112ffed..41c1c043bd 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts @@ -1,9 +1,10 @@ -import { CoreModule, LazyLoadService, noop, ConfigState } from '@abp/ng.core'; +import { ConfigState, CoreModule, noop } from '@abp/ng.core'; import { DatePipe } from '@angular/common'; import { APP_INITIALIZER, Injector, ModuleWithProviders, NgModule } from '@angular/core'; import { NgbDateParserFormatter, NgbPaginationModule } from '@ng-bootstrap/ng-bootstrap'; import { NgxValidateCoreModule } from '@ngx-validate/core'; -import { NgxDatatableModule, INgxDatatableConfig } from '@swimlane/ngx-datatable'; +import { Store } from '@ngxs/store'; +import { INgxDatatableConfig, NgxDatatableModule } from '@swimlane/ngx-datatable'; import { BreadcrumbComponent } from './components/breadcrumb/breadcrumb.component'; import { ButtonComponent } from './components/button/button.component'; import { ChartComponent } from './components/chart/chart.component'; @@ -19,8 +20,8 @@ import { TableEmptyMessageComponent } from './components/table-empty-message/tab import { TableComponent } from './components/table/table.component'; import { ToastContainerComponent } from './components/toast-container/toast-container.component'; import { ToastComponent } from './components/toast/toast.component'; -import styles from './constants/styles'; import { LoadingDirective } from './directives/loading.directive'; +import { NgxDatatableListDirective } from './directives/ngx-datatable-list.directive'; import { TableSortDirective } from './directives/table-sort.directive'; import { ErrorHandler } from './handlers/error.handler'; import { initLazyStyleHandler } from './handlers/lazy-style.handler'; @@ -28,8 +29,6 @@ import { RootParams } from './models/common'; import { THEME_SHARED_APPEND_CONTENT } from './tokens/append-content.token'; import { httpErrorConfigFactory, HTTP_ERROR_CONFIG } from './tokens/http-error.token'; import { DateParserFormatter } from './utils/date-parser-formatter'; -import { chartJsLoaded$ } from './utils/widget-utils'; -import { Store } from '@ngxs/store'; export function ngxDatatableMessageFactory(store: Store) { const emptyMessage = store.selectSnapshot( @@ -65,6 +64,7 @@ export function ngxDatatableMessageFactory(store: Store) { ToastComponent, ToastContainerComponent, SortOrderIconComponent, + NgxDatatableListDirective, LoadingDirective, TableSortDirective, ], @@ -83,6 +83,7 @@ export function ngxDatatableMessageFactory(store: Store) { ToastComponent, ToastContainerComponent, SortOrderIconComponent, + NgxDatatableListDirective, LoadingDirective, TableSortDirective, ], From e81930100e80bcc10088e96b65cf771daafc62aa Mon Sep 17 00:00:00 2001 From: Arman Ozak Date: Mon, 8 Jun 2020 17:42:06 +0300 Subject: [PATCH 27/81] feat: add bordered style for datatable --- .../packages/theme-shared/src/lib/constants/styles.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/npm/ng-packs/packages/theme-shared/src/lib/constants/styles.ts b/npm/ng-packs/packages/theme-shared/src/lib/constants/styles.ts index a3698f2164..f997eb6e5c 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/constants/styles.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/constants/styles.ts @@ -45,6 +45,11 @@ export default ` background: #8a8686; } +.bordered .datatable-body-row { + border-top: 1px solid #eee; + margin-top: -1px; +} + .abp-ellipsis-inline { display: inline-block; overflow: hidden; From aebb40396949139d5a3815ace6f04081e9a91e05 Mon Sep 17 00:00:00 2001 From: Arman Ozak Date: Mon, 8 Jun 2020 17:42:55 +0300 Subject: [PATCH 28/81] feat: place abpList directive on datatable instances --- .../lib/components/roles/roles.component.html | 17 +---------------- .../lib/components/users/users.component.html | 18 +----------------- .../components/tenants/tenants.component.html | 17 +---------------- 3 files changed, 3 insertions(+), 49 deletions(-) diff --git a/npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.html b/npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.html index 3ecc6413ea..9d87bae629 100644 --- a/npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.html +++ b/npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.html @@ -20,22 +20,7 @@
- +
- + - + Date: Tue, 9 Jun 2020 01:15:19 +0300 Subject: [PATCH 29/81] refactor: update how abpList directive handles defaults --- .../ngx-datatable-list.directive.ts | 33 +++++++++---------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-list.directive.ts b/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-list.directive.ts index 0f603e0eaa..c10df704cc 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-list.directive.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-list.directive.ts @@ -10,7 +10,7 @@ import { OnInit, SimpleChanges, } from '@angular/core'; -import { DatatableComponent } from '@swimlane/ngx-datatable'; +import { ColumnMode, DatatableComponent } from '@swimlane/ngx-datatable'; import { Subscription } from 'rxjs'; @Directive({ @@ -22,26 +22,25 @@ export class NgxDatatableListDirective implements OnChanges, OnDestroy, OnInit { /* tslint:disable-next-line:no-input-rename */ @Input('abpList') list: ListService; - @Input() columnMode: 'standard' | 'flex' | 'force' = 'force'; - @Input() externalPaging = true; - @Input() externalSorting = true; - @Input() footerHeight = 50; - @Input() headerHeight = 50; - @Input() rowHeight: Function | number | 'auto' | undefined = 'auto'; - @HostBinding() @Input() class = 'ngx-datatable material bordered'; + @Input() class = 'material bordered'; - constructor( - @Host() private cdRef: ChangeDetectorRef, - @Host() private table: DatatableComponent, - ) {} + @HostBinding('class') + get classes(): string { + return `ngx-datatable ${this.class}`; + } - ngOnChanges({ list, ...changes }: SimpleChanges) { - if (!(list && list.firstChange)) return; + constructor(@Host() private cdRef: ChangeDetectorRef, @Host() private table: DatatableComponent) { + this.table.columnMode = ColumnMode.force; + this.table.externalPaging = true; + this.table.externalSorting = true; + this.table.footerHeight = 50; + this.table.headerHeight = 50; + this.table.rowHeight = 'auto'; + } - ['columnMode', 'externalPaging', 'externalSorting', 'footerHeight', 'headerHeight', 'rowHeight'] - .filter(key => Object.keys(changes).indexOf(key) < 0) - .forEach(key => (this.table[key] = this[key])); + ngOnChanges({ list }: SimpleChanges) { + if (!(list && list.firstChange)) return; const { maxResultCount, page } = list.currentValue; this.table.limit = maxResultCount; From c046dac4075cab1b43e0f37d7f9d7fbea6438d90 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Tue, 9 Jun 2020 15:24:51 +0800 Subject: [PATCH 30/81] Upgrade RabbitMQ.Client to 6.1.0 --- .../Volo/Abp/BackgroundJobs/RabbitMQ/JobQueue.cs | 4 ++-- .../Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs | 4 ++-- framework/src/Volo.Abp.RabbitMQ/Volo.Abp.RabbitMQ.csproj | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/JobQueue.cs b/framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/JobQueue.cs index 879cf4f8ff..8d61850dd1 100644 --- a/framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/JobQueue.cs +++ b/framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/JobQueue.cs @@ -181,7 +181,7 @@ namespace Volo.Abp.BackgroundJobs.RabbitMQ var context = new JobExecutionContext( scope.ServiceProvider, JobConfiguration.JobType, - Serializer.Deserialize(ea.Body, typeof(TArgs)) + Serializer.Deserialize(ea.Body.ToArray(), typeof(TArgs)) ); try @@ -210,4 +210,4 @@ namespace Volo.Abp.BackgroundJobs.RabbitMQ } } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs b/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs index c530437e6f..ed7d37db20 100644 --- a/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs +++ b/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs @@ -83,7 +83,7 @@ namespace Volo.Abp.EventBus.RabbitMq return; } - var eventData = Serializer.Deserialize(ea.Body, eventType); + var eventData = Serializer.Deserialize(ea.Body.ToArray(), eventType); await TriggerHandlersAsync(eventType, eventData); } @@ -237,4 +237,4 @@ namespace Volo.Abp.EventBus.RabbitMq return false; } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.RabbitMQ/Volo.Abp.RabbitMQ.csproj b/framework/src/Volo.Abp.RabbitMQ/Volo.Abp.RabbitMQ.csproj index 1a7860deeb..a21be8bdfa 100644 --- a/framework/src/Volo.Abp.RabbitMQ/Volo.Abp.RabbitMQ.csproj +++ b/framework/src/Volo.Abp.RabbitMQ/Volo.Abp.RabbitMQ.csproj @@ -15,7 +15,7 @@ - + From cd34500aa50d2e84456f40ec4c5fcc3726694879 Mon Sep 17 00:00:00 2001 From: Arman Ozak Date: Tue, 9 Jun 2020 11:39:47 +0300 Subject: [PATCH 31/81] refactor: create a separate directive to style ngx-datatable --- .../lib/components/roles/roles.component.html | 2 +- .../lib/components/users/users.component.html | 2 +- .../components/tenants/tenants.component.html | 2 +- .../theme-shared/src/lib/directives/index.ts | 1 + .../ngx-datatable-default.directive.ts | 23 +++++++++++++++++++ .../ngx-datatable-list.directive.ts | 22 ++++-------------- .../src/lib/theme-shared.module.ts | 3 +++ 7 files changed, 35 insertions(+), 20 deletions(-) create mode 100644 npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-default.directive.ts diff --git a/npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.html b/npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.html index 9d87bae629..802e272dce 100644 --- a/npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.html +++ b/npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.html @@ -20,7 +20,7 @@
- +
- + - + Date: Tue, 9 Jun 2020 12:56:04 +0300 Subject: [PATCH 32/81] refactor: remove Host decorator from datatable helper directives --- .../src/lib/directives/ngx-datatable-default.directive.ts | 4 ++-- .../src/lib/directives/ngx-datatable-list.directive.ts | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-default.directive.ts b/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-default.directive.ts index 58f9c1b6fb..3672bde3b3 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-default.directive.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-default.directive.ts @@ -1,4 +1,4 @@ -import { Directive, Host, HostBinding, Input } from '@angular/core'; +import { Directive, HostBinding, Input } from '@angular/core'; import { ColumnMode, DatatableComponent } from '@swimlane/ngx-datatable'; @Directive({ @@ -14,7 +14,7 @@ export class NgxDatatableDefaultDirective { return `ngx-datatable ${this.class}`; } - constructor(@Host() private table: DatatableComponent) { + constructor(private table: DatatableComponent) { this.table.columnMode = ColumnMode.force; this.table.footerHeight = 50; this.table.headerHeight = 50; diff --git a/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-list.directive.ts b/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-list.directive.ts index 0f558eca4a..d14b91cf34 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-list.directive.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-list.directive.ts @@ -2,7 +2,6 @@ import { ListService } from '@abp/ng.core'; import { ChangeDetectorRef, Directive, - Host, Input, OnChanges, OnDestroy, @@ -22,7 +21,7 @@ export class NgxDatatableListDirective implements OnChanges, OnDestroy, OnInit { @Input() list: ListService; - constructor(@Host() private cdRef: ChangeDetectorRef, @Host() private table: DatatableComponent) { + constructor(private table: DatatableComponent, private cdRef: ChangeDetectorRef) { this.table.externalPaging = true; this.table.externalSorting = true; } From 707b4ef08d79829c8d1d31507b6990f4fbe99bf0 Mon Sep 17 00:00:00 2001 From: Arman Ozak Date: Tue, 9 Jun 2020 13:01:20 +0300 Subject: [PATCH 33/81] refactor: stop checking if list SimpleChange exists --- .../src/lib/directives/ngx-datatable-list.directive.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-list.directive.ts b/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-list.directive.ts index d14b91cf34..9f27226560 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-list.directive.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-list.directive.ts @@ -27,7 +27,7 @@ export class NgxDatatableListDirective implements OnChanges, OnDestroy, OnInit { } ngOnChanges({ list }: SimpleChanges) { - if (!(list && list.firstChange)) return; + if (!list.firstChange) return; const { maxResultCount, page } = list.currentValue; this.table.limit = maxResultCount; From 6e01b27fbf4fa9fbbe405e76c0fff4fc9bf5e34e Mon Sep 17 00:00:00 2001 From: Arman Ozak Date: Tue, 9 Jun 2020 13:17:20 +0300 Subject: [PATCH 34/81] refactor: split subscription inilitalizers into separate methods --- .../ngx-datatable-list.directive.ts | 44 ++++++++++++------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-list.directive.ts b/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-list.directive.ts index 9f27226560..85e574d63d 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-list.directive.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-list.directive.ts @@ -26,6 +26,30 @@ export class NgxDatatableListDirective implements OnChanges, OnDestroy, OnInit { this.table.externalSorting = true; } + private subscribeToPage() { + const sub = this.table.page.subscribe(({ offset }) => { + this.list.page = offset; + this.table.offset = offset; + }); + this.subscription.add(sub); + } + + private subscribeToSort() { + const sub = this.table.sort.subscribe(({ sorts: [{ prop, dir }] }) => { + this.list.sortKey = prop; + this.list.sortOrder = dir; + }); + this.subscription.add(sub); + } + + private subscribeToIsLoading() { + const sub = this.list.isLoading$.subscribe(loading => { + this.table.loadingIndicator = loading; + this.cdRef.markForCheck(); + }); + this.subscription.add(sub); + } + ngOnChanges({ list }: SimpleChanges) { if (!list.firstChange) return; @@ -39,22 +63,8 @@ export class NgxDatatableListDirective implements OnChanges, OnDestroy, OnInit { } ngOnInit() { - const subPage = this.table.page.subscribe(({ offset }) => { - this.list.page = offset; - this.table.offset = offset; - }); - this.subscription.add(subPage); - - const subSort = this.table.sort.subscribe(({ sorts: [{ prop, dir }] }) => { - this.list.sortKey = prop; - this.list.sortOrder = dir; - }); - this.subscription.add(subSort); - - const subIsLoading = this.list.isLoading$.subscribe(loading => { - this.table.loadingIndicator = loading; - this.cdRef.markForCheck(); - }); - this.subscription.add(subIsLoading); + this.subscribeToPage(); + this.subscribeToSort(); + this.subscribeToIsLoading(); } } From f1f3413274eb0eea8c32e8b891182e1a638fb050 Mon Sep 17 00:00:00 2001 From: maliming <6908465+maliming@users.noreply.github.com> Date: Wed, 10 Jun 2020 11:20:18 +0800 Subject: [PATCH 35/81] Reuse azure configuration. --- .../Abp/BlobStoring/Azure/AzureBlobProvider.cs | 18 +++++++++++------- .../Azure/AzureBlobProviderConfiguration.cs | 5 +++++ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProvider.cs b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProvider.cs index ec854b7be3..af5150c0a9 100644 --- a/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProvider.cs +++ b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProvider.cs @@ -22,12 +22,12 @@ namespace Volo.Abp.BlobStoring.Azure if (!args.OverrideExisting && await BlobExistsAsync(configuration, blobName)) { - throw new BlobAlreadyExistsException($"Saving BLOB '{args.BlobName}' does already exists in the container '{args.ContainerName}'! Set {nameof(args.OverrideExisting)} if it should be overwritten."); + throw new BlobAlreadyExistsException($"Saving BLOB '{args.BlobName}' does already exists in the container '{configuration.ContainerName}'! Set {nameof(args.OverrideExisting)} if it should be overwritten."); } if (configuration.CreateContainerIfNotExists) { - await CreateContainerIfNotExists(args.Configuration.GetAzureConfiguration()); + await CreateContainerIfNotExists(configuration); } await GetBlobClient(configuration, blobName).UploadAsync(args.BlobStream, true); @@ -36,10 +36,11 @@ namespace Volo.Abp.BlobStoring.Azure public override async Task DeleteAsync(BlobProviderDeleteArgs args) { var blobName = AzureBlobNameCalculator.Calculate(args); + var configuration = args.Configuration.GetAzureConfiguration(); - if (await BlobExistsAsync(args.Configuration.GetAzureConfiguration(), blobName)) + if (await BlobExistsAsync(configuration, blobName)) { - return await GetBlobClient(args.Configuration.GetAzureConfiguration(), blobName).DeleteIfExistsAsync(); + return await GetBlobClient(configuration, blobName).DeleteIfExistsAsync(); } return false; @@ -48,19 +49,22 @@ namespace Volo.Abp.BlobStoring.Azure public override async Task ExistsAsync(BlobProviderExistsArgs args) { var blobName = AzureBlobNameCalculator.Calculate(args); - return await BlobExistsAsync(args.Configuration.GetAzureConfiguration(), blobName); + var configuration = args.Configuration.GetAzureConfiguration(); + + return await BlobExistsAsync(configuration, blobName); } public override async Task GetOrNullAsync(BlobProviderGetArgs args) { var blobName = AzureBlobNameCalculator.Calculate(args); + var configuration = args.Configuration.GetAzureConfiguration(); - if (!await BlobExistsAsync(args.Configuration.GetAzureConfiguration(), blobName)) + if (!await BlobExistsAsync(configuration, blobName)) { return null; } - var blobClient = GetBlobClient(args.Configuration.GetAzureConfiguration(), blobName); + var blobClient = GetBlobClient(configuration, blobName); var download = await blobClient.DownloadAsync(); var memoryStream = new MemoryStream(); await download.Value.Content.CopyToAsync(memoryStream); diff --git a/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProviderConfiguration.cs b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProviderConfiguration.cs index a0906ed31f..8c232b7729 100644 --- a/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProviderConfiguration.cs +++ b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProviderConfiguration.cs @@ -8,6 +8,11 @@ set => _containerConfiguration.SetConfiguration(AzureBlobProviderConfigurationNames.ConnectionString, Check.NotNullOrWhiteSpace(value, nameof(value))); } + /// + /// This name may only contain lowercase letters, numbers, and hyphens, and must begin with a letter or a number. + /// Each hyphen must be preceded and followed by a non-hyphen character. + /// The name must also be between 3 and 63 characters long. + /// public string ContainerName { get => _containerConfiguration.GetConfiguration(AzureBlobProviderConfigurationNames.ContainerName); From decdfde0a563437edacc531616f8bc79eac45526 Mon Sep 17 00:00:00 2001 From: maliming <6908465+maliming@users.noreply.github.com> Date: Wed, 10 Jun 2020 13:08:10 +0800 Subject: [PATCH 36/81] Use ContainerName of the BlobProviderArgs if ContainerName of the AzureBlobProviderConfiguration is not specified. --- .../BlobStoring/Azure/AzureBlobProvider.cs | 52 +++++++++++-------- .../Azure/AzureBlobProviderConfiguration.cs | 1 + 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProvider.cs b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProvider.cs index af5150c0a9..1afc3b6a53 100644 --- a/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProvider.cs +++ b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProvider.cs @@ -1,7 +1,7 @@ -using System.IO; +using System; +using System.IO; using System.Threading.Tasks; using Azure.Storage.Blobs; -using Azure.Storage.Blobs.Specialized; using Volo.Abp.DependencyInjection; namespace Volo.Abp.BlobStoring.Azure @@ -20,27 +20,26 @@ namespace Volo.Abp.BlobStoring.Azure var blobName = AzureBlobNameCalculator.Calculate(args); var configuration = args.Configuration.GetAzureConfiguration(); - if (!args.OverrideExisting && await BlobExistsAsync(configuration, blobName)) + if (!args.OverrideExisting && await BlobExistsAsync(args, blobName)) { - throw new BlobAlreadyExistsException($"Saving BLOB '{args.BlobName}' does already exists in the container '{configuration.ContainerName}'! Set {nameof(args.OverrideExisting)} if it should be overwritten."); + throw new BlobAlreadyExistsException($"Saving BLOB '{args.BlobName}' does already exists in the container '{GetContainerName(args)}'! Set {nameof(args.OverrideExisting)} if it should be overwritten."); } if (configuration.CreateContainerIfNotExists) { - await CreateContainerIfNotExists(configuration); + await CreateContainerIfNotExists(args); } - await GetBlobClient(configuration, blobName).UploadAsync(args.BlobStream, true); + await GetBlobClient(args, blobName).UploadAsync(args.BlobStream, true); } public override async Task DeleteAsync(BlobProviderDeleteArgs args) { var blobName = AzureBlobNameCalculator.Calculate(args); - var configuration = args.Configuration.GetAzureConfiguration(); - if (await BlobExistsAsync(configuration, blobName)) + if (await BlobExistsAsync(args, blobName)) { - return await GetBlobClient(configuration, blobName).DeleteIfExistsAsync(); + return await GetBlobClient(args, blobName).DeleteIfExistsAsync(); } return false; @@ -49,51 +48,58 @@ namespace Volo.Abp.BlobStoring.Azure public override async Task ExistsAsync(BlobProviderExistsArgs args) { var blobName = AzureBlobNameCalculator.Calculate(args); - var configuration = args.Configuration.GetAzureConfiguration(); - return await BlobExistsAsync(configuration, blobName); + return await BlobExistsAsync(args, blobName); } public override async Task GetOrNullAsync(BlobProviderGetArgs args) { var blobName = AzureBlobNameCalculator.Calculate(args); - var configuration = args.Configuration.GetAzureConfiguration(); - if (!await BlobExistsAsync(configuration, blobName)) + if (!await BlobExistsAsync(args, blobName)) { return null; } - var blobClient = GetBlobClient(configuration, blobName); + var blobClient = GetBlobClient(args, blobName); var download = await blobClient.DownloadAsync(); var memoryStream = new MemoryStream(); await download.Value.Content.CopyToAsync(memoryStream); return memoryStream; } - protected virtual BlobClient GetBlobClient(AzureBlobProviderConfiguration configuration, string blobName) + protected virtual BlobClient GetBlobClient(BlobProviderArgs args, string blobName) { - var blobContainerClient = GetBlobContainerClient(configuration); + var blobContainerClient = GetBlobContainerClient(args); return blobContainerClient.GetBlobClient(blobName); } - protected virtual BlobContainerClient GetBlobContainerClient(AzureBlobProviderConfiguration configuration) + protected virtual BlobContainerClient GetBlobContainerClient(BlobProviderArgs args) { + var configuration = args.Configuration.GetAzureConfiguration(); var blobServiceClient = new BlobServiceClient(configuration.ConnectionString); - return blobServiceClient.GetBlobContainerClient(configuration.ContainerName); + return blobServiceClient.GetBlobContainerClient(GetContainerName(args)); } - protected virtual async Task CreateContainerIfNotExists(AzureBlobProviderConfiguration configuration) + protected virtual async Task CreateContainerIfNotExists(BlobProviderArgs args) { - var blobContainerClient = GetBlobContainerClient(configuration); + var blobContainerClient = GetBlobContainerClient(args); await blobContainerClient.CreateIfNotExistsAsync(); } - private async Task BlobExistsAsync(AzureBlobProviderConfiguration configuration, string blobName) + private async Task BlobExistsAsync(BlobProviderArgs args, string blobName) { // Make sure Blob Container exists. - return await ContainerExistsAsync(GetBlobContainerClient(configuration)) && - (await GetBlobClient(configuration, blobName).ExistsAsync()).Value; + return await ContainerExistsAsync(GetBlobContainerClient(args)) && + (await GetBlobClient(args, blobName).ExistsAsync()).Value; + } + + private static string GetContainerName(BlobProviderArgs args) + { + var configuration = args.Configuration.GetAzureConfiguration(); + return configuration.ContainerName.IsNullOrWhiteSpace() + ? args.ContainerName + : configuration.ContainerName; } private static async Task ContainerExistsAsync(BlobContainerClient blobContainerClient) diff --git a/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProviderConfiguration.cs b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProviderConfiguration.cs index 8c232b7729..7ab338794b 100644 --- a/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProviderConfiguration.cs +++ b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProviderConfiguration.cs @@ -12,6 +12,7 @@ /// This name may only contain lowercase letters, numbers, and hyphens, and must begin with a letter or a number. /// Each hyphen must be preceded and followed by a non-hyphen character. /// The name must also be between 3 and 63 characters long. + /// If this parameter is not specified, the ContainerName of the will be used. /// public string ContainerName { From b5915801debe66b63e262ce215c26da18517c43e Mon Sep 17 00:00:00 2001 From: Yunus Emre Kalkan Date: Wed, 10 Jun 2020 10:06:13 +0300 Subject: [PATCH 37/81] Fix: Feature values are not cleared entirely in database resolves https://github.com/abpframework/abp/issues/4289 --- .../Abp/FeatureManagement/FeatureManagementStore.cs | 6 +++--- .../Volo/Abp/FeatureManagement/FeatureManager.cs | 2 +- .../Abp/FeatureManagement/IFeatureValueRepository.cs | 2 ++ .../EfCoreFeatureValueRepository.cs | 10 +++++++++- .../MongoDB/MongoFeatureValueRepository.cs | 8 +++++++- .../FeatureValueRepository_Tests.cs | 12 ++++++++++++ 6 files changed, 34 insertions(+), 6 deletions(-) diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManagementStore.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManagementStore.cs index 8f3574d4a2..b35225edb2 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManagementStore.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManagementStore.cs @@ -44,8 +44,8 @@ namespace Volo.Abp.FeatureManagement public virtual async Task DeleteAsync(string name, string providerName, string providerKey) { - var featureValue = await FeatureValueRepository.FindAsync(name, providerName, providerKey); - if (featureValue != null) + var featureValues = await FeatureValueRepository.FindAllAsync(name, providerName, providerKey); + foreach (var featureValue in featureValues) { await FeatureValueRepository.DeleteAsync(featureValue); } @@ -78,4 +78,4 @@ namespace Volo.Abp.FeatureManagement return FeatureValueCacheItem.CalculateCacheKey(name, providerName, providerKey); } } -} \ No newline at end of file +} diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManager.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManager.cs index 06ca345bf6..04b7ab6682 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManager.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManager.cs @@ -183,4 +183,4 @@ namespace Volo.Abp.FeatureManagement return value; } } -} \ No newline at end of file +} diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/IFeatureValueRepository.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/IFeatureValueRepository.cs index c630d045a1..f5b5c85da4 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/IFeatureValueRepository.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/IFeatureValueRepository.cs @@ -9,6 +9,8 @@ namespace Volo.Abp.FeatureManagement { Task FindAsync(string name, string providerName, string providerKey); + Task> FindAllAsync(string name, string providerName, string providerKey); + Task> GetListAsync(string providerName, string providerKey); } } diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.EntityFrameworkCore/Volo/Abp/FeatureManagement/EntityFrameworkCore/EfCoreFeatureValueRepository.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.EntityFrameworkCore/Volo/Abp/FeatureManagement/EntityFrameworkCore/EfCoreFeatureValueRepository.cs index 34a6c1bbb3..22e7b2775d 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.EntityFrameworkCore/Volo/Abp/FeatureManagement/EntityFrameworkCore/EfCoreFeatureValueRepository.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.EntityFrameworkCore/Volo/Abp/FeatureManagement/EntityFrameworkCore/EfCoreFeatureValueRepository.cs @@ -23,6 +23,14 @@ namespace Volo.Abp.FeatureManagement.EntityFrameworkCore ); } + public async Task> FindAllAsync(string name, string providerName, string providerKey) + { + return await DbSet + .Where( + s => s.Name == name && s.ProviderName == providerName && s.ProviderKey == providerKey + ).ToListAsync(); + } + public virtual async Task> GetListAsync(string providerName, string providerKey) { return await DbSet @@ -31,4 +39,4 @@ namespace Volo.Abp.FeatureManagement.EntityFrameworkCore ).ToListAsync(); } } -} \ No newline at end of file +} diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.MongoDB/Volo/Abp/FeatureManagement/MongoDB/MongoFeatureValueRepository.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.MongoDB/Volo/Abp/FeatureManagement/MongoDB/MongoFeatureValueRepository.cs index 7db01d5288..72e5ac4b3b 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.MongoDB/Volo/Abp/FeatureManagement/MongoDB/MongoFeatureValueRepository.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.MongoDB/Volo/Abp/FeatureManagement/MongoDB/MongoFeatureValueRepository.cs @@ -22,6 +22,12 @@ namespace Volo.Abp.FeatureManagement.MongoDB .FirstOrDefaultAsync(s => s.Name == name && s.ProviderName == providerName && s.ProviderKey == providerKey); } + public async Task> FindAllAsync(string name, string providerName, string providerKey) + { + return await GetMongoQueryable() + .Where(s => s.Name == name && s.ProviderName == providerName && s.ProviderKey == providerKey).ToListAsync(); + } + public virtual async Task> GetListAsync(string providerName, string providerKey) { return await GetMongoQueryable() @@ -29,4 +35,4 @@ namespace Volo.Abp.FeatureManagement.MongoDB .ToListAsync(); } } -} \ No newline at end of file +} diff --git a/modules/feature-management/test/Volo.Abp.FeatureManagement.TestBase/Volo/Abp/FeatureManagement/FeatureValueRepository_Tests.cs b/modules/feature-management/test/Volo.Abp.FeatureManagement.TestBase/Volo/Abp/FeatureManagement/FeatureValueRepository_Tests.cs index c7cbb0d8ae..db606b2582 100644 --- a/modules/feature-management/test/Volo.Abp.FeatureManagement.TestBase/Volo/Abp/FeatureManagement/FeatureValueRepository_Tests.cs +++ b/modules/feature-management/test/Volo.Abp.FeatureManagement.TestBase/Volo/Abp/FeatureManagement/FeatureValueRepository_Tests.cs @@ -40,6 +40,18 @@ namespace Volo.Abp.FeatureManagement featureValue.ShouldBeNull(); } + [Fact] + public async Task FindAAllsync() + { + var featureValues = await Repository.FindAllAsync( + TestFeatureDefinitionProvider.ProjectCount, + EditionFeatureValueProvider.ProviderName, + TestEditionIds.Enterprise.ToString() + ); + + featureValues.Count.ShouldBe(1); + } + [Fact] public async Task GetListAsync() { From f258f55e9d6eed7d743ea2a54614acf8db3196ac Mon Sep 17 00:00:00 2001 From: Galip Tolga Erdem Date: Wed, 10 Jun 2020 13:02:06 +0300 Subject: [PATCH 38/81] Create Button-groups.md --- .../AspNetCore/Tag-Helpers/Button-groups.md | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 docs/en/UI/AspNetCore/Tag-Helpers/Button-groups.md diff --git a/docs/en/UI/AspNetCore/Tag-Helpers/Button-groups.md b/docs/en/UI/AspNetCore/Tag-Helpers/Button-groups.md new file mode 100644 index 0000000000..93865e0d74 --- /dev/null +++ b/docs/en/UI/AspNetCore/Tag-Helpers/Button-groups.md @@ -0,0 +1,37 @@ +# Button groups + +## Introduction + +`abp-button-group` is the main container for grouped button elements. + +Basic usage: + +````csharp + + Left + Middle + Right + +```` + +## Demo + +See the [button groups demo page](https://bootstrap-taghelpers.abp.io/Components/Button-groups) to see it in action. + +## Attributes + +### direction + +A value indicates the direction of the buttons. Should be one of the following values: + +* `Horizontal` (default value) +* `Vertical` + +### size + +A value indicates the size of the buttons in the group. Should be one of the following values: + +* `Default` (default value) +* `Small` +* `Medium` +* `Large` From 18d22c163ce08b1259c34d2d8126e9e73c2a04bd Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Wed, 10 Jun 2020 23:27:35 +0800 Subject: [PATCH 39/81] Update document --- docs/en/CurrentUser.md | 2 +- docs/zh-Hans/Blob-Storing-Azure.md | 1 + docs/zh-Hans/Blob-Storing-Custom-Provider.md | 1 + docs/zh-Hans/Blob-Storing-File-System.md | 1 + docs/zh-Hans/Blob-Storing.md | 1 + docs/zh-Hans/CLI.md | 1 + docs/zh-Hans/Connection-Strings.md | 14 +- docs/zh-Hans/CurrentUser.md | 168 +++++++++++++++++- docs/zh-Hans/Index.md | 4 +- docs/zh-Hans/Startup-Templates/Console.md | 19 ++ docs/zh-Hans/Startup-Templates/Index.md | 3 +- .../UI/Angular/Component-Replacement.md | 4 + ...ission-Management-Component-Replacement.md | 1 + .../UI/AspNetCore/Tag-Helpers/Badges.md | 38 ++++ .../UI/AspNetCore/Tag-Helpers/Borders.md | 124 +++++++++++++ .../UI/AspNetCore/Tag-Helpers/Breadcrumbs.md | 25 +++ .../zh-Hans/UI/AspNetCore/Tag-Helpers/Navs.md | 114 ++++++++++++ .../UI/AspNetCore/Tag-Helpers/Tables.md | 59 ++++++ docs/zh-Hans/docs-nav.json | 30 ++++ 19 files changed, 602 insertions(+), 8 deletions(-) create mode 100644 docs/zh-Hans/Blob-Storing-Azure.md create mode 100644 docs/zh-Hans/Blob-Storing-Custom-Provider.md create mode 100644 docs/zh-Hans/Blob-Storing-File-System.md create mode 100644 docs/zh-Hans/Blob-Storing.md create mode 100644 docs/zh-Hans/Startup-Templates/Console.md create mode 100644 docs/zh-Hans/UI/Angular/Permission-Management-Component-Replacement.md create mode 100644 docs/zh-Hans/UI/AspNetCore/Tag-Helpers/Badges.md create mode 100644 docs/zh-Hans/UI/AspNetCore/Tag-Helpers/Borders.md create mode 100644 docs/zh-Hans/UI/AspNetCore/Tag-Helpers/Breadcrumbs.md create mode 100644 docs/zh-Hans/UI/AspNetCore/Tag-Helpers/Navs.md create mode 100644 docs/zh-Hans/UI/AspNetCore/Tag-Helpers/Tables.md diff --git a/docs/en/CurrentUser.md b/docs/en/CurrentUser.md index f9057dd97e..e4aca40811 100644 --- a/docs/en/CurrentUser.md +++ b/docs/en/CurrentUser.md @@ -59,7 +59,7 @@ Here are the fundamental properties of the `ICurrentUser` interface: * **UserName** (string): User name of the current user. Returns `null`, if the current user has not logged in. * **TenantId** (Guid?): Tenant Id of the current user, which can be useful for a [multi-tenant](Multi-Tenancy.md) application. Returns `null`, if the current user is not assigned to a tenant. * **Email** (string): Email address of the current user.Returns `null`, if the current user has not logged in or not set an email address. -* **EmailVerified** (bool): Returns `true`, if the phone number of the current user has been verified. +* **EmailVerified** (bool): Returns `true`, if the email address of the current user has been verified. * **PhoneNumber** (string): Phone number of the current user. Returns `null`, if the current user has not logged in or not set a phone number. * **PhoneNumberVerified** (bool): Returns `true`, if the phone number of the current user has been verified. * **Roles** (string[]): Roles of the current user. Returns a string array of the role names of the current user. diff --git a/docs/zh-Hans/Blob-Storing-Azure.md b/docs/zh-Hans/Blob-Storing-Azure.md new file mode 100644 index 0000000000..cb82a640d5 --- /dev/null +++ b/docs/zh-Hans/Blob-Storing-Azure.md @@ -0,0 +1 @@ +TODO... \ No newline at end of file diff --git a/docs/zh-Hans/Blob-Storing-Custom-Provider.md b/docs/zh-Hans/Blob-Storing-Custom-Provider.md new file mode 100644 index 0000000000..cb82a640d5 --- /dev/null +++ b/docs/zh-Hans/Blob-Storing-Custom-Provider.md @@ -0,0 +1 @@ +TODO... \ No newline at end of file diff --git a/docs/zh-Hans/Blob-Storing-File-System.md b/docs/zh-Hans/Blob-Storing-File-System.md new file mode 100644 index 0000000000..cb82a640d5 --- /dev/null +++ b/docs/zh-Hans/Blob-Storing-File-System.md @@ -0,0 +1 @@ +TODO... \ No newline at end of file diff --git a/docs/zh-Hans/Blob-Storing.md b/docs/zh-Hans/Blob-Storing.md new file mode 100644 index 0000000000..cb82a640d5 --- /dev/null +++ b/docs/zh-Hans/Blob-Storing.md @@ -0,0 +1 @@ +TODO... \ No newline at end of file diff --git a/docs/zh-Hans/CLI.md b/docs/zh-Hans/CLI.md index c0147aa3a8..788c4a67ed 100644 --- a/docs/zh-Hans/CLI.md +++ b/docs/zh-Hans/CLI.md @@ -87,6 +87,7 @@ abp new Acme.BookStore * `mongodb`: MongoDB. * `module`: [Module template](Startup-Templates/Module.md). 其他选项: * `--no-ui`: 不包含UI.仅创建服务模块(也称为微服务 - 没有UI). + * **`console`**: [Console template](Startup-Templates/Console.md). * `--output-folder` 或者 `-o`: 指定输出文件夹,默认是当前目录. * `--version` 或者 `-v`: 指定ABP和模板的版本.它可以是 [release tag](https://github.com/abpframework/abp/releases) 或者 [branch name](https://github.com/abpframework/abp/branches). 如果没有指定,则使用最新版本.大多数情况下,你会希望使用最新的版本. * `--template-source` 或者 `-ts`: 指定自定义模板源用于生成项目,可以使用本地源和网络源(例如 `D\localTemplate` 或 `https://.zip`). diff --git a/docs/zh-Hans/Connection-Strings.md b/docs/zh-Hans/Connection-Strings.md index 562ae700ce..4694040309 100644 --- a/docs/zh-Hans/Connection-Strings.md +++ b/docs/zh-Hans/Connection-Strings.md @@ -73,8 +73,18 @@ public class IdentityServerDbContext 启动模板(使用 EF Core ORM) 带有一个数据库和一个 `.EntityFrameworkCore.DbMigrations` 项目,其中包含数据库的迁移文件. 该项目主要定义了一个*YourProjectName*MigrationsDbContext,它调用所有模块的 `Configure...()` 方法,例如 `builder.ConfigurePermissionManagement()`. -一旦要分离模块的数据库,通常需要创建第二个迁移路径. 最简单的方法是创建一个带有 `DbContext` 的 `.EntityFrameworkCore.DbMigrations` 项目副本, 更改为只调用需要存储在第二个数据库中的模块的 `Configure...()` 方法并重新创建迁移. 这时你还需要更改 `.DbMigrator` 应用程序使其兼容第二个数据库,这样每个数据库将有一个单独的迁移DbContext. +一旦要分离模块的数据库,通常需要创建第二个迁移路径. 请参阅[EF Core迁移文档](Entity-Framework-Core-Migrations.md)了解如何为所需模块创建和使用其他数据库. ## 多租户 -参阅 [多租户文档](Multi-Tenancy.md)了解如何为租户使用单独的数据库. \ No newline at end of file +参阅 [多租户文档](Multi-Tenancy.md)了解如何为租户使用单独的数据库. + +## 替换连接字符串解析器 + +ABP定义了 `IConnectionStringResolver`,并在需要连接字符串时使用它. 有两个预构建的实现: + +* `DefaultConnectionStringResolver` 根据上面"配置连接字符串"一节中定义的规则,使用 `AbpDbConnectionOptions` 选择连接字符串. +* `MultiTenantConnectionStringResolver` used for multi-tenant applications and tries to get the configured connection string for the current tenant if available. It uses the `ITenantStore` to find the connection strings. It inherits from the `DefaultConnectionStringResolver` and fallbacks to the base logic if no connection string specified for the current tenant. +* `MultiTenantConnectionStringResolver` 用于多租户应用程序,并尝试获取当前租户的已配置连接字符串(如果有). 它使用 `ITenantStore` 查找连接字符串. 它继承了 `DefaultConnectionStringResolver`, 如果没有为当前租户指定连接字符串则回退到基本逻辑. + +如果需要自定义逻辑来确定连接字符串,可以实现 `IConnectionStringResolver` 接口(也可以从现有类派生)并使用[依赖注入](Dependency-Injection.md)系统替换现有实现. \ No newline at end of file diff --git a/docs/zh-Hans/CurrentUser.md b/docs/zh-Hans/CurrentUser.md index b240a4421d..49ebaaaba0 100644 --- a/docs/zh-Hans/CurrentUser.md +++ b/docs/zh-Hans/CurrentUser.md @@ -1,3 +1,167 @@ -# Current User +# 当前用户 -TODO! \ No newline at end of file +在Web应用程序中检索有关已登录用户的信息是很常见的. 当前用户是与Web应用程序中的当前请求相关的活动用户. + +## ICurrentUser + +`ICurrentUser` 是主要的服务,用于获取有关当前活动的用户信息. + +示例: [注入](Dependency-Injection.md) `ICurrentUser` 到服务中: + +````csharp +using System; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Users; + +namespace AbpDemo +{ + public class MyService : ITransientDependency + { + private readonly ICurrentUser _currentUser; + + public MyService(ICurrentUser currentUser) + { + _currentUser = currentUser; + } + + public void Foo() + { + Guid? userId = _currentUser.Id; + } + } +} +```` + +公共基类已经将此服务作为基本属性注入. 例如你可以直接在[应用服务](Application-Services.md)中使用 `CurrentUser` 属性: + +````csharp +using System; +using Volo.Abp.Application.Services; + +namespace AbpDemo +{ + public class MyAppService : ApplicationService + { + public void Foo() + { + Guid? userId = CurrentUser.Id; + } + } +} +```` + +### 属性 + +以下是 `ICurrentUser` 接口的基本属性: + +* **IsAuthenticated** 如果当前用户已登录(已认证),则返回 `true`. 如果用户尚未登录,则 `Id` 和 `UserName` 将返回 `null`. +* **Id** (Guid?): 当前用户的Id,如果用户未登录,返回 `null`. +* **UserName** (string): 当前用户的用户名称. 如果用户未登录,返回 `null`. +* **TenantId** (Guid?): 当前用户的租户Id. 对于[多租户](Multi-Tenancy.md) 应用程序很有用. 如果当前用户未分配给租户,返回 `null`. +* **Email** (string): 当前用户的电子邮件地址. 如果当前用户尚未登录或未设置电子邮件地址,返回 `null`. +* **EmailVerified** (bool): 如果当前用户的电子邮件地址已经过验证,返回 `true`. +* **PhoneNumber** (string): 当前用户的电话号码. 如果当前用户尚未登录或未设置电话号码,返回 `null`. +* **PhoneNumberVerified** (bool): 如果当前用户的电话号码已经过验证,返回 `true`. +* **Roles** (string[]): 当前用户的角色. 返回当前用户角色名称的字符串数组. + +### Methods + +`ICurrentUser` 是在 `ICurrentPrincipalAccessor` 上实现的(请参阅以下部分),并可以处理声明. 实际上所有上述属性都是从当前经过身份验证的用户的声明中检索的. + +如果你有自定义声明或获取其他非常见声明类型, `ICurrentUser` 有一些直接使用声明的方法. + +* **FindClaim**: 获取给定名称的声明,如果未找到返回 `null`. +* **FindClaims**: 获取具有给定名称的所有声明(允许具有相同名称的多个声明值). +* **GetAllClaims**: 获取所有声明. +* **IsInRole**: 一种检查当前用户是否在指定角色中的简化方法. + +除了这些标准方法,还有一些扩展方法: + +* **FindClaimValue**: 获取具有给定名称的声明的值,如果未找到返回 `null`. 它有一个泛型重载将值强制转换为特定类型. +* **GetId**: 返回当前用户的 `Id`. 如果当前用户没有登录它会抛出一个异常(而不是返回`null`). 仅在你确定用户已经在你的代码上下文中进行了身份验证时才使用此选项. + +### 验证和授权 + +`ICurrentUser` 的工作方式与用户的身份验证或授权方式无关. 它可以与使用当前主体的任何身份验证系统无缝地配合使用(请参阅下面的部分). + +## ICurrentPrincipalAccessor + +`ICurrentPrincipalAccessor` 是当需要当前用户的principle时使用的服务(由ABP框架和你的应用程序代码使用). + +对于Web应用程序, 它获取当前 `HttpContext` 的 `User` 属性,对于非Web应用程序它将返回 `Thread.CurrentPrincipal`. + +> 通常你不需要这种低级别的 `ICurrentPrincipalAccessor` 服务,直接使用上述的 `ICurrentUser` 即可. + +### 基本用法 + +你可以注入 `ICurrentPrincipalAccessor` 并且使用 `Principal` 属性获取当前principal: + +````csharp +public class MyService : ITransientDependency +{ + private readonly ICurrentPrincipalAccessor _currentPrincipalAccessor; + + public MyService(ICurrentPrincipalAccessor currentPrincipalAccessor) + { + _currentPrincipalAccessor = currentPrincipalAccessor; + } + + public void Foo() + { + var allClaims = _currentPrincipalAccessor.Principal.Claims.ToList(); + //... + } +} +```` + +### 更改当前Principle + +除了某些高级场景外,你不需要设置或更改当前principle. 如果需要可以使用 `ICurrentPrincipalAccessor` 的 `Change` 方法. 它接受一个 `ClaimsPrinciple` 对象并使其成为作用域的"当前"对象. + +示例: + +````csharp +public class MyAppService : ApplicationService +{ + private readonly ICurrentPrincipalAccessor _currentPrincipalAccessor; + + public MyAppService(ICurrentPrincipalAccessor currentPrincipalAccessor) + { + _currentPrincipalAccessor = currentPrincipalAccessor; + } + + public void Foo() + { + var newPrinciple = new ClaimsPrincipal( + new ClaimsIdentity( + new Claim[] + { + new Claim(AbpClaimTypes.UserId, Guid.NewGuid().ToString()), + new Claim(AbpClaimTypes.UserName, "john"), + new Claim("MyCustomCliam", "42") + } + ) + ); + + using (_currentPrincipalAccessor.Change(newPrinciple)) + { + var userName = CurrentUser.UserName; //returns "john" + //... + } + } +} +```` + +始终在 `using` 语句中使用 `Change` 方法,在 `using` 范围结束后它将恢复为原始值. + +这可以是一种模拟用户登录的应用程序代码范围的方法,但是请尝试谨慎使用它. + +## AbpClaimTypes + +`AbpClaimTypes` 是一个静态类它定义了标准声明的名称被ABP框架使用. + +* `UserName`, `UserId`, `Role` 和 `Email` 属性的默认值是通常[System.Security.Claims.ClaimTypes](https://docs.microsoft.com/en-us/dotnet/api/system.security.claims.claimtypes)类设置的, 但你可以改变它们. + +* 其他属性,如 `EmailVerified`, `PhoneNumber`, `TenantId` ...是由ABP框架通过尽可能遵循标准名称来定义的. + +建议使用这个类的属性来代替声明名称的魔术字符串. \ No newline at end of file diff --git a/docs/zh-Hans/Index.md b/docs/zh-Hans/Index.md index ce4fcfa3b4..3dd728c846 100644 --- a/docs/zh-Hans/Index.md +++ b/docs/zh-Hans/Index.md @@ -10,8 +10,8 @@ ABP是一个**开源应用程序框架**,专注于基于ASP.NET Core的Web应用 使用ABP开发新项目的最简单方法是使用启动模板: -* [ASP.NET Core MVC (Razor Pages) UI 启动模板](Getting-Started?UI=MVC&DB=EF&Tiered=No) -* [Angular UI 启动模板](Getting-Started?UI=NG&DB=EF&Tiered=No) +* [ASP.NET Core MVC (Razor Pages) UI 启动模板](Getting-Started.md?UI=MVC&DB=EF&Tiered=No) +* [Angular UI 启动模板](Getting-Started.md?UI=NG&DB=EF&Tiered=No) 如果你想从头开始(使用空项目),请手动安装ABP框架并使用以下教程: diff --git a/docs/zh-Hans/Startup-Templates/Console.md b/docs/zh-Hans/Startup-Templates/Console.md new file mode 100644 index 0000000000..caeb036d3d --- /dev/null +++ b/docs/zh-Hans/Startup-Templates/Console.md @@ -0,0 +1,19 @@ +# 控制台应用程序启动模板 + +此模板用于创建一个最小的依赖关系的ABP控制台应用程序项目. + +## 如何开始? + +首先,如果你没有安装[ABP CLI](../CLI.md),请先安装它: + +````bash +dotnet tool install -g Volo.Abp.Cli +```` + +在一个空文件夹使用 `abp new` 命令创建新解决方案: + +````bash +abp new Acme.MyConsoleApp -t console +```` + +`Acme.MyConsoleApp` 是解决方案的名称, 如*YourCompany.YourProduct*. 你可以使用单级或多级名称. \ No newline at end of file diff --git a/docs/zh-Hans/Startup-Templates/Index.md b/docs/zh-Hans/Startup-Templates/Index.md index 160a2b3e20..fbc91c7549 100644 --- a/docs/zh-Hans/Startup-Templates/Index.md +++ b/docs/zh-Hans/Startup-Templates/Index.md @@ -5,4 +5,5 @@ 单击下面列表中的名称以查看相关启动模板的文档: * [**app**](Application.md): 应用程序模板. -* [**module**](Module.md): 模块/服务模板. \ No newline at end of file +* [**module**](Module.md): 模块/服务模板. +* [**console**](Console.md): 控制台模板. \ No newline at end of file diff --git a/docs/zh-Hans/UI/Angular/Component-Replacement.md b/docs/zh-Hans/UI/Angular/Component-Replacement.md index 4465f34893..145359c348 100644 --- a/docs/zh-Hans/UI/Angular/Component-Replacement.md +++ b/docs/zh-Hans/UI/Angular/Component-Replacement.md @@ -543,6 +543,10 @@ export class AppComponent implements OnInit { ![New nav-items](./images/replaced-nav-items-component.png) +## 另请参阅 + +- [如何替换PermissionManagementComponent](./Permission-Management-Component-Replacement.md) + ## 下一步是什么? - [自定义设置页面](./Custom-Setting-Page.md) \ No newline at end of file diff --git a/docs/zh-Hans/UI/Angular/Permission-Management-Component-Replacement.md b/docs/zh-Hans/UI/Angular/Permission-Management-Component-Replacement.md new file mode 100644 index 0000000000..d39074a957 --- /dev/null +++ b/docs/zh-Hans/UI/Angular/Permission-Management-Component-Replacement.md @@ -0,0 +1 @@ +TODO.... \ No newline at end of file diff --git a/docs/zh-Hans/UI/AspNetCore/Tag-Helpers/Badges.md b/docs/zh-Hans/UI/AspNetCore/Tag-Helpers/Badges.md new file mode 100644 index 0000000000..b15dd502b8 --- /dev/null +++ b/docs/zh-Hans/UI/AspNetCore/Tag-Helpers/Badges.md @@ -0,0 +1,38 @@ +# 徽章 + +## 结合扫 + +`abp-badge` 和 `abp-badge-pill` 是abp徽章标签. + +基本用法: + +````csharp +Primary +Info +Danger +```` + +## Demo + +参阅[徽章demo页面](https://bootstrap-taghelpers.abp.io/Components/Badges)查看示例. + +### Values + +* 表示徽章的类型. 应为下列值之一: + + * `_` (默认值) + * `Default` (默认值) + * `Primary` + * `Secondary` + * `Success` + * `Danger` + * `Warning` + * `Info` + * `Light` + * `Dark` + +示例: + +````csharp +Danger +```` diff --git a/docs/zh-Hans/UI/AspNetCore/Tag-Helpers/Borders.md b/docs/zh-Hans/UI/AspNetCore/Tag-Helpers/Borders.md new file mode 100644 index 0000000000..5b57ce76c3 --- /dev/null +++ b/docs/zh-Hans/UI/AspNetCore/Tag-Helpers/Borders.md @@ -0,0 +1,124 @@ +# 边框 + +## 介绍 + +`abp-border` 是边框样式的主要元素. + +基本用法: + +````csharp + + + + + +```` + +## Demo + +参阅[边框demo页面](https://bootstrap-taghelpers.abp.io/Components/Borders)查看示例. + +## Values + +值代表类型,位置和边框的颜色.应为下列值之一: + +* `Default` +* `_0` +* `Primary` +* `Secondary` +* `Success` +* `Danger` +* `Warning` +* `Info` +* `Light` +* `Dark` +* `White` +* `Primary_0` +* `Secondary_0` +* `Success_0` +* `Danger_0` +* `Warning_0` +* `Info_0` +* `Light_0` +* `Dark_0` +* `White_0` +* `Top` +* `Top_0` +* `Top_Primary` +* `Top_Secondary` +* `Top_Success` +* `Top_Danger` +* `Top_Warning` +* `Top_Info` +* `Top_Light` +* `Top_Dark` +* `Top_White` +* `Top_Primary_0` +* `Top_Secondary_0` +* `Top_Success_0` +* `Top_Danger_0` +* `Top_Warning_0` +* `Top_Info_0` +* `Top_Light_0` +* `Top_Dark_0` +* `Top_White_0` +* `Right` +* `Right_0` +* `Right_Primary` +* `Right_Secondary` +* `Right_Success` +* `Right_Danger` +* `Right_Warning` +* `Right_Info` +* `Right_Light` +* `Right_Dark` +* `Right_White` +* `Right_Primary_0` +* `Right_Secondary_0` +* `Right_Success_0` +* `Right_Danger_0` +* `Right_Warning_0` +* `Right_Info_0` +* `Right_Light_0` +* `Right_Dark_0` +* `Right_White_0` +* `Left` +* `Left_0` +* `Left_Primary` +* `Left_Secondary` +* `Left_Success` +* `Left_Danger` +* `Left_Warning` +* `Left_Info` +* `Left_Light` +* `Left_Dark` +* `Left_White` +* `Left_Primary_0` +* `Left_Secondary_0` +* `Left_Success_0` +* `Left_Danger_0` +* `Left_Warning_0` +* `Left_Info_0` +* `Left_Light_0` +* `Left_Dark_0` +* `Left_White_0` +* `Bottom` +* `Bottom_0` +* `Bottom_Primary` +* `Bottom_Secondary` +* `Bottom_Success` +* `Bottom_Danger` +* `Bottom_Warning` +* `Bottom_Info` +* `Bottom_Light` +* `Bottom_Dark` +* `Bottom_White` +* `Bottom_Primary_0` +* `Bottom_Secondary_0` +* `Bottom_Success_0` +* `Bottom_Danger_0` +* `Bottom_Warning_0` +* `Bottom_Info_0` +* `Bottom_Light_0` +* `Bottom_Dark_0` +* `Bottom_White_0` diff --git a/docs/zh-Hans/UI/AspNetCore/Tag-Helpers/Breadcrumbs.md b/docs/zh-Hans/UI/AspNetCore/Tag-Helpers/Breadcrumbs.md new file mode 100644 index 0000000000..10bc729fcb --- /dev/null +++ b/docs/zh-Hans/UI/AspNetCore/Tag-Helpers/Breadcrumbs.md @@ -0,0 +1,25 @@ +# 面包屑 + +## Introduction + +`ABP-breadcrumb` 是面包屑项主容器. + +基本用法: + +````csharp + + + + + +```` + +## Demo + +参阅[面包屑demo页面](https://bootstrap-taghelpers.abp.io/Components/Breadcrumbs)查看示例. + +## abp-breadcrumb-item Attributes + +- **title**: 设置面包屑项文本. +- **active**: 设置活动面包屑项. 如果没有其他项是活动的,默认最后一项为活动项. +- **href**: 表示 `abp-breadcrumb-item` 是否有链接. 值应该是字符串链接. \ No newline at end of file diff --git a/docs/zh-Hans/UI/AspNetCore/Tag-Helpers/Navs.md b/docs/zh-Hans/UI/AspNetCore/Tag-Helpers/Navs.md new file mode 100644 index 0000000000..6edbc1b96f --- /dev/null +++ b/docs/zh-Hans/UI/AspNetCore/Tag-Helpers/Navs.md @@ -0,0 +1,114 @@ +# 导航 + +## 介绍 + +`abp-nav` 是从bootstrap nav元素派生的基本标签助手. + +基本用法: + +````csharp + + +Active + + +Longer nav link + + +link + + +disabled + + +```` + +## Demo + +参阅[导航demo页面](https://bootstrap-taghelpers.abp.io/Components/Navs)查看示例. + +## abp-nav Attributes + +- **nav-style**: 指示包含项的位置和样式. 应为以下值之一: + * `Default` (默认值) + * `Vertical` + * `Pill` + * `PillVertical` +- **align:** 指示包含项的对齐方式: + * `Default` (默认值) + * `Start` + * `Center` + * `End` + +### abp-nav-bar Attributes + +- **nav-style**: 指示基本导航栏的颜色布局. 应为以下值之一: + * `Default` (默认值) + * `Dark` + * `Light` + * `Dark_Primary` + * `Dark_Secondary` + * `Dark_Success` + * `Dark_Danger` + * `Dark_Warning` + * `Dark_Info` + * `Dark_Dark` + * `Dark_Link` + * `Light_Primary` + * `Light_Secondary` + * `Light_Success` + * `Light_Danger` + * `Light_Warning` + * `Light_Info` + * `Light_Dark` + * `Light_Link` +- **size:** 指示基本导航栏的大小. 应为以下值之一: + * `Default` (默认值) + * `Sm` + * `Md` + * `Lg` + * `Xl` + +### abp-nav-item Attributes + +**dropdown**: 将导航项设置为下拉菜单(如果提供的话). 可以是下列值之一: + +* `false` (默认值) +* `true` + +示例: + +````csharp + + Navbar + + + + Home (current) + + + Link + + + + + + Dropdown header + Action + Another disabled action + Something else here + + Separated link + + + + + Disabled + + + + Sample Text + + + +```` diff --git a/docs/zh-Hans/UI/AspNetCore/Tag-Helpers/Tables.md b/docs/zh-Hans/UI/AspNetCore/Tag-Helpers/Tables.md new file mode 100644 index 0000000000..24c61d28fc --- /dev/null +++ b/docs/zh-Hans/UI/AspNetCore/Tag-Helpers/Tables.md @@ -0,0 +1,59 @@ +# 表格 + +## 介绍 + +`ABP-table` 在ABP中用于表格的基本标签组件. + +基本用法: + +````csharp + + + + # + First + Last + Handle + + + + + 1 + Mark + Otto + mdo + + + 2 + Jacob + Thornton + fat + + + 3 + Larry + the Bird + twitter + + + +```` + +## Demo + +参阅[表格demo页面](https://bootstrap-taghelpers.abp.io/Components/Tables)查看示例. + +## abp-table Attributes + +- **responsive**: 用于创建直至特定断点的响应表. 请参阅[特定断点](https://getbootstrap.com/docs/4.1/content/tables/#breakpoint-specific)获取更多信息. +- **responsive-sm**: 如果没有设置为false,则为小屏幕设备设置表响应性. +- **responsive-md**: 如果未设置为false,则为中等屏幕设备设置表响应性. +- **responsive-lg**: 如果未设置为false,则为大屏幕设备设置表响应性. +- **responsive-xl**: 如果未设置为false,则为超大屏幕设备设置表响应性. +- **dark-theme**: 如果设置为true,则将表格颜色主题设置为黑暗. +- **striped-rows**: 如果设置为true,则将斑马条纹添加到表行中. +- **hoverable-rows**: 如果设置为true,则将悬停状态添加到表行. +- **border-style**: 设置表格的边框样式. 应为以下值之一: + - `Default` (默认) + - `Bordered` + - `Borderless` diff --git a/docs/zh-Hans/docs-nav.json b/docs/zh-Hans/docs-nav.json index 23b17c1231..91e11119a9 100644 --- a/docs/zh-Hans/docs-nav.json +++ b/docs/zh-Hans/docs-nav.json @@ -181,6 +181,36 @@ "path": "Object-To-Object-Mapping.md" }, + { + "text": "BLOB存储", + "items": [ + { + "text": "BLOB存储系统", + "path": "Blob-Storing.md" + }, + { + "text": "存储提供者", + "items": [ + { + "text": "文件系统提供者", + "path": "Blob-Storing-File-System.md" + }, + { + "text": "数据库系统提供者", + "path": "Blob-Storing-Database.md" + }, + { + "text": "Azure提供者", + "path": "Blob-Storing-Azure.md" + }, + { + "text": "创建自定义提供者", + "path": "Blob-Storing-Custom-Provider.md" + } + ] + } + ] + }, { "text": "文本模板", "path": "Text-Templating.md" From b819811d0fc17ecd822f4bcff2bbdb93d84916c3 Mon Sep 17 00:00:00 2001 From: Arman Ozak Date: Wed, 10 Jun 2020 18:40:34 +0300 Subject: [PATCH 40/81] test: update specs for page property --- .../packages/core/src/lib/tests/list.service.spec.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/npm/ng-packs/packages/core/src/lib/tests/list.service.spec.ts b/npm/ng-packs/packages/core/src/lib/tests/list.service.spec.ts index c2118d7f3a..f26c39d4ad 100644 --- a/npm/ng-packs/packages/core/src/lib/tests/list.service.spec.ts +++ b/npm/ng-packs/packages/core/src/lib/tests/list.service.spec.ts @@ -49,8 +49,8 @@ describe('ListService', () => { }); describe('#page', () => { - it('should initially be 1', () => { - expect(service.page).toBe(1); + it('should initially be 0', () => { + expect(service.page).toBe(0); }); it('should be changed', () => { @@ -110,7 +110,7 @@ describe('ListService', () => { filter: 'foo', sorting: 'bar baz', maxResultCount: 20, - skipCount: 160, + skipCount: 180, }); done(); From 5758e476d247c2b976c9508bc8f10f13ff1e19dd Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Thu, 11 Jun 2020 00:00:11 +0800 Subject: [PATCH 41/81] Add phone number filter --- .../Abp/Identity/MongoDB/MongoOrganizationUnitRepository.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoOrganizationUnitRepository.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoOrganizationUnitRepository.cs index 943d570153..448ee5754e 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoOrganizationUnitRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoOrganizationUnitRepository.cs @@ -122,7 +122,8 @@ namespace Volo.Abp.Identity.MongoDB !filter.IsNullOrWhiteSpace(), u => u.UserName.Contains(filter) || - u.Email.Contains(filter) + u.Email.Contains(filter) || + (u.PhoneNumber != null && u.PhoneNumber.Contains(filter)) ) .OrderBy(sorting ?? nameof(IdentityUser.UserName)) .As>() From c904c10085583ae9065ce01e0f5b5a78b3c0f2a8 Mon Sep 17 00:00:00 2001 From: MaxRiz <10518283+maxrizwork@users.noreply.github.com> Date: Wed, 10 Jun 2020 21:52:04 +0200 Subject: [PATCH 42/81] Typo on Entities.md Just a small typo reading the doc --- docs/en/Entities.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/Entities.md b/docs/en/Entities.md index 8a234b94a5..0d34c35ce6 100644 --- a/docs/en/Entities.md +++ b/docs/en/Entities.md @@ -382,7 +382,7 @@ The way to store this dictionary in the database depends on the database provide Extra Properties system is especially useful if you are using a **re-usable module** that defines an entity inside and you want to get/set some data related to this entity in an easy way. -You normally **don't need** to this system for your own entities, because it has the following drawbacks: +You typically **don't need** to use this system for your own entities, because it has the following drawbacks: * It is **not fully type safe** since it works with strings as property names. * It is **not easy to [auto map](Object-To-Object-Mapping.md)** these properties from/to other objects. From aaecacd09b34a824438a491a836959feb2bc3db4 Mon Sep 17 00:00:00 2001 From: Galip Tolga Erdem Date: Thu, 11 Jun 2020 01:05:18 +0300 Subject: [PATCH 43/81] Update AbpCarouselTagHelperService.cs Added div for carausel items --- .../TagHelpers/Carousel/AbpCarouselTagHelperService.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Carousel/AbpCarouselTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Carousel/AbpCarouselTagHelperService.cs index ffba80fb6f..c92e08365e 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Carousel/AbpCarouselTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Carousel/AbpCarouselTagHelperService.cs @@ -38,6 +38,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Carousel protected virtual void SetItems(TagHelperContext context, TagHelperOutput output, List itemList) { var itemsHtml = new StringBuilder(""); + itemsHtml.Append("
"); foreach (var carouselItem in itemList) { @@ -46,6 +47,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Carousel itemsHtml.AppendLine(carouselItem.Html); } + itemsHtml.Append("
"); output.Content.SetHtmlContent(itemsHtml.ToString()); } @@ -137,4 +139,4 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Carousel } } -} \ No newline at end of file +} From 9bd70d8041590d1b5cf6ffc8e00b63e861cf1c42 Mon Sep 17 00:00:00 2001 From: Galip Tolga Erdem Date: Thu, 11 Jun 2020 02:41:50 +0300 Subject: [PATCH 44/81] Create Carousel.md --- docs/en/UI/AspNetCore/Tag-Helpers/Carousel.md | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 docs/en/UI/AspNetCore/Tag-Helpers/Carousel.md diff --git a/docs/en/UI/AspNetCore/Tag-Helpers/Carousel.md b/docs/en/UI/AspNetCore/Tag-Helpers/Carousel.md new file mode 100644 index 0000000000..6088977068 --- /dev/null +++ b/docs/en/UI/AspNetCore/Tag-Helpers/Carousel.md @@ -0,0 +1,74 @@ +# Carousel + +## Introduction + +`abp-carousel` is a the abp tag for carousel element. + +Basic usage: + +````csharp + + + + + +```` + + + +## Demo + +See the [carousel_demo page](https://bootstrap-taghelpers.abp.io/Components/Carousel) to see it in action. + +## Attributes + +### id + +A value sets the id of the carousel. If not set, generated id will be set whenever the tag is created. + +### controls + +A value to enable the controls (previous and next buttons) on carousel. Should be one of the following values: + +* `false` +* `true` + +### indicators + +A value to enables the indicators on carousel. Should be one of the following values: + +* `false` +* `true` + +### crossfade + +A value to enables the fade animation instead of slide on carousel. Should be one of the following values: + +* `false` +* `true` + +## abp-carousel-item Attributes + +### caption-title + +A value sets the caption title of the carousel item. + +### caption + +A value sets the caption of the carousel item. + +### src + +A link value sets the source of the image displayed on carousel item. + +### active + +A value to set the active carousel item. Should be one of the following values: + +* `false` +* `true` + +### alt + +A value sets the alternate text for the carousel item image when the image can not be displayed. + From 9914b09b7f360b11e7b3a4804778c9473ffc1de0 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Thu, 11 Jun 2020 08:51:40 +0800 Subject: [PATCH 45/81] The GetMembersCount method add filter --- .../Identity/IOrganizationUnitRepository.cs | 1 + .../EfCoreOrganizationUnitRepository.cs | 41 +++++++++++-------- .../MongoOrganizationUnitRepository.cs | 33 +++++++++------ 3 files changed, 44 insertions(+), 31 deletions(-) diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IOrganizationUnitRepository.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IOrganizationUnitRepository.cs index bf698ca54f..6650f62c82 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IOrganizationUnitRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IOrganizationUnitRepository.cs @@ -67,6 +67,7 @@ namespace Volo.Abp.Identity Task GetMembersCountAsync( OrganizationUnit organizationUnit, + string filter = null, CancellationToken cancellationToken = default ); diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreOrganizationUnitRepository.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreOrganizationUnitRepository.cs index 06b2084707..7bdb7d6837 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreOrganizationUnitRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreOrganizationUnitRepository.cs @@ -121,33 +121,19 @@ namespace Volo.Abp.Identity.EntityFrameworkCore CancellationToken cancellationToken = default ) { - var query = from userOu in DbContext.Set() - join user in DbContext.Users.IncludeDetails(includeDetails) on userOu.UserId equals user.Id - where userOu.OrganizationUnitId == organizationUnit.Id - select user; + var query = CreateGetMembersFilteredQuery(organizationUnit, filter); - if (!filter.IsNullOrWhiteSpace()) - { - query = query.Where(u => - u.UserName.Contains(filter) || - u.Email.Contains(filter) || - (u.PhoneNumber != null && u.PhoneNumber.Contains(filter)) - ); - } - - return await query.OrderBy(sorting ?? nameof(IdentityUser.UserName)) + return await query.IncludeDetails(includeDetails).OrderBy(sorting ?? nameof(IdentityUser.UserName)) .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task GetMembersCountAsync( OrganizationUnit organizationUnit, + string filter = null, CancellationToken cancellationToken = default) { - var query = from userOu in DbContext.Set() - join user in DbContext.Users on userOu.UserId equals user.Id - where userOu.OrganizationUnitId == organizationUnit.Id - select user; + var query = CreateGetMembersFilteredQuery(organizationUnit, filter); return await query.CountAsync(GetCancellationToken(cancellationToken)); } @@ -175,5 +161,24 @@ namespace Volo.Abp.Identity.EntityFrameworkCore DbContext.Set().RemoveRange(ouMembersQuery); } + + protected virtual IQueryable CreateGetMembersFilteredQuery(OrganizationUnit organizationUnit, string filter = null) + { + var query = from userOu in DbContext.Set() + join user in DbContext.Users on userOu.UserId equals user.Id + where userOu.OrganizationUnitId == organizationUnit.Id + select user; + + if (!filter.IsNullOrWhiteSpace()) + { + query = query.Where(u => + u.UserName.Contains(filter) || + u.Email.Contains(filter) || + (u.PhoneNumber != null && u.PhoneNumber.Contains(filter)) + ); + } + + return query; + } } } diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoOrganizationUnitRepository.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoOrganizationUnitRepository.cs index 448ee5754e..8c163d4126 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoOrganizationUnitRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoOrganizationUnitRepository.cs @@ -116,15 +116,9 @@ namespace Volo.Abp.Identity.MongoDB bool includeDetails = false, CancellationToken cancellationToken = default) { - return await DbContext.Users.AsQueryable() - .Where(u => u.OrganizationUnits.Any(uou => uou.OrganizationUnitId == organizationUnit.Id)) - .WhereIf>( - !filter.IsNullOrWhiteSpace(), - u => - u.UserName.Contains(filter) || - u.Email.Contains(filter) || - (u.PhoneNumber != null && u.PhoneNumber.Contains(filter)) - ) + var query = CreateGetMembersFilteredQuery(organizationUnit, filter); + + return await query .OrderBy(sorting ?? nameof(IdentityUser.UserName)) .As>() .PageBy>(skipCount, maxResultCount) @@ -133,12 +127,12 @@ namespace Volo.Abp.Identity.MongoDB public virtual async Task GetMembersCountAsync( OrganizationUnit organizationUnit, + string filter = null, CancellationToken cancellationToken = default) { - return await DbContext.Users.AsQueryable() - .Where(u => u.OrganizationUnits.Any(uou => uou.OrganizationUnitId == organizationUnit.Id)) - .As>() - .CountAsync(GetCancellationToken(cancellationToken)); + var query = CreateGetMembersFilteredQuery(organizationUnit, filter); + + return await query.CountAsync(GetCancellationToken(cancellationToken)); } public virtual Task RemoveAllRolesAsync(OrganizationUnit organizationUnit, CancellationToken cancellationToken = default) @@ -160,5 +154,18 @@ namespace Volo.Abp.Identity.MongoDB DbContext.Users.ReplaceOne(u => u.Id == user.Id, user); } } + + protected virtual IMongoQueryable CreateGetMembersFilteredQuery(OrganizationUnit organizationUnit, string filter = null) + { + return DbContext.Users.AsQueryable() + .Where(u => u.OrganizationUnits.Any(uou => uou.OrganizationUnitId == organizationUnit.Id)) + .WhereIf>( + !filter.IsNullOrWhiteSpace(), + u => + u.UserName.Contains(filter) || + u.Email.Contains(filter) || + (u.PhoneNumber != null && u.PhoneNumber.Contains(filter)) + ); + } } } From 5f412d860d20a818f48029bd73abedd10415ac8b Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Thu, 11 Jun 2020 10:02:28 +0800 Subject: [PATCH 46/81] Add unit test --- .../Identity/OrganizationUnitRepository_Tests.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/OrganizationUnitRepository_Tests.cs b/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/OrganizationUnitRepository_Tests.cs index 5ff0284194..0e6717f29c 100644 --- a/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/OrganizationUnitRepository_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/OrganizationUnitRepository_Tests.cs @@ -143,6 +143,19 @@ namespace Volo.Abp.Identity usersCount.ShouldBeGreaterThan(1); } + [Fact] + public async Task GetMembersCountOfOrganizationUnitWithParamsAsync() + { + OrganizationUnit ou = await _organizationUnitRepository.GetAsync("OU111", true); + var usersCount = await _organizationUnitRepository.GetMembersCountAsync(ou,"n"); + + usersCount.ShouldBeGreaterThan(1); + usersCount.ShouldBeLessThanOrEqualTo(5); + + usersCount = await _organizationUnitRepository.GetMembersCountAsync(ou,"undefined-username"); + usersCount.ShouldBe(0); + } + [Fact] public async Task GetRolesCountOfOrganizationUnit() { From d3169082d78a167728a40fb35dd9add31e838641 Mon Sep 17 00:00:00 2001 From: maliming <6908465+maliming@users.noreply.github.com> Date: Thu, 11 Jun 2020 16:29:24 +0800 Subject: [PATCH 47/81] Document the Azure BLOB storage integration. Resolve #4299 --- docs/en/Blob-Storing-Azure.md | 68 ++++++++++++++++++++++++++++++++++- 1 file changed, 67 insertions(+), 1 deletion(-) diff --git a/docs/en/Blob-Storing-Azure.md b/docs/en/Blob-Storing-Azure.md index 9bf912c0d2..fb173722c0 100644 --- a/docs/en/Blob-Storing-Azure.md +++ b/docs/en/Blob-Storing-Azure.md @@ -1,3 +1,69 @@ # BLOB Storing Azure Provider -This feature will be available with v3.0! \ No newline at end of file +BLOB Storing Azure Provider can store BLOBs in [Azure Blob storage](https://azure.microsoft.com/en-us/services/storage/blobs/). + +> Read the [BLOB Storing document](Blob-Storing.md) to understand how to use the BLOB storing system. This document only covers how to configure containers to use a database as the storage provider. + +## Installation + +You can use dotnet cli to install [the package](https://www.nuget.org/packages/Volo.Abp.BlobStoring.Azure). + +````bash +dotnet add package Volo.Abp.BlobStoring.Azure +```` + +After installation, add `DepenedsOn` attribute of the `AbpBlobStoringAzureModule` module to your [module](Module-Development-Basics.md). + +Whenever you add a NuGet package to a project, also add the module class dependency. + +### Configuring the Containers + +Configuration is done in the `ConfigureServices` method of your [module](Module-Development-Basics.md) class, as explained in the [BLOB Storing document](Blob-Storing.md). + +**Example: Configure to use the azure storage provider by default** + +````csharp +Configure(options => +{ + options.Containerscontainer.UseAzure(azure => + { + azure.ConnectionString = "your azure connection string"; + azure.ContainerName = "your azure container name"; + azure.CreateContainerIfNotExists = false; + }); +}); +```` + +> See the [BLOB Storing document](Blob-Storing.md) to learn how to configure this provider for a specific container. + +## Options + +* **ConnectionString** (string): A connection string includes the authorization information required for your application to access data in an Azure Storage account at runtime using Shared Key authorization. Please refer to Azure documentation: https://docs.microsoft.com/en-us/azure/storage/common/storage-configure-connection-string + +* **ContainerName** (string): You can specify the container name in azure. If it is not specified, the `ContainerName` of the `BlobProviderArgs` will be used. However, please note that Azure has some rules for naming containers. A container name must be a valid DNS name, conforming to the [following naming rules](https://docs.microsoft.com/en-us/rest/api/storageservices/naming-and-referencing-containers--blobs--and-metadata#container-names). + +* Container-names rules: + - Container names must start or end with a letter or number, and can contain only letters, numbers, and the dash (-) character. + - Every dash (-) character must be immediately preceded and followed by a letter or number; consecutive dashes are not permitted in container names. + - All letters in a container name must be lowercase. + - Container names must be from 3 through 63 characters long. + +* **CreateContainerIfNotExists** (bool): Default value is `false`, If a container does not exist in azure, `AzureBlobProvider` will try to create it. Please refer to the naming rules mentioned above. + + +## Azure Blob Name Calculator + +Azure Blob Provider organizes BLOB name and implements some conventions. The full name of a BLOB is determined by the following rules by default: + +* Appends `host` string if [current tenant](Multi-Tenancy.md) is `null` (or multi-tenancy is disabled for the container - see the [BLOB Storing document](Blob-Storing.md) to learn how to disable multi-tenancy for a container). +* Appends `tenants/` string if current tenant is not `null`. + +```csharp +var blobName = CurrentTenant.Id == null + ? $"host/{args.BlobName}" + : $"tenants/{CurrentTenant.Id.Value.ToString("D")}/{args.BlobName}"; +``` + +### Other Services + +* `AzureBlobProvider` is the main service that implements the Azure BLOB storage provider, if you want to override/replace it via [dependency injection](Dependency-Injection.md) (don't replace `IBlobProvider` interface, but replace `AzureBlobProvider` class). \ No newline at end of file From ab724699c8e239214dd1888b94319386c27ed444 Mon Sep 17 00:00:00 2001 From: maliming <6908465+maliming@users.noreply.github.com> Date: Thu, 11 Jun 2020 16:30:29 +0800 Subject: [PATCH 48/81] Update Blob-Storing-Azure.md --- docs/en/Blob-Storing-Azure.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/en/Blob-Storing-Azure.md b/docs/en/Blob-Storing-Azure.md index fb173722c0..edc0b58a8e 100644 --- a/docs/en/Blob-Storing-Azure.md +++ b/docs/en/Blob-Storing-Azure.md @@ -2,7 +2,7 @@ BLOB Storing Azure Provider can store BLOBs in [Azure Blob storage](https://azure.microsoft.com/en-us/services/storage/blobs/). -> Read the [BLOB Storing document](Blob-Storing.md) to understand how to use the BLOB storing system. This document only covers how to configure containers to use a database as the storage provider. +> Read the [BLOB Storing document](Blob-Storing.md) to understand how to use the BLOB storing system. This document only covers how to configure containers to use a Azure blob as the storage provider. ## Installation @@ -66,4 +66,4 @@ var blobName = CurrentTenant.Id == null ### Other Services -* `AzureBlobProvider` is the main service that implements the Azure BLOB storage provider, if you want to override/replace it via [dependency injection](Dependency-Injection.md) (don't replace `IBlobProvider` interface, but replace `AzureBlobProvider` class). \ No newline at end of file +* `AzureBlobProvider` is the main service that implements the Azure BLOB storage provider, if you want to override/replace it via [dependency injection](Dependency-Injection.md) (don't replace `IBlobProvider` interface, but replace `AzureBlobProvider` class). From f176159ae193b7e20b908f2c3902e7fce9a3e856 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Thu, 11 Jun 2020 14:04:32 +0300 Subject: [PATCH 49/81] #4312 Revise the BLOB Storage Azure Provider document. --- docs/en/Blob-Storing-Azure.md | 44 ++++++++++++++--------------------- 1 file changed, 17 insertions(+), 27 deletions(-) diff --git a/docs/en/Blob-Storing-Azure.md b/docs/en/Blob-Storing-Azure.md index edc0b58a8e..d43f8b3a43 100644 --- a/docs/en/Blob-Storing-Azure.md +++ b/docs/en/Blob-Storing-Azure.md @@ -2,21 +2,19 @@ BLOB Storing Azure Provider can store BLOBs in [Azure Blob storage](https://azure.microsoft.com/en-us/services/storage/blobs/). -> Read the [BLOB Storing document](Blob-Storing.md) to understand how to use the BLOB storing system. This document only covers how to configure containers to use a Azure blob as the storage provider. +> Read the [BLOB Storing document](Blob-Storing.md) to understand how to use the BLOB storing system. This document only covers how to configure containers to use a Azure BLOB as the storage provider. ## Installation -You can use dotnet cli to install [the package](https://www.nuget.org/packages/Volo.Abp.BlobStoring.Azure). +Use the ABP CLI to add [Volo.Abp.BlobStoring.Azure](https://www.nuget.org/packages/Volo.Abp.BlobStoring.Azure) NuGet package to your project: -````bash -dotnet add package Volo.Abp.BlobStoring.Azure -```` - -After installation, add `DepenedsOn` attribute of the `AbpBlobStoringAzureModule` module to your [module](Module-Development-Basics.md). +* Install the [ABP CLI](https://docs.abp.io/en/abp/latest/CLI) if you haven't installed before. +* Open a command line (terminal) in the directory of the `.csproj` file you want to add the `Volo.Abp.BlobStoring.Azure` package. +* Run `abp add-package Volo.Abp.BlobStoring.Azure` command. -Whenever you add a NuGet package to a project, also add the module class dependency. +If you want to do it manually, install the [Volo.Abp.BlobStoring.Azure](https://www.nuget.org/packages/Volo.Abp.BlobStoring.Azure) NuGet package to your project and add `[DependsOn(typeof(AbpBlobStoringAzureModule))]` to the [ABP module](Module-Development-Basics.md) class inside your project. -### Configuring the Containers +## Configuration Configuration is done in the `ConfigureServices` method of your [module](Module-Development-Basics.md) class, as explained in the [BLOB Storing document](Blob-Storing.md). @@ -36,19 +34,15 @@ Configure(options => > See the [BLOB Storing document](Blob-Storing.md) to learn how to configure this provider for a specific container. -## Options +### Options * **ConnectionString** (string): A connection string includes the authorization information required for your application to access data in an Azure Storage account at runtime using Shared Key authorization. Please refer to Azure documentation: https://docs.microsoft.com/en-us/azure/storage/common/storage-configure-connection-string - -* **ContainerName** (string): You can specify the container name in azure. If it is not specified, the `ContainerName` of the `BlobProviderArgs` will be used. However, please note that Azure has some rules for naming containers. A container name must be a valid DNS name, conforming to the [following naming rules](https://docs.microsoft.com/en-us/rest/api/storageservices/naming-and-referencing-containers--blobs--and-metadata#container-names). - -* Container-names rules: - - Container names must start or end with a letter or number, and can contain only letters, numbers, and the dash (-) character. - - Every dash (-) character must be immediately preceded and followed by a letter or number; consecutive dashes are not permitted in container names. - - All letters in a container name must be lowercase. - - Container names must be from 3 through 63 characters long. - -* **CreateContainerIfNotExists** (bool): Default value is `false`, If a container does not exist in azure, `AzureBlobProvider` will try to create it. Please refer to the naming rules mentioned above. +* **ContainerName** (string): You can specify the container name in azure. If this is not specified, it uses the name of the BLOB container defined with the `BlogContainerName` attribute (see the [BLOB storing document](Blob-Storing.md)). Please note that Azure has some **rules for naming containers**. A container name must be a valid DNS name, conforming to the [following naming rules](https://docs.microsoft.com/en-us/rest/api/storageservices/naming-and-referencing-containers--blobs--and-metadata#container-names): + * Container names must start or end with a letter or number, and can contain only letters, numbers, and the dash (-) character. + * Every dash (-) character must be immediately preceded and followed by a letter or number; consecutive dashes are not permitted in container names. + * All letters in a container name must be **lowercase**. + * Container names must be from **3** through **63** characters long. +* **CreateContainerIfNotExists** (bool): Default value is `false`, If a container does not exist in azure, `AzureBlobProvider` will try to create it. ## Azure Blob Name Calculator @@ -57,13 +51,9 @@ Azure Blob Provider organizes BLOB name and implements some conventions. The ful * Appends `host` string if [current tenant](Multi-Tenancy.md) is `null` (or multi-tenancy is disabled for the container - see the [BLOB Storing document](Blob-Storing.md) to learn how to disable multi-tenancy for a container). * Appends `tenants/` string if current tenant is not `null`. +* Appends the BLOB name. -```csharp -var blobName = CurrentTenant.Id == null - ? $"host/{args.BlobName}" - : $"tenants/{CurrentTenant.Id.Value.ToString("D")}/{args.BlobName}"; -``` - -### Other Services +## Other Services * `AzureBlobProvider` is the main service that implements the Azure BLOB storage provider, if you want to override/replace it via [dependency injection](Dependency-Injection.md) (don't replace `IBlobProvider` interface, but replace `AzureBlobProvider` class). +* `IAzureBlobNameCalculator` is used to calculate the full BLOB name (that is explained above). It is implemented by the `DefaultAzureBlobNameCalculator` by default. From cf8c0d0231e9c4e0b57cb909c5bc94a9fad91fde Mon Sep 17 00:00:00 2001 From: maliming <6908465+maliming@users.noreply.github.com> Date: Thu, 11 Jun 2020 22:55:38 +0800 Subject: [PATCH 50/81] Make WebRequestResources store resources according to the current request Path. Resolve #4309 --- .../TagHelpers/AbpTagHelperResourceService.cs | 5 +++- .../Mvc/UI/Resources/IWebRequestResources.cs | 2 +- .../Mvc/UI/Resources/WebRequestResources.cs | 28 +++++++++++++------ 3 files changed, 25 insertions(+), 10 deletions(-) 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 2971716b90..048da5e8df 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 @@ -73,7 +73,10 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling.TagHelpers throw new AbpException($"Could not find the bundle file '{bundleFile}' from {nameof(IWebContentFileProvider)}"); } - AddHtmlTag(viewContext, context, output, bundleFile + "?_v=" + file.LastModified.UtcTicks); + if (file.Length > 0) + { + AddHtmlTag(viewContext, context, output, bundleFile + "?_v=" + file.LastModified.UtcTicks); + } } stopwatch.Stop(); diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Resources/IWebRequestResources.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Resources/IWebRequestResources.cs index f18a759b21..a1a03a42cf 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Resources/IWebRequestResources.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Resources/IWebRequestResources.cs @@ -4,6 +4,6 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Resources { public interface IWebRequestResources { - List TryAdd(IEnumerable resources); + List TryAdd(List resources); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Resources/WebRequestResources.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Resources/WebRequestResources.cs index 8865095bc4..68bc42d6ad 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Resources/WebRequestResources.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Resources/WebRequestResources.cs @@ -1,23 +1,35 @@ using System.Collections.Generic; using System.Linq; +using Microsoft.AspNetCore.Http; using Volo.Abp.DependencyInjection; namespace Volo.Abp.AspNetCore.Mvc.UI.Resources { public class WebRequestResources : IWebRequestResources, IScopedDependency { - protected List Resources { get; } + protected Dictionary> Resources { get; } - public WebRequestResources() + protected IHttpContextAccessor HttpContextAccessor{ get; } + + public WebRequestResources(IHttpContextAccessor httpContextAccessor) { - Resources = new List(); + HttpContextAccessor = httpContextAccessor; + Resources = new Dictionary>(); } - public List TryAdd(IEnumerable resources) + public List TryAdd(List resources) { - var resourceToBeAdded = resources.Except(Resources).ToList(); - Resources.AddRange(resourceToBeAdded); - return resourceToBeAdded; + var path = HttpContextAccessor.HttpContext?.Request?.Path ?? ""; + + if (Resources.TryGetValue(path, out var res)) + { + var resourceToBeAdded = resources.Except(res).ToList(); + res.AddRange(resourceToBeAdded); + return resourceToBeAdded; + } + + Resources.Add(path, resources); + return resources; } } -} \ No newline at end of file +} From d34ee9c4d3c45309a0d86f77d12671d7b92390ce Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Thu, 11 Jun 2020 23:32:58 +0800 Subject: [PATCH 51/81] Translate BLOB storing system document --- docs/en/Blob-Storing-Custom-Provider.md | 2 +- docs/zh-Hans/Blob-Storing-Azure.md | 59 +++- docs/zh-Hans/Blob-Storing-Custom-Provider.md | 178 ++++++++++- docs/zh-Hans/Blob-Storing-Database.md | 94 ++++++ docs/zh-Hans/Blob-Storing-File-System.md | 59 +++- docs/zh-Hans/Blob-Storing.md | 307 ++++++++++++++++++- docs/zh-Hans/docs-nav.json | 10 +- 7 files changed, 699 insertions(+), 10 deletions(-) create mode 100644 docs/zh-Hans/Blob-Storing-Database.md diff --git a/docs/en/Blob-Storing-Custom-Provider.md b/docs/en/Blob-Storing-Custom-Provider.md index fc41973fdb..cb3364cd80 100644 --- a/docs/en/Blob-Storing-Custom-Provider.md +++ b/docs/en/Blob-Storing-Custom-Provider.md @@ -64,7 +64,7 @@ Configure(options => If you want to provide a simpler configuration, create an extension method for the `BlobContainerConfiguration` class: -```` +````csharp public static class MyBlobContainerConfigurationExtensions { public static BlobContainerConfiguration UseMyCustomBlobProvider( diff --git a/docs/zh-Hans/Blob-Storing-Azure.md b/docs/zh-Hans/Blob-Storing-Azure.md index cb82a640d5..892d299fc0 100644 --- a/docs/zh-Hans/Blob-Storing-Azure.md +++ b/docs/zh-Hans/Blob-Storing-Azure.md @@ -1 +1,58 @@ -TODO... \ No newline at end of file +# BLOB Storing Azure提供程序 + +BLOB存储Azure提供程序可以将BLOB存储在[Azure Blob storage](https://azure.microsoft.com/en-us/services/storage/blobs/)中. + +> 阅读[BLOB存储文档](Blob-Storing.md)了解如何使用BLOB存储系统. 本文档仅介绍如何为容器配置Azure提供程序. + +## 安装 + +使用ABP CLI添加[Volo.Abp.BlobStoring.Azure](https://www.nuget.org/packages/Volo.Abp.BlobStoring.Azure)NuGet包到你的项目: + +* 安装 [ABP CLI](https://docs.abp.io/en/abp/latest/CLI), 如果你还没有安装. +* 在要添加 `Volo.Abp.BlobStoring.Azure` 包的 `.csproj` 文件目录打开命令行. +* 运行 `Volo.Abp.BlobStoring.Azure` 命令. + +如果要手动安装,在你的项目中安装 `Volo.Abp.BlobStoring.Azure` NuGet包然后将`[DependsOn(typeof(AbpBlobStoringAzureModule))]`添加到项目内的[ABP模块](Module-Development-Basics.md)类中. + +## 配置 + +如同[BLOB存储文档](Blob-Storing.md)所述,配置是在[模块](Module-Development-Basics.md)类的 `ConfigureServices` 方法完成的. + +**示例: 配置为默认使用Azure存储提供程序** + +````csharp +Configure(options => +{ + options.Containerscontainer.UseAzure(azure => + { + azure.ConnectionString = "your azure connection string"; + azure.ContainerName = "your azure container name"; + azure.CreateContainerIfNotExists = false; + }); +}); +```` + +> 参阅[BLOB存储文档](Blob-Storing.md) 学习如何为指定容器配置提供程序. + +### 选项 + +* **ConnectionString** (string): 连接字符串包括应用程序在运行时使用共享密钥授权访问Azure存储帐户中的数据所需的授权信息. 请参考[Azure文档](https://docs.microsoft.com/en-us/azure/storage/common/storage-configure-connection-string). +* **ContainerName** (string): 你可以在azure中指定容器名称. 如果没有指定它将使用 `BlogContainerName` 属性定义的BLOB容器的名称(请参阅[BLOB存储文档](Blob-Storing.md)). 请注意Azure有一些**命名容器的规则**,容器名称必须是有效的DNS名称,[符合以下命名规则](https://docs.microsoft.com/en-us/rest/api/storageservices/naming-and-referencing-containers--blobs--and-metadata#container-names): + * 容器名称必须以字母或数字开头或结尾,并且只能包含字母,数字和破折号(-)字符. + * 每个破折号(-)必须紧跟在字母或数字之后;容器名称中不允许使用连续的破折号. + * 容器名称中的所有字母都必须**小写**. + * 容器名称的长度必须在**3**到**63**个字符之间. +* **CreateContainerIfNotExists** (bool): 默认值为 `false`, 如果azure中不存在容器, `AzureBlobProvider` 将尝试创建它. + +## Azure BLOB 名称计算器 + +Azure BLOB提供程序组织BLOB名称并实现一些约定. 默认情况下BLOB的全名由以下规则确定: + +* 如果当前租户为 `null`(或容器禁用多租户 - 请参阅[BLOB存储文档](Blob-Storing.md) 了解如何禁用容器的多租户),则追加 `host` 字符串. +* 如果当前租户不为 `null`,则追加 `tenants/` 字符串. +* 追加 BLOB 名称. + +## 其他服务 + +* `AzureBlobProvider` 是实现Azure BLOB存储提供程序的主要服务,如果你想要通过[依赖注入](Dependency-Injection.md)覆盖/替换它(不要替换 `IBlobProvider` 接口,而是替换 `AzureBlobProvider` 类). +* `IAzureBlobNameCalculator` 服务用于计算文件路径. 默认实现是 `DefaultAzureBlobNameCalculator` . 如果你想自定义文件路径计算,可以替换/覆盖它. diff --git a/docs/zh-Hans/Blob-Storing-Custom-Provider.md b/docs/zh-Hans/Blob-Storing-Custom-Provider.md index cb82a640d5..a7f43cd7a4 100644 --- a/docs/zh-Hans/Blob-Storing-Custom-Provider.md +++ b/docs/zh-Hans/Blob-Storing-Custom-Provider.md @@ -1 +1,177 @@ -TODO... \ No newline at end of file +# BLOB 存储: 创建自定义提供程序 + +本文档通过一个示例说明如何为BLOB存储系统创建新的存储提供程序. + +> 阅读[BLOB存储文档](Blob-Storing.md)了解如何使用BLOB存储系统. 本文档仅介绍如何创建新存储提供程序. + +## 示例实现 + +第一步是创建一个实现 `IBlobProvider` 接口或 `BlobProviderBase` 抽象类继承的类. + +````csharp +using System.IO; +using System.Threading.Tasks; +using Volo.Abp.BlobStoring; +using Volo.Abp.DependencyInjection; + +namespace AbpDemo +{ + public class MyCustomBlobProvider : BlobProviderBase, ITransientDependency + { + public override Task SaveAsync(BlobProviderSaveArgs args) + { + //TODO... + } + + public override Task DeleteAsync(BlobProviderDeleteArgs args) + { + //TODO... + } + + public override Task ExistsAsync(BlobProviderExistsArgs args) + { + //TODO... + } + + public override Task GetOrNullAsync(BlobProviderGetArgs args) + { + //TODO... + } + } +} +```` + +* `MyCustomBlobProvider` 继承 `BlobProviderBase` 并覆盖 `abstract` 方法. 实际的实现取决于你. +* 实现 `ITransientDependency` 接口将这个类注做为瞬态服务注册到[依赖注入](Dependency-Injection.md)系统. + +> **注意: 命名约定很重要**. 如果类名没有以 `BlobProvider` 结尾,则必须手动注册/公开你的服务为 `IBlobProvider`. + +这是所有. 现在你可以配置容器(在[模块](Module-Development-Basics.md)的 `ConfigureServices` 方法中)使用 `MyCustomBlobProvider` 类: + +````csharp +Configure(options => +{ + options.Containers.ConfigureDefault(container => + { + container.ProviderType = typeof(MyCustomBlobProvider); + }); +}); +```` + +> 如果你想配置特定的容器,请参阅[BLOB存储文档](Blob-Storing.md). + +### BlobContainerConfiguration 扩展方法 + +如果你想提供一个更简单的配置方式,可以为 `BlobContainerConfiguration` 类创建一个扩展方法: + +````csharp +public static class MyBlobContainerConfigurationExtensions +{ + public static BlobContainerConfiguration UseMyCustomBlobProvider( + this BlobContainerConfiguration containerConfiguration) + { + containerConfiguration.ProviderType = typeof(MyCustomBlobProvider); + return containerConfiguration; + } +} +```` + +然后你可以使用扩展方法更容易地配置容器: + +````csharp +Configure(options => +{ + options.Containers.ConfigureDefault(container => + { + container.UseMyCustomBlobProvider(); + }); +}); +```` + +### 额外的配置选项 + +`BlobContainerConfiguration` 允许添加/删除提供程序特定的配置对象. 如果你的提供者需要额外的配置,你可以为 `BlobContainerConfiguration` 创建一个包装类提供的类型安全配置选项: + +````csharp + public class MyCustomBlobProviderConfiguration + { + public string MyOption1 + { + get => _containerConfiguration + .GetConfiguration("MyCustomBlobProvider.MyOption1"); + set => _containerConfiguration + .SetConfiguration("MyCustomBlobProvider.MyOption1", value); + } + + private readonly BlobContainerConfiguration _containerConfiguration; + + public MyCustomBlobProviderConfiguration( + BlobContainerConfiguration containerConfiguration) + { + _containerConfiguration = containerConfiguration; + } + } +```` + +然后你可以这样更改 `MyBlobContainerConfigurationExtensions` 类: + +````csharp +public static class MyBlobContainerConfigurationExtensions +{ + public static BlobContainerConfiguration UseMyCustomBlobProvider( + this BlobContainerConfiguration containerConfiguration, + Action configureAction) + { + containerConfiguration.ProviderType = typeof(MyCustomBlobProvider); + + configureAction.Invoke( + new MyCustomBlobProviderConfiguration(containerConfiguration) + ); + + return containerConfiguration; + } + + public static MyCustomBlobProviderConfiguration GetMyCustomBlobProviderConfiguration( + this BlobContainerConfiguration containerConfiguration) + { + return new MyCustomBlobProviderConfiguration(containerConfiguration); + } +} +```` + +* 向 `UseMyCustomBlobProvider` 方法添加了一个参数,允许开发人员设置其他选项. +* 添加了一个新的 `GetMyCustomBlobProviderConfiguration` 方法,该方法将在 `MyCustomBlobProvider` 类内使用获取配置的值. + +然后任何人都可以如下设置 `MyOption1`: + +````csharp +Configure(options => +{ + options.Containers.ConfigureDefault(container => + { + container.UseMyCustomBlobProvider(provider => + { + provider.MyOption1 = "my value"; + }); + }); +}); +```` + +最后你可以使用 `GetMyCustomBlobProviderConfiguration` 方法访问额外的选项: + +````csharp +public class MyCustomBlobProvider : BlobProviderBase, ITransientDependency +{ + public override Task SaveAsync(BlobProviderSaveArgs args) + { + var config = args.Configuration.GetMyCustomBlobProviderConfiguration(); + var value = config.MyOption1; + + //... + } +} +```` + +## 贡献? + +如果你创建了一个新的提供程序,并且认为它对其他开发者有用,请考虑为GitHub上的ABP框架做出[贡献](Contribution/Index.md). \ No newline at end of file diff --git a/docs/zh-Hans/Blob-Storing-Database.md b/docs/zh-Hans/Blob-Storing-Database.md new file mode 100644 index 0000000000..653aa9f904 --- /dev/null +++ b/docs/zh-Hans/Blob-Storing-Database.md @@ -0,0 +1,94 @@ +# BLOB存储数据库提供程序 + +BLOB存储数据库提供程序可以将BLOB存储在关系或非关系数据库中. + +有两个数据库提供程序实现; + +* [Volo.Abp.BlobStoring.Database.EntityFrameworkCore](https://www.nuget.org/packages/Volo.Abp.BlobStoring.Database.EntityFrameworkCore) 包实现[EF Core](Entity-Framework-Core.md), 它可以通过EF Core存储BLOB在[任何支持的DBMS](https://docs.microsoft.com/en-us/ef/core/providers/)中. +* [Volo.Abp.BlobStoring.Database.MongoDB](https://www.nuget.org/packages/Volo.Abp.BlobStoring.Database.MongoDB) 包实现了[MongoDB](MongoDB.md). + +> 阅读[BLOB存储文档](Blob-Storing.md)了解如何使用BLOB存储系统. 本文档仅介绍如何为容器配置数据库提供程序. + +## 安装 + +### 自动安装 + +如果你已基于[应用程序启动模板](Startup-Templates/Application.md)创建了解决方案,则可以使用 `abp add-module` [CLI](CLI.md)命令将相关软件包自动添加到解决方案中. + +在包含解决方案(`.sln`)文件的文件夹中打开命令行运行以下命令: + +````bash +abp add-module Volo.Abp.BlobStoring.Database +```` + +此命令将所有NuGet软件包添加到解决方案的相应层. 如果使用的是EF Core,它会添加必要的配置,添加新的数据库迁移并更新数据库. + +### 手动安装 + +这里是此提供程序定义的所有包: + +* [Volo.Abp.BlobStoring.Database.Domain.Shared](https://www.nuget.org/packages/Volo.Abp.BlobStoring.Domain.Shared) +* [Volo.Abp.BlobStoring.Database.Domain](https://www.nuget.org/packages/Volo.Abp.BlobStoring.Database.Domain) +* [Volo.Abp.BlobStoring.Database.EntityFrameworkCore](https://www.nuget.org/packages/Volo.Abp.BlobStoring.Database.EntityFrameworkCore) +* [Volo.Abp.BlobStoring.Database.MongoDB](https://www.nuget.org/packages/Volo.Abp.BlobStoring.Database.MongoDB) + +你可以只安装 `Volo.Abp.BlobStoring.Database.EntityFrameworkCore` 或 `Volo.Abp.BlobStoring.Database.MongoDB` (根据你的偏好),因为它们依赖其他包. + +安装完成后,添加 `DepenedsOn` 属性到相关[模块](Module-Development-Basics.md).下面是由上面列出的相关NuGet包定义的模块类列表: + +* `BlobStoringDatabaseDomainModule` +* `BlobStoringDatabaseDomainSharedModule` +* `BlobStoringDatabaseEntityFrameworkCoreModule` +* `BlobStoringDatabaseMongoDbModule` + +如果你正在使用EF Core,还需要配置你的**Migration DbContext**将BLOB存储表添加到你的数据库. 在 `OnModelCreating` 方法中调用 `builder.ConfigureBlobStoring()` 扩展方法来包含到DbContext的映射. 你可以使用标准的 `Add-Migration` 和 `Update-Database` [命令](https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/)在数据库中创建必要的表. + +## 配置 + +### 连接字符串 + +如果你要使用你的 `Default` 连接字符串,则不需要做任何其他配置. + +如果要将BLOB存储到单独的数据库,请在配置文件(`appsettings.json`)中将 `AbpBlobStoring` 用作连接字符串名称. 请阅读[EF Core Migrations](Entity-Framework-Core-Migrations.md)文档了解如何为所需模块创建和使用其他数据库. + +### 配置容器 + +如同[BLOB存储文档](Blob-Storing.md)所述,配置是在[模块](Module-Development-Basics.md)类的 `ConfigureServices` 方法完成的. + +**示例: 配置为默认使用数据库系统存储提供程序** + +````csharp +Configure(options => +{ + options.Containers.ConfigureDefault(container => + { + container.UseDatabase(); + }); +}); +```` + +> 参阅[BLOB存储文档](Blob-Storing.md) 学习如何为指定容器配置提供程序. + +## 附加信息 + +它需要使用[BLOB存储服务](Blob-Storing.md)来使用BLOB存储系统. 但是如果要处理数据库表/实体,可以使用以下信息. + +### 实体 + +此模块定义的实体: + +* `DatabaseBlobContainer` (aggregate root) 表示存储在数据库中的容器. +* `DatabaseBlob` (aggregate root) 表示数据库中的BLOB. + +参阅[实体文档](Entities.md)了解什么是实体和聚合根. + +### 仓储 + +* `IDatabaseBlobContainerRepository` +* `IDatabaseBlobRepository` + +你还可以使用 `IRepository` 和 `IRepository` 来获得 `IQueryable` 能力. 更多信息请参阅[仓储文档](Repositories.md). + +### 其他服务 + +* `DatabaseBlobProvider` 是实现数据库BLOB存储提供程序的主要服务,如果你想要通过[依赖注入](Dependency-Injection.md)覆盖/替换它(不要替换 `IBlobProvider` 接口,而是替换 `DatabaseBlobProvider` 类). \ No newline at end of file diff --git a/docs/zh-Hans/Blob-Storing-File-System.md b/docs/zh-Hans/Blob-Storing-File-System.md index cb82a640d5..58c4bdb1d7 100644 --- a/docs/zh-Hans/Blob-Storing-File-System.md +++ b/docs/zh-Hans/Blob-Storing-File-System.md @@ -1 +1,58 @@ -TODO... \ No newline at end of file +# BLOB存储文件系统提供程序 + +文件系统存储提供程序用于将BLOB作为文件夹中的标准文件存储在本地文件系统中. + +> 阅读[BLOB存储文档](Blob-Storing.md)了解如何使用BLOB存储系统. 本文档仅介绍如何为容器配置文件系统. + +## 介绍 + +使用ABP CLI添加[Volo.Abp.BlobStoring.FileSystem](https://www.nuget.org/packages/Volo.Abp.BlobStoring.FileSystem)NuGet包到你的项目: + +* 安装 [ABP CLI](https://docs.abp.io/en/abp/latest/CLI), 如果你还没有安装. +* 在要添加 `Volo.Abp.BlobStoring.FileSystem` 包的 `.csproj` 文件目录打开命令行. +* 运行 `abp add-package Volo.Abp.BlobStoring.FileSystem` 命令. + +如果要手动安装,在你的项目中安装 `Volo.Abp.BlobStoring.FileSystem` NuGet包然后将`[DependsOn(typeof(AbpBlobStoringFileSystemModule))]`添加到项目内的[ABP模块](Module-Development-Basics.md)类中. + +## 配置 + +如同[BLOB存储文档](Blob-Storing.md)所述,配置是在[模块](Module-Development-Basics.md)类的 `ConfigureServices` 方法完成的. + +**示例: 配置为默认使用文件系统存储提供程序** + +````csharp +Configure(options => +{ + options.Containers.ConfigureDefault(container => + { + container.UseFileSystem(fileSystem => + { + fileSystem.BasePath = "C:\\my-files"; + }); + }); +}); +```` + +`UseFileSystem` 扩展方法用于为容器设置文件系统提供程序并配置文件系统选项. + +> 参阅[BLOB存储文档](Blob-Storing.md) 学习如何为指定容器配置提供程序. + +### 选项 + +* **BasePath** (string): 存储BLOB的基本文件夹路径,它是必选的. +* **AppendContainerNameToBasePath** (bool; 默认: `true`): 指定是否在基本文件夹中创建具有容器名称的文件夹. 如果你在同一个 `BaseFolder` 中存储多个容器,请将其保留为`true`. 如果你不喜欢不必要的更深层次的文件夹,你可以将它设置为 `false`. + +## 文件路径计算 + +文件系统提供程序在文件夹中组织BLOB文件并实现一些约定. 默认情况下,BLOB文件的完整路径由以下规则确定: + +* 它以如上所述配置的 `BasePath` 开始. +* 如果当前租户为 `null`(或容器禁用多租户 - 请参阅[BLOB存储文档](Blob-Storing.md) 了解如何禁用容器的多租户),则追加 `host` 文件夹. +* 如果当前租户不为 `null`,则追加 `tenants/` 文件夹. +* 如果 `AppendContainerNameToBasePath` 为`true`,则追加容器的名称. 如果容器名称包含 `/`,将导致文件夹嵌套. +* 追加BLOB名称,如果BLOB名称包含 `/` 它创建文件夹. 如果BLOB名称包含 `.` 它将有一个文件扩展名. + +## 扩展文件系统提供程序 + +* `FileSystemBlobProvider` 是实现文件系统存储的主要服务. 你可以从这个类继承并[覆盖](Customizing-Application-Modules-Overriding-Services.md)方法进行自定义. +* `IBlobFilePathCalculator` 服务用于计算文件路径. 默认实现是 `DefaultBlobFilePathCalculator` . 如果你想自定义文件路径计算,可以替换/覆盖它. \ No newline at end of file diff --git a/docs/zh-Hans/Blob-Storing.md b/docs/zh-Hans/Blob-Storing.md index cb82a640d5..788b104edb 100644 --- a/docs/zh-Hans/Blob-Storing.md +++ b/docs/zh-Hans/Blob-Storing.md @@ -1 +1,306 @@ -TODO... \ No newline at end of file +# BLOB 存储 + +通常将文件内容存储在应用程序中并根据需要读取这些文件内容. 不仅是文件你可能还需要将各种类型的[BLOB](https://en.wikipedia.org/wiki/Binary_large_object)(大型二进制对象)保存到存储中. 例如你可能要保存用户个人资料图片. + +BLOB通常是一个**字节数组**. 有很多地方可以存储BLOB项. 可以选择将其存储在本地文件系统中,共享数据库中或[Azure BLOB存储](https://azure.microsoft.com/zh-cn/services/storage/blobs/)中. + +ABP框架为BLOB提供了抽象,并提供了一些可以轻松集成到的预构建存储提供程序. 抽象有一些好处; + +* 你可以通过几行配置**轻松的集成**你喜欢的BLOB存储提供程序. +* 你可以**轻松的更改**BLOB存储,而不用改变你的应用程序代码. +* 如果你想创建**可重用的应用程序模块**,无需假设BLOB的存储方式. + +ABP BLOG存储系统兼容ABP框架其他功能,如[多租户](Multi-Tenancy.md). + +## BLOB 存储提供程序 + +ABP框架已经有以下存储提供程序的实现; + +* [File System](Blob-Storing-File-System.md):将BLOB作为标准文件存储在本地文件系统的文件夹中. +* [Database](Blob-Storing-Database.md): 将BLOB存储在数据库中. +* [Azure](Blob-Storing-Azure.md): 将BLOG存储在 [Azure BLOB storage](https://azure.microsoft.com/en-us/services/storage/blobs/)中. + +以后会实现更多的提供程序,你可以为自己喜欢的提供程序创建[请求](https://github.com/abpframework/abp/issues/new),或者你也可以[自己实现](Blob-Storing-Custom-Provider.md)它并[贡献](Contribution/Index.md)到ABP框架. + +可以在**容器系统**的帮助下一起**使用多个提供程序**,其中每个容器可以使用不同的提供程序. + +> 除非你**配置存储提供程序**否则BLOB存储系统无法工作. 有关存储提供程序配置请参考链接的文档. + +## 安装 + +[Volo.Abp.BlobStoring](https://www.nuget.org/packages/Volo.Abp.BlobStoring)是定义BLOB存储服务的主要包. 你可以用此包使用BLOB存储系统而不依赖特定存储提供程序. + +使用ABP CLI这个包添加到你的项目: + +* 安装 [ABP CLI](https://docs.abp.io/en/abp/latest/CLI), 如果你还没有安装. +* 在要添加 `Volo.Abp.BlobStoring` 包的 `.csproj` 文件目录打开命令行. +* 运行 `abp add-package Volo.Abp.BlobStoring` 命令. + +如果要手动安装,在你的项目中安装 `Volo.Abp.BlobStoring` NuGet包然后将`[DependsOn(typeof(AbpBlobStoringModule))]`添加到项目内的[ABP模块](Module-Development-Basics.md)类中. + +## IBlobContainer + +`IBlobContainer` 是存储和读取BLOB的主要接口. 应用程序可能有多个容器,每个容器都可以单独配置. 有一个**默认容器**可以通过注入 `IBlobContainer` 来简单使用. + +**示例: 简单地保存和读取命名BLOB的字节** + +````csharp +using System.Threading.Tasks; +using Volo.Abp.BlobStoring; +using Volo.Abp.DependencyInjection; + +namespace AbpDemo +{ + public class MyService : ITransientDependency + { + private readonly IBlobContainer _blobContainer; + + public MyService(IBlobContainer blobContainer) + { + _blobContainer = blobContainer; + } + + public async Task SaveBytesAsync(byte[] bytes) + { + await _blobContainer.SaveAsync("my-blob-1", bytes); + } + + public async Task GetBytesAsync() + { + return await _blobContainer.GetAllBytesOrNullAsync("my-blob-1"); + } + } +} +```` + +该服务用 `my-blob-1` 名称保存给定的字节,然后以相同的名称获取先前保存的字节. + +> 一个BLOB是一个命名对象,**每个BLOB都应该有一个唯一的名称**,它是一个任意的字符串. + +`IBlobContainer` 可以处理 `Stream` 和 `byte[]` 对象,在下一节中将详细介绍. + +### 保存 BLOB + +`SaveAsync` 方法用于保存新的或替换现有的BLOB. 默认情况下,它可以保存 `Stream`,但是有一个快捷的扩展方法来保存字节数组. + +`SaveAsync` 有以下参数: + +* **name** (string): 唯一的BLOB名称. +* **stream** (Stream) or **byte** (byte[]): 读取BLOB内容或字节数组的流. +* **overrideExisting** (bool): 设置为 `true`,如果BLOB内容已经存在,则替换它. 默认值为 `false`,则抛出 `BlobAlreadyExistsException` 异常. + +### 读取/获取 BLOB + +* `GetAsync`: 返回给定BLOB名称可用于读取BLOB内容的 `Stream` 对象. 使用后始终要**dispose流**. 如果找不到具有给定名称的BLOB,则抛出异常. +* `GetOrNullAsync`: 与 `GetAsync` 方法相反,如果未找到给定名称的BLOG,则返回 `null`. +* `GetAllBytesAsync`: 返回 `byte[]` 而不是 `Stream`. 如果找不到具有给定名称的BLOB,则抛出异常. +* `GetAllBytesOrNullAsync`: 与 `GetAllBytesAsync` 方法相反,如果未找到给定名称的BLOG,则返回 `null`. + +### 删除 BLOB + +`DeleteAsync` 使用给定BLOB名称删除BLOB数据. 如果找不到给定的BLOB不会引发任何异常. 相反如果你关心BLOB,它会返回一个 `bool`,表示BLOB实际上是否已删除. + +### 其他方法 + +* `ExistsAsync` 方法简单的检查容器中是否存在具有给定名称的BLOB. + +### 关于命名BLOB + +没有命名BLOB的规则. BLOB名称只是每个容器(和每个租户-参见"*多租户*"部分)唯一的字符串. 但是不同的存储提供程序可能会按惯例实施某些做法. 例如[文件系统提供程序](Blob-Storing-File-System.md)在BLOB名称中使用目录分隔符 (`/`) 和文件扩展名(如果BLOB名称为 `images/common/x.png` ,则在根容器文件夹下的 `images/common` 文件夹中存储 `x.png`). + +## 类型化 IBlobContainer + +类型化BLOB容器系统是一种在应用程序中创建和管理**多个容器**的方法; + +* **每个容器分别存储**. 这意味着BLOB名称在一个容器中应该是唯一的,两个具有相同名称的BLOB可以存在不同的容器中不会互相影响. +* **每个容器可以单独配置**,因此每个容器可以根据你的配置使用不同的存储提供程序. + +要创建类型化容器,需要创建一个简单的用 `BlobContainerName` 属性装饰的类: + +````csharp +using Volo.Abp.BlobStoring; + +namespace AbpDemo +{ + [BlobContainerName("profile-pictures")] + public class ProfilePictureContainer + { + + } +} +```` + +> 如果不使用 `BlobContainerName` attribute,ABP Framework将使用类的全名(带有名称空间),但是始终建议使用稳定的容器名称,即使重命名该类也不会被更改. + +创建容器类后,可以为容器类型注入 `IBlobContainer`. + +**示例: 用于保存和读取[当前用户](CurrentUser.md)的个人资料图片的[应用服务](Application-Services.md)** + +````csharp +[Authorize] +public class ProfileAppService : ApplicationService +{ + private readonly IBlobContainer _blobContainer; + + public ProfileAppService(IBlobContainer blobContainer) + { + _blobContainer = blobContainer; + } + + public async Task SaveProfilePictureAsync(byte[] bytes) + { + var blobName = CurrentUser.GetId().ToString(); + await _blobContainer.SaveAsync(blobName, bytes); + } + + public async Task GetProfilePictureAsync() + { + var blobName = CurrentUser.GetId().ToString(); + return await _blobContainer.GetAllBytesOrNullAsync(blobName); + } +} +```` + +`IBlobContainer` 有与 `IBlobContainer` 相同的方法. + +> 在开发可重复使用的模块时,**始终使用类型化的容器是一个好习惯**,这样最终的应用程序就可以为你的容器配置提供程序,而不会影响其他容器. + +### 默认容器 + +如果不使用泛型参数,直接注入 `IBlobContainer` (如上所述),会得到默认容器. 注入默认容器的另一种方法是使用 `IBlobContainer`,它返回完全相同的容器. + +默认容器的名称是 `Default`. + +### 命令容器 + +类型容器只是命名容器的快捷方式. 你可以注入并使用 `IBlobContainerFactory` 来获得一个BLOB容器的名称: + +````csharp +public class ProfileAppService : ApplicationService +{ + private readonly IBlobContainer _blobContainer; + + public ProfileAppService(IBlobContainerFactory blobContainerFactory) + { + _blobContainer = blobContainerFactory.Create("profile-pictures"); + } + + //... +} +```` + +## IBlobContainerFactory + +`IBlobContainerFactory` 是用于创建BLOB容器的服务. 上面提供了一个示例. + +**示例: 通过名称创建容器** + +````csharp +var blobContainer = blobContainerFactory.Create("profile-pictures"); +```` + +**示例: 通过类型创建容器** + +````csharp +var blobContainer = blobContainerFactory.Create(); +```` + +> 通常你不需要使用 `IBlobContainerFactory`, 因为在注入 `IBlobContainer` 或`IBlobContainer` 时会在内部使用它. + +## 配置容器 + +在使用容器之前应先对其进行配置. 最基本的配置是选择一个 **BLOB存储提供程序**(请参阅上面的"*BLOB存储提供程序*"部分). + +`AbpBlobStoringOptions` 是用于配置容器的[选项类](Options.md). 你可以在[模块](Module-Development-Basics.md)的 `ConfigureServices` 方法中配置选项. + +### 配置单个容器 + +````csharp +Configure(options => +{ + options.Containers.Configure(container => + { + //TODO... + }); +}); +```` + +这个例子配置 `ProfilePictureContainer`. 你还可以通过容器名称进行配置: + +````csharp +Configure(options => +{ + options.Containers.Configure("profile-pictures", container => + { + //TODO... + }); +}); +```` + +### 配置默认容器 + +````csharp +Configure(options => +{ + options.Containers.ConfigureDefault(container => + { + //TODO... + }); +}); +```` + +> 默认容器有一个特殊情况;如果不为容器指定配置,则**返回到默认容器配置**. 这是一种为所有容器配置默认值并在需要时专门针对特定容器进行配置的好方法. + +### 配置所有容器 + +````csharp +Configure(options => +{ + options.Containers.ConfigureAll((containerName, containerConfiguration) => + { + //TODO... + }); +}); +```` + +这是配置所有容器的方式. + +> 与配置默认容器的主要区别在于, `ConfigureAll` 会覆盖配置,即使它是专门为特定容器配置的. + +## 多租户 + + +如果你的应用程序是多租户的,BLOB存储系统可以**与[多租户](Multi-Tenancy.md)无缝协作**. 所有提供程序都将多租户实现为标准功能. 它们将不同租户的**BLOB彼此隔离**,因此它们只能访问自己的BLOB. 这意味着你可以**为不同的租户使用相同的BLOB名称**. + +如果应用程序是多租户的,则可能需要单独控制容器的**多租户行为**. 例如你可能希望**禁用特定容器的多租户**,这样容器中的BLOB将对**所有租户可用**. 这是在所有租户之间共享BLOB的一种方法. + +**示例: 禁用特定容器的多租户** + +````csharp +Configure(options => +{ + options.Containers.Configure(container => + { + container.IsMultiTenant = false; + }); +}); +```` + +> 如果你的应用程序不是多租户的,不用担心,它会正常工作. 你不需要配置 `IsMultiTenant` 选项. + +## 扩展BLOB存储系统 + +大多数时候除了创建定制的BLOB存储提供程序外,你不需要[自定义BLOB存储系统](Blob-Storing-Custom-Provider.md).但是如果需要,你可以替换任何服务(通过[依赖注入](Dependency-Injection.md)). 这里有一些上面没有提到的其他服务,但你可能想知道: + +* `IBlobProviderSelector` 用于通过容器名称获取 `IBlobProvider` 实例. 默认实现(`DefaultBlobProviderSelector`)使用配置选择提供程序. +* `IBlobContainerConfigurationProvider` 用于获取给定容器名称的`BlobContainerConfiguration`. 默认实现(`DefaultBlobContainerConfigurationProvider`)从上述 `AbpBlobStoringOptions` 获取配置. + +## BLOB 存储 vs 文件管理系统 + +注意BLOB存储不是一个文件管理系统. 它是一个用于保存,获取和删除命名BLOG的低级别系统. 它不提供目录那样的层次结构,这是典型文件系统所期望的. + +如果你想创建文件夹并在文件夹之间移动文件,为文件分配权限并在用户之间共享文件,那么你需要在BLOB存储系统上实现你自己的应用程序. + +## 另请参阅 + +* [创建自定义BLOB存储提供程序](Blob-Storing-Custom-Provider.md) \ No newline at end of file diff --git a/docs/zh-Hans/docs-nav.json b/docs/zh-Hans/docs-nav.json index 91e11119a9..2a2c66ebb6 100644 --- a/docs/zh-Hans/docs-nav.json +++ b/docs/zh-Hans/docs-nav.json @@ -189,22 +189,22 @@ "path": "Blob-Storing.md" }, { - "text": "存储提供者", + "text": "存储提供程序", "items": [ { - "text": "文件系统提供者", + "text": "文件系统提供程序", "path": "Blob-Storing-File-System.md" }, { - "text": "数据库系统提供者", + "text": "数据库系统提供程序", "path": "Blob-Storing-Database.md" }, { - "text": "Azure提供者", + "text": "Azure提供程序", "path": "Blob-Storing-Azure.md" }, { - "text": "创建自定义提供者", + "text": "创建自定义提供程序", "path": "Blob-Storing-Custom-Provider.md" } ] From 84721d9f15f33bd801fe1f3b4a854db99c0e722e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Thu, 11 Jun 2020 23:06:39 +0300 Subject: [PATCH 52/81] Add csharp language to the code block --- docs/en/Blob-Storing-Custom-Provider.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/en/Blob-Storing-Custom-Provider.md b/docs/en/Blob-Storing-Custom-Provider.md index fc41973fdb..0b1255e0b7 100644 --- a/docs/en/Blob-Storing-Custom-Provider.md +++ b/docs/en/Blob-Storing-Custom-Provider.md @@ -64,7 +64,7 @@ Configure(options => If you want to provide a simpler configuration, create an extension method for the `BlobContainerConfiguration` class: -```` +````csharp public static class MyBlobContainerConfigurationExtensions { public static BlobContainerConfiguration UseMyCustomBlobProvider( @@ -174,4 +174,4 @@ public class MyCustomBlobProvider : BlobProviderBase, ITransientDependency ## Contribute? -If you create a new provider and you think it can be useful for other developers, please consider to [contribute](Contribution/Index.md) to the ABP Framework on GitHub. \ No newline at end of file +If you create a new provider and you think it can be useful for other developers, please consider to [contribute](Contribution/Index.md) to the ABP Framework on GitHub. From 5835562aed3dc10e36a5baa7869d1ba75b315d13 Mon Sep 17 00:00:00 2001 From: Luis Pignataro Date: Thu, 11 Jun 2020 17:17:56 -0300 Subject: [PATCH 53/81] Update spanish traslations, addedd keys for v 2.9 --- .../src/Volo.Abp.UI/Localization/Resources/AbpUi/es.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/es.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/es.json index a7c511fe02..69ac5dfc56 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/es.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/es.json @@ -13,11 +13,13 @@ "DefaultErrorMessage404": "No se encontró el recurso!", "DefaultErrorMessage404Detail": "El recurso solicitado no se encontró en el servidor!", "EntityNotFoundErrorMessage": "No hay una entidad {0} con el id = {1}!", + "Languages": "Lenguajes", "Error": "Error", "AreYouSure": "¿Está seguro?", "Cancel": "Cancelar", "Yes": "Si", "No": "No", + "Ok": "Aceptar", "Close": "Cerrar", "Save": "Guardar", "SavingWithThreeDot": "Guardando...", @@ -25,6 +27,8 @@ "Delete": "Eliminar", "Edit": "Editar", "Refresh": "Refrescar", + "Language": "Lenguaje", + "LoadMore": "Cargar más", "ProcessingWithThreeDot": "Procesando...", "LoadingWithThreeDot": "Cargando...", "Welcome": "Bienvenido", @@ -57,4 +61,4 @@ "GoBack": "Atras", "Search": "Buscar" } -} +} \ No newline at end of file From b8b21d4b31a4db918c2c5011ac1c6d6c2ec49a3d Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Thu, 11 Jun 2020 23:31:52 +0300 Subject: [PATCH 54/81] chore: remove old unnecessary scripts --- .../scripts/install-new-dependencies.ts | 59 ------------------- npm/ng-packs/scripts/package.json | 5 +- npm/ng-packs/scripts/post-install.ts | 29 --------- npm/ng-packs/scripts/push.ts | 19 ------ npm/ng-packs/scripts/sync.ts | 37 ------------ 5 files changed, 1 insertion(+), 148 deletions(-) delete mode 100644 npm/ng-packs/scripts/install-new-dependencies.ts delete mode 100644 npm/ng-packs/scripts/post-install.ts delete mode 100644 npm/ng-packs/scripts/push.ts delete mode 100644 npm/ng-packs/scripts/sync.ts diff --git a/npm/ng-packs/scripts/install-new-dependencies.ts b/npm/ng-packs/scripts/install-new-dependencies.ts deleted file mode 100644 index 50dd0133c0..0000000000 --- a/npm/ng-packs/scripts/install-new-dependencies.ts +++ /dev/null @@ -1,59 +0,0 @@ -import execa from 'execa'; -import fse from 'fs-extra'; - -const updateAndInstall = async () => { - const { projects } = await fse.readJSON('../angular.json'); - const projectNames = Object.keys(projects).filter(project => project !== 'dev-app'); - - const packageJson = await fse.readJSON('../package.json'); - - projectNames.forEach(project => { - // do not convert to async - const { dependencies = {}, peerDependencies = {}, name, version } = fse.readJSONSync( - `../packages/${project}/package.json`, - ); - - packageJson.devDependencies = { - ...packageJson.devDependencies, - ...dependencies, - ...peerDependencies, - [name]: `~${version}`, - }; - - packageJson.devDependencies = Object.keys(packageJson.devDependencies) - .sort() - .reduce((acc, key) => ({ ...acc, [key]: packageJson.devDependencies[key] }), {}); - }); - - // tslint:disable-next-line: no-console - console.log('Searching the packages on NPM to check if it is exist. It takes a while.'); - Object.keys(packageJson.devDependencies).forEach(pkg => { - const isPackageExistOnNPM = !( - execa.sync('npm', ['search', pkg]).stdout.indexOf('No matches found for') > -1 - ); - - if (!isPackageExistOnNPM) delete packageJson.devDependencies[pkg]; - }); - - await fse.writeJSON('../package.json', packageJson, { spaces: 2 }); - - try { - await execa('yarn', ['install', '--ignore-scripts'], { - stdout: 'inherit', - cwd: '../', - }); - - await execa('yarn', ['post-install'], { - stdout: 'inherit', - }); - } catch (error) { - console.error(error.stderr); - process.exit(1); - } - - process.exit(0); -}; - -updateAndInstall(); - -export default updateAndInstall; diff --git a/npm/ng-packs/scripts/package.json b/npm/ng-packs/scripts/package.json index 9f2e047b7f..932abe4f64 100644 --- a/npm/ng-packs/scripts/package.json +++ b/npm/ng-packs/scripts/package.json @@ -7,10 +7,7 @@ "build": "ts-node -r tsconfig-paths/register build.ts", "build:prod": "ts-node -r tsconfig-paths/register prod-build.ts", "publish-packages": "ts-node -r tsconfig-paths/register publish.ts", - "install-new-dependencies": "ts-node -r tsconfig-paths/register install-new-dependencies.ts", - "post-install": "ts-node -r tsconfig-paths/register post-install.ts", - "replace-with-tilde": "ts-node -r tsconfig-paths/register replace-with-tilde.ts", - "sync": "ts-node -r tsconfig-paths/register sync.ts" + "replace-with-tilde": "ts-node -r tsconfig-paths/register replace-with-tilde.ts" }, "author": "", "dependencies": { diff --git a/npm/ng-packs/scripts/post-install.ts b/npm/ng-packs/scripts/post-install.ts deleted file mode 100644 index 1d3e6a9f50..0000000000 --- a/npm/ng-packs/scripts/post-install.ts +++ /dev/null @@ -1,29 +0,0 @@ -import execa from 'execa'; -import fse from 'fs-extra'; - -(async () => { - rename(true); - - try { - await execa('yarn', ['ngcc'], { - stdout: 'inherit', - cwd: '../', - }); - } catch (error) { - rename(false); - console.error(error); - process.exit(1); - } - - rename(false); -})(); - -async function rename(prodToMain: boolean) { - try { - await fse.rename('../tsconfig.json', `../tsconfig.${prodToMain ? 'temp' : 'prod'}.json`); - await fse.rename(`../tsconfig.${prodToMain ? 'prod' : 'temp'}.json`, '../tsconfig.json'); - } catch (error) { - console.error(error); - process.exit(1); - } -} diff --git a/npm/ng-packs/scripts/push.ts b/npm/ng-packs/scripts/push.ts deleted file mode 100644 index 6c41b0b697..0000000000 --- a/npm/ng-packs/scripts/push.ts +++ /dev/null @@ -1,19 +0,0 @@ -const Confirm = require('prompt-confirm'); -const execa = require('execa'); - -(async () => { - const answer = await new Confirm('Would you like to push?').run().then(answer => answer); - - const remote = execa.sync('git', ['remote']).stdout; - const branch = execa.sync('git', ['rev-parse', '--abbrev-ref', 'HEAD']).stdout; - - if (answer) { - try { - await execa('git', ['push', remote, branch], { stdout: 'inherit' }); - await execa('git', ['fetch', remote], { stdout: 'inherit' }); - console.log('Successfully!'); - } catch (error) { - console.log('An error occured.' + error); - } - } -})(); diff --git a/npm/ng-packs/scripts/sync.ts b/npm/ng-packs/scripts/sync.ts deleted file mode 100644 index 60615a1027..0000000000 --- a/npm/ng-packs/scripts/sync.ts +++ /dev/null @@ -1,37 +0,0 @@ -import fse from 'fs-extra'; -import execa from 'execa'; - -(async () => { - const { projects } = await fse.readJSON('../angular.json'); - const projectNames = Object.keys(projects).filter(project => project !== 'dev-app'); - - for (let i = 0; i < projectNames.length; i++) { - const project = projectNames[i]; - const { dependencies: distDependencies, version } = await fse.readJson( - `../dist/${project}/package.json`, - ); - const srcPackagePath = `../packages/${project}/package.json`; - const srcPackage = await fse.readJson(srcPackagePath); - - if (distDependencies) { - for (const key in srcPackage.dependencies) { - if (distDependencies.hasOwnProperty(key)) { - srcPackage.dependencies[key] = distDependencies[key]; - } - } - } - - await fse.writeJson(srcPackagePath, { ...srcPackage, version }, { spaces: 2 }); - } - - try { - await execa('git', ['add', '../packages/*', '../package.json'], { stdout: 'inherit' }); - await execa('git', ['commit', '-m', 'Update source packages versions', '--no-verify'], { - stdout: 'inherit', - }); - } catch (error) { - console.error(error.stderr); - } - - process.exit(0); -})(); From 9cfd74a344eca725824ea859d3853e64ae4bc76e Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Thu, 11 Jun 2020 23:32:33 +0300 Subject: [PATCH 55/81] fix: ngcc compiling problem --- npm/ng-packs/angular.json | 3 +- npm/ng-packs/package.json | 6 +- npm/ng-packs/scripts/build.ts | 4 +- npm/ng-packs/scripts/publish.ts | 2 +- npm/ng-packs/yarn.lock | 466 +++++++++++++++++++------------- 5 files changed, 286 insertions(+), 195 deletions(-) diff --git a/npm/ng-packs/angular.json b/npm/ng-packs/angular.json index 7601119eca..87948c6f14 100644 --- a/npm/ng-packs/angular.json +++ b/npm/ng-packs/angular.json @@ -493,7 +493,7 @@ "index": "apps/dev-app/src/index.html", "main": "apps/dev-app/src/main.ts", "polyfills": "apps/dev-app/src/polyfills.ts", - "tsConfig": "apps/dev-app/tsconfig.prod.json", + "tsConfig": "apps/dev-app/tsconfig.dev.json", "aot": true, "extractCss": true, "assets": ["apps/dev-app/src/favicon.ico", "apps/dev-app/src/assets"], @@ -538,6 +538,7 @@ "scripts": [] }, "configurations": { + "tsConfig": "apps/dev-app/tsconfig.prod.json", "production": { "fileReplacements": [ { diff --git a/npm/ng-packs/package.json b/npm/ng-packs/package.json index 5653ef5446..e42cf9ecc2 100644 --- a/npm/ng-packs/package.json +++ b/npm/ng-packs/package.json @@ -14,13 +14,13 @@ "commit": "git-cz", "lint": "ng lint", "scripts:build": "cd scripts && yarn && yarn build", - "prepare:workspace": "yarn scripts:build", + "prepare:workspace": "yarn scripts:build --noInstall", "ci": "yarn ng lint && yarn prepare:workspace && yarn ci:test && yarn ci:build", "ci:test": "ng test --coverage=false", "ci:build": "cd scripts && yarn build:prod", "lerna": "lerna", - "postinstall": "cd scripts && npm install && npm run post-install", - "generate:changelog": "conventional-changelog -p angular -i CHANGELOG.md -s" + "compile:ivy": "ngcc --properties es2015 browser module main --first-only --create-ivy-entry-points --tsconfig './tsconfig.prod.json'", + "postinstall": "npm run compile:ivy" }, "devDependencies": { "@abp/ng.account": "~2.9.0", diff --git a/npm/ng-packs/scripts/build.ts b/npm/ng-packs/scripts/build.ts index 5e72245bd6..e458b8285c 100644 --- a/npm/ng-packs/scripts/build.ts +++ b/npm/ng-packs/scripts/build.ts @@ -8,7 +8,7 @@ import program from 'commander'; try { if (!program.noInstall) { - await execa('yarn', ['install-new-dependencies'], { stdout: 'inherit' }); + await execa('yarn', ['install'], { stdout: 'inherit', cwd: '../' }); } await execa( @@ -54,6 +54,8 @@ import program from 'commander'; ], { stdout: 'inherit', cwd: '../' }, ); + + await execa('yarn', ['compile:ivy'], { stdout: 'inherit', cwd: '../' }); } catch (error) { console.error(error.stderr); process.exit(1); diff --git a/npm/ng-packs/scripts/publish.ts b/npm/ng-packs/scripts/publish.ts index 21f750b27e..f32afce7f7 100644 --- a/npm/ng-packs/scripts/publish.ts +++ b/npm/ng-packs/scripts/publish.ts @@ -22,7 +22,7 @@ const publish = async () => { const registry = program.preview ? 'http://localhost:4873' : 'https://registry.npmjs.org'; try { - await execa('yarn', ['install-new-dependencies'], { stdout: 'inherit' }); + await execa('yarn', ['install'], { stdout: 'inherit', cwd: '../' }); await fse.rename('../lerna.version.json', '../lerna.json'); diff --git a/npm/ng-packs/yarn.lock b/npm/ng-packs/yarn.lock index 2193f0236c..bdfcea9f74 100644 --- a/npm/ng-packs/yarn.lock +++ b/npm/ng-packs/yarn.lock @@ -139,29 +139,29 @@ jest-preset-angular "^8.1.2" lodash "^4.17.10" -"@angular-devkit/architect@0.901.7", "@angular-devkit/architect@>=0.900.0 < 0.1000.0": - version "0.901.7" - resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.901.7.tgz#6a09cb076ca92b3202053fca757a456d1f8e4395" - integrity sha512-yW/PUEqle55QihOFbmeNXaVTodhfeXkteoFDUpz+YpX3xiQDXDtNbIJSzKOQTojtBKdSMKMvZkQLr+RAa7/1EA== +"@angular-devkit/architect@0.901.8", "@angular-devkit/architect@>=0.900.0 < 0.1000.0": + version "0.901.8" + resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.901.8.tgz#d2f5f4c16fba3ed61ee27c7fc72118421ea2b45d" + integrity sha512-tK9ZQlubH6n+q+c2J9Wvfcxg3RFuRiTfJriNoodo6GHvtF2KLdPY67w3Gen0Sp172A5Q8Y927NseddNI8RZ/0A== dependencies: - "@angular-devkit/core" "9.1.7" + "@angular-devkit/core" "9.1.8" rxjs "6.5.4" "@angular-devkit/build-angular@~0.901.7": - version "0.901.7" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-angular/-/build-angular-0.901.7.tgz#10d55e3c73213971ba7d733f15d66494dfe9918a" - integrity sha512-NiBwapx/XJqYGzSmENff78i6Yif9PjYDJ9BB+59t2eDofkCZUcPFrhQmRgliO7rt6RATvT81lDP89+LBXCTQPw== - dependencies: - "@angular-devkit/architect" "0.901.7" - "@angular-devkit/build-optimizer" "0.901.7" - "@angular-devkit/build-webpack" "0.901.7" - "@angular-devkit/core" "9.1.7" + version "0.901.8" + resolved "https://registry.yarnpkg.com/@angular-devkit/build-angular/-/build-angular-0.901.8.tgz#6450be4743dacf564af143c85d2a03b7bdd81551" + integrity sha512-W2RTjtPPJRbke6K7Qt9eZOPRGfFBFsYzskxsuxXwkW2RPopj6k1wUWh9Be8CtAMAUlhyPvlzviOtv3F7leYr3w== + dependencies: + "@angular-devkit/architect" "0.901.8" + "@angular-devkit/build-optimizer" "0.901.8" + "@angular-devkit/build-webpack" "0.901.8" + "@angular-devkit/core" "9.1.8" "@babel/core" "7.9.0" "@babel/generator" "7.9.3" "@babel/preset-env" "7.9.0" "@babel/template" "7.8.6" "@jsdevtools/coverage-istanbul-loader" "3.0.3" - "@ngtools/webpack" "9.1.7" + "@ngtools/webpack" "9.1.8" ajv "6.12.0" autoprefixer "9.7.4" babel-loader "8.0.6" @@ -169,7 +169,7 @@ cacache "15.0.0" caniuse-lite "^1.0.30001032" circular-dependency-plugin "5.2.0" - copy-webpack-plugin "5.1.1" + copy-webpack-plugin "6.0.2" core-js "3.6.4" css-loader "3.5.1" cssnano "4.1.10" @@ -178,7 +178,7 @@ glob "7.1.6" jest-worker "25.1.0" karma-source-map-support "1.4.0" - less "3.11.1" + less "3.11.3" less-loader "5.0.0" license-webpack-plugin "2.1.4" loader-utils "2.0.0" @@ -215,17 +215,17 @@ worker-plugin "4.0.3" "@angular-devkit/build-ng-packagr@~0.901.7": - version "0.901.7" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-ng-packagr/-/build-ng-packagr-0.901.7.tgz#d8bce9c67cba4299f6c4a5bdd13840bc39ed0f58" - integrity sha512-HJ6nzXIUyI8yUuXGtdk26qDgLzlmfSwsSuc8JWdeqieP82fz/qokf78vVAqyHyJ9gi90IZiPO2+oh6Ot6UMo+g== + version "0.901.8" + resolved "https://registry.yarnpkg.com/@angular-devkit/build-ng-packagr/-/build-ng-packagr-0.901.8.tgz#7a8fee590f0898451c98da410ff36edc160912d9" + integrity sha512-7a419fmAq+uYunVEBm79MncqOvmprH+6QmGXkORYPAKZ+p5wWdu84AM1aKK/l0UaZ335ErxexpEVnbvSVtVc1Q== dependencies: - "@angular-devkit/architect" "0.901.7" + "@angular-devkit/architect" "0.901.8" rxjs "6.5.4" -"@angular-devkit/build-optimizer@0.901.7": - version "0.901.7" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-optimizer/-/build-optimizer-0.901.7.tgz#e72fc3031207a78aee175a76d3317cdf226984e9" - integrity sha512-Xuce3StdxhcgLYb0BAaFGr3Bzj5EM2OsAqIT15PkikWY1k5cK50vPxoC/BkX4QDL9eXSHtqAfMBfA6h5N422vw== +"@angular-devkit/build-optimizer@0.901.8": + version "0.901.8" + resolved "https://registry.yarnpkg.com/@angular-devkit/build-optimizer/-/build-optimizer-0.901.8.tgz#55a6cecf9b963bac15f84b5db8ec211c82119954" + integrity sha512-k9DynuWKMsJk5xg+LthdsqmOlGVMVP/TEu2odiVty9gnTVlIjs1bUzs+HNAF/w11juIBcVKa690K+FkSCalo9w== dependencies: loader-utils "2.0.0" source-map "0.7.3" @@ -233,13 +233,13 @@ typescript "3.6.5" webpack-sources "1.4.3" -"@angular-devkit/build-webpack@0.901.7": - version "0.901.7" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-webpack/-/build-webpack-0.901.7.tgz#6d93c38756540a02e67d2c3ccfac4220c62962de" - integrity sha512-pTLW5Eqy9cHgv78LKiH0e30lxqKzUPjh1djvNtFsEemOHsfKQdAfjLjikoaQvqMoBKVaUU7r2vmyyS17cH+1yw== +"@angular-devkit/build-webpack@0.901.8": + version "0.901.8" + resolved "https://registry.yarnpkg.com/@angular-devkit/build-webpack/-/build-webpack-0.901.8.tgz#19fbac49c3f60c16d6814d61e518431503ab746a" + integrity sha512-OyLfPI0yo1Qg4I1QP8ZxEYVxrf3IDjGfpxlKXqSChpEy5m/uZmBIRDZ/n/G3+32xFc6MWEdU4EHfRrfn17ae/w== dependencies: - "@angular-devkit/architect" "0.901.7" - "@angular-devkit/core" "9.1.7" + "@angular-devkit/architect" "0.901.8" + "@angular-devkit/core" "9.1.8" rxjs "6.5.4" "@angular-devkit/core@7.3.10", "@angular-devkit/core@^7.3.6": @@ -253,10 +253,10 @@ rxjs "6.3.3" source-map "0.7.3" -"@angular-devkit/core@8.3.26", "@angular-devkit/core@^8.0.3": - version "8.3.26" - resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-8.3.26.tgz#a331f02603a64fe53b9527b07e04ee18c798b9a6" - integrity sha512-b1ng9091o33s55/cwQYh1kboiJtj8y8z8xQWATDI9kRmNIQkWYVwVa/MzgPRJ4bzbEGG3zIUHCsp52A6vuGr2A== +"@angular-devkit/core@8.3.27", "@angular-devkit/core@^8.0.3": + version "8.3.27" + resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-8.3.27.tgz#d99e797bb0c8be643f01c707fdb3904ab347b106" + integrity sha512-Mf2u86mIMqCEbbhaN74r4lvMb4nKgAZIQo3s/GQIfKkGaGYvxmiQHkltdVvSR+fgaQ0CMh4ARI0uefmzQyUsAA== dependencies: ajv "6.10.2" fast-json-stable-stringify "2.0.0" @@ -264,10 +264,10 @@ rxjs "6.4.0" source-map "0.7.3" -"@angular-devkit/core@9.1.7", "@angular-devkit/core@^9.0.0": - version "9.1.7" - resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-9.1.7.tgz#f193ccbae4c80b34188bc9cc401c16b3ced50339" - integrity sha512-guvolu9Cl+qYMTtedLZD9wCqustJjdqzJ2psD2C1Sr1LrX9T0mprmDldR/YnhsitThveJEb6sM/0EvqWxoSvKw== +"@angular-devkit/core@9.1.8", "@angular-devkit/core@^9.0.0": + version "9.1.8" + resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-9.1.8.tgz#7c517a14e3ddfd180858972d9f1836aa90a1248e" + integrity sha512-4k1pZwje2oh5c/ULg7pnCBzTstx3l3uF7O5tQq/KXomDDsam97IhLm6cKUqQpaoyC1NUsBV6xJARJ0PyUP5TPQ== dependencies: ajv "6.12.0" fast-json-stable-stringify "2.1.0" @@ -275,12 +275,12 @@ rxjs "6.5.4" source-map "0.7.3" -"@angular-devkit/schematics@9.1.7": - version "9.1.7" - resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-9.1.7.tgz#45394a1c928db449b412dacf205c3ec78fb5ef0c" - integrity sha512-oeHPJePBcPp/bd94jHQeFUnft93PGF5iJiKV9szxqS8WWC5OMZ5eK7icRY0PwvLyfenspAZxdZcNaqJqPMul5A== +"@angular-devkit/schematics@9.1.8": + version "9.1.8" + resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-9.1.8.tgz#8eeea0b6f9702a5b065f909cdcaf1d35cc8e2fa3" + integrity sha512-/8L5J4X6SkcFMRmrSQHvJWOPilrMWTNlv1lD+1z06D3xGJEktVxXM3gCUXhDrbMvpoi+lYtR2Fuia0E6zvyjCQ== dependencies: - "@angular-devkit/core" "9.1.7" + "@angular-devkit/core" "9.1.8" ora "4.0.3" rxjs "6.5.4" @@ -293,28 +293,28 @@ rxjs "6.3.3" "@angular-devkit/schematics@^8.0.6": - version "8.3.26" - resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-8.3.26.tgz#91fcea47279a09d7504051bec17277c07f16e03b" - integrity sha512-IoZbXVFGLvVi5d0ozfssWDXuzot0/pMSKbQPzWIG8K7nCo7nNMVYpsMHrEVYUikA9EQEL5LqMCGohH36/zVPcA== + version "8.3.27" + resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-8.3.27.tgz#1e2c720cd464a14ec65a963025e7eb0d980eda33" + integrity sha512-SGh/yubOPT7jFZTfTyBLJqYUUBYU6pcTY3ifKVoa1JG28GegKSycusCMeX19gEY7awKYIuxR9WJeGgV6evSQPA== dependencies: - "@angular-devkit/core" "8.3.26" + "@angular-devkit/core" "8.3.27" rxjs "6.4.0" "@angular/animations@~9.1.9": - version "9.1.10" - resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-9.1.10.tgz#c0f0b7e30dbe95ef8edd62e5d6c2ea3224d76966" - integrity sha512-xuiL2iE8vka3IZpvwnOYDhfKKn9xKB+qyn7mcWzr6xnFP3UPfxN/1HuDJYgtwd+KXtTZmzlsm8orh+DZ3MGxbA== + version "9.1.11" + resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-9.1.11.tgz#2c7b6e584df0ba0884d05f01fa7ab86c1fdd1c5e" + integrity sha512-VKAExUnEJfo1PDQKagpx2pn+QMZCsPLRiADzTdl4U0VPylK3ALbn4ZNY9UbdwyE2plitz++LkH7sEGGfh+PNrQ== "@angular/cli@~9.1.7": - version "9.1.7" - resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-9.1.7.tgz#0532b9c55d267cd6ee3edb79fec8b19c4e64e607" - integrity sha512-NhsIa725S/U/n7nDxp6ForusdYHEXF4aSIvsFRdoK6vbQ889c5e1Rdj+T5EWXLmpQZxeprSKhLI2alNX0nVhhQ== - dependencies: - "@angular-devkit/architect" "0.901.7" - "@angular-devkit/core" "9.1.7" - "@angular-devkit/schematics" "9.1.7" - "@schematics/angular" "9.1.7" - "@schematics/update" "0.901.7" + version "9.1.8" + resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-9.1.8.tgz#fd143e26c913ccea5b8ac1716e1c168432ac96d3" + integrity sha512-yfF7glPo3Xm7fTJVln1bFZVXqHu8wkIGZRZGb6lsJa+QH4ePxHgn+dNYXho0MYpGUnhY7xOBW4MJzjS7E+1y5Q== + dependencies: + "@angular-devkit/architect" "0.901.8" + "@angular-devkit/core" "9.1.8" + "@angular-devkit/schematics" "9.1.8" + "@schematics/angular" "9.1.8" + "@schematics/update" "0.901.8" "@yarnpkg/lockfile" "1.1.0" ansi-colors "4.1.1" debug "4.1.1" @@ -332,14 +332,14 @@ uuid "7.0.2" "@angular/common@~9.1.9": - version "9.1.10" - resolved "https://registry.yarnpkg.com/@angular/common/-/common-9.1.10.tgz#34c36f9b889ec009c5a4aa1628acb4e002a4e280" - integrity sha512-qX7ZUIwRkQi/kO6aKmpa8iGdkLXfe+80D+svC02x5PvafdQAcuBlUQQkrr1XapBqYE/Nu2GK0yYmvpa2CzxjPQ== + version "9.1.11" + resolved "https://registry.yarnpkg.com/@angular/common/-/common-9.1.11.tgz#1323f7b043410791bd2d0d71b0bbb1f862319c04" + integrity sha512-Vh5lF7zWwDK9RedmYXUc8vUXyrecR3j1mAWlTlnmcHYxxFThPzN/dr0slQcPi6nyJn0EmyRKUGvAoZx4rIb7wg== "@angular/compiler-cli@~9.1.9": - version "9.1.10" - resolved "https://registry.yarnpkg.com/@angular/compiler-cli/-/compiler-cli-9.1.10.tgz#4ad54e9df3f0b00bc53493a2247ca4d22d67fdb0" - integrity sha512-D2JYI9GHzybG/NJ03aCd+95mSz+f4UhgDZ1c0GbYlsNLvk1B0UrDrmgGv0gOdP9yW1XxQjW3ldZAqpVurYru3Q== + version "9.1.11" + resolved "https://registry.yarnpkg.com/@angular/compiler-cli/-/compiler-cli-9.1.11.tgz#39da68ddadb52008fe5231141707bddd3aa790b2" + integrity sha512-9qIxbtpRXOQnRm6inxCa5HuH87MSuMzuceD0YBVzl8v+vLtewon9KXYMmF4kTBhWa/LEa8FrajljLh0azf3VLg== dependencies: canonical-path "1.0.0" chokidar "^3.0.0" @@ -355,48 +355,48 @@ yargs "15.3.0" "@angular/compiler@~9.1.9": - version "9.1.10" - resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-9.1.10.tgz#2e43cb51203e18faf3673244a78946d7a7194041" - integrity sha512-VlyTVK9elvtKGXxrkW9BWfKYRfeqXVLR3erukv03vy9u/pZppkG1xJ32SgAPKzYckGRV3kKHP6B7ZOXWMb9cog== + version "9.1.11" + resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-9.1.11.tgz#4c7100f53c87f47e793e149427b8bdee44302381" + integrity sha512-MbVheCG0U8gt6xtiipau20N26mD2sXjLChVmRKgO6rbDruxboNMZfEd94q9NP9JRaUsVnjXvY7GMDldoymdXig== "@angular/core@~9.1.9": - version "9.1.10" - resolved "https://registry.yarnpkg.com/@angular/core/-/core-9.1.10.tgz#cb9c99cd99a61cc55337220cafac005332ff9fdf" - integrity sha512-pp8g0razdSi3HzSBHRzBdn5WmnVJZ5IF+sWuApvplnl4edBO0CFdZAKALmRgjctRD9y9aVPXhkEi17Spiip9aA== + version "9.1.11" + resolved "https://registry.yarnpkg.com/@angular/core/-/core-9.1.11.tgz#7a92d27292212ed381be15f9000d4019867f1c7c" + integrity sha512-KAlEedBo761O1aeoTJVziOSHi8Fttk9ipvbDZXYT/o0W/KdVwubxP34g9t5aD8LCcF8+L0z4VLw++HjdJAUpwg== "@angular/forms@~9.1.9": - version "9.1.10" - resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-9.1.10.tgz#74da1653581bb5021015cf76fa04316a627376e6" - integrity sha512-Qp/tO3bayvP3lkpuMe2oWGBhATd39Vd9z9z/LIWtM+PkEZCZ0xCh0d6AiKrO9sc1vDATCi4SKxEnNCkmPBWOuQ== + version "9.1.11" + resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-9.1.11.tgz#fa246144649236613598a0471aa7f39b60f986b5" + integrity sha512-t4WHrh6ot1r8zdV+3fJz7g9rCok77c9CiIevhH2dR/idxD+HtFR0wqmcBQzsn+rNVB0f0TiSHDrj+TeELIFyWw== "@angular/language-service@~9.1.9": - version "9.1.10" - resolved "https://registry.yarnpkg.com/@angular/language-service/-/language-service-9.1.10.tgz#515abfaf79ae9c1ab2649c48201dcd4aae4b7c74" - integrity sha512-rj+otf/uPRhEH4L3kDX13RouKg5YT0uc/CbBlgwTbEX9kOOBGxvHxoUxPT8rysBjHuLubBd2mQozZofj/IYa8Q== + version "9.1.11" + resolved "https://registry.yarnpkg.com/@angular/language-service/-/language-service-9.1.11.tgz#a2afed4f0167e6f4d3d748214b8e1c27980703ce" + integrity sha512-jfm4etbqldj6MTwECwyoAs7tXEAR8K/8P8dBZnsELhY+V8oFidTJI3NY52PB3Ym7leSPorYdOAeUMMuQfPaVxg== "@angular/localize@~9.1.0", "@angular/localize@~9.1.9": - version "9.1.10" - resolved "https://registry.yarnpkg.com/@angular/localize/-/localize-9.1.10.tgz#230ab75155c16d84d61eb34ccff2e3283c85b995" - integrity sha512-gAc2Xuz4clPp8+YDK+M21q+DKnLNx+J/i8L9b9Z7rj8a/gHqOQWaTun4grLgd86AbpNxp/urkr+tEFHiHaNz6Q== + version "9.1.11" + resolved "https://registry.yarnpkg.com/@angular/localize/-/localize-9.1.11.tgz#25921d794836fb7a07d284c1ac0ed06c10e77d50" + integrity sha512-CrR7RniwJIK3+QKH8nHl35KDAHZn1mp1QAd5vujTWKw6YRLfio7SjM9qIfzw5y4WZuUitTsqKlQT/m/NK146Ag== dependencies: "@babel/core" "7.8.3" glob "7.1.2" yargs "15.3.0" "@angular/platform-browser-dynamic@~9.1.9": - version "9.1.10" - resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-9.1.10.tgz#a885b7903c1dcce36c327e9ca9b5f6e7ec1aa716" - integrity sha512-z8urbP03LYxiCci076SYXz+9elCukePP0ykq5RVJYe5300V6JhamGftTQgsaKszas0KlGYUz/jTULhWQ+OEv/A== + version "9.1.11" + resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-9.1.11.tgz#82af336b05e0d7b7478a2ca7f6282825b211f340" + integrity sha512-Qw3rfVFF0Wtu+UwraqKPCgTA3uoNPGf4vKSfuCuXTrG0p7j+3mCP59aUv5gGH7GV1UQ++jZRx5pbWF43zrC8Hw== "@angular/platform-browser@~9.1.9": - version "9.1.10" - resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-9.1.10.tgz#d014e59a2ec4722d0bb428910116c41176868d77" - integrity sha512-u8PHq92+OV0vrRKwc5bqS0SCR/VkzhuaUUXKYbjYeLsmXG+HUtg/pUCDo95ze4zPO1WFSeUvwsnRb2x1hurYAw== + version "9.1.11" + resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-9.1.11.tgz#4da8e2a4231d5162304746a39f54cb2d3f241b7c" + integrity sha512-KDxoiFhW4UD+EqchcKpQVSLwg9Rd3JbWytZLchFV6nH8BFnshfJtw2tyPT8bMhFVG9n9zSR4QSGaozWgoDs9mw== "@angular/router@~9.1.9": - version "9.1.10" - resolved "https://registry.yarnpkg.com/@angular/router/-/router-9.1.10.tgz#e0e9c5b1c35c9ab9b843c478c3cec038a0d15e19" - integrity sha512-nvMSzgmsjyj+vzw0meHpN1lea7kf106ml+g97RgxiOgHAtBUnuuedXpBKrajK2kA2m9QbwQvIaKrxkdBzyLuSw== + version "9.1.11" + resolved "https://registry.yarnpkg.com/@angular/router/-/router-9.1.11.tgz#b6d28af55fe5631bbc46f306a0e7866253d4f3b1" + integrity sha512-D6CCDeSK/F6dWSB/a1g/zB072xG5LadLSV8afQ57oX1KHePx21LcoRG4tUtFMMHh/jZXRc9pMQIR1/9FrrXF3Q== "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.1", "@babel/code-frame@^7.8.3": version "7.10.1" @@ -2262,12 +2262,12 @@ schematics-utilities "^1.1.1" tslib "^1.9.0" -"@ngtools/webpack@9.1.7": - version "9.1.7" - resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-9.1.7.tgz#4322757b029e1175a3361183c06b31d0576538d8" - integrity sha512-A7VB2I42Kn+7jl0tDKzGNLAoZLWSqkKo9Hg1bmKpvAAIz+DSbq3uV+JWgGgTprM3tn0lfkVgmqk4H17HKwAOcg== +"@ngtools/webpack@9.1.8": + version "9.1.8" + resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-9.1.8.tgz#50a906047b284098e5cd669e8174c9cfcaf3bafc" + integrity sha512-2Y27PrHLMyrIDmuicjp2OU7KIr9bggwMLNZdjfpcuXlOPP/BYviuhgkkYsfJysrpDRUJUHlXRJG7OJbgyFM7gQ== dependencies: - "@angular-devkit/core" "9.1.7" + "@angular-devkit/core" "9.1.8" enhanced-resolve "4.1.1" rxjs "6.5.4" webpack-sources "1.4.3" @@ -2314,24 +2314,52 @@ dependencies: tslib "^1.9.0" +"@nodelib/fs.scandir@2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b" + integrity sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw== + dependencies: + "@nodelib/fs.stat" "2.0.3" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.3", "@nodelib/fs.stat@^2.0.2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz#34dc5f4cabbc720f4e60f75a747e7ecd6c175bd3" + integrity sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA== + "@nodelib/fs.stat@^1.1.2": version "1.1.3" resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== +"@nodelib/fs.walk@^1.2.3": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz#011b9202a70a6366e436ca5c065844528ab04976" + integrity sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ== + dependencies: + "@nodelib/fs.scandir" "2.1.3" + fastq "^1.6.0" + +"@npmcli/move-file@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@npmcli/move-file/-/move-file-1.0.1.tgz#de103070dac0f48ce49cf6693c23af59c0f70464" + integrity sha512-Uv6h1sT+0DrblvIrolFtbvM1FgWm+/sy4B3pvLp67Zys+thcukzS5ekn7HsZFGpWP4Q3fYJCljbWQE/XivMRLw== + dependencies: + mkdirp "^1.0.4" + "@octokit/auth-token@^2.4.0": - version "2.4.1" - resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-2.4.1.tgz#375d79eebd03750e6a9b0299e80b8167c7c85655" - integrity sha512-NB81O5h39KfHYGtgfWr2booRxp2bWOJoqbWwbyUg2hw6h35ArWYlAST5B3XwAkbdcx13yt84hFXyFP5X0QToWA== + version "2.4.2" + resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-2.4.2.tgz#10d0ae979b100fa6b72fa0e8e63e27e6d0dbff8a" + integrity sha512-jE/lE/IKIz2v1+/P0u4fJqv0kYwXOTujKemJMFr6FeopsxlIK3+wKDCJGnysg81XID5TgZQbIfuJ5J0lnTiuyQ== dependencies: - "@octokit/types" "^4.0.1" + "@octokit/types" "^5.0.0" "@octokit/endpoint@^6.0.1": - version "6.0.2" - resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-6.0.2.tgz#e876aafe68d7f9b6c6d80bf29458403f9afe7b2b" - integrity sha512-xs1mmCEZ2y4shXCpFjNq3UbmNR+bLzxtZim2L0zfEtj9R6O6kc4qLDvYw66hvO6lUsYzPTM5hMkltbuNAbRAcQ== + version "6.0.3" + resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-6.0.3.tgz#dd09b599662d7e1b66374a177ab620d8cdf73487" + integrity sha512-Y900+r0gIz+cWp6ytnkibbD95ucEzDSKzlEnaWS52hbCDNcCJYO5mRmWW7HRAnDc7am+N/5Lnd8MppSaTYx1Yg== dependencies: - "@octokit/types" "^4.0.1" + "@octokit/types" "^5.0.0" is-plain-object "^3.0.0" universal-user-agent "^5.0.0" @@ -2379,13 +2407,13 @@ once "^1.4.0" "@octokit/request@^5.2.0": - version "5.4.4" - resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.4.4.tgz#dc57e85e86284fa016d0c1a2701a70a10cec4ff2" - integrity sha512-vqv1lz41c6VTxUvF9nM+a6U+vvP3vGk7drDpr0DVQg4zyqlOiKVrY17DLD6de5okj+YLHKcoqaUZTBtlNZ1BtQ== + version "5.4.5" + resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.4.5.tgz#8df65bd812047521f7e9db6ff118c06ba84ac10b" + integrity sha512-atAs5GAGbZedvJXXdjtKljin+e2SltEs48B3naJjqWupYl2IUBbB/CJisyjbNHcKpHzb3E+OYEZ46G8eakXgQg== dependencies: "@octokit/endpoint" "^6.0.1" "@octokit/request-error" "^2.0.0" - "@octokit/types" "^4.0.1" + "@octokit/types" "^5.0.0" deprecation "^2.0.0" is-plain-object "^3.0.0" node-fetch "^2.3.0" @@ -2428,6 +2456,13 @@ dependencies: "@types/node" ">= 8" +"@octokit/types@^5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@octokit/types/-/types-5.0.0.tgz#cbdf3c060f6c0436c004ec402c5082c32de72511" + integrity sha512-3LVS+MbeqwSd5G4KS8123cZz+hWomsiGeMnQ/QJIBFDwL/YHX8kkr0FZXrgWEMO7Fgi2/VOrhbiFnk9sZ+s4qA== + dependencies: + "@types/node" ">= 8" + "@rollup/plugin-commonjs@^11.0.2": version "11.1.0" resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-11.1.0.tgz#60636c7a722f54b41e419e1709df05c7234557ef" @@ -2468,21 +2503,21 @@ estree-walker "^1.0.1" picomatch "^2.2.2" -"@schematics/angular@9.1.7": - version "9.1.7" - resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-9.1.7.tgz#b7801a5e20f844da560db81d2971590e8ac090ff" - integrity sha512-ld3WcoMWvup04V3OWioQ+AFGQBzz7IDM4Fxc5+Qc3wILWkDJnNkrc4EmJAow96Ab4/T1+Wl1vof3tV4At0BTzA== +"@schematics/angular@9.1.8": + version "9.1.8" + resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-9.1.8.tgz#da6cd63b65776b18c43d8515bfca754dd9acdbc9" + integrity sha512-fjyAP9m4aF51OVdksRXCOF8BTyt96PqFmKK9G0kuwOzgfx2gPZNOO3wOZH6xFAMZ09y86VGzasZxZNeDdyN4sQ== dependencies: - "@angular-devkit/core" "9.1.7" - "@angular-devkit/schematics" "9.1.7" + "@angular-devkit/core" "9.1.8" + "@angular-devkit/schematics" "9.1.8" -"@schematics/update@0.901.7": - version "0.901.7" - resolved "https://registry.yarnpkg.com/@schematics/update/-/update-0.901.7.tgz#164bff4e97383a0a7d266fe5eb2e1bf41f14dfe9" - integrity sha512-6IpQVFvbu47CrXfqqHAzv2vi7AOdfi1S+SiayXU6FWTeA2wV47H8R60VjxurL8JkDGoVhFgC4+lK6KG++g3dQw== +"@schematics/update@0.901.8": + version "0.901.8" + resolved "https://registry.yarnpkg.com/@schematics/update/-/update-0.901.8.tgz#d48be9931a2462062d4d4ac05c4b24b319bc064a" + integrity sha512-v1tEYX6yM5vuwXW7AG7OZ4OtjqRwTo3kd69LVJyOdF/d9HlqaAFU301RuEsAPwOrPqZEQdTwklH1fNJnqgpB/w== dependencies: - "@angular-devkit/core" "9.1.7" - "@angular-devkit/schematics" "9.1.7" + "@angular-devkit/core" "9.1.8" + "@angular-devkit/schematics" "9.1.8" "@yarnpkg/lockfile" "1.1.0" ini "1.3.5" npm-package-arg "^8.0.0" @@ -2952,9 +2987,9 @@ acorn@^6.0.1, acorn@^6.2.1: integrity sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA== acorn@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.2.0.tgz#17ea7e40d7c8640ff54a694c889c26f31704effe" - integrity sha512-apwXVmYVpQ34m/i71vrApRrRKCWQnZZF1+npOD0WV5xZFfwWOmKGQ2RWlfdy9vWITsenisM8M0Qeq8agcFHNiQ== + version "7.3.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.3.1.tgz#85010754db53c3fbaf3b9ea3e083aa5c5d147ffd" + integrity sha512-tLc0wSnatxAQHVHUapaHdz72pi9KUyHjq5KyHjGg9Y8Ifdc79pTh2XvI6I1/chZbnM7QtNKzh66ooDogPZSleA== add-stream@^1.0.0: version "1.0.0" @@ -3248,6 +3283,11 @@ array-union@^1.0.1, array-union@^1.0.2: dependencies: array-uniq "^1.0.1" +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + array-uniq@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" @@ -3893,6 +3933,29 @@ cacache@^13.0.1: ssri "^7.0.0" unique-filename "^1.1.1" +cacache@^15.0.4: + version "15.0.4" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.0.4.tgz#b2c23cf4ac4f5ead004fb15a0efb0a20340741f1" + integrity sha512-YlnKQqTbD/6iyoJvEY3KJftjrdBYroCbxxYXzhOzsFLWlp6KX4BOlEf4mTx0cMUfVaTS3ENL2QtDWeRYoGLkkw== + dependencies: + "@npmcli/move-file" "^1.0.1" + chownr "^2.0.0" + fs-minipass "^2.0.0" + glob "^7.1.4" + infer-owner "^1.0.4" + lru-cache "^5.1.1" + minipass "^3.1.1" + minipass-collect "^1.0.2" + minipass-flush "^1.0.5" + minipass-pipeline "^1.2.2" + mkdirp "^1.0.3" + p-map "^4.0.0" + promise-inflight "^1.0.1" + rimraf "^3.0.2" + ssri "^8.0.0" + tar "^6.0.2" + unique-filename "^1.1.1" + cache-base@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" @@ -4782,23 +4845,22 @@ copy-descriptor@^0.1.0: resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= -copy-webpack-plugin@5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-5.1.1.tgz#5481a03dea1123d88a988c6ff8b78247214f0b88" - integrity sha512-P15M5ZC8dyCjQHWwd4Ia/dm0SgVvZJMYeykVIVYXbGyqO4dWB5oyPHp9i7wjwo5LhtlhKbiBCdS2NvM07Wlybg== - dependencies: - cacache "^12.0.3" - find-cache-dir "^2.1.0" - glob-parent "^3.1.0" - globby "^7.1.1" - is-glob "^4.0.1" - loader-utils "^1.2.3" - minimatch "^3.0.4" +copy-webpack-plugin@6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-6.0.2.tgz#10efc6ad219a61acbf2f5fb50af83da38431bc34" + integrity sha512-9Gm8X0c6eXlKnmltMPFCBeGOKjtcRIyTt4VaO3k1TkNgVTe5Ov2lYsYVuyLp0kp8DItO3apewflM+1GYgh6V2Q== + dependencies: + cacache "^15.0.4" + fast-glob "^3.2.2" + find-cache-dir "^3.3.1" + glob-parent "^5.1.1" + globby "^11.0.1" + loader-utils "^2.0.0" normalize-path "^3.0.0" - p-limit "^2.2.1" - schema-utils "^1.0.0" - serialize-javascript "^2.1.2" - webpack-log "^2.0.0" + p-limit "^2.3.0" + schema-utils "^2.7.0" + serialize-javascript "^3.1.0" + webpack-sources "^1.4.3" core-js-compat@^3.6.2: version "3.6.5" @@ -5448,13 +5510,20 @@ diffie-hellman@^5.0.0: miller-rabin "^4.0.0" randombytes "^2.0.0" -dir-glob@^2.0.0, dir-glob@^2.2.2: +dir-glob@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.2.2.tgz#fa09f0694153c8918b18ba0deafae94769fc50c4" integrity sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw== dependencies: path-type "^3.0.0" +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + directory-tree@^2.2.3: version "2.2.4" resolved "https://registry.yarnpkg.com/directory-tree/-/directory-tree-2.2.4.tgz#6d5bd7d82e48378e256a1e87b678a43c50076e2e" @@ -5573,9 +5642,9 @@ ee-first@1.1.1: integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= electron-to-chromium@^1.3.413: - version "1.3.466" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.466.tgz#89f716db3afc4bb482ea2aaaa16c4808f89f762a" - integrity sha512-eieqkoM2hCkZZRhETKyCouMziDV3l4XEKHRLuzcHG+HV+P7PeODU/z9HAmBgMQkzvHg2DoyQhfIDmmeguLZT/Q== + version "1.3.467" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.467.tgz#84eeb332134d49f0e49b88588824e56b20af9e27" + integrity sha512-U+QgsL8TZDU/n+rDnYDa3hY5uy3C4iry9mrJS0PNBBGwnocuQ+aHSfgY44mdlaK9744X5YqrrGUvD9PxCLY1HA== elliptic@^6.0.0, elliptic@^6.5.2: version "6.5.2" @@ -6004,6 +6073,18 @@ fast-glob@^2.2.6: merge2 "^1.2.3" micromatch "^3.1.10" +fast-glob@^3.1.1, fast-glob@^3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.2.tgz#ade1a9d91148965d4bf7c51f72e1ca662d32e63d" + integrity sha512-UDV82o4uQyljznxwMxyVRJgZZt3O5wENYojjzbaGEGZgeOxkLFf+V4cnUD+krzb2F72E18RhamkMZ7AdeggF7A== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.0" + merge2 "^1.3.0" + micromatch "^4.0.2" + picomatch "^2.2.1" + fast-json-stable-stringify@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" @@ -6024,6 +6105,13 @@ fastparse@^1.1.2: resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.2.tgz#91728c5a5942eced8531283c79441ee4122c35a9" integrity sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ== +fastq@^1.6.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.8.0.tgz#550e1f9f59bbc65fe185cb6a9b4d95357107f481" + integrity sha512-SMIZoZdLh/fgofivvIkmknUXyPnvxRE3DhtZ5Me3Mrsk5gyPL42F0xr51TdRXskBxHfMp+07bcYzfsYEsSQA9Q== + dependencies: + reusify "^1.0.4" + faye-websocket@^0.10.0: version "0.10.0" resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.10.0.tgz#4e492f8d04dfb6f89003507f6edbf2d501e7c6f4" @@ -6112,7 +6200,7 @@ finalhandler@~1.1.2: statuses "~1.5.0" unpipe "~1.0.0" -find-cache-dir@3.3.1, find-cache-dir@^3.2.0: +find-cache-dir@3.3.1, find-cache-dir@^3.2.0, find-cache-dir@^3.3.1: version "3.3.1" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.1.tgz#89b33fad4a4670daa94f855f7fbe31d6d84fe880" integrity sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ== @@ -6478,7 +6566,7 @@ glob-parent@^3.1.0: is-glob "^3.1.0" path-dirname "^1.0.0" -glob-parent@^5.0.0, glob-parent@~5.1.0: +glob-parent@^5.0.0, glob-parent@^5.1.0, glob-parent@^5.1.1, glob-parent@~5.1.0: version "5.1.1" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== @@ -6565,6 +6653,18 @@ globals@^11.1.0: resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== +globby@^11.0.1: + version "11.0.1" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.1.tgz#9a2bf107a068f3ffeabc49ad702c79ede8cfd357" + integrity sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.1.1" + ignore "^5.1.4" + merge2 "^1.3.0" + slash "^3.0.0" + globby@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" @@ -6588,18 +6688,6 @@ globby@^6.1.0: pify "^2.0.0" pinkie-promise "^2.0.0" -globby@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/globby/-/globby-7.1.1.tgz#fb2ccff9401f8600945dfada97440cca972b8680" - integrity sha1-+yzP+UAfhgCUXfral0QMypcrhoA= - dependencies: - array-union "^1.0.1" - dir-glob "^2.0.0" - glob "^7.1.2" - ignore "^3.3.5" - pify "^3.0.0" - slash "^1.0.0" - globby@^9.2.0: version "9.2.0" resolved "https://registry.yarnpkg.com/globby/-/globby-9.2.0.tgz#fd029a706c703d29bdd170f4b6db3a3f7a7cb63d" @@ -6982,16 +7070,16 @@ ignore-walk@^3.0.1: dependencies: minimatch "^3.0.4" -ignore@^3.3.5: - version "3.3.10" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" - integrity sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug== - ignore@^4.0.3: version "4.0.6" resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== +ignore@^5.1.4: + version "5.1.8" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" + integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== + image-size@~0.5.0: version "0.5.5" resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.5.5.tgz#09dfd4ab9d20e29eb1c3e80b8990378df9e3cb9c" @@ -8377,24 +8465,7 @@ less-loader@5.0.0: loader-utils "^1.1.0" pify "^4.0.1" -less@3.11.1: - version "3.11.1" - resolved "https://registry.yarnpkg.com/less/-/less-3.11.1.tgz#c6bf08e39e02404fe6b307a3dfffafdc55bd36e2" - integrity sha512-tlWX341RECuTOvoDIvtFqXsKj072hm3+9ymRBe76/mD6O5ZZecnlAOVDlWAleF2+aohFrxNidXhv2773f6kY7g== - dependencies: - clone "^2.1.2" - tslib "^1.10.0" - optionalDependencies: - errno "^0.1.1" - graceful-fs "^4.1.2" - image-size "~0.5.0" - mime "^1.4.1" - mkdirp "^0.5.0" - promise "^7.1.1" - request "^2.83.0" - source-map "~0.6.0" - -less@^3.10.3: +less@3.11.3, less@^3.10.3: version "3.11.3" resolved "https://registry.yarnpkg.com/less/-/less-3.11.3.tgz#2d853954fcfe0169a8af869620bcaa16563dcc1c" integrity sha512-VkZiTDdtNEzXA3LgjQiC3D7/ejleBPFVvq+aRI9mIj+Zhmif5TvFPM244bT4rzkvOCvJ9q4zAztok1M7Nygagw== @@ -8887,7 +8958,7 @@ merge-stream@^2.0.0: resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== -merge2@^1.2.3: +merge2@^1.2.3, merge2@^1.3.0: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== @@ -9110,7 +9181,7 @@ mkdirp-promise@^5.0.1: dependencies: mkdirp "*" -mkdirp@*, mkdirp@^1.0.3: +mkdirp@*, mkdirp@^1.0.3, mkdirp@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== @@ -9863,7 +9934,7 @@ p-limit@^1.1.0: dependencies: p-try "^1.0.0" -p-limit@^2.0.0, p-limit@^2.2.0, p-limit@^2.2.1, p-limit@^2.2.2: +p-limit@^2.0.0, p-limit@^2.2.0, p-limit@^2.2.2, p-limit@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== @@ -9910,6 +9981,13 @@ p-map@^3.0.0: dependencies: aggregate-error "^3.0.0" +p-map@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" + integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== + dependencies: + aggregate-error "^3.0.0" + p-pipe@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/p-pipe/-/p-pipe-1.2.0.tgz#4b1a11399a11520a67790ee5a0c1d5881d6befe9" @@ -10188,6 +10266,11 @@ path-type@^3.0.0: dependencies: pify "^3.0.0" +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + pbkdf2@^3.0.3: version "3.1.1" resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.1.tgz#cb8724b0fada984596856d1a6ebafd3584654b94" @@ -11427,6 +11510,11 @@ retry@^0.12.0: resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs= +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + rgb-regex@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/rgb-regex/-/rgb-regex-1.0.1.tgz#c0e0d6882df0e23be254a475e8edd41915feaeb1" @@ -11442,7 +11530,7 @@ right-pad@^1.0.1: resolved "https://registry.yarnpkg.com/right-pad/-/right-pad-1.0.1.tgz#8ca08c2cbb5b55e74dafa96bf7fd1a27d568c8d0" integrity sha1-jKCMLLtbVedNr6lr9/0aJ9VoyNA= -rimraf@3.0.2, rimraf@^3.0.0: +rimraf@3.0.2, rimraf@^3.0.0, rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== @@ -11496,6 +11584,11 @@ run-async@^2.2.0, run-async@^2.4.0: resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== +run-parallel@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" + integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== + run-queue@^1.0.0, run-queue@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47" @@ -11621,7 +11714,7 @@ schema-utils@^1.0.0: ajv-errors "^1.0.0" ajv-keywords "^3.1.0" -schema-utils@^2.5.0, schema-utils@^2.6.1, schema-utils@^2.6.4, schema-utils@^2.6.5: +schema-utils@^2.5.0, schema-utils@^2.6.1, schema-utils@^2.6.4, schema-utils@^2.6.5, schema-utils@^2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.0.tgz#17151f76d8eae67fbbf77960c33c676ad9f4efc7" integrity sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A== @@ -11869,11 +11962,6 @@ sisteransi@^1.0.4: resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== -slash@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" - integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU= - slash@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" @@ -12572,7 +12660,7 @@ tar@^4.4.10, tar@^4.4.12, tar@^4.4.8: safe-buffer "^5.1.2" yallist "^3.0.3" -tar@^6.0.1: +tar@^6.0.1, tar@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/tar/-/tar-6.0.2.tgz#5df17813468a6264ff14f766886c622b84ae2f39" integrity sha512-Glo3jkRtPcvpDlAs/0+hozav78yoXKFr+c4wgw62NNMO3oo4AaJdCo21Uu7lcwr55h39W2XD1LMERc64wtbItg== From 791ddaecd6d9bd77bc9b632399c5ff44eb1438ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Fri, 12 Jun 2020 10:00:44 +0300 Subject: [PATCH 56/81] Change EditionId.ToString() to format with "N" --- .../Abp/FeatureManagement/EditionFeatureManagementProvider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/EditionFeatureManagementProvider.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/EditionFeatureManagementProvider.cs index cef7983235..d904ef124a 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/EditionFeatureManagementProvider.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/EditionFeatureManagementProvider.cs @@ -26,7 +26,7 @@ namespace Volo.Abp.FeatureManagement return providerKey; } - return PrincipalAccessor.Principal?.FindEditionId()?.ToString(); + return PrincipalAccessor.Principal?.FindEditionId()?.ToString("N"); } } } \ No newline at end of file From bb5f2f9b69a85f384760d1708f4d5405c82c5687 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Fri, 12 Jun 2020 10:27:17 +0300 Subject: [PATCH 57/81] chore: add skipNgcc option to build script --- npm/ng-packs/scripts/build.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/npm/ng-packs/scripts/build.ts b/npm/ng-packs/scripts/build.ts index e458b8285c..a69f1c768a 100644 --- a/npm/ng-packs/scripts/build.ts +++ b/npm/ng-packs/scripts/build.ts @@ -3,6 +3,7 @@ import program from 'commander'; (async () => { program.option('-i, --noInstall', 'skip updating package.json and installation', false); + program.option('-c, --skipNgcc', 'skip ngcc', false); program.parse(process.argv); @@ -55,7 +56,7 @@ import program from 'commander'; { stdout: 'inherit', cwd: '../' }, ); - await execa('yarn', ['compile:ivy'], { stdout: 'inherit', cwd: '../' }); + if (!program.skipNgcc) await execa('yarn', ['compile:ivy'], { stdout: 'inherit', cwd: '../' }); } catch (error) { console.error(error.stderr); process.exit(1); From 1a7d74dc9f8eb2c3a2c4ec4dbb8dc265de8a156d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Fri, 12 Jun 2020 10:39:36 +0300 Subject: [PATCH 58/81] #4323 Implemented: Set AbpSequentialGuidGeneratorOptions.DefaultSequentialGuidType by the database provider packages --- .../MySQL/AbpEntityFrameworkCoreMySQLModule.cs | 14 ++++++++++++-- ...AbpEntityFrameworkCoreOracleDevartModule.cs | 14 ++++++++++++-- .../AbpEntityFrameworkCorePostgreSqlModule.cs | 14 ++++++++++++-- .../AbpEntityFrameworkCoreSqlServerModule.cs | 14 ++++++++++++-- .../Guids/AbpSequentialGuidGeneratorOptions.cs | 18 +++++++++++++----- .../Volo/Abp/Guids/SequentialGuidGenerator.cs | 2 +- 6 files changed, 62 insertions(+), 14 deletions(-) diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.MySQL/Volo/Abp/EntityFrameworkCore/MySQL/AbpEntityFrameworkCoreMySQLModule.cs b/framework/src/Volo.Abp.EntityFrameworkCore.MySQL/Volo/Abp/EntityFrameworkCore/MySQL/AbpEntityFrameworkCoreMySQLModule.cs index 7c42014fc4..6cf424f422 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore.MySQL/Volo/Abp/EntityFrameworkCore/MySQL/AbpEntityFrameworkCoreMySQLModule.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore.MySQL/Volo/Abp/EntityFrameworkCore/MySQL/AbpEntityFrameworkCoreMySQLModule.cs @@ -1,4 +1,5 @@ -using Volo.Abp.Modularity; +using Volo.Abp.Guids; +using Volo.Abp.Modularity; namespace Volo.Abp.EntityFrameworkCore.MySQL { @@ -7,6 +8,15 @@ namespace Volo.Abp.EntityFrameworkCore.MySQL )] public class AbpEntityFrameworkCoreMySQLModule : AbpModule { - + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + if (options.DefaultSequentialGuidType == null) + { + options.DefaultSequentialGuidType = SequentialGuidType.SequentialAsString; + } + }); + } } } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/Oracle/Devart/AbpEntityFrameworkCoreOracleDevartModule.cs b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/Oracle/Devart/AbpEntityFrameworkCoreOracleDevartModule.cs index ec28190702..7b5970bb59 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/Oracle/Devart/AbpEntityFrameworkCoreOracleDevartModule.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/Oracle/Devart/AbpEntityFrameworkCoreOracleDevartModule.cs @@ -1,4 +1,5 @@ -using Volo.Abp.Modularity; +using Volo.Abp.Guids; +using Volo.Abp.Modularity; namespace Volo.Abp.EntityFrameworkCore.Oracle.Devart { @@ -7,6 +8,15 @@ namespace Volo.Abp.EntityFrameworkCore.Oracle.Devart )] public class AbpEntityFrameworkCoreOracleDevartModule : AbpModule { - + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + if (options.DefaultSequentialGuidType == null) + { + options.DefaultSequentialGuidType = SequentialGuidType.SequentialAsBinary; + } + }); + } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/PostgreSql/AbpEntityFrameworkCorePostgreSqlModule.cs b/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/PostgreSql/AbpEntityFrameworkCorePostgreSqlModule.cs index 4973af3966..4e76b89113 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/PostgreSql/AbpEntityFrameworkCorePostgreSqlModule.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/PostgreSql/AbpEntityFrameworkCorePostgreSqlModule.cs @@ -1,4 +1,5 @@ -using Volo.Abp.Modularity; +using Volo.Abp.Guids; +using Volo.Abp.Modularity; namespace Volo.Abp.EntityFrameworkCore.PostgreSql { @@ -7,6 +8,15 @@ namespace Volo.Abp.EntityFrameworkCore.PostgreSql )] public class AbpEntityFrameworkCorePostgreSqlModule : AbpModule { - + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + if (options.DefaultSequentialGuidType == null) + { + options.DefaultSequentialGuidType = SequentialGuidType.SequentialAsString; + } + }); + } } } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.SqlServer/Volo/Abp/EntityFrameworkCore/SqlServer/AbpEntityFrameworkCoreSqlServerModule.cs b/framework/src/Volo.Abp.EntityFrameworkCore.SqlServer/Volo/Abp/EntityFrameworkCore/SqlServer/AbpEntityFrameworkCoreSqlServerModule.cs index 762e8ce355..ae54df624f 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore.SqlServer/Volo/Abp/EntityFrameworkCore/SqlServer/AbpEntityFrameworkCoreSqlServerModule.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore.SqlServer/Volo/Abp/EntityFrameworkCore/SqlServer/AbpEntityFrameworkCoreSqlServerModule.cs @@ -1,4 +1,5 @@ -using Volo.Abp.Modularity; +using Volo.Abp.Guids; +using Volo.Abp.Modularity; namespace Volo.Abp.EntityFrameworkCore.SqlServer { @@ -7,6 +8,15 @@ namespace Volo.Abp.EntityFrameworkCore.SqlServer )] public class AbpEntityFrameworkCoreSqlServerModule : AbpModule { - + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + if (options.DefaultSequentialGuidType == null) + { + options.DefaultSequentialGuidType = SequentialGuidType.SequentialAtEnd; + } + }); + } } } diff --git a/framework/src/Volo.Abp.Guids/Volo/Abp/Guids/AbpSequentialGuidGeneratorOptions.cs b/framework/src/Volo.Abp.Guids/Volo/Abp/Guids/AbpSequentialGuidGeneratorOptions.cs index c712f8084b..83695b6a30 100644 --- a/framework/src/Volo.Abp.Guids/Volo/Abp/Guids/AbpSequentialGuidGeneratorOptions.cs +++ b/framework/src/Volo.Abp.Guids/Volo/Abp/Guids/AbpSequentialGuidGeneratorOptions.cs @@ -3,13 +3,21 @@ public class AbpSequentialGuidGeneratorOptions { /// - /// Default value: . + /// Default value: null (unspecified). + /// Use method + /// to get the value on use, since it fall backs to a default value. /// - public SequentialGuidType DefaultSequentialGuidType { get; set; } - - public AbpSequentialGuidGeneratorOptions() + public SequentialGuidType? DefaultSequentialGuidType { get; set; } + + /// + /// Get the value + /// or returns + /// if was null. + /// + public SequentialGuidType GetDefaultSequentialGuidType() { - DefaultSequentialGuidType = SequentialGuidType.SequentialAtEnd; + return DefaultSequentialGuidType ?? + SequentialGuidType.SequentialAtEnd; } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.Guids/Volo/Abp/Guids/SequentialGuidGenerator.cs b/framework/src/Volo.Abp.Guids/Volo/Abp/Guids/SequentialGuidGenerator.cs index 331ed066a4..a57e21f657 100644 --- a/framework/src/Volo.Abp.Guids/Volo/Abp/Guids/SequentialGuidGenerator.cs +++ b/framework/src/Volo.Abp.Guids/Volo/Abp/Guids/SequentialGuidGenerator.cs @@ -24,7 +24,7 @@ namespace Volo.Abp.Guids public Guid Create() { - return Create(Options.DefaultSequentialGuidType); + return Create(Options.GetDefaultSequentialGuidType()); } public Guid Create(SequentialGuidType guidType) From d720b397404c07ff7160dd8392845e0df7f06f42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Fri, 12 Jun 2020 10:45:48 +0300 Subject: [PATCH 59/81] Document for #4323. --- docs/en/Entities.md | 6 +++--- docs/en/Guid-Generation.md | 4 +++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/en/Entities.md b/docs/en/Entities.md index 0d34c35ce6..538d298461 100644 --- a/docs/en/Entities.md +++ b/docs/en/Entities.md @@ -26,9 +26,9 @@ public class Book : Entity If your entity's Id type is `Guid`, there are some good practices to implement: * Create a constructor that gets the Id as a parameter and passes to the base class. - * If you don't set a GUID Id, ABP Framework sets it on save, but it is good to have a valid Id on the entity even before saving it to the database. -* If you create an entity with a constructor that takes parameters, also create a `protected` empty constructor. This is used while your database provider reads your entity from the database (on deserialization). -* Don't use the `Guid.NewGuid()` to set the Id! Use [the `IGuidGenerator` service](Guid-Generation.md) while passing the Id from the code that creates the entity. `IGuidGenerator` optimized to generate sequential GUIDs, which is critical for clustered indexes in the relational databases. + * If you don't set a GUID Id, **ABP Framework sets it on save**, but it is good to have a valid Id on the entity even before saving it to the database. +* If you create an entity with a constructor that takes parameters, also create a `private` or `protected` empty constructor. This is used while your database provider reads your entity from the database (on deserialization). +* Don't use the `Guid.NewGuid()` to set the Id! **Use [the `IGuidGenerator` service](Guid-Generation.md)** while passing the Id from the code that creates the entity. `IGuidGenerator` optimized to generate sequential GUIDs, which is critical for clustered indexes in the relational databases. An example entity: diff --git a/docs/en/Guid-Generation.md b/docs/en/Guid-Generation.md index 1cd2d6c218..0990f5b6dd 100644 --- a/docs/en/Guid-Generation.md +++ b/docs/en/Guid-Generation.md @@ -106,4 +106,6 @@ Configure(options => { options.DefaultSequentialGuidType = SequentialGuidType.SequentialAsBinary; }); -```` \ No newline at end of file +```` + +> EF Core [integration packages](https://docs.abp.io/en/abp/latest/Entity-Framework-Core-Other-DBMS) sets this option to a proper value for the related DBMS. So, most of the times, you don't need to set this option if you are using these integration packages. \ No newline at end of file From 8f9ef8389e67640b8601b917727e9f97617e2a65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Fri, 12 Jun 2020 11:04:03 +0300 Subject: [PATCH 60/81] Resolved #4298: Database BLOB provider can configure the default container if not configured before --- docs/en/Blob-Storing-Database.md | 2 ++ .../Database/BlobStoringDatabaseDomainModule.cs | 14 +++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/docs/en/Blob-Storing-Database.md b/docs/en/Blob-Storing-Database.md index b413882227..69b9232ee8 100644 --- a/docs/en/Blob-Storing-Database.md +++ b/docs/en/Blob-Storing-Database.md @@ -55,6 +55,8 @@ If you want to use a separate database for BLOB storage, use the `AbpBlobStoring ### Configuring the Containers +If you are using only the database storage provider, you don't need to manually configure it, since it is automatically done. If you are using multiple storage providers, you may want to configure it. + Configuration is done in the `ConfigureServices` method of your [module](Module-Development-Basics.md) class, as explained in the [BLOB Storing document](Blob-Storing.md). **Example: Configure to use the database storage provider by default** diff --git a/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo/Abp/BlobStoring/Database/BlobStoringDatabaseDomainModule.cs b/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo/Abp/BlobStoring/Database/BlobStoringDatabaseDomainModule.cs index e49f9ce63b..316659af67 100644 --- a/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo/Abp/BlobStoring/Database/BlobStoringDatabaseDomainModule.cs +++ b/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo/Abp/BlobStoring/Database/BlobStoringDatabaseDomainModule.cs @@ -10,6 +10,18 @@ namespace Volo.Abp.BlobStoring.Database )] public class BlobStoringDatabaseDomainModule : AbpModule { - + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.Containers.ConfigureDefault(container => + { + if (container.ProviderType == null) + { + container.UseDatabase(); + } + }); + }); + } } } From f37e0440c6c11e796bfe4ae869130e100ad7b392 Mon Sep 17 00:00:00 2001 From: maliming <6908465+maliming@users.noreply.github.com> Date: Fri, 12 Jun 2020 16:06:33 +0800 Subject: [PATCH 61/81] Add high-performance AddDeveloperSigningCredential method. --- .../AbpIdentityServerBuilderExtensions.cs | 81 ++++++++++++++++++- .../AbpIdentityServerDomainModule.cs | 2 +- 2 files changed, 80 insertions(+), 3 deletions(-) diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerBuilderExtensions.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerBuilderExtensions.cs index 6719192fdd..52ff0ac9c5 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerBuilderExtensions.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerBuilderExtensions.cs @@ -1,9 +1,14 @@ -using System; +using System; using System.IdentityModel.Tokens.Jwt; +using System.IO; +using System.Security.Cryptography; using IdentityModel; +using IdentityServer4; +using IdentityServer4.Configuration; using IdentityServer4.Services; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; +using Newtonsoft.Json.Linq; using Volo.Abp.Identity; using Volo.Abp.IdentityServer.AspNetIdentity; using Volo.Abp.Security.Claims; @@ -49,5 +54,77 @@ namespace Volo.Abp.IdentityServer return builder; } + + public static IIdentityServerBuilder AddAbpDeveloperSigningCredential( + this IIdentityServerBuilder builder, + bool persistKey = true, + string filename = null, + IdentityServerConstants.RsaSigningAlgorithm signingAlgorithm = IdentityServerConstants.RsaSigningAlgorithm.RS256) + { + if (filename == null) + { + filename = Path.Combine(Directory.GetCurrentDirectory(), "tempkey.rsa"); + } + + if (File.Exists(filename)) + { + var keyFile = File.ReadAllText(filename); + + var json = JObject.Parse(keyFile); + var keyId = json.GetValue("KeyId").Value(); + var jsonParameters = json.GetValue("Parameters"); + RSAParameters rsaParameters; + rsaParameters.D = Convert.FromBase64String(jsonParameters["D"].Value()); + rsaParameters.DP = Convert.FromBase64String(jsonParameters["DP"].Value()); + rsaParameters.DQ = Convert.FromBase64String(jsonParameters["DQ"].Value()); + rsaParameters.Exponent = Convert.FromBase64String(jsonParameters["Exponent"].Value()); + rsaParameters.InverseQ = Convert.FromBase64String(jsonParameters["InverseQ"].Value()); + rsaParameters.Modulus = Convert.FromBase64String(jsonParameters["Modulus"].Value()); + rsaParameters.P = Convert.FromBase64String(jsonParameters["P"].Value()); + rsaParameters.Q = Convert.FromBase64String(jsonParameters["Q"].Value()); + + return builder.AddSigningCredential(CryptoHelper.CreateRsaSecurityKey(rsaParameters, keyId), signingAlgorithm); + } + else + { + var key = CryptoHelper.CreateRsaSecurityKey(); + + RSAParameters parameters; + + if (key.Rsa != null) + { + parameters = key.Rsa.ExportParameters(includePrivateParameters: true); + } + else + { + parameters = key.Parameters; + } + + var jObject = new JObject + { + { + "KeyId", key.KeyId + }, + { + "Parameters", new JObject + { + {"D", Convert.ToBase64String(parameters.D)}, + {"DP", Convert.ToBase64String(parameters.DP)}, + {"DQ", Convert.ToBase64String(parameters.DQ)}, + {"Exponent", Convert.ToBase64String(parameters.Exponent)}, + {"Modulus", Convert.ToBase64String(parameters.Modulus)}, + {"P", Convert.ToBase64String(parameters.P)}, + {"Q", Convert.ToBase64String(parameters.Q)} + } + } + }; + + if (persistKey) + { + File.WriteAllText(filename, jObject.ToString()); + } + return builder.AddSigningCredential(key, signingAlgorithm); + } + } } -} \ No newline at end of file +} diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerDomainModule.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerDomainModule.cs index 95c8eec537..01001aeb35 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerDomainModule.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerDomainModule.cs @@ -67,7 +67,7 @@ namespace Volo.Abp.IdentityServer if (builderOptions.AddDeveloperSigningCredential) { - identityServerBuilder = identityServerBuilder.AddDeveloperSigningCredential(); + identityServerBuilder = identityServerBuilder.AddAbpDeveloperSigningCredential(); } identityServerBuilder.AddAbpIdentityServer(builderOptions); From a530566e2275d7f97e1a0d170176b0e4617fca38 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Fri, 12 Jun 2020 16:34:01 +0800 Subject: [PATCH 62/81] Update document --- docs/en/Modules/Docs.md | 29 ++++++++++++++++-- docs/en/Modules/Virtual-File-Explorer.md | 8 +++-- docs/zh-Hans/Modules/Docs.md | 30 +++++++++++++++++-- docs/zh-Hans/Modules/Virtual-File-Explorer.md | 8 +++-- 4 files changed, 64 insertions(+), 11 deletions(-) diff --git a/docs/en/Modules/Docs.md b/docs/en/Modules/Docs.md index bbed28e8fe..b8f678dc48 100644 --- a/docs/en/Modules/Docs.md +++ b/docs/en/Modules/Docs.md @@ -58,14 +58,18 @@ Now an empty ABP project has been created! You can now run your project and see To login your website enter `admin` as the username and `1q2w3E*` as the password. -### 2- Referencing Docs Module Packages +### 3- Installation Module Docs module packages are hosted on NuGet. There are 4 packages that needs be to installed to your application. Each package has to be installed to the relevant project. +#### 3.1- Use ABP CLI + It is recommended to use the ABP CLI to install the module, open the CMD window in the solution file (`.sln`) directory, and run the following command: `abp add-module Volo.Docs` +#### 3.2- Manually install + Or you can also manually install nuget package to each project: * Install [Volo.Docs.Domain](https://www.nuget.org/packages/Volo.Docs.Domain/) nuget package to `Acme.MyProject.Domain` project. @@ -84,7 +88,7 @@ Or you can also manually install nuget package to each project: `Install-Package Volo.Docs.Web` -### 3- Adding Module Dependencies +##### 3.2.1- Adding Module Dependencies An ABP module must declare `[DependsOn]` attribute if it has a dependency upon another module. Each module has to be added in`[DependsOn]` attribute to the relevant project. @@ -165,6 +169,27 @@ An ABP module must declare `[DependsOn]` attribute if it has a dependency upon a } ``` +##### 3.2.2- Adding NPM Package + +Open `package.json` and add `@abp/docs": "^2.9.0` as shown below: + + ```json + { + "version": "1.0.0", + "name": "my-app", + "private": true, + "dependencies": { + "@abp/aspnetcore.mvc.ui.theme.basic": "^2.9.0", + "@abp/docs": "^2.9.0" + } + } + ``` + + Then open the command line terminal in the `Acme.MyProject.Web` project folder and run the following command: + + 1. `yarn` + 2. `gulp` + ### 4- Database Integration #### 4.1- Entity Framework Integration diff --git a/docs/en/Modules/Virtual-File-Explorer.md b/docs/en/Modules/Virtual-File-Explorer.md index 81059ff870..bae87ba95a 100644 --- a/docs/en/Modules/Virtual-File-Explorer.md +++ b/docs/en/Modules/Virtual-File-Explorer.md @@ -8,19 +8,21 @@ Virtual File Explorer Module provided a simple UI to view all files in [virtual ### Installation -#### 1- Referencing Virtual File Explorer Module Packages +#### 1- Use ABP CLI It is recommended to use the ABP CLI to install the module, open the CMD window in the solution file (`.sln`) directory, and run the following command: `abp add-module Volo.VirtualFileExplorer` +#### 2- Manually install + Or you can also manually install nuget package to `Acme.MyProject.Web` project: * Install [Volo.Abp.VirtualFileExplorer.Web](https://www.nuget.org/packages/Volo.Abp.VirtualFileExplorer.Web/) nuget package to `Acme.MyProject.Web` project. `Install-Package Volo.Abp.VirtualFileExplorer.Web` -#### 2- Adding Module Dependencies +##### 2.1- Adding Module Dependencies * Open `MyProjectWebModule.cs`and add `typeof(AbpVirtualFileExplorerWebModule)` as shown below; @@ -40,7 +42,7 @@ Or you can also manually install nuget package to `Acme.MyProject.Web` project: } ``` -#### 3- Adding NPM Package +##### 2.2- Adding NPM Package * Open `package.json` and add `@abp/virtual-file-explorer": "^2.9.0` as shown below: diff --git a/docs/zh-Hans/Modules/Docs.md b/docs/zh-Hans/Modules/Docs.md index 96452f2bd5..63759d1462 100644 --- a/docs/zh-Hans/Modules/Docs.md +++ b/docs/zh-Hans/Modules/Docs.md @@ -58,14 +58,18 @@ ABP框架的[文档](docs.abp.io)也是使用的此模块. 输入用户名 `admin` 密码 `1q2w3E*` 登录到网站. -### 2- 引用文档模块包 +### 3- 安装模块 文档模块包托管在Nuget上面. 需要有四个包安装到你的应用程序中. 每个包必须安装到相关的项目. +#### 3.1- 使用ABP CLI + 建议使用ABP CLI安装模块,在解决方案文件 (`.sln`) 目录打开 `CMD` 窗口,运行以下命令: `abp add-module Volo.Docs` +#### 3.2- 手动安装 + 或者你也可以手动安装nuget包到每个项目: * 安装[Volo.Docs.Domain](https://www.nuget.org/packages/Volo.Docs.Domain/) nuget包到 `Acme.MyProject.Domain` 项目. @@ -83,7 +87,7 @@ ABP框架的[文档](docs.abp.io)也是使用的此模块. * 安装[Volo.Docs.Web](https://www.nuget.org/packages/Volo.Docs.Domain/) nuget包到 `Acme.MyProject.Web` 项目. `Install-Package Volo.Docs.Web` -### 3- 添加模块依赖 +##### 3.2.1- 添加模块依赖 一个ABP模块必须声明 `[DependsOn]` attribute 如果它依赖于另一个模块. 每个模块都必须在相关的项目的`[DependsOn]`Attribute 中添加. @@ -122,7 +126,6 @@ ABP框架的[文档](docs.abp.io)也是使用的此模块. } ``` - * 打开 `MyProjectApplicationModule.cs`并且添加 `typeof(DocsApplicationModule)` 如下所示; ```csharp @@ -165,6 +168,27 @@ ABP框架的[文档](docs.abp.io)也是使用的此模块. } ``` +##### 3.2.2- 添加NPM包 + +打开 `package.json` 添加 `@abp/docs` 如下所示: + + ```json + { + "version": "1.0.0", + "name": "my-app", + "private": true, + "dependencies": { + "@abp/aspnetcore.mvc.ui.theme.basic": "^2.9.0", + "@abp/docs": "^2.9.0" + } + } + ``` + + 然后在 `Acme.MyProject.Web` 项目目录打开命令行终端运行以下命令: + + 1. `yarn` + 2. `gulp` + ### 4- 数据库集成 #### 4.1- Entity Framework 集成 diff --git a/docs/zh-Hans/Modules/Virtual-File-Explorer.md b/docs/zh-Hans/Modules/Virtual-File-Explorer.md index 375165d221..024b3d23df 100644 --- a/docs/zh-Hans/Modules/Virtual-File-Explorer.md +++ b/docs/zh-Hans/Modules/Virtual-File-Explorer.md @@ -8,19 +8,21 @@ ### 安装 -#### 1- 引用虚拟文件浏览器模块包 +#### 1- 使用ABP CLI 建议使用ABP CLI安装模块,在解决方案文件 (`.sln`) 目录打开 `CMD` 窗口,运行以下命令: `abp add-module Volo.VirtualFileExplorer` +#### 2- 手动安装 + 或者你也可以手动安装nuget包到 `Acme.MyProject.Web` 项目: * 安装[Volo.Abp.VirtualFileExplorer.Web](https://www.nuget.org/packages/Volo.Abp.VirtualFileExplorer.Web/) nuget包到 `Acme.MyProject.Web` 项目. `Install-Package Volo.Abp.VirtualFileExplorer.Web` -#### 2- 添加模块依赖 +##### 2.1- 添加模块依赖 * 打开 `MyProjectWebModule.cs` 并且添加 `typeof(AbpVirtualFileExplorerWebModule)` 如下所示; @@ -40,7 +42,7 @@ } ``` -#### 3- 添加NPM包 +##### 2.2- 添加NPM包 * 打开 `package.json` 添加 `@abp/virtual-file-explorer": "^2.9.0` 如下所示: From 640786d5e821ed267a0514e4d4aa62d9980943ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Fri, 12 Jun 2020 11:52:16 +0300 Subject: [PATCH 63/81] Data-Seeding initial document --- docs/en/Data-Seeding.md | 70 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/docs/en/Data-Seeding.md b/docs/en/Data-Seeding.md index 0b424e7e0d..3b8e878a4f 100644 --- a/docs/en/Data-Seeding.md +++ b/docs/en/Data-Seeding.md @@ -1,3 +1,73 @@ # Data Seeding +## Introduction + +Some applications (or modules) using a database may need to have some **initial data** to be able to properly start and run. For example, an **admin user** & roles must be available at the beginning. Otherwise you can not **login** to the application to create new users and roles. + +Data seeding is also useful for [testing](Testing.md) purpose, so your automatic tests can assume some initial data available in the database. + +### Why a Data Seed System? + +While EF Core Data Seeding system provides a way, it is very limited and doesn't cover production scenarios. Also, it is only for EF Core. + +ABP Framework provides a data seed system that is; + +* **Modular**: Any [module](Module-Development-Basics.md) can silently contribute to the data seeding process without knowing and effecting each other. In this way, a module seeds its own initial data. +* **Database Independent**: It is not only for EF Core, it also works for other database providers (like [MongoDB](MongoDB.md)). +* **Production Ready**: It solves the problems on production environments. See the "*On Production*" section below. +* **Dependency Injection**: It takes the full advantage of dependency injection, so you can use any internal or external service while seeding the initial data. Actually, you can do much more than data seeding. + +## IDataSeeder + +`IDataSeeder` is the main service that is used to seed initial data. It is pretty easy to use; + +````csharp +public class MyService : ITransientDependency +{ + private readonly IDataSeeder _dataSeeder; + + public MyService(IDataSeeder dataSeeder) + { + _dataSeeder = dataSeeder; + } + + public async Task FooAsync() + { + await _dataSeeder.SeedAsync(); + } +} +```` + +You can [inject](Dependency-Injection.md) the `IDataSeeder` and use it to seed the initial data. We will see the *IDataSeedContributor* section below to learn how to insert data. But before that, we should understand that: Where & how to execute the `IDataSeeder.SeedAsync()`? + +### On Production + +The [application startup template](Startup-Templates/Application.md) comes with a *YourProjectName***.DbMigrator** project (Acme.BookStore.DbMigrator on the picture below), which is a **console application** that is responsible to **migrate** the database schema (for relational databases) and **seed** the initial data: + +![bookstore-visual-studio-solution-v3](images/bookstore-visual-studio-solution-v3.png) + +This console application is properly configured for you. It even supports **multi-tenant** scenarios where each tenant has its own database (migrates & seeds all necessary databases). + +It is expected to run this DbMigrator application whenever you **deploy a new version** of your solution to the server. It will migrate your **database schema** (create new tables/fields... etc.) and **seed new initial data** needed to properly run the new version of your solution. Then you can deploy/start your actual application. + +Even if you are using MongoDB or another NoSQL database, it is recommended to use the DbMigrator application to seed your data or perform your data migration. + +Having such a separate console application has several advantages; + +* You can run it before updating your application, so your application will run on the ready database. +* Your application starts faster compared to if it seeds the initial data itself. +* Your application can properly run on a clustered environment (where multiple instances of your application run concurrently). If you seed data on application startup you would have conflicts in this case. + +### On Development + +We suggest the same way on development. Run the DbMigrator console application whenever you [create a database migration](https://docs.microsoft.com/en-us/ef/ef6/modeling/code-first/migrations/) (using EF Core `Add-Migration` command, for example) or change the data seed code (will be explained later). + +You can continue to use the standard `Update-Database` command for EF Core, but it will not seed if you've created a new seed data. + +### On Testing + +TODO + +## IDataSeedContributor + TODO \ No newline at end of file From 00660cd2ef392da5ddaa4071237147b833d1221a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Fri, 12 Jun 2020 12:58:35 +0300 Subject: [PATCH 64/81] Complete the Data Seed document --- docs/en/Data-Seeding.md | 113 +++++++++++++++++++++++++++++++++++----- 1 file changed, 100 insertions(+), 13 deletions(-) diff --git a/docs/en/Data-Seeding.md b/docs/en/Data-Seeding.md index 3b8e878a4f..d6236da9d9 100644 --- a/docs/en/Data-Seeding.md +++ b/docs/en/Data-Seeding.md @@ -17,8 +17,79 @@ ABP Framework provides a data seed system that is; * **Production Ready**: It solves the problems on production environments. See the "*On Production*" section below. * **Dependency Injection**: It takes the full advantage of dependency injection, so you can use any internal or external service while seeding the initial data. Actually, you can do much more than data seeding. +## IDataSeedContributor + +`IDataSeedContributor` is the interface that should be implemented in order to seed data to the database. + +**Example: Seed one initial book to the database if there is no book** + +````csharp +using System; +using System.Threading.Tasks; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Domain.Repositories; +using Volo.Abp.Guids; + +namespace Acme.BookStore +{ + public class BookStoreDataSeedContributor + : IDataSeedContributor, ITransientDependency + { + private readonly IRepository _bookRepository; + private readonly IGuidGenerator _guidGenerator; + + public BookStoreDataSeedContributor( + IRepository bookRepository, + IGuidGenerator guidGenerator) + { + _bookRepository = bookRepository; + _guidGenerator = guidGenerator; + } + + public async Task SeedAsync(DataSeedContext context) + { + if (await _bookRepository.GetCountAsync() > 0) + { + return; + } + + var book = new Book( + id: _guidGenerator.Create(), + name: "The Hitchhiker's Guide to the Galaxy", + type: BookType.ScienceFiction, + publishDate: new DateTime(1979, 10, 12), + price: 42 + ); + + await _bookRepository.InsertAsync(book); + } + } +} +```` + +* `IDataSeedContributor` defines the `SeedAsync` method to execute the **data seed logic**. +* It is typical to **check database** if the seeding data is already present. +* You can **inject** and service and perform any logic needed to seed the data. + +> Data seed contributors are automatically discovered by the ABP Framework and executed as a part of the data seed process. + +### DataSeedContext + +`DataSeedContext` contains `TenantId` if your application is [multi-tenant](Multi-Tenancy.md), so you can use this value while inserting data or performing custom logic based on the tenant. + +`DataSeedContext` also contains name-value style configuration parameters for passing to the seeder contributors from the `IDataSeeder`. + +## Modularity + +An application can have multiple data seed contributor (`IDataSeedContributor`) class. So, any reusable module can also implement this interface to seed its own initial data. + +For example, the [Identity Module](Modules/Identity.md) has a data seed contributor that creates an admin role and admin user and assign all the permissions. + ## IDataSeeder +> You typically never need to directly use the `IDataSeeder` service since it is already done if you've started with the [application startup template](Startup-Templates/Application.md). But its suggested to read it to understand the design behind the data seed system. + `IDataSeeder` is the main service that is used to seed initial data. It is pretty easy to use; ````csharp @@ -38,9 +109,27 @@ public class MyService : ITransientDependency } ```` -You can [inject](Dependency-Injection.md) the `IDataSeeder` and use it to seed the initial data. We will see the *IDataSeedContributor* section below to learn how to insert data. But before that, we should understand that: Where & how to execute the `IDataSeeder.SeedAsync()`? +You can [inject](Dependency-Injection.md) the `IDataSeeder` and use it to seed the initial data when you need. It internally calls all the `IDataSeedContributor` implementations to complete the data seeding. + +It is possible to send named configuration parameters to the `SeedAsync` method as shown below: -### On Production +````csharp +await _dataSeeder.SeedAsync( + new DataSeedContext() + .WithProperty("MyProperty1", "MyValue1") + .WithProperty("MyProperty2", 42) +); +```` + +Then the data seed contributors can access to these properties via the `DataSeedContext` explained before. + +If a module needs to a parameter, it should be declared on the [module documentation](Modules/Index.md). For example, the [Identity Module](Modules/Identity.md) can use `AdminEmail` and `AdminPassword` parameters if you provide (otherwise uses the default values). + +### Where & How to Seed Data? + +It is important to understand where & how to execute the `IDataSeeder.SeedAsync()`? + +#### On Production The [application startup template](Startup-Templates/Application.md) comes with a *YourProjectName***.DbMigrator** project (Acme.BookStore.DbMigrator on the picture below), which is a **console application** that is responsible to **migrate** the database schema (for relational databases) and **seed** the initial data: @@ -50,24 +139,22 @@ This console application is properly configured for you. It even supports **mult It is expected to run this DbMigrator application whenever you **deploy a new version** of your solution to the server. It will migrate your **database schema** (create new tables/fields... etc.) and **seed new initial data** needed to properly run the new version of your solution. Then you can deploy/start your actual application. -Even if you are using MongoDB or another NoSQL database, it is recommended to use the DbMigrator application to seed your data or perform your data migration. +Even if you are using MongoDB or another NoSQL database (that doesn't need to schema migrations), it is recommended to use the DbMigrator application to seed your data or perform your data migration. Having such a separate console application has several advantages; -* You can run it before updating your application, so your application will run on the ready database. -* Your application starts faster compared to if it seeds the initial data itself. -* Your application can properly run on a clustered environment (where multiple instances of your application run concurrently). If you seed data on application startup you would have conflicts in this case. +* You can **run it before** updating your application, so your application will run on the ready database. +* Your application **starts faster** compared to if it seeds the initial data itself. +* Your application can properly run on a **clustered environment** (where multiple instances of your application run concurrently). If you seed data on application startup you would have conflicts in this case. -### On Development +#### On Development We suggest the same way on development. Run the DbMigrator console application whenever you [create a database migration](https://docs.microsoft.com/en-us/ef/ef6/modeling/code-first/migrations/) (using EF Core `Add-Migration` command, for example) or change the data seed code (will be explained later). -You can continue to use the standard `Update-Database` command for EF Core, but it will not seed if you've created a new seed data. - -### On Testing +> You can continue to use the standard `Update-Database` command for EF Core, but it will not seed if you've created a new seed data. -TODO +#### On Testing -## IDataSeedContributor +You probably want to seed the data also for automated [testing](Testing.md), so want to use the `IDataSeeder.SeedAsync()`. In the [application startup template](Startup-Templates/Application.md), it is done in the [OnApplicationInitialization](Module-Development-Basics.md) method of the *YourProjectName*TestBaseModule class of the TestBase project. -TODO \ No newline at end of file +In addition to the standard seed data (that is also used on production), you may want to seed additional data unique to the automated tests. If so, you can create a new data seed contributor in the test project to have more data to work on. \ No newline at end of file From 5a4ea02ae74aade15f5237f0b40addd15b45a92b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Fri, 12 Jun 2020 13:01:59 +0300 Subject: [PATCH 65/81] Add API documentation URL. --- docs/en/docs-nav.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs-nav.json b/docs/en/docs-nav.json index 5b75278c0b..c2184c3cea 100644 --- a/docs/en/docs-nav.json +++ b/docs/en/docs-nav.json @@ -571,6 +571,10 @@ { "text": "Contribution Guide", "path": "Contribution/Index.md" + }, + { + "text": "API Documentation", + "path": "{ApiDocumentationUrl}" } ] } From 2da36a05705fe7f25fd52910b70835a4fe31c7be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Fri, 12 Jun 2020 13:05:37 +0300 Subject: [PATCH 66/81] Added Data Seeding --- docs/en/docs-nav.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs-nav.json b/docs/en/docs-nav.json index c2184c3cea..d384902edf 100644 --- a/docs/en/docs-nav.json +++ b/docs/en/docs-nav.json @@ -477,6 +477,10 @@ "path": "Dapper.md" } ] + }, + { + "text": "Data Seeding", + "path": "Data-Seeding.md" } ] }, From 2812d0b8f83667b4cc1b5fdbb09bd43c04997f36 Mon Sep 17 00:00:00 2001 From: Yunus Emre Kalkan Date: Fri, 12 Jun 2020 13:41:36 +0300 Subject: [PATCH 67/81] Removing duplicate content on Blog module index page resolves https://github.com/volosoft/volo/issues/2375 --- .../src/Volo.Blogging.Web/Pages/Blogs/Posts/Index.cshtml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Index.cshtml b/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Index.cshtml index 43c7ca2ce8..db9644a9ed 100644 --- a/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Index.cshtml +++ b/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Index.cshtml @@ -92,7 +92,7 @@ }
- @for (var index = 0; index < Model.Posts.Count && index < 3; index++) + @for (var index = 1; index < Model.Posts.Count && index < 4; index++) { var post = Model.Posts[index];
@@ -140,16 +140,16 @@
- @if (Model.Posts.Count > 3) + @if (Model.Posts.Count > 4) {

@L["LastPosts"]

- @for (var index = 3; index < Model.Posts.Count; index++) + @for (var index = 4; index < Model.Posts.Count; index++) { var post = Model.Posts[index]; - var oddPost = index % 2 == 1; + var oddPost = index % 2 == 0;
From a21fb0602c20c751a1e486fddda4e77ca26055ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Fri, 12 Jun 2020 14:58:13 +0300 Subject: [PATCH 68/81] Rename Clock to Timing. --- docs/en/AspNet-Boilerplate-Migration-Guide.md | 2 +- docs/en/Clock.md | 3 --- docs/en/Timing.md | 3 +++ docs/en/docs-nav.json | 4 ++++ 4 files changed, 8 insertions(+), 4 deletions(-) delete mode 100644 docs/en/Clock.md create mode 100644 docs/en/Timing.md diff --git a/docs/en/AspNet-Boilerplate-Migration-Guide.md b/docs/en/AspNet-Boilerplate-Migration-Guide.md index 39dd01eaa4..9929b6d24d 100644 --- a/docs/en/AspNet-Boilerplate-Migration-Guide.md +++ b/docs/en/AspNet-Boilerplate-Migration-Guide.md @@ -595,7 +595,7 @@ ABP Framework separates it and provides the setting management module (pre-added ASP.NET Boilerplate has a static `Clock` service ([see](https://aspnetboilerplate.com/Pages/Documents/Timing)) which is used to abstract the `DateTime` kind, so you can easily switch between Local and UTC times. You don't inject it, but just use the `Clock.Now` static method to obtain the current time. -ABP Framework has the `IClock` service ([see](Clock.md)) which has a similar goal, but now you need to inject it whenever you need it. +ABP Framework has the `IClock` service ([see](Timing.md)) which has a similar goal, but now you need to inject it whenever you need it. ### Event Bus diff --git a/docs/en/Clock.md b/docs/en/Clock.md deleted file mode 100644 index 46ef1235e0..0000000000 --- a/docs/en/Clock.md +++ /dev/null @@ -1,3 +0,0 @@ -# Clock - -TODO \ No newline at end of file diff --git a/docs/en/Timing.md b/docs/en/Timing.md new file mode 100644 index 0000000000..0fe80ee99b --- /dev/null +++ b/docs/en/Timing.md @@ -0,0 +1,3 @@ +# Timing + +TODO \ No newline at end of file diff --git a/docs/en/docs-nav.json b/docs/en/docs-nav.json index d384902edf..6efda6af9d 100644 --- a/docs/en/docs-nav.json +++ b/docs/en/docs-nav.json @@ -216,6 +216,10 @@ { "text": "GUID Generation", "path": "Guid-Generation.md" + }, + { + "text": "Timing", + "path": "Timing.md" } ] }, From 994a0fa777c07105bb53ea9c25011538c521e152 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Fri, 12 Jun 2020 16:18:53 +0300 Subject: [PATCH 69/81] Complete IClock part of the Timing document. --- docs/en/Json.md | 3 ++ docs/en/Timing.md | 98 ++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 docs/en/Json.md diff --git a/docs/en/Json.md b/docs/en/Json.md new file mode 100644 index 0000000000..f0082ea9d6 --- /dev/null +++ b/docs/en/Json.md @@ -0,0 +1,3 @@ +# JSON + +TODO \ No newline at end of file diff --git a/docs/en/Timing.md b/docs/en/Timing.md index 0fe80ee99b..f67bd5d180 100644 --- a/docs/en/Timing.md +++ b/docs/en/Timing.md @@ -1,3 +1,99 @@ # Timing -TODO \ No newline at end of file +Working with times & [time zones](https://en.wikipedia.org/wiki/Time_zone) is always tricky, especially if you need to build a **global system** that is used by users in **different time zones**. + +ABP provides a basic infrastructure to make it easy and handle automatically wherever possible. This document covers the ABP Framework services and systems related to time and time zones. + +> If you are creating a local application that runs in a single time zone region, you may not need all these systems. But even in this case, it is suggested to use the `IClock` service introduced in this document. + +## IClock + +`DateTime.Now` returns a `DateTime` object with the **local date & time of the server**. A `DateTime` object **doesn't store the time zone information**. So, you can not know the **absolute date & time** stored in this object. You can only make **assumptions**, like assuming that it was created in UTC+05 time zone. The things especially gets complicated when you save this value to a database and read later, or send it to a client in a **different time zone**. + +One solution to this problem is always use `DateTime.UtcNow` and assume all `DateTime` objects as UTC time. In this was, you can convert it to the time zone of the target client when needed. + +`IClock` provides an abstraction while getting the current time, so you can control the kind of the date time (UTC or local) in a single point in your application. + +**Example: Getting the current time** + +````csharp +using Volo.Abp.DependencyInjection; +using Volo.Abp.Timing; + +namespace AbpDemo +{ + public class MyService : ITransientDependency + { + private readonly IClock _clock; + + public MyService(IClock clock) + { + _clock = clock; + } + + public void Foo() + { + //Get the current time! + var now = _clock.Now; + } + } +} +```` + +* Inject the `IClock` service when you need to get the current time. Common base classes (like ApplicationService) already injects it and provides as a base property - so, you can directly use as `Clock`. +* Use the `Now` property to get the current time. + +> Most of the times, `IClock` is the only service you need to know and use in your application. + +### Clock Options + +`AbpClockOptions` is the [options](Options.md) class that used to set the clock kind. + +**Example: Use UTC Clock** + +````csharp +Configure(options => +{ + options.Kind = DateTimeKind.Utc; +}); +```` + +Write this inside the `ConfigureServices` method of your [module](Module-Development-Basics.md). + +> Default `Kind` is `Unspecified`, that actually make the Clock as it doesn't exists at all. Either make it `Utc` or `Local` if you want to get benefit of the Clock system. + +### DateTime Normalization + +Other important function of the `IClock` is to normalize `DateTime` objects. + +**Example usage:** + +````csharp +DateTime dateTime = ...; //Get from somewhere +var normalizedDateTime = Clock.Normalize(dateTime) +```` + +`Normalize` method works as described below: + +* Converts the given `DateTime` to the UTC (by using the `DateTime.ToUniversalTime()` method) if current Clock is UTC and given `DateTime` is local. +* Converts the given `DateTime` to the local (by using the `DateTime.ToLocalTime()` method) if current Clock is local and given `DateTime` is UTC. +* Sets `Kind` of the given `DateTime` (using the `DateTime.SpecifyKind(...)` method) to the `Kind` of the current Clock if given `DateTime`'s `Kind` is `Unspecified`. + +`Normalize` method is used by the ABP Framework when the it gets a `DateTime` that is not created by `IClock.Now` and may not be compatible with the current Clock type. Examples; + +* `DateTime` type binding in the ASP.NET Core MVC model binding. +* Saving data to and reading data from database via [Entity Framework Core](Entity-Framework-Core.md). +* Working with `DateTime` objects on [JSON deserialization](Json.md). + +#### DisableDateTimeNormalization Attribute + +`DisableDateTimeNormalization` attribute can be used to disable the normalization operation for desired classes or properties. + +### Other IClock Properties + +In addition to the `Now`, `IClock` service has the following properties: + +* `Kind`: Returns a `DateTimeKind` for the currently used clock type (`DateTimeKind.Utc`, `DateTimeKind.Local` or `DateTimeKind.Unspecified`). +* `SupportsMultipleTimezone`: Returns `true` if currently used clock is UTC. + +### \ No newline at end of file From 75b255f10f540c15ba8ccddc164d43697d353255 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Fri, 12 Jun 2020 18:25:29 +0300 Subject: [PATCH 70/81] Don't set null for the timing config. --- .../AbpApplicationConfigurationAppService.cs | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationAppService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationAppService.cs index f68d4d1450..6ad5b3276e 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationAppService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationAppService.cs @@ -188,7 +188,8 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations ThreeLetterIsoLanguageName = CultureInfo.CurrentUICulture.ThreeLetterISOLanguageName, DateTimeFormat = new DateTimeFormatDto { - CalendarAlgorithmType = CultureInfo.CurrentUICulture.DateTimeFormat.Calendar.AlgorithmType.ToString(), + CalendarAlgorithmType = + CultureInfo.CurrentUICulture.DateTimeFormat.Calendar.AlgorithmType.ToString(), DateTimeFormatLong = CultureInfo.CurrentUICulture.DateTimeFormat.LongDatePattern, ShortDatePattern = CultureInfo.CurrentUICulture.DateTimeFormat.ShortDatePattern, FullDateTimePattern = CultureInfo.CurrentUICulture.DateTimeFormat.FullDateTimePattern, @@ -238,25 +239,24 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations protected virtual async Task GetTimingConfigAsync() { - var result = new TimingDto(); - var windowsTimeZoneId = await _settingProvider.GetOrNullAsync(TimingSettingNames.TimeZone); - if (!windowsTimeZoneId.IsNullOrWhiteSpace()) + + return new TimingDto { - result.TimeZone = new TimeZone + TimeZone = new TimeZone { Windows = new WindowsTimeZone { TimeZoneId = windowsTimeZoneId }, - Iana = new IanaTimeZone() + Iana = new IanaTimeZone { - TimeZoneName = _timezoneProvider.WindowsToIana(windowsTimeZoneId) + TimeZoneName = windowsTimeZoneId.IsNullOrWhiteSpace() + ? null + : _timezoneProvider.WindowsToIana(windowsTimeZoneId) } - }; - } - - return result; + } + }; } protected virtual ClockDto GetClockConfig() @@ -267,4 +267,4 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations }; } } -} +} \ No newline at end of file From 4003b64ca10d05c29fa8c084761225fa333f350c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Fri, 12 Jun 2020 19:06:53 +0300 Subject: [PATCH 71/81] Added Application Configuration Endpoint document --- docs/en/API/Application-Configuration.md | 23 +++++++++++++++++++++++ docs/en/docs-nav.json | 9 +++++++++ 2 files changed, 32 insertions(+) create mode 100644 docs/en/API/Application-Configuration.md diff --git a/docs/en/API/Application-Configuration.md b/docs/en/API/Application-Configuration.md new file mode 100644 index 0000000000..db624987c5 --- /dev/null +++ b/docs/en/API/Application-Configuration.md @@ -0,0 +1,23 @@ +# Application Configuration Endpoint + +ABP Framework provides a pre-built and standard endpoint that contains some useful information about the application/service. Here, the list of some fundamental information at this endpoint: + +* [Localization](Localization.md) values, supported and the current language of the application. +* Available and granted [policies](Authorization.md) (permissions) for the current user. +* [Setting](Settings.md) values for the current user. +* Info about the [current user](CurrentUser.md) (like id and user name). +* Info about the current [tenant](Multi-Tenancy.md) (like id and name). +* [Time zone](Timing.md) information for the current user and the [clock](Timing.md) type of the application. + +## HTTP API + +If you navigate to the `/api/abp/application-configuration` URL of an ABP Framework based web application or HTTP Service, you can access the configuration as a JSON object. This endpoint is useful to create the client of your application. + +## Script + +For ASP.NET Core MVC (Razor Pages) applications, the same configuration values are also available on the JavaScript side. `/Abp/ApplicationConfigurationScript` is the URL of the script that is auto-generated based on the HTTP API above. + +See the [JavaScript API document](../UI/AspNetCore/JavaScript-API/Index.md) for the ASP.NET Core UI. + +Other UI types provide services native to the related platform. For example, see the [Angular UI localization documentation](../UI/Angular/Localization.md) to learn how to use the localization values exposes by this endpoint. + diff --git a/docs/en/docs-nav.json b/docs/en/docs-nav.json index 6efda6af9d..15abdb22ff 100644 --- a/docs/en/docs-nav.json +++ b/docs/en/docs-nav.json @@ -300,6 +300,15 @@ { "text": "Dynamic C# API Clients", "path": "API/Dynamic-CSharp-API-Clients.md" + }, + { + "text": "ABP Endpoints", + "items": [ + { + "text": "Application Configuration", + "path": "API/Application-Configuration.md" + } + ] } ] }, From 87078bbd2792cf535325c20817ea33a8fcdbbf22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Fri, 12 Jun 2020 19:07:47 +0300 Subject: [PATCH 72/81] Move JavaScript-API document and enhance timing doc. --- docs/en/API/JavaScript-API/Auth.md | 3 --- docs/en/AspNetCore/JavaScript-API/Auth.md | 3 --- docs/en/AspNetCore/JavaScript-API/Index.md | 3 --- docs/en/Timing.md | 16 +++++++++++++++- .../AspNetCore}/JavaScript-API/Index.md | 5 ++--- 5 files changed, 17 insertions(+), 13 deletions(-) delete mode 100644 docs/en/API/JavaScript-API/Auth.md delete mode 100644 docs/en/AspNetCore/JavaScript-API/Auth.md delete mode 100644 docs/en/AspNetCore/JavaScript-API/Index.md rename docs/en/{API => UI/AspNetCore}/JavaScript-API/Index.md (92%) diff --git a/docs/en/API/JavaScript-API/Auth.md b/docs/en/API/JavaScript-API/Auth.md deleted file mode 100644 index 60c9eb8866..0000000000 --- a/docs/en/API/JavaScript-API/Auth.md +++ /dev/null @@ -1,3 +0,0 @@ -# abp.auth JavaScript API - -TODO \ No newline at end of file diff --git a/docs/en/AspNetCore/JavaScript-API/Auth.md b/docs/en/AspNetCore/JavaScript-API/Auth.md deleted file mode 100644 index fb83bcfbff..0000000000 --- a/docs/en/AspNetCore/JavaScript-API/Auth.md +++ /dev/null @@ -1,3 +0,0 @@ -This document has moved. - -[Click to navigate to JavaScript Auth document](../../API/JavaScript-API/Auth.md) \ No newline at end of file diff --git a/docs/en/AspNetCore/JavaScript-API/Index.md b/docs/en/AspNetCore/JavaScript-API/Index.md deleted file mode 100644 index 1ed7f0285c..0000000000 --- a/docs/en/AspNetCore/JavaScript-API/Index.md +++ /dev/null @@ -1,3 +0,0 @@ -This document has moved. - -[Click to navigate to JavaScript API document](../../API/JavaScript-API/Index.md) \ No newline at end of file diff --git a/docs/en/Timing.md b/docs/en/Timing.md index f67bd5d180..fbdd899f22 100644 --- a/docs/en/Timing.md +++ b/docs/en/Timing.md @@ -96,4 +96,18 @@ In addition to the `Now`, `IClock` service has the following properties: * `Kind`: Returns a `DateTimeKind` for the currently used clock type (`DateTimeKind.Utc`, `DateTimeKind.Local` or `DateTimeKind.Unspecified`). * `SupportsMultipleTimezone`: Returns `true` if currently used clock is UTC. -### \ No newline at end of file +## Time Zones + +This section covers the ABP Framework infrastructure related to managing time zones. + +### TimeZone Setting + +ABP Framework defines a setting, named `Abp.Timing.Timezone`, that can be used to set and get the time zone for a user, [tenant](Multi-Tenancy.md) or globally for the application. The default value is `UTC`. + +See the [setting documentation](Settings.md) to learn more about the setting system. + +### ITimezoneProvider + +`ITimezoneProvider` is a service to simple convert [Windows Time Zone Id](https://support.microsoft.com/en-us/help/973627/microsoft-time-zone-index-values) values to [Iana Time Zone Name](https://www.iana.org/time-zones) values and vice verse. It also provides methods to get list of these time zones and get a `TimeZoneInfo` with a given name. + +It has been implemented using the [TimeZoneConverter](https://github.com/mj1856/TimeZoneConverter) library. \ No newline at end of file diff --git a/docs/en/API/JavaScript-API/Index.md b/docs/en/UI/AspNetCore/JavaScript-API/Index.md similarity index 92% rename from docs/en/API/JavaScript-API/Index.md rename to docs/en/UI/AspNetCore/JavaScript-API/Index.md index ca9afca97f..9f584eacfb 100644 --- a/docs/en/API/JavaScript-API/Index.md +++ b/docs/en/UI/AspNetCore/JavaScript-API/Index.md @@ -5,7 +5,7 @@ ABP provides some JavaScript APIs for ASP.NET Core MVC / Razor Pages application ## APIs * abp.ajax -* [abp.auth](Auth.md) +* abp.auth * abp.currentUser * abp.dom * abp.event @@ -20,5 +20,4 @@ ABP provides some JavaScript APIs for ASP.NET Core MVC / Razor Pages application * abp.utils * abp.ResourceLoader * abp.WidgetManager -* Other APIs - +* Other APIs \ No newline at end of file From 9f0e2bd0514f7278793846fb7c99af13d43151b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Fri, 12 Jun 2020 22:32:24 +0300 Subject: [PATCH 73/81] Update Timing.md --- docs/en/Timing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/Timing.md b/docs/en/Timing.md index fbdd899f22..4d48fa6d51 100644 --- a/docs/en/Timing.md +++ b/docs/en/Timing.md @@ -102,7 +102,7 @@ This section covers the ABP Framework infrastructure related to managing time zo ### TimeZone Setting -ABP Framework defines a setting, named `Abp.Timing.Timezone`, that can be used to set and get the time zone for a user, [tenant](Multi-Tenancy.md) or globally for the application. The default value is `UTC`. +ABP Framework defines **a setting**, named `Abp.Timing.Timezone`, that can be used to set and get the time zone for a user, [tenant](Multi-Tenancy.md) or globally for the application. The default value is `UTC`. See the [setting documentation](Settings.md) to learn more about the setting system. From ca47f5ad0c60d400f9938139de257b53b92fe003 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Sat, 13 Jun 2020 00:55:12 +0300 Subject: [PATCH 74/81] Complete the Data Transfer Objects document. --- docs/en/Application-Services.md | 4 +- docs/en/Data-Transfer-Objects.md | 281 ++++++++++++++++++++++++++++++- docs/en/Domain-Driven-Design.md | 4 +- docs/en/docs-nav.json | 3 +- 4 files changed, 285 insertions(+), 7 deletions(-) diff --git a/docs/en/Application-Services.md b/docs/en/Application-Services.md index f7f7675f46..d28a7290fb 100644 --- a/docs/en/Application-Services.md +++ b/docs/en/Application-Services.md @@ -2,7 +2,7 @@ Application services are used to implement the **use cases** of an application. They are used to **expose domain logic to the presentation layer**. -An Application Service is called from the presentation layer (optionally) with a **DTO (Data Transfer Object)** as the parameter. It uses domain objects to **perform some specific business logic** and (optionally) returns a DTO back to the presentation layer. Thus, the presentation layer is completely **isolated** from domain layer. +An Application Service is called from the presentation layer (optionally) with a **DTO ([Data Transfer Object](Data-Transfer-Objects.md))** as the parameter. It uses domain objects to **perform some specific business logic** and (optionally) returns a DTO back to the presentation layer. Thus, the presentation layer is completely **isolated** from domain layer. ## Example @@ -205,7 +205,7 @@ See the [object to object mapping document](Object-To-Object-Mapping.md) for mor ## Validation -Inputs of application service methods are automatically validated (like ASP.NET Core controller actions). You can use the standard data annotation attributes or custom validation method to perform the validation. ABP also ensures that the input is not null. +Inputs of application service methods are automatically validated (like ASP.NET Core controller actions). You can use the standard data annotation attributes or a custom validation method to perform the validation. ABP also ensures that the input is not null. See the [validation document](Validation.md) for more. diff --git a/docs/en/Data-Transfer-Objects.md b/docs/en/Data-Transfer-Objects.md index b0d80246f7..bc81205b66 100644 --- a/docs/en/Data-Transfer-Objects.md +++ b/docs/en/Data-Transfer-Objects.md @@ -1,3 +1,280 @@ -## Data Transfer Objects +# Data Transfer Objects -TODO \ No newline at end of file +## Introduction + +**Data Transfer Objects** (DTO) are used to transfer data between the **Application Layer** and the **Presentation Layer** or other type of clients. + +Typically, an [application service](Application-Services.md) is called from the presentation layer (optionally) with a **DTO** as the parameter. It uses domain objects to **perform some specific business logic** and (optionally) returns a DTO back to the presentation layer. Thus, the presentation layer is completely **isolated** from domain layer. + +### The Need for DTOs + +> **You can skip this section** if you feel that you know and confirm the benefits of using DTOs. + +At first, creating a DTO class for each application service method can be seen as tedious and time-consuming work. However, they can save your application if you correctly use them. Why & how? + +#### Abstraction of the Domain Layer + +DTOs provide an efficient way of **abstracting domain objects** from the presentation layer. In effect, your **layers** are correctly separated. If you want to change the presentation layer completely, you can continue with the existing application and domain layers. Alternatively, you can re-write your domain layer, completely change the database schema, entities and O/RM framework, all without changing the presentation layer. This, of course, is as long as the contracts (method signatures and DTOs) of your application services remain unchanged. + +#### Data Hiding + +Say you have a `User` entity with the properties Id, Name, EmailAddress and Password. If a `GetAllUsers()` method of a `UserAppService` returns a `List`, anyone can access the passwords of all your users, even if you do not show it on the screen. It's not just about security, it's about data hiding. Application services should return only what it needs by the presentation layer (or client). Not more, not less. + +#### Serialization & Lazy Load Problems + +When you return data (an object) to the presentation layer, it's most likely serialized. For example, in a REST API that returns JSON, your object will be serialized to JSON and sent to the client. Returning an Entity to the presentation layer can be problematic in that regard, especially if you are using a relational database and an ORM provider like Entity Framework Core. How? + +In a real-world application, your entities may have references to each other. The `User` entity can have a reference to it's `Role`s. If you want to serialize `User`, its `Role`s are also serialized. The `Role` class may have a `List` and the `Permission` class can has a reference to a `PermissionGroup` class and so on... Imagine all of these objects being serialized at once. You could easily and accidentally serialize your whole database! Also, if your objects have circular references, they may **not** be serialized at all. + +What's the solution? Marking properties as `NonSerialized`? No, you can not know when it should be serialized and when it shouldn't be. It may be needed in one application service method, and not needed in another. Returning safe, serializable, and specially designed DTOs is a good choice in this situation. + +Almost all O/RM frameworks support lazy-loading. It's a feature that loads entities from the database when they're needed. Say a `User` class has a reference to a `Role` class. When you get a `User` from the database, the `Role` property (or collection) is not filled. When you first read the `Role` property, it's loaded from the database. So, if you return such an Entity to the presentation layer, it will cause it to retrieve additional entities from the database by executing additional queries. If a serialization tool reads the entity, it reads all properties recursively and again your whole database can be retrieved (if there are relations between entities). + +More problems can arise if you use Entities in the presentation layer. **It's best not to reference the domain/business layer assembly in the presentation layer.** + +If you are convinced about using DTOs, we can continue to what ABP Framework provides and suggests about DTOs. + +> ABP doesn't force you to use DTOs, however using DTOs is **strongly suggested as a best practice**. + +## Standard Interfaces & Base Classes + +A DTO is a simple class that has no dependency and you can design it in any way. However, ABP introduces some **interfaces** to determine the **conventions** for naming **standard properties** and **base classes** to **don't repeat yourself** while declaring **common properties**. + +**None of them are required**, but using them **simplifies and standardizes** your application code. + +### Entity Related DTOs + +You typically create DTOs corresponding to your entities, which results similar classes to your entities. ABP Framework provides some base classes to simplify while creating such DTOs. + +#### EntityDto + +`IEntityDto` is a simple interface that only defines an `Id` property. You can implement it or inherit from the `EntityDto` for your DTOs that matches to an [entity](Entities.md). + +**Example:** + +````csharp +using System; +using Volo.Abp.Application.Dtos; + +namespace AbpDemo +{ + public class ProductDto : EntityDto + { + public string Name { get; set; } + //... + } +} +```` + +#### Audited DTOs + +If your entity inherits from audited entity classes (or implements auditing interfaces), you can use the following base classes to create your DTOs: + +* `CreationAuditedEntityDto` +* `CreationAuditedEntityWithUserDto` +* `AuditedEntityDto` +* `AuditedEntityWithUserDto` +* `FullAuditedEntityDto` +* `FullAuditedEntityWithUserDto` + +#### Extensible DTOs + +If you want to use the [object extension system](Object-Extensions.md) for your DTOs, you can use or inherit from the following DTO classes: + +* `ExtensibleObject` implements the `IHasExtraProperties` (other classes inherits this class). +* `ExtensibleEntityDto` +* `ExtensibleCreationAuditedEntityDto` +* `ExtensibleCreationAuditedEntityWithUserDto` +* `ExtensibleAuditedEntityDto` +* `ExtensibleAuditedEntityWithUserDto` +* `ExtensibleFullAuditedEntityDto` +* `ExtensibleFullAuditedEntityWithUserDto` + +### List Results + +It is common to return a list of DTOs to the client. `IListResult` interface and `ListResultDto` class is used to make it standard. + +The definition of the `IListResult` interface: + +````csharp +public interface IListResult +{ + IReadOnlyList Items { get; set; } +} +```` + +**Example: Return a list of products** + +````csharp +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Application.Services; +using Volo.Abp.Domain.Repositories; + +namespace AbpDemo +{ + public class ProductAppService : ApplicationService, IProductAppService + { + private readonly IRepository _productRepository; + + public ProductAppService(IRepository productRepository) + { + _productRepository = productRepository; + } + + public async Task> GetListAsync() + { + //Get entities from the repository + List products = await _productRepository.GetListAsync(); + + //Map entities to DTOs + List productDtos = + ObjectMapper.Map, List>(products); + + //Return the result + return new ListResultDto(productDtos); + } + } +} +```` + +You could simply return the `productDtos` object (and change the method return type) and it has nothing wrong. Returning a `ListResultDto` makes your `List` wrapped into another object as an `Items` property. This has one advantage: You can later add more properties to your return value without breaking your remote clients (when they get the value as a JSON result). So, it is especially suggested when you are developing reusable application modules. + +### Paged & Sorted List Results + +It is more common to request a paged list from server and return a paged list to the client. ABP defines a few interface and classes to standardize it: + +#### Input (Request) Types + +The following interfaces and classes is to standardize the input sent by the clients. + +* `ILimitedResultRequest`: Defines a `MaxResultCount` (`int`) property to request a limited result from the server. +* `IPagedResultRequest`: Inherits from the `ILimitedResultRequest` (so it inherently has the `MaxResultCount` property) and defines a `SkipCount` (`int`) to declare the skip count while requesting a paged result from the server. +* `ISortedResultRequest`: Defines a `Sorting` (`string`) property to request a sorted result from the server. Sorting value can be "*Name*", "*Name DESC*", "*Name ASC, Age DESC*"... etc. +* `IPagedAndSortedResultRequest` inherits from both of the `IPagedResultRequest` and `ISortedResultRequest`, so has `MaxResultCount`, `SkipCount` and `Sorting` properties. + +Instead of implementing the interfaces manually, it is suggested to inherit one of the following base DTO classes: + +* `LimitedResultRequestDto` implements `ILimitedResultRequest`. +* `PagedResultRequestDto` implements `IPagedResultRequest` (and inherits from the `LimitedResultRequestDto`). +* `PagedAndSortedResultRequestDto` implements `IPagedAndSortedResultRequest` (and inherit from the `PagedResultRequestDto`). + +##### Max Result Count + +`LimitedResultRequestDto` (and inherently the others) limits and validates the `MaxResultCount` by the following rules; + +* If the client doesn't set `MaxResultCount`, it is assumed as **10** (the default page size). This value can be changed by setting the `LimitedResultRequestDto.DefaultMaxResultCount` static property. +* If the client sends `MaxResultCount` greater than **1,000**, it produces a **validation error**. It is important to protect the server from abuse of the service. If you want, you can change this value by setting the `LimitedResultRequestDto.MaxMaxResultCount` static property. + +Static properties suggested to be set on application startup since they are static (global). + +#### Output (Response) Types + +The following interfaces and classes is to standardize the output sent to the clients. + +* `IHasTotalCount` defines a `TotalCount` (`long`) property to return the total count of the records in case of paging. +* `IPagedResult` inherits from the `IListResult` and `IHasTotalCount`, so it has the `Items` and `TotalCount` properties. + +Instead of implementing the interfaces manually, it is suggested to inherit one of the following base DTO classes: + +* `PagedResultDto` inherits from the `ListResultDto` and also implements the `IPagedResult`. + +**Example: Request a paged & sorted result from server and return a paged list** + +````csharp +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Dynamic.Core; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Application.Services; +using Volo.Abp.Domain.Repositories; + +namespace AbpDemo +{ + public class ProductAppService : ApplicationService, IProductAppService + { + private readonly IRepository _productRepository; + + public ProductAppService(IRepository productRepository) + { + _productRepository = productRepository; + } + + public async Task> GetListAsync( + PagedAndSortedResultRequestDto input) + { + //Create the query + var query = _productRepository + .OrderBy(input.Sorting) + .Skip(input.SkipCount) + .Take(input.MaxResultCount); + + //Get total count from the repository + var totalCount = await query.CountAsync(); + + //Get entities from the repository + List products = await query.ToListAsync(); + + //Map entities to DTOs + List productDtos = + ObjectMapper.Map, List>(products); + + //Return the result + return new PagedResultDto(totalCount, productDtos); + } + } +} +```` + +ABP Framework also defines a `PageBy` extension method (that is compatible with the `IPagedResultRequest`) that can be used instead of `Skip` + `Take` calls: + +````csharp +var query = _productRepository + .OrderBy(input.Sorting) + .PageBy(input); +```` + +> Notice that we added `Volo.Abp.EntityFrameworkCore` package to the project to be able to use the `ToListAsync` and `CountAsync` methods since they are not included in the standard LINQ, but defined by the Entity Framework Core. + +See also the [repository documentation](Repositories.md) to if you haven't understood the example code. + +## Related Topics + +### Validation + +Inputs of [application service](Application-Services.md) methods, controller actions, page model inputs... are automatically validated. You can use the standard data annotation attributes or a custom validation method to perform the validation. + +See the [validation document](Validation.md) for more. + +### Object to Object Mapping + +When you create a DTO that is related to an entity, you generally need to map these objects. ABP provides an object to object mapping system to simplify the mapping process. See the following documents: + +* [Object to Object Mapping document](Object-To-Object-Mapping.md) covers all the features. +* [Application Services document](Application-Services.md) provides a full example. + +## Best Practices + +You are free to design your DTO classes. However, there are some best practices & suggestions that you may want to follow. + +### Common Principles + +* DTOs should be **well serializable** since they are generally serialized and deserialized (to JSON or other format). It is suggested to have an empty (parameterless) public constructor if you have another constructor with parameter(s). +* DTOs **should not contain any business logic**, except some formal [validation](Validation.md) code. +* Do not inherit DTOs from entities and **do not reference to entities**. The [application startup template](Startup-Templates/Application.md) already prevents it by separating the projects. +* If you use an auto [object to object mapping](Object-To-Object-Mapping.md) library, like AutoMapper, enable the **mapping configuration validation** to prevent potential bugs. + +### Input DTO Principles + +* Define only the **properties needed** for the use case. Do not include properties not used for the use case, which confuses developers if you do so. + +* **Don't reuse** input DTOs among different application service methods. Because, different use cases will need to and use different properties of the DTO which results some properties are not used in some cases and that makes harder to understand and use the services and causes potential bugs in the future. + +### Output DTO Principles + +* You can **reuse output DTOs** if you **fill all the properties** on all the cases. \ No newline at end of file diff --git a/docs/en/Domain-Driven-Design.md b/docs/en/Domain-Driven-Design.md index 4f2d06be7d..ce33295492 100644 --- a/docs/en/Domain-Driven-Design.md +++ b/docs/en/Domain-Driven-Design.md @@ -2,7 +2,7 @@ ## What is DDD? -ABP framework provides an **infrastructure** to make **DDD** based development easier to implement. DDD is [defined in the Wikipedia](https://en.wikipedia.org/wiki/Domain-driven_design) as below: +ABP framework provides an **infrastructure** to make **Domain Driven Design** based development easier to implement. DDD is [defined in the Wikipedia](https://en.wikipedia.org/wiki/Domain-driven_design) as below: > **Domain-driven design** (**DDD**) is an approach to software development for complex needs by connecting the implementation to an evolving model. The premise of domain-driven design is the following: > @@ -16,7 +16,7 @@ ABP follows DDD principles and patterns to achieve a layered application model w - **Presentation Layer**: Provides an interface to the user. Uses the *Application Layer* to achieve user interactions. - **Application Layer**: Mediates between the Presentation and Domain Layers. Orchestrates business objects to perform specific application tasks. Implements use cases as the application logic. -- **Domain Layer**: Includes business objects and their business rules. This is the heart of the application. +- **Domain Layer**: Includes business objects and the core (domain) business rules. This is the heart of the application. - **Infrastructure Layer**: Provides generic technical capabilities that support higher layers mostly using 3rd-party libraries. ## Contents diff --git a/docs/en/docs-nav.json b/docs/en/docs-nav.json index 15abdb22ff..b3c57338eb 100644 --- a/docs/en/docs-nav.json +++ b/docs/en/docs-nav.json @@ -281,7 +281,8 @@ "path": "Application-Services.md" }, { - "text": "Data Transfer Objects" + "text": "Data Transfer Objects", + "path": "Data-Transfer-Objects.md" }, { "text": "Unit Of Work" From f1bbd7c24bd536acf8062245079c4aca1b818adb Mon Sep 17 00:00:00 2001 From: "liangshiw@outlook.com" Date: Sat, 13 Jun 2020 13:42:06 +0800 Subject: [PATCH 75/81] Translate document --- docs/en/Data-Seeding.md | 2 +- docs/zh-Hans/API/Application-Configuration.md | 22 ++ docs/zh-Hans/Application-Services.md | 2 +- docs/zh-Hans/Blob-Storing-Database.md | 2 + docs/zh-Hans/Data-Seeding.md | 161 +++++++++- docs/zh-Hans/Data-Transfer-Objects.md | 281 +++++++++++++++++- docs/zh-Hans/Domain-Driven-Design.md | 2 +- docs/zh-Hans/Entities.md | 6 +- docs/zh-Hans/Guid-Generation.md | 112 ++++++- docs/zh-Hans/Timing.md | 113 +++++++ .../UI/AspNetCore/JavaScript-API/Index.md | 23 ++ .../AspNetCore/Tag-Helpers/Button-groups.md | 37 +++ .../UI/AspNetCore/Tag-Helpers/Carousel.md | 71 +++++ docs/zh-Hans/docs-nav.json | 28 +- 14 files changed, 839 insertions(+), 23 deletions(-) create mode 100644 docs/zh-Hans/API/Application-Configuration.md create mode 100644 docs/zh-Hans/Timing.md create mode 100644 docs/zh-Hans/UI/AspNetCore/JavaScript-API/Index.md create mode 100644 docs/zh-Hans/UI/AspNetCore/Tag-Helpers/Button-groups.md create mode 100644 docs/zh-Hans/UI/AspNetCore/Tag-Helpers/Carousel.md diff --git a/docs/en/Data-Seeding.md b/docs/en/Data-Seeding.md index d6236da9d9..8827fe96c0 100644 --- a/docs/en/Data-Seeding.md +++ b/docs/en/Data-Seeding.md @@ -70,7 +70,7 @@ namespace Acme.BookStore * `IDataSeedContributor` defines the `SeedAsync` method to execute the **data seed logic**. * It is typical to **check database** if the seeding data is already present. -* You can **inject** and service and perform any logic needed to seed the data. +* You can **inject** service and perform any logic needed to seed the data. > Data seed contributors are automatically discovered by the ABP Framework and executed as a part of the data seed process. diff --git a/docs/zh-Hans/API/Application-Configuration.md b/docs/zh-Hans/API/Application-Configuration.md new file mode 100644 index 0000000000..ba062d9cef --- /dev/null +++ b/docs/zh-Hans/API/Application-Configuration.md @@ -0,0 +1,22 @@ +# 应用程序配置端点 + +ABP框架提供了一个预构建的标准端点,其中包含一些有关应用程序/服务的有用信息. 这里是此端点的一些基本信息的列表: + +* [本地化](Localization.md)值, 支持应用程序的当前语言. +* 当前用户可用和已授予的[策略](Authorization.md)(权限). +* 当前用户的[设置](Settings.md)值. +* 关于[当前用户](CurrentUser.md)的信息 (如 id 和用户名). +* 关于当前[租户](Multi-Tenancy.md)的信息 (如 id 和名称). +* 当前用户的[时区](Timing.md)信息和应用程序的[时钟](Timing.md)类型. + +## HTTP API + +如果您导航到基于ABP框架的web应用程序或HTTP服务的 `/api/abp/application-configuration` URL, 你可以得到JSON对象形式配置. 该端点对于创建应用程序的客户端很有用. + +## Script + +对于ASP.NET Core MVC(剃刀页)应用程序,同样的配置值在JavaScript端也可用. `/Abp/ApplicationConfigurationScript` 是基于上述HTTP API自动生成的脚本的URL. + +参阅 [JavaScript API文档](../UI/AspNetCore/JavaScript-API/Index.md) 了解关于ASP.NET Core UI. + +其他UI类型提供相关平台的本地服务. 例如查看[Angular UI本地化文档](../UI/Angular/Localization.md)来学习如何使用这个端点公开的本地化值. \ No newline at end of file diff --git a/docs/zh-Hans/Application-Services.md b/docs/zh-Hans/Application-Services.md index d0e29c2881..6bb18daa37 100644 --- a/docs/zh-Hans/Application-Services.md +++ b/docs/zh-Hans/Application-Services.md @@ -2,7 +2,7 @@ 应用服务实现应用程序的**用例**, 将**领域层逻辑公开给表示层**. -从表示层(可选)调用应用服务,**DTO (数据传对象)** 作为参数. 返回(可选)DTO给表示层. +从表示层(可选)调用应用服务,**DTO ([数据传对象](Data-Transfer-Objects.md))** 作为参数. 返回(可选)DTO给表示层. ## 示例 diff --git a/docs/zh-Hans/Blob-Storing-Database.md b/docs/zh-Hans/Blob-Storing-Database.md index 653aa9f904..e45c79d179 100644 --- a/docs/zh-Hans/Blob-Storing-Database.md +++ b/docs/zh-Hans/Blob-Storing-Database.md @@ -53,6 +53,8 @@ abp add-module Volo.Abp.BlobStoring.Database ### 配置容器 +如果只使用数据库存储提供程序,则不需要手动配置,因为它是自动完成的. 如果使用多个存储提供程序,可能需要对其进行配置. + 如同[BLOB存储文档](Blob-Storing.md)所述,配置是在[模块](Module-Development-Basics.md)类的 `ConfigureServices` 方法完成的. **示例: 配置为默认使用数据库系统存储提供程序** diff --git a/docs/zh-Hans/Data-Seeding.md b/docs/zh-Hans/Data-Seeding.md index 0b424e7e0d..68f6fc1e73 100644 --- a/docs/zh-Hans/Data-Seeding.md +++ b/docs/zh-Hans/Data-Seeding.md @@ -1,3 +1,160 @@ -# Data Seeding +# 种子数据 -TODO \ No newline at end of file +## 介绍 + +使用数据库的某些应用程序(或模块),可能需要有一些**初始数据**才能​​够正常启动和运行. 例如**管理员用户**和角色必须在一开始就可用. 否则你就无法**登录**到应用程序创建新用户和角色. + +数据种子也可用于[测试](Testing.md)的目的,你的自动测试可以假定数据库中有一些可用的初始数据. + +### 为什么要有种子数据系统? + +尽管EF Core Data Seeding系统提供了一种方法,但它非常有限,不包括生产场景. 此外它仅适用于EF Core. + +ABP框架提供了种子数据系统; + +* **模块化**: 任何[模块](Module-Development-Basics.md)都可以无声地参与数据播种过程,而不相互了解和影响. 通过这种方式模块将种子化自己的初始数据. +* **数据库独立**: 它不仅适用于 EF Core, 也使用其他数据库提供程序(如 [MongoDB](MongoDB.md)). +* **生产准备**: 它解决了生产环境中的问题. 参见下面的*On Production*部分. +* **依赖注入**: 它充分利用了依赖项注入,你可以在播种初始数据时使用任何内部或外部服务. 实际上你可以做的不仅仅是数据播种. + +## IDataSeedContributor + +将数据种子化到数据库需要实现 `IDataSeedContributor` 接口. + +**示例: 如果没有图书,则向数据库播种一个初始图书** + +````csharp +using System; +using System.Threading.Tasks; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Domain.Repositories; +using Volo.Abp.Guids; + +namespace Acme.BookStore +{ + public class BookStoreDataSeedContributor + : IDataSeedContributor, ITransientDependency + { + private readonly IRepository _bookRepository; + private readonly IGuidGenerator _guidGenerator; + + public BookStoreDataSeedContributor( + IRepository bookRepository, + IGuidGenerator guidGenerator) + { + _bookRepository = bookRepository; + _guidGenerator = guidGenerator; + } + + public async Task SeedAsync(DataSeedContext context) + { + if (await _bookRepository.GetCountAsync() > 0) + { + return; + } + + var book = new Book( + id: _guidGenerator.Create(), + name: "The Hitchhiker's Guide to the Galaxy", + type: BookType.ScienceFiction, + publishDate: new DateTime(1979, 10, 12), + price: 42 + ); + + await _bookRepository.InsertAsync(book); + } + } +} +```` + +* `IDataSeedContributor` 定义了 `SeedAsync` 方法用于执行 **数据种子逻辑**. +* 通常**检查数据库**是否已经存在种子数据. +* 你可以**注入**服务,检查数据播种所需的任何逻辑. + +> 数据种子贡献者由ABP框架自动发现,并作为数据播种过程的一部分执行. + +### DataSeedContext + +如果你的应用程序是[多租户](Multi-Tenancy.md), `DataSeedContext` 包含 `TenantId`,因此你可以在插入数据或基于租户执行自定义逻辑时使用该值. + +`DataSeedContext` 还包含用于从 `IDataSeeder` 传递到种子提供者的name-value配置参数. + +## 模块化 + +一个应用程序可以具有多个种子数据贡献者(`IDataSeedContributor`)类. 任何可重用模块也可以实现此接口播种其自己的初始数据. + +例如[Identity模块](Modules/Identity.md)有一个种子数据贡献者,它创建一个管理角色和管理用户并分配所有权限. + +## IDataSeeder + +> 通常你不需要直接使用 `IDataSeeder` 服务,因为如果你从[应用程序启动模板](Startup-Templates/Application.md)开始,该服务已经完成. 但是建议阅读以了解种子数据系统背后的设计. + +`IDataSeeder` 是用于生成初始数据的主要服务. 使用它很容易; + +````csharp +public class MyService : ITransientDependency +{ + private readonly IDataSeeder _dataSeeder; + + public MyService(IDataSeeder dataSeeder) + { + _dataSeeder = dataSeeder; + } + + public async Task FooAsync() + { + await _dataSeeder.SeedAsync(); + } +} +```` + +你可以[注入](Dependency-Injection.md) `IDataSeeder` 并且在你需要时使用它初始化种子数据. 它内部调用 `IDataSeedContributor` 的实现去完成数据播种. + +可以将命名的配置参数发送到 `SeedAsync` 方法,如下所示: + +````csharp +await _dataSeeder.SeedAsync( + new DataSeedContext() + .WithProperty("MyProperty1", "MyValue1") + .WithProperty("MyProperty2", 42) +); +```` + +然后种子数据提供者可以通过前面解释的 `DataSeedContext` 访问这些属性. + +如果模块需要参数,应该在[模块文档](Modules/Index.md)中声明它. 例如[Identity Module](Modules/Identity.md)使用 `AdminEmail` 和 `AdminPassword` 参数,如果你提供了(默认使用默认值). + +### 在何处以及如何播种数据? + +重要的是要了解在何处以及如何执行 `IDataSeeder.SeedAsync()`. + +#### On Production + +[应用程序启动模板](Startup-Templates/Application.md)带有一个*YourProjectName***.DbMigrator** 项目(图中的Acme.BookStore.DbMigrator). 这是一个**控制台应用程序**,负责**迁移**数据库架构(关系数据库)和初始种子数据: + +![bookstore-visual-studio-solution-v3](images/bookstore-visual-studio-solution-v3.png) + +控制台应用程序已经为你正确配置,它甚至支持**多租户**场景,其中每个租户拥有自己的数据库(迁移和必须的数据库). + +当你将解决方案的**新版本部署到服务器**时,都需要运行这个DbMigrator应用程序. 它会迁移你的**数据库架构**(创建新的表/字段…)和播种正确运行解决方案的新版本所需的**新初始数据**. 然后就可以部署/启动实际的应用程序了. + +即使你使用的是MongoDB或其他NoSQL数据库(不需要进行架构迁移),也建议使用DbMigrator应用程序为你的数据添加种子或执行数据迁移. + +有这样一个单独的控制台应用程序有几个优点; + +* 你可以在更新你的应用程序**之前运行它**,所以你的应用程序可以在准备就绪的数据库上运行. +* 与本身初始化种子数据相比,你的应用程序**启动速度更快**. +* 应用程序可以在**集群环境**中正确运行(其中应用程序的多个实例并发运行). 在这种情况下如果在应用程序启动时播种数据就会有冲突. + +#### On Development + +我们建议以相同的方式进行开发. 每当你[创建数据库迁移](https://docs.microsoft.com/en-us/ef/ef6/modeling/code-first/migrations/)(例如使用EF Core `Add-Migration` 命令)或更改数据种子代码(稍后说明)时,请运行DbMigrator控制台应用程序. + +> 你可以使用EF Core继续执行标准的 `Update-Database` 命令,但是它不会初始化种子数据. + +#### On Testing + +你可能想为自动[测试](Testing.md)初始化数据种子, 这需要使用 `IDataSeeder.SeedAsync()`. 在[应用程序启动模板](Startup-Templates/Application.md)中,它在TestBase项目的*YourProjectName*TestBaseModule类的[OnApplicationInitialization](Module-Development-Basics.md)方法中完成. + +除了标准种子数据(也在生产中使用)之外,你可能还希望为自动测试添加其他种子数据. 你可以在测试项目中创建一个新的数据种子贡献者以处理更多数据. \ No newline at end of file diff --git a/docs/zh-Hans/Data-Transfer-Objects.md b/docs/zh-Hans/Data-Transfer-Objects.md index b0d80246f7..eb844e7ea7 100644 --- a/docs/zh-Hans/Data-Transfer-Objects.md +++ b/docs/zh-Hans/Data-Transfer-Objects.md @@ -1,3 +1,280 @@ -## Data Transfer Objects +# 数据传输对象 -TODO \ No newline at end of file +## 介绍 + +**数据传输对象**(DTO)用于在**应用层**和**表示层**或其他类型的客户端之间传输数据. + +通常用**DTO**作为参数在表示层(可选)调用[应用服务](Application-Services.md). 它使用领域对象执行某些**特定的业务逻辑**,并(可选)将DTO返回到表示层.因此表示层与领域层完全**隔离**. + +### DTO的需求 + +> 如果你感觉你已经知道并确认使用DTO的好处,你可以**跳过这一节**. + +首先为每个应用程序服务方法创建DTO类可能被看作是一项冗长而耗时的工作. 但是如果正确使用它们,它们可以保存在应用程序. 为什么和如何> + +#### 领域层的抽象 + +DTO提供了一种从表示层**抽象领域对象**的有效方法. 实际上你的**层**被正确地分开了. 如果希望完全更改表示层,可以继续使用现有的应用程序层和领域层. 或者你可以重写领域层完全更改数据库架构,实体和O/RM框架,而无需更改表示层. 当然前提是应用程序服务的契约(方法签名和dto)保持不变. + +#### 数据隐藏 + +假设你有一个具有属性Id,名称,电子邮件地址和密码的 `User` 实体. 如果 `UserAppService` 的 `GetAllUsers()` 方法返回 `List`,任何人都可以访问你所有用户的密码,即使你没有在屏幕上显示它. 这不仅关乎安全,还关乎数据隐藏. 应用程序服务应该只返回表示层(或客户端)所需要的内容,不多也不少. + +#### 序列化和延迟加载问题 + +当你将数据(一个对象)返回到表示层时,它很可能是序列化的. 例如在返回JSON的REST API中,你的对象将被序列化为JSON并发送给客户端. 在这方面将实体返回到表示层可能会有问题,尤其是在使用关系数据库和像Entity Framework Core这样的ORM提供者时. + +在真实的应用程序中你的实体可以相互引用. `User` 实体可以引用它的角色. 如果你想序列化用户,它的角色也必须是序列化的. `Role` 类可以有 `List `,而 `Permission` 类可以有一个对 `PermissionGroup` 类的引用,依此类推...想象一下所有这些对象都被立即序列化了. 你可能会意外地序列化整个数据库! 同样,如果你的对象具有循环引用,则它们可能根本**不会**序列化成功. + +有什么解决方案? 将属性标记为 `NonSerialized` 吗? 不,你不知道什么时候应该序列化什么时候应该序列化. 一个应用程序服务方法可能需要它,而另一个则不需要. 在这种情况下返回安全,可序列化且经过特殊设计的DTO是一个不错的选择. + +几乎所有的O/RM框架都支持延迟加载. 此功能可在需要时从数据库加载实体. 假设 `User` 类具有对 `Role` 类的引用. 当你从数据库中获取用户时,`Role` 属性(或集合)不会被立即填充. 首次读取 `Role` 属性时,它是从数据库加载的. 因此如果将这样的实体返回到表示层,它将通过执行额外的查询从数据库中检索额外的实体. 如果序列化工具读取实体,它会递归读取所有属性,并且可以再次检索整个数据库(如果实体之间存在关系). + +如果在表示层中使用实体,可能会出现更多问题.**最好不要在表示层中引用领域/业务层程序集**. + +如果你确定使用DTO,我们可以继续讨论ABP框架提供的关于dto的建议. + +> ABP并不强迫你使用DTO,但是**强烈建议将DTO作为最佳实践**. + +## 标准接口和基类 + +DTO是一个没有依赖性的简单类,你可以用任何方式进行设计. 但是ABP引入了一些**接口**来确定命名**标准属性**和**基类**的**约定**,以免在声明**公共属性**时**重复工作**. + +**它们都不是必需的**,但是使用它们可以**简化和标准化**应用程序代码. + +### 实体相关DTO + +通常你需要创建与你的实体相对应的DTO,从而生成与实体类似的类. ABP框架在创建DTO时提供了一些基类来简化. + +#### EntityDto + +`IEntityDto` 是一个只定义 `Id` 属性的简单接口. 你可以实现它或从 `EntityDto` 继承. + +**Example:** + +````csharp +using System; +using Volo.Abp.Application.Dtos; + +namespace AbpDemo +{ + public class ProductDto : EntityDto + { + public string Name { get; set; } + //... + } +} +```` + +#### 审计DTO + +如果你的实体继承自被审计的实体类(或实现审计接口)可以使用以下基类来创建DTO: + +* `CreationAuditedEntityDto` +* `CreationAuditedEntityWithUserDto` +* `AuditedEntityDto` +* `AuditedEntityWithUserDto` +* `FullAuditedEntityDto` +* `FullAuditedEntityWithUserDto` + +#### 可扩展的DTO + +如果你想为你的DTO使用[对象扩展系统](Object-Extensions.md),你可以使用或继承以下DTO类: + +* `ExtensibleObject` 实现 `IHasExtraProperties` (其它类继承这个类). +* `ExtensibleEntityDto` +* `ExtensibleCreationAuditedEntityDto` +* `ExtensibleCreationAuditedEntityWithUserDto` +* `ExtensibleAuditedEntityDto` +* `ExtensibleAuditedEntityWithUserDto` +* `ExtensibleFullAuditedEntityDto` +* `ExtensibleFullAuditedEntityWithUserDto` + +### 列表结果 + +通常将DTO列表返回给客户端. `IListResult` 接口和 `ListResultDto` 类用于使其成为标准. + +`IListResult` 接口的定义: + +````csharp +public interface IListResult +{ + IReadOnlyList Items { get; set; } +} +```` + +**示例: 返回产品列表** + +````csharp +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Application.Services; +using Volo.Abp.Domain.Repositories; + +namespace AbpDemo +{ + public class ProductAppService : ApplicationService, IProductAppService + { + private readonly IRepository _productRepository; + + public ProductAppService(IRepository productRepository) + { + _productRepository = productRepository; + } + + public async Task> GetListAsync() + { + //Get entities from the repository + List products = await _productRepository.GetListAsync(); + + //Map entities to DTOs + List productDtos = + ObjectMapper.Map, List>(products); + + //Return the result + return new ListResultDto(productDtos); + } + } +} +```` + +你可以简单地返回 `productDtos` 对象(并更改方法的返回类型), 这也没有错. 返回一个 `ListResultDto` 会使`List` 做为 `Item` 属性包装到另一个对象中. 这具有一个优点:以后可以在不破坏远程客户端的情况下(当它们作为JSON结果获得值时)在返回值中添加更多属性. 在开发可重用的应用程序模块时特别建议使用这种方式. + +### 分页 & 排序列表结果 + +从服务器请求分页列表并将分页列表返回给客户端是更常见的情况. ABP定义了一些接口和类来对其进行标准化: + +#### 输入 (请求) 类型 + +以下接口和类用于标准化客户端发送的输入. + +* `ILimitedResultRequest`: 定义 `MaxResultCount`(`int`) 属性从服务器请求指定数量的结果. +* `IPagedResultRequest`: 继承自 `ILimitedResultRequest` (所以它具有 `MaxResultCount` 属性)并且定义了 `SkipCount` (`int`)用于请求服务器的分页结果时跳过计数. +* `ISortedResultRequest`: 定义 `Sorting` (`string`)属性以请求服务器的排序结果. 排序值可以是“名称”,"*Name*", "*Name DESC*", "*Name ASC, Age DESC*"... 等. +* `IPagedAndSortedResultRequest` 继承自 `IPagedResultRequest` 和 `ISortedResultRequest`,所以它有上述所有属性. + +建议你继承以下基类DTO类之一,而不是手动实现接口: + +* `LimitedResultRequestDto` 实现了 `ILimitedResultRequest`. +* `PagedResultRequestDto` 实现了 `IPagedResultRequest` (和继承自 `LimitedResultRequestDto`). +* `PagedAndSortedResultRequestDto` 实现了 `IPagedAndSortedResultRequest` (和继承自 `PagedResultRequestDto`). + +##### 最大返回数量 + +`LimitedResultRequestDto`(和其它固有的)通过以下规则限制和验证 `MaxResultCount`; + +* 如果客户端未设置 `MaxResultCount`,则假定为**10**(默认页面大小). 可以通过设置 `LimitedResultRequestDto.DefaultMaxResultCoun` t静态属性来更改此值. +* 如果客户端发送的 `MaxResultCount` 大于*1,000**,则会产生**验证错误**. 保护服务器免受滥用服务很重要. 如果需要可以通过设置 `LimitedResultRequestDto.MaxMaxResultCount` 静态属性来更改此值. + +建议在应用程序启动时设置静态属性,因为它们是静态的(全局). + +#### 输出 (响应) 类型 + +以下接口和类用于标准化发送给客户端的输出. + +* `IHasTotalCount` 定义 `TotalCount`(`long`)属性以在分页的情况下返回记录的总数. +* `IPagedResult` 集成自 `IListResult` 和 `IHasTotalCount`, 所以它有 `Items` 和 `TotalCount` 属性. + +建议你继承以下基类DTO类之一,而不是手动实现接口: + +* `PagedResultDto` 继承自 `ListResultDto` 和实现了 `IPagedResult`. + +**示例: 从服务器请求分页和排序的结果并返回分页列表** + +````csharp +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Dynamic.Core; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Application.Services; +using Volo.Abp.Domain.Repositories; + +namespace AbpDemo +{ + public class ProductAppService : ApplicationService, IProductAppService + { + private readonly IRepository _productRepository; + + public ProductAppService(IRepository productRepository) + { + _productRepository = productRepository; + } + + public async Task> GetListAsync( + PagedAndSortedResultRequestDto input) + { + //Create the query + var query = _productRepository + .OrderBy(input.Sorting) + .Skip(input.SkipCount) + .Take(input.MaxResultCount); + + //Get total count from the repository + var totalCount = await query.CountAsync(); + + //Get entities from the repository + List products = await query.ToListAsync(); + + //Map entities to DTOs + List productDtos = + ObjectMapper.Map, List>(products); + + //Return the result + return new PagedResultDto(totalCount, productDtos); + } + } +} +```` + +ABP框架还定义了一种 `PageBy` 扩展方法(与`IPagedResultRequest`兼容),可用于代替 `Skip` + `Take`调用: + +````csharp +var query = _productRepository + .OrderBy(input.Sorting) + .PageBy(input); +```` + +> 注意我们将`Volo.Abp.EntityFrameworkCore`包添加到项目中以使用 `ToListAsync` 和 `CountAsync` 方法,因为它们不包含在标准LINQ中,而是由Entity Framework Core定义. + +如果你不了解示例代码,另请参阅[仓储文档](Repositories.md). + +## 相关话题 + +### 验证 + +[应用服务](Application-Services.md)方法,控制器操作,页面模型输入...的输入会自动验证. 你可以使用标准数据注释属性或自定义验证方法来执行验证. + +参阅[验证文档](Validation.md)了解更多. + +### 对象到对象的映射 + +创建与实体相关的DTO时通常需要映射这些对象. ABP提供了一个对象到对象的映射系统简化映射过程. 请参阅以下文档: + +* [对象到对象映射文档](Object-To-Object-Mapping.md)介绍了这些功能. +* [应用服务文档](Application-Services.md)提供了完整的示例. + +## 最佳实践 + +你可以自由设计DTO类,然而这里有一些你可能想要遵循的最佳实践和建议. + +### 共同原则 + +* DTO应该是**可序列化的**,因为它们通常是序列化和反序列化的(JSON或其他格式). 如果你有另一个带参数的构造函数,建议使用空(无参数)的公共构造函数. +* 除某些[验证](Validation.md)代码外,DTO**不应包含任何业务逻辑**. +* DTO不要继承实体,也**不要引用实体**. [应用程序启动模板](Startup-Templates/Application.md)已经通过分隔项目来阻止它. +* 如果你使用自动[对象到对象](Object-To-Object-Mapping.md)映射库,如AutoMapper,请启用**映射配置验证**以防止潜在的错误. + +### 输入DTO原则 + +* 只定义用例**所需的属性**. 不要包含不用于用例的属性,这样做会使开发人员感到困惑. + +* **不要在**不同的应用程序服务方法之间重用输入DTO. 因为不同的用例将需要和使用DTO的不同属性,从而导致某些属性在某些情况下没有使用,这使得理解和使用服务更加困难,并在将来导致潜在的错误. + +### 输出DTO原则 + +* 如果在所有情况下填充**所有属性**,就可以**重用输出DTO**. \ No newline at end of file diff --git a/docs/zh-Hans/Domain-Driven-Design.md b/docs/zh-Hans/Domain-Driven-Design.md index 2197d35f50..d088f7596b 100644 --- a/docs/zh-Hans/Domain-Driven-Design.md +++ b/docs/zh-Hans/Domain-Driven-Design.md @@ -2,7 +2,7 @@ ## 什么是DDD? -ABP框架提供了**基础设施**使基于**DDD**的开发更易实现. DDD在[维基百科中的定义](https://zh.wikipedia.org/wiki/%E5%9F%9F%E9%A9%B1%E5%8A%A8%E5%BC%80%E5%8F%91)如下: +ABP框架提供了**基础设施**使基于**领域驱动设计**的开发更易实现. DDD在[维基百科中的定义](https://zh.wikipedia.org/wiki/%E5%9F%9F%E9%A9%B1%E5%8A%A8%E5%BC%80%E5%8F%91)如下: > **领域驱动设计(DDD)** 是一种通过将实现连接到持续进化的模型来满足复杂需求的软件开发方法. 领域驱动设计的前提是: > diff --git a/docs/zh-Hans/Entities.md b/docs/zh-Hans/Entities.md index fd8528dc30..190088753f 100644 --- a/docs/zh-Hans/Entities.md +++ b/docs/zh-Hans/Entities.md @@ -26,9 +26,9 @@ public class Book : Entity 如果你的实体Id类型为 `Guid`,有一些好的实践可以实现: * 创建一个构造函数,获取ID作为参数传递给基类. - * 如果没有为GUID Id斌值,ABP框架会在保存时设置它,但是在将实体保存到数据库之前最好在实体上有一个有效的Id. -* 如果使用带参数的构造函数创建实体,那么还要创建一个 `protected` 构造函数. 当数据库提供程序从数据库读取你的实体时(反序列化时)将使用它. -* 不要使用 `Guid.NewGuid()` 来设置Id! 在创建实体的代码中使用[`IGuidGenerator`服务](Guid-Generation.md)传递Id参数. `IGuidGenerator`经过优化可以产生连续的GUID.这对于关系数据库中的聚集索引非常重要. + * 如果没有为GUID Id斌值,**ABP框架会在保存时设置它**,但是在将实体保存到数据库之前最好在实体上有一个有效的Id. +* 如果使用带参数的构造函数创建实体,那么还要创建一个 `private` 或 `protected` 构造函数. 当数据库提供程序从数据库读取你的实体时(反序列化时)将使用它. +* 不要使用 `Guid.NewGuid()` 来设置Id! 在创建实体的代码中**使用[`IGuidGenerator`服务](Guid-Generation.md)**传递Id参数. `IGuidGenerator`经过优化可以产生连续的GUID.这对于关系数据库中的聚集索引非常重要. 示例实体: diff --git a/docs/zh-Hans/Guid-Generation.md b/docs/zh-Hans/Guid-Generation.md index be0c1f425b..1b097f8b08 100644 --- a/docs/zh-Hans/Guid-Generation.md +++ b/docs/zh-Hans/Guid-Generation.md @@ -1,3 +1,111 @@ -## Guid 生成 +# GUID 生成 -待添加 +GUID是数据库管理系统中使用的常见**主键类型**, ABP框架更喜欢GUID作为预构建[应用模块](Modules/Index.md)的主要对象. `ICurrentUser.Id` 属性([参见文档](CurrentUser.md))是GUID类型,这意味着ABP框架假定用户ID始终是GUID, + +## 为什么偏爱GUID? + +GUID有优缺点. 你可以在网上找到许多与此主题相关的文章,因此我们不再赘述,而是列出了最基本的优点: + +* 它可在所有数据库提供程序中**使用**. +* 它允许在客户端**确定主键**,而不需要通过**数据库往返**来生成Id值. 在向数据库插入新记录时,这可以提高性能并允许我们在与数据库交互之前知道PK. +* GUID是**自然唯一的**在以下情况下有一些优势; + * 你需要与**外部**系统集成, + * 你需要**拆分或合并**不同的表. + * 你正在创建**分布式系统** +* GUID是无法猜测的,因此在某些情况下与自动递增的Id值相比,GUID**更安全**. + +尽管存在一些缺点(只需在Web上搜索),但在设计ABP框架时我们发现这些优点更为重要. + +## IGuidGenerator + +GUID的最重要问题是**默认情况下它不是连续的**. 当你将GUID用作主键并将其设置为表的**聚集索引**(默认设置)时,这会在**插入时带来严重的性能问题**(因为插入新记录可能需要对现有记录进行重新排序). + +所以,**永远不要为你的实体使用 `Guid.NewGuid()` 创建ID**!. + +这个问题的一个好的解决方案是生成**连续的GUID**,由ABP框架提供的开箱即用的. `IGuidGenerator` 服务创建顺序的GUID(默认由 `SequentialGuidGenerator` 实现). 当需要手动设置[实体](Entities.md)的Id时,请使用 `IGuidGenerator.Create()`. + +**示例: 具有GUID主键的实体并创建该实体** + +假设你有一个具有 `Guid` 主键的 `Product` [实体](Entities.md): + +````csharp +using System; +using Volo.Abp.Domain.Entities; + +namespace AbpDemo +{ + public class Product : AggregateRoot + { + public string Name { get; set; } + + private Product() { /* This constructor is used by the ORM/database provider */ } + + public Product(Guid id, string name) + : base(id) + { + Name = name; + } + } +} +```` + +然后你想要创建一个产品: + +````csharp +using System; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Domain.Repositories; +using Volo.Abp.Guids; + +namespace AbpDemo +{ + public class MyProductService : ITransientDependency + { + private readonly IRepository _productRepository; + private readonly IGuidGenerator _guidGenerator; + + public MyProductService( + IRepository productRepository, + IGuidGenerator guidGenerator) + { + _productRepository = productRepository; + _guidGenerator = guidGenerator; + } + + public async Task CreateAsync(string productName) + { + var product = new Product(_guidGenerator.Create(), productName); + + await _productRepository.InsertAsync(product); + } + } +} +```` + +该服务将 `IGuidGenerator` 注入构造函数中. 如果你的类是[应用服务](Application-Services.md)或派生自其他基类之一,可以直接使用 `GuidGenerator` 基类属性,该属性是预先注入的 `IGuidGenerator` 实例. + +## Options + +### AbpSequentialGuidGeneratorOptions + +`AbpSequentialGuidGeneratorOptions` 是用于配置顺序生成GUID的[选项类](Options.md). 它只有一个属性: + +* `DefaultSequentialGuidType` (`SequentialGuidType` 类型的枚举): 生成GUID值时使用的策略. + +数据库提供程序在处理GUID时的行为有所不同,你应根据数据库提供程序进行设置. `SequentialGuidType` 有以下枚举成员: + +* `SequentialAtEnd` (**default**) 用于[SQL Server](Entity-Framework-Core.md). +* `SequentialAsString` 用于[MySQL](Entity-Framework-Core-MySQL.md)和[PostgreSQL](Entity-Framework-Core-PostgreSQL.md). +* `SequentialAsBinary` 用于[Oracle](Entity-Framework-Core-Oracle.md). + +在你的[模块](Module-Development-Basics.md)的 `ConfigureServices` 方法配置选项,如下: + +````csharp +Configure(options => +{ + options.DefaultSequentialGuidType = SequentialGuidType.SequentialAsBinary; +}); +```` + +> EF Core[集成包](https://docs.abp.io/en/abp/latest/Entity-Framework-Core-Other-DBMS)已为相关的DBMS设置相应的值. 如果你正在使用这些集成包,在大多数情况下则无需设置此选项. diff --git a/docs/zh-Hans/Timing.md b/docs/zh-Hans/Timing.md new file mode 100644 index 0000000000..71ddbb9058 --- /dev/null +++ b/docs/zh-Hans/Timing.md @@ -0,0 +1,113 @@ +# 时钟 + +使用时间和[时区](https://en.wikipedia.org/wiki/Time_zone)总是很棘手,尤其是当你需要构建供**不同时区**的用户使用的**全局系统**时. + +ABP提供了一个基本的基础结构,使其变得容易并在可能的情况下自动进行处理. 本文档涵盖了与时间和时区相关的ABP框架服务和系统. + +> 如果你正在创建在单个时区区域运行的本地应用程序,则可能不需要这些系统. 但也建议使用本文中介绍的 `IClock` 服务. + +## IClock + +`DateTime.Now` 返回带有**服务器本地日期和时间**的 `DateTime` 对象. `DateTime` 对象**不存储时区信息**. 因此你无法知道此对象中存储的**绝对日期和时间**. 你只能做一些**假设**,例如假设它是在UTC+05时区创建的. 当你此值保存到数据库中并稍后读取,或发送到**不同时区**的客户端时,事情就变得特别复杂. + +解决此问题的一种方法是始终使用 `DateTime.UtcNow` 并将所有 `DateTime` 对象假定为UTC时间. 在这种情况下你可以在需要时将其转换为目标客户端的时区. + +`IClock` 在获取当前时间的同时提供了一种抽象,你可以在应用程序中的单个点上控制日期时间的类型(UTC或本地时间). + +**示例: 获取当前时间** + +````csharp +using Volo.Abp.DependencyInjection; +using Volo.Abp.Timing; + +namespace AbpDemo +{ + public class MyService : ITransientDependency + { + private readonly IClock _clock; + + public MyService(IClock clock) + { + _clock = clock; + } + + public void Foo() + { + //Get the current time! + var now = _clock.Now; + } + } +} +```` + +* 当你需要获取当前时间时注入 `IClock` 服务. 常用的服务基类(如ApplicationService)已经注入并且做为基类属性提供,所以你可以直接使用 `Clock`. +* 使用 `Now` 属性获取当前时间. + +> 在大多数情况下 `IClock` 是你需要在应用程序中了解和使用的唯一服务. + +### Clock 选项 + +`AbpClockOptions` 是用于设置时钟种类的[选项](Options.md)类. + +**示例: 使用 UTC Clock** + +````csharp +Configure(options => +{ + options.Kind = DateTimeKind.Utc; +}); +```` + +在你的[模块](Module-Development-Basics.md)的 `ConfigureServices` 方法添加以上内容. + +> 默认 `Kind` 是 `Unspecified`,实际上使时钟不存在. 如果要利用Clock系统,要么使用 `Utc` 或 `Local`. + +### DateTime 标准化 + +`IClock` 的其他重要功能是规范化 `DateTime` 对象. + +**示例用法 :** + +````csharp +DateTime dateTime = ...; //Get from somewhere +var normalizedDateTime = Clock.Normalize(dateTime) +```` + +`Normalize` 方法的工作原理如下: + +* 如果当前时钟为UTC,并且给定的 `DateTime` 为本地时间,将给定的 `DateTime` 转换为UTC(通过使用 `DateTime.ToUniversalTime()` 方法). +* 如果当前时钟是本地的,并且给定的 `DateTime` 是UTC,将给定的 `DateTime` 转换为本地时间(通过使用 `DateTime.ToUniversalTime()` 方法). +* 如果未指定给定的 `DateTime` 的 `Kind`,将给定的 `DateTime` 的 `Kind`(使用 `DateTime.SpecifyKind(...)` 方法)设置为当前时钟的 `Kind`. + +当获取的 `DateTime` 不是由 `IClock` 创建且可能与当前Clock类型不兼容的时候,ABP框架会使用 `Normalize` 方法. 例如; + +* ASP.NET Core MVC模型绑定中的 `DateTime` 类型绑定. +* 通过[Entity Framework Core](Entity-Framework-Core.md)将数据保存到数据库或从数据库读取数据. +* 在[JSON反序列化](Json.md)上使用 `DateTime` 对象. + +#### DisableDateTimeNormalization Attribute + +`DisableDateTimeNormalization` attribute可用于禁用所需类或属性的规范化操作. + +### 其他 IClock 属性 + +除了 `Now`, `IClock` 服务还具有以下属性: + +* `Kind`: 返回当前使用的时钟类型(`DateTimeKind.Utc`, `DateTimeKind.Local` 或 `DateTimeKind.Unspecified`)的 `DateTimeKind`. +* `SupportsMultipleTimezone`: 如果当前时间是UTC,则返回 `true`. + +## 时区 + +本节介绍与管理时区有关的ABP框架基础结构 + +### 时区设置 + +ABP框架定义了一个名为 `Abp.Timing.Timezone` 的**设置**,可用于为应用程序的用户,[租户](Multi-Tenancy.md)或全局设置和获取时区. 默认值为 `UTC`. + +参阅[设置系统]了解更多关于设置系统. + +### ITimezoneProvider + +`ITimezoneProvider` 是一个服务,可将[Windows时区ID](https://support.microsoft.com/en-us/help/973627/microsoft-time-zone-index-values)值简单转换为[Iana时区名称](https://www.iana.org/time-zones)值,反之亦然. 它还提供了获取这些时区列表与获取具有给定名称的 `TimeZoneInfo` 的方法. + +它已使用[TimeZoneConverter](https://github.com/mj1856/TimeZoneConverter)库实现. \ No newline at end of file diff --git a/docs/zh-Hans/UI/AspNetCore/JavaScript-API/Index.md b/docs/zh-Hans/UI/AspNetCore/JavaScript-API/Index.md new file mode 100644 index 0000000000..b06025cd16 --- /dev/null +++ b/docs/zh-Hans/UI/AspNetCore/JavaScript-API/Index.md @@ -0,0 +1,23 @@ +# JavaScript API + +ABP为ASP.NET Core MVC / Razor页面应用程序提供了一些执行客户端常见需求的JavaScrpt Api. + +## APIs + +* abp.ajax +* [abp.auth] +* abp.currentUser +* abp.dom +* abp.event +* abp.features +* abp.localization +* abp.log +* abp.ModalManager +* abp.notify +* abp.security +* abp.setting +* abp.ui +* abp.utils +* abp.ResourceLoader +* abp.WidgetManager +* Other APIs \ No newline at end of file diff --git a/docs/zh-Hans/UI/AspNetCore/Tag-Helpers/Button-groups.md b/docs/zh-Hans/UI/AspNetCore/Tag-Helpers/Button-groups.md new file mode 100644 index 0000000000..b69f39c7b4 --- /dev/null +++ b/docs/zh-Hans/UI/AspNetCore/Tag-Helpers/Button-groups.md @@ -0,0 +1,37 @@ +# 按钮组 + +## 介绍 + +`abp-button-group` 是创建分组按钮的主要元素. + +基本用法: + +````csharp + + Left + Middle + Right + +```` + +## Demo + +参阅[按钮组demo页面](https://bootstrap-taghelpers.abp.io/Components/Button-groups)查看示例. + +## Attributes + +### direction + +按钮的方向. 应为以下值之一: + +* `Horizontal` (默认值) +* `Vertical` + +### size + +组中按钮的大小. 应为以下值之一: + +* `Default` (默认值) +* `Small` +* `Medium` +* `Large` diff --git a/docs/zh-Hans/UI/AspNetCore/Tag-Helpers/Carousel.md b/docs/zh-Hans/UI/AspNetCore/Tag-Helpers/Carousel.md new file mode 100644 index 0000000000..f230428c15 --- /dev/null +++ b/docs/zh-Hans/UI/AspNetCore/Tag-Helpers/Carousel.md @@ -0,0 +1,71 @@ +# 轮播 + +## 介绍 + +`abp-carousel` 是abp标签轮播元素 + +基本用法: + +````csharp + + + + + +```` + +## Demo + +参阅[轮播demo页面](https://bootstrap-taghelpers.abp.io/Components/Carousel)查看示例. + +## Attributes + +### id + +轮播的ID. 如果未设置则会生成一个ID. + +### controls + +用于启用轮播上的控件(previous和next按钮). 应为以下值之一: + +* `false` +* `true` + +### indicators + +启用轮播指标. 应为以下值之一: + +* `false` +* `true` + +### crossfade + +用于启用淡入淡出动画而不是在轮播上滑动. 应为以下值之一: + +* `false` +* `true` + +## abp-carousel-item Attributes + +### caption-title + +设置轮播项的标题 + +### caption + +设置轮播项的说明. + +### src + +链接值设置显示在轮播项上的图像的来源. + +### active + +设置活动轮播项. 应为以下值之一: + +* `false` +* `true` + +### alt + +当无法显示图像时,该值设置轮播项目图像的替代文本. \ No newline at end of file diff --git a/docs/zh-Hans/docs-nav.json b/docs/zh-Hans/docs-nav.json index 2a2c66ebb6..d105400184 100644 --- a/docs/zh-Hans/docs-nav.json +++ b/docs/zh-Hans/docs-nav.json @@ -216,19 +216,12 @@ "path": "Text-Templating.md" }, { - "text": "JSON序列化" + "text": "GUID 生成", + "path": "Guid-Generation.md" }, { - "text": "邮件" - }, - { - "text": "GUIDs" - }, - { - "text": "线程" - }, - { - "text": "定时" + "text": "时钟", + "path": "Timing.md" } ] }, @@ -309,6 +302,15 @@ { "text": "动态C# API客户端", "path": "API/Dynamic-CSharp-API-Clients.md" + }, + { + "text": "ABP端点", + "items": [ + { + "text": "应用程序配置", + "path": "API/Application-Configuration.md" + } + ] } ] }, @@ -481,6 +483,10 @@ "path": "Dapper.md" } ] + }, + { + "text": "种子数据", + "path": "Data-Seeding.md" } ] }, From eca7781dc187e6c360dc98449236a7502863a976 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Sun, 14 Jun 2020 00:01:39 +0300 Subject: [PATCH 76/81] Revised IAsyncQueryableExecuter and implemented chain of responsibility to support multiple providers in a single application. --- .../Services/AbstractKeyCrudAppService.cs | 7 +-- .../Services/ApplicationService.cs | 5 ++ .../Volo/Abp/Domain/Services/DomainService.cs | 4 ++ .../EfCoreAsyncQueryableProvider.cs | 34 +++++++++++ .../Repositories/MongoDB/MongoDbRepository.cs | 2 - .../MongoDB/MongoDbAsyncQueryableProvider.cs | 35 ++++++++++++ .../Volo/Abp/Linq/AsyncQueryableExecuter.cs | 53 +++++++++++++++++ .../Abp/Linq/DefaultAsyncQueryableExecuter.cs | 37 ------------ .../Volo/Abp/Linq/IAsyncQueryableExecuter.cs | 20 ++++--- .../Volo/Abp/Linq/IAsyncQueryableProvider.cs | 18 ++++++ .../Volo/Abp/Threading/AbpThreadingModule.cs | 2 - .../EfCoreAsyncQueryableProvider_Tests.cs | 57 +++++++++++++++++++ .../MongoDbAsyncQueryableProvider_Tests.cs | 57 +++++++++++++++++++ .../TestApp/Application/DistrictAppService.cs | 2 +- 14 files changed, 278 insertions(+), 55 deletions(-) create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/EfCoreAsyncQueryableProvider.cs create mode 100644 framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoDbAsyncQueryableProvider.cs create mode 100644 framework/src/Volo.Abp.Threading/Volo/Abp/Linq/AsyncQueryableExecuter.cs delete mode 100644 framework/src/Volo.Abp.Threading/Volo/Abp/Linq/DefaultAsyncQueryableExecuter.cs create mode 100644 framework/src/Volo.Abp.Threading/Volo/Abp/Linq/IAsyncQueryableProvider.cs create mode 100644 framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/EfCoreAsyncQueryableProvider_Tests.cs create mode 100644 framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/MongoDbAsyncQueryableProvider_Tests.cs diff --git a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AbstractKeyCrudAppService.cs b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AbstractKeyCrudAppService.cs index 45915826e4..e6f433cad6 100644 --- a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AbstractKeyCrudAppService.cs +++ b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AbstractKeyCrudAppService.cs @@ -6,7 +6,6 @@ using Volo.Abp.Application.Dtos; using Volo.Abp.Auditing; using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Repositories; -using Volo.Abp.Linq; using Volo.Abp.MultiTenancy; using Volo.Abp.ObjectMapping; @@ -66,7 +65,6 @@ namespace Volo.Abp.Application.Services ICrudAppService where TEntity : class, IEntity { - public IAsyncQueryableExecuter AsyncQueryableExecuter { get; set; } protected IRepository Repository { get; } @@ -83,7 +81,6 @@ namespace Volo.Abp.Application.Services protected AbstractKeyCrudAppService(IRepository repository) { Repository = repository; - AsyncQueryableExecuter = DefaultAsyncQueryableExecuter.Instance; } public virtual async Task GetAsync(TKey id) @@ -100,12 +97,12 @@ namespace Volo.Abp.Application.Services var query = CreateFilteredQuery(input); - var totalCount = await AsyncQueryableExecuter.CountAsync(query); + var totalCount = await AsyncExecuter.CountAsync(query); query = ApplySorting(query, input); query = ApplyPaging(query, input); - var entities = await AsyncQueryableExecuter.ToListAsync(query); + var entities = await AsyncExecuter.ToListAsync(query); return new PagedResultDto( totalCount, diff --git a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ApplicationService.cs b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ApplicationService.cs index df0aa25f0d..900343800f 100644 --- a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ApplicationService.cs +++ b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ApplicationService.cs @@ -9,9 +9,11 @@ using System.Collections.Generic; using System.Threading.Tasks; using Volo.Abp.Aspects; using Volo.Abp.Auditing; +using Volo.Abp.Authorization; using Volo.Abp.DependencyInjection; using Volo.Abp.Features; using Volo.Abp.Guids; +using Volo.Abp.Linq; using Volo.Abp.Localization; using Volo.Abp.MultiTenancy; using Volo.Abp.ObjectMapping; @@ -59,6 +61,9 @@ namespace Volo.Abp.Application.Services protected IUnitOfWorkManager UnitOfWorkManager => LazyGetRequiredService(ref _unitOfWorkManager); private IUnitOfWorkManager _unitOfWorkManager; + + protected IAsyncQueryableExecuter AsyncExecuter => LazyGetRequiredService(ref _asyncExecuter); + private IAsyncQueryableExecuter _asyncExecuter; protected Type ObjectMapperContext { get; set; } protected IObjectMapper ObjectMapper diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Services/DomainService.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Services/DomainService.cs index 36cade51be..9792cbd0e6 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Services/DomainService.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Services/DomainService.cs @@ -3,6 +3,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp.Guids; +using Volo.Abp.Linq; using Volo.Abp.MultiTenancy; using Volo.Abp.Timing; @@ -38,6 +39,9 @@ namespace Volo.Abp.Domain.Services protected ICurrentTenant CurrentTenant => LazyGetRequiredService(ref _currentTenant); private ICurrentTenant _currentTenant; + + protected IAsyncQueryableExecuter AsyncExecuter => LazyGetRequiredService(ref _asyncExecuter); + private IAsyncQueryableExecuter _asyncExecuter; protected ILogger Logger => _lazyLogger.Value; private Lazy _lazyLogger => new Lazy(() => LoggerFactory?.CreateLogger(GetType().FullName) ?? NullLogger.Instance, true); diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/EfCoreAsyncQueryableProvider.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/EfCoreAsyncQueryableProvider.cs new file mode 100644 index 0000000000..f9ef8c86e0 --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/EfCoreAsyncQueryableProvider.cs @@ -0,0 +1,34 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Query.Internal; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Linq; + +namespace Volo.Abp.EntityFrameworkCore +{ + public class EfCoreAsyncQueryableProvider : IAsyncQueryableProvider, ITransientDependency + { + public bool CanExecute(IQueryable queryable) + { + return queryable.Provider is EntityQueryProvider; + } + + public Task CountAsync(IQueryable queryable, CancellationToken cancellationToken = default) + { + return queryable.CountAsync(cancellationToken); + } + + public Task> ToListAsync(IQueryable queryable, CancellationToken cancellationToken = default) + { + return queryable.ToListAsync(cancellationToken); + } + + public Task FirstOrDefaultAsync(IQueryable queryable, CancellationToken cancellationToken = default) + { + return queryable.FirstOrDefaultAsync(cancellationToken); + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs index 956bc7853f..3ac6ab5239 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs @@ -15,8 +15,6 @@ using Volo.Abp.EventBus.Local; using Volo.Abp.Guids; using Volo.Abp.MongoDB; using Volo.Abp.MultiTenancy; -using Volo.Abp.Reflection; -using Volo.Abp.Threading; namespace Volo.Abp.Domain.Repositories.MongoDB { diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoDbAsyncQueryableProvider.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoDbAsyncQueryableProvider.cs new file mode 100644 index 0000000000..8b0c56c812 --- /dev/null +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoDbAsyncQueryableProvider.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Linq; +using MongoDB.Driver; +using MongoDB.Driver.Linq; + +namespace Volo.Abp.MongoDB +{ + public class MongoDbAsyncQueryableProvider : IAsyncQueryableProvider, ITransientDependency + { + public bool CanExecute(IQueryable queryable) + { + return queryable.Provider.GetType().Namespace?.StartsWith("MongoDB") ?? false; + } + + public Task CountAsync(IQueryable queryable, CancellationToken cancellationToken = default) + { + return ((IMongoQueryable) queryable).CountAsync(cancellationToken); + } + + public Task> ToListAsync(IQueryable queryable, CancellationToken cancellationToken = default) + { + return ((IMongoQueryable) queryable).ToListAsync(cancellationToken); + } + + public Task FirstOrDefaultAsync(IQueryable queryable, CancellationToken cancellationToken = default) + { + return ((IMongoQueryable) queryable).FirstOrDefaultAsync(cancellationToken); + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Threading/Volo/Abp/Linq/AsyncQueryableExecuter.cs b/framework/src/Volo.Abp.Threading/Volo/Abp/Linq/AsyncQueryableExecuter.cs new file mode 100644 index 0000000000..3548f81ad1 --- /dev/null +++ b/framework/src/Volo.Abp.Threading/Volo/Abp/Linq/AsyncQueryableExecuter.cs @@ -0,0 +1,53 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Linq +{ + public class AsyncQueryableExecuter : IAsyncQueryableExecuter, ITransientDependency + { + protected IEnumerable Providers { get; } + + public AsyncQueryableExecuter(IEnumerable providers) + { + Providers = providers; + } + + public virtual Task CountAsync( + IQueryable queryable, + CancellationToken cancellationToken = default) + { + var provider = FindProvider(queryable); + return provider != null + ? provider.CountAsync(queryable, cancellationToken) + : Task.FromResult(queryable.Count()); + } + + public virtual Task> ToListAsync( + IQueryable queryable, + CancellationToken cancellationToken = default) + { + var provider = FindProvider(queryable); + return provider != null + ? provider.ToListAsync(queryable, cancellationToken) + : Task.FromResult(queryable.ToList()); + } + + public virtual Task FirstOrDefaultAsync( + IQueryable queryable, + CancellationToken cancellationToken = default) + { + var provider = FindProvider(queryable); + return provider != null + ? provider.FirstOrDefaultAsync(queryable, cancellationToken) + : Task.FromResult(queryable.FirstOrDefault()); + } + + protected virtual IAsyncQueryableProvider FindProvider(IQueryable queryable) + { + return Providers.FirstOrDefault(p => p.CanExecute(queryable)); + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Threading/Volo/Abp/Linq/DefaultAsyncQueryableExecuter.cs b/framework/src/Volo.Abp.Threading/Volo/Abp/Linq/DefaultAsyncQueryableExecuter.cs deleted file mode 100644 index 2a5da24a58..0000000000 --- a/framework/src/Volo.Abp.Threading/Volo/Abp/Linq/DefaultAsyncQueryableExecuter.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace Volo.Abp.Linq -{ - public class DefaultAsyncQueryableExecuter : IAsyncQueryableExecuter - { - public static DefaultAsyncQueryableExecuter Instance { get; } = new DefaultAsyncQueryableExecuter(); - - private DefaultAsyncQueryableExecuter() - { - - } - - public Task CountAsync(IQueryable queryable) - { - return Task.FromResult(queryable.Count()); - } - - public Task> ToListAsync(IQueryable queryable) - { - return Task.FromResult(queryable.ToList()); - } - - public Task FirstOrDefaultAsync(IQueryable queryable) - { - return Task.FromResult(queryable.FirstOrDefault()); - } - - public Task FirstOrDefaultAsync(IQueryable queryable, CancellationToken cancellationToken) - { - return Task.FromResult(queryable.FirstOrDefault()); - } - } -} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Threading/Volo/Abp/Linq/IAsyncQueryableExecuter.cs b/framework/src/Volo.Abp.Threading/Volo/Abp/Linq/IAsyncQueryableExecuter.cs index f2c34fd2ad..0a19318c40 100644 --- a/framework/src/Volo.Abp.Threading/Volo/Abp/Linq/IAsyncQueryableExecuter.cs +++ b/framework/src/Volo.Abp.Threading/Volo/Abp/Linq/IAsyncQueryableExecuter.cs @@ -5,17 +5,21 @@ using System.Threading.Tasks; namespace Volo.Abp.Linq { - /// - /// This interface is intended to be used by ABP. - /// public interface IAsyncQueryableExecuter { - Task CountAsync(IQueryable queryable); + Task CountAsync( + IQueryable queryable, + CancellationToken cancellationToken = default + ); - Task> ToListAsync(IQueryable queryable); + Task> ToListAsync( + IQueryable queryable, + CancellationToken cancellationToken = default + ); - Task FirstOrDefaultAsync(IQueryable queryable); - - Task FirstOrDefaultAsync(IQueryable queryable, CancellationToken cancellationToken); + Task FirstOrDefaultAsync( + IQueryable queryable, + CancellationToken cancellationToken = default + ); } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.Threading/Volo/Abp/Linq/IAsyncQueryableProvider.cs b/framework/src/Volo.Abp.Threading/Volo/Abp/Linq/IAsyncQueryableProvider.cs new file mode 100644 index 0000000000..43d8b6d40e --- /dev/null +++ b/framework/src/Volo.Abp.Threading/Volo/Abp/Linq/IAsyncQueryableProvider.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace Volo.Abp.Linq +{ + public interface IAsyncQueryableProvider + { + bool CanExecute(IQueryable queryable); + + Task CountAsync(IQueryable queryable, CancellationToken cancellationToken = default); + + Task> ToListAsync(IQueryable queryable, CancellationToken cancellationToken = default); + + Task FirstOrDefaultAsync(IQueryable queryable, CancellationToken cancellationToken = default); + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/AbpThreadingModule.cs b/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/AbpThreadingModule.cs index 14bb90834e..bf72d3ce44 100644 --- a/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/AbpThreadingModule.cs +++ b/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/AbpThreadingModule.cs @@ -1,5 +1,4 @@ using Microsoft.Extensions.DependencyInjection; -using Volo.Abp.Linq; using Volo.Abp.Modularity; namespace Volo.Abp.Threading @@ -8,7 +7,6 @@ namespace Volo.Abp.Threading { public override void ConfigureServices(ServiceConfigurationContext context) { - context.Services.AddSingleton(DefaultAsyncQueryableExecuter.Instance); context.Services.AddSingleton(NullCancellationTokenProvider.Instance); context.Services.AddSingleton(typeof(IAmbientScopeProvider<>), typeof(AmbientDataContextAmbientScopeProvider<>)); } diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/EfCoreAsyncQueryableProvider_Tests.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/EfCoreAsyncQueryableProvider_Tests.cs new file mode 100644 index 0000000000..9a6c0817f2 --- /dev/null +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/EfCoreAsyncQueryableProvider_Tests.cs @@ -0,0 +1,57 @@ +using System; +using System.Linq; +using System.Linq.Dynamic.Core; +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.Domain.Repositories; +using Volo.Abp.TestApp.Domain; +using Volo.Abp.Uow; +using Xunit; + +namespace Volo.Abp.EntityFrameworkCore +{ + public class EfCoreAsyncQueryableProvider_Tests : EntityFrameworkCoreTestBase + { + private readonly IRepository _personRepository; + private readonly EfCoreAsyncQueryableProvider _efCoreAsyncQueryableProvider; + private readonly IUnitOfWorkManager _unitOfWorkManager; + + public EfCoreAsyncQueryableProvider_Tests() + { + _personRepository = GetRequiredService>(); + _efCoreAsyncQueryableProvider = GetRequiredService(); + _unitOfWorkManager = GetRequiredService(); + } + + [Fact] + public void Should_Accept_EfCore_Related_Queries() + { + var query = _personRepository.Where(p => p.Age > 0); + + _efCoreAsyncQueryableProvider.CanExecute(query).ShouldBeTrue(); + } + + [Fact] + public void Should_Not_Accept_Other_Providers() + { + var query = new[] {1, 2, 3}.AsQueryable().Where(x => x > 0); + + _efCoreAsyncQueryableProvider.CanExecute(query).ShouldBeFalse(); + } + + [Fact] + public async Task Should_Execute_Queries() + { + using (var uow = _unitOfWorkManager.Begin()) + { + var query = _personRepository.Where(p => p.Age > 0); + + (await _efCoreAsyncQueryableProvider.CountAsync(query) > 0).ShouldBeTrue(); + (await _efCoreAsyncQueryableProvider.FirstOrDefaultAsync(query)).ShouldNotBeNull(); + (await _efCoreAsyncQueryableProvider.ToListAsync(query)).Count.ShouldBeGreaterThan(0); + + await uow.CompleteAsync(); + } + } + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/MongoDbAsyncQueryableProvider_Tests.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/MongoDbAsyncQueryableProvider_Tests.cs new file mode 100644 index 0000000000..22013d9b63 --- /dev/null +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/MongoDbAsyncQueryableProvider_Tests.cs @@ -0,0 +1,57 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.Domain.Repositories; +using Volo.Abp.TestApp.Domain; +using Volo.Abp.Uow; +using Xunit; + +namespace Volo.Abp.MongoDB +{ + [Collection(MongoTestCollection.Name)] + public class MongoDbAsyncQueryableProvider_Tests : MongoDbTestBase + { + private readonly IRepository _personRepository; + private readonly MongoDbAsyncQueryableProvider _mongoDbAsyncQueryableProvider; + private readonly IUnitOfWorkManager _unitOfWorkManager; + + public MongoDbAsyncQueryableProvider_Tests() + { + _personRepository = GetRequiredService>(); + _mongoDbAsyncQueryableProvider = GetRequiredService(); + _unitOfWorkManager = GetRequiredService(); + } + + [Fact] + public void Should_Accept_MongoDb_Related_Queries() + { + var query = _personRepository.Where(p => p.Age > 0); + + _mongoDbAsyncQueryableProvider.CanExecute(query).ShouldBeTrue(); + } + + [Fact] + public void Should_Not_Accept_Other_Providers() + { + var query = new[] {1, 2, 3}.AsQueryable().Where(x => x > 0); + + _mongoDbAsyncQueryableProvider.CanExecute(query).ShouldBeFalse(); + } + + [Fact] + public async Task Should_Execute_Queries() + { + using (var uow = _unitOfWorkManager.Begin()) + { + var query = _personRepository.Where(p => p.Age > 0).OrderBy(p => p.Name); + + (await _mongoDbAsyncQueryableProvider.CountAsync(query) > 0).ShouldBeTrue(); + (await _mongoDbAsyncQueryableProvider.FirstOrDefaultAsync(query)).ShouldNotBeNull(); + (await _mongoDbAsyncQueryableProvider.ToListAsync(query)).Count.ShouldBeGreaterThan(0); + + await uow.CompleteAsync(); + } + } + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Application/DistrictAppService.cs b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Application/DistrictAppService.cs index 81052d17cc..f7e7fde5e2 100644 --- a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Application/DistrictAppService.cs +++ b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Application/DistrictAppService.cs @@ -22,7 +22,7 @@ namespace Volo.Abp.TestApp.Application protected override async Task GetEntityByIdAsync(DistrictKey id) { - return await AsyncQueryableExecuter.FirstOrDefaultAsync( + return await AsyncExecuter.FirstOrDefaultAsync( Repository.Where(d => d.CityId == id.CityId && d.Name == id.Name) ); } From 8ffb79a801f967f7fe2f4fb62277418469557a98 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Sun, 14 Jun 2020 19:45:58 +0800 Subject: [PATCH 77/81] Translate document --- ...ission-Management-Component-Replacement.md | 501 +++++++++++++++++- .../UI/Angular/images/layout-components.png | Bin 0 -> 76333 bytes .../UI/Angular/images/logo-component.png | Bin 0 -> 79008 bytes .../UI/Angular/images/nav-items-component.png | Bin 0 -> 72976 bytes .../images/permission-management-modal.png | Bin 0 -> 257876 bytes .../images/replaced-logo-component.png | Bin 0 -> 9345 bytes .../images/replaced-nav-items-component.png | Bin 0 -> 11519 bytes .../images/replaced-routes-component.png | Bin 0 -> 14733 bytes .../UI/Angular/images/routes-component.png | Bin 0 -> 72262 bytes docs/zh-Hans/docs-nav.json | 30 +- 10 files changed, 525 insertions(+), 6 deletions(-) create mode 100644 docs/zh-Hans/UI/Angular/images/layout-components.png create mode 100644 docs/zh-Hans/UI/Angular/images/logo-component.png create mode 100644 docs/zh-Hans/UI/Angular/images/nav-items-component.png create mode 100644 docs/zh-Hans/UI/Angular/images/permission-management-modal.png create mode 100644 docs/zh-Hans/UI/Angular/images/replaced-logo-component.png create mode 100644 docs/zh-Hans/UI/Angular/images/replaced-nav-items-component.png create mode 100644 docs/zh-Hans/UI/Angular/images/replaced-routes-component.png create mode 100644 docs/zh-Hans/UI/Angular/images/routes-component.png diff --git a/docs/zh-Hans/UI/Angular/Permission-Management-Component-Replacement.md b/docs/zh-Hans/UI/Angular/Permission-Management-Component-Replacement.md index d39074a957..0b1f71035e 100644 --- a/docs/zh-Hans/UI/Angular/Permission-Management-Component-Replacement.md +++ b/docs/zh-Hans/UI/Angular/Permission-Management-Component-Replacement.md @@ -1 +1,500 @@ -TODO.... \ No newline at end of file +# 如何替换 PermissionManagementComponent + +![权限管理模态框](./images/permission-management-modal.png) + +在 `angular` 文件夹中运行以下命令来创建一个名为 `PermissionManagementComponent` 新组件. + +```bash +yarn ng generate component permission-management --entryComponent --inlineStyle + +# You don't need the --entryComponent option in Angular 9 +``` + +打开 `src/app/permission-management` 文件夹下生成的 `permission-management.component.ts` 用以下内容替换它: + +```js +import { + Component, + EventEmitter, + Input, + Output, + Renderer2, + TrackByFunction, + Inject, + Optional, +} from '@angular/core'; +import { ReplaceableComponents } from '@abp/ng.core'; +import { Select, Store } from '@ngxs/store'; +import { Observable } from 'rxjs'; +import { finalize, map, pluck, take, tap } from 'rxjs/operators'; +import { + GetPermissions, + UpdatePermissions, + PermissionManagement, + PermissionManagementState, +} from '@abp/ng.permission-management'; + +type PermissionWithMargin = PermissionManagement.Permission & { + margin: number; +}; + +@Component({ + selector: 'app-permission-management', + templateUrl: './permission-management.component.html', + styles: [ + ` + .overflow-scroll { + max-height: 70vh; + overflow-y: scroll; + } + `, + ], +}) +export class PermissionManagementComponent + implements + PermissionManagement.PermissionManagementComponentInputs, + PermissionManagement.PermissionManagementComponentOutputs { + protected _providerName: string; + @Input() + get providerName(): string { + if (this.replaceableData) return this.replaceableData.inputs.providerName; + + return this._providerName; + } + + set providerName(value: string) { + this._providerName = value; + } + + protected _providerKey: string; + @Input() + get providerKey(): string { + if (this.replaceableData) return this.replaceableData.inputs.providerKey; + + return this._providerKey; + } + + set providerKey(value: string) { + this._providerKey = value; + } + + protected _hideBadges = false; + @Input() + get hideBadges(): boolean { + if (this.replaceableData) return this.replaceableData.inputs.hideBadges; + + return this._hideBadges; + } + + set hideBadges(value: boolean) { + this._hideBadges = value; + } + + protected _visible = false; + @Input() + get visible(): boolean { + return this._visible; + } + + set visible(value: boolean) { + if (value === this._visible) return; + + if (value) { + this.openModal().subscribe(() => { + this._visible = true; + this.visibleChange.emit(true); + if (this.replaceableData) this.replaceableData.outputs.visibleChange(true); + }); + } else { + this.selectedGroup = null; + this._visible = false; + this.visibleChange.emit(false); + if (this.replaceableData) this.replaceableData.outputs.visibleChange(false); + } + } + + @Output() readonly visibleChange = new EventEmitter(); + + @Select(PermissionManagementState.getPermissionGroups) + groups$: Observable; + + @Select(PermissionManagementState.getEntityDisplayName) + entityName$: Observable; + + selectedGroup: PermissionManagement.Group; + + permissions: PermissionManagement.Permission[] = []; + + selectThisTab = false; + + selectAllTab = false; + + modalBusy = false; + + trackByFn: TrackByFunction = (_, item) => item.name; + + get selectedGroupPermissions$(): Observable { + return this.groups$.pipe( + map((groups) => + this.selectedGroup + ? groups.find((group) => group.name === this.selectedGroup.name).permissions + : [] + ), + map((permissions) => + permissions.map( + (permission) => + (({ + ...permission, + margin: findMargin(permissions, permission), + isGranted: this.permissions.find((per) => per.name === permission.name).isGranted, + } as any) as PermissionWithMargin) + ) + ) + ); + } + + get isVisible(): boolean { + if (!this.replaceableData) return this.visible; + + return this.replaceableData.inputs.visible; + } + + constructor( + @Optional() + @Inject('REPLACEABLE_DATA') + public replaceableData: ReplaceableComponents.ReplaceableTemplateData< + PermissionManagement.PermissionManagementComponentInputs, + PermissionManagement.PermissionManagementComponentOutputs + >, + private store: Store + ) {} + + getChecked(name: string) { + return (this.permissions.find((per) => per.name === name) || { isGranted: false }).isGranted; + } + + isGrantedByOtherProviderName(grantedProviders: PermissionManagement.GrantedProvider[]): boolean { + if (grantedProviders.length) { + return grantedProviders.findIndex((p) => p.providerName !== this.providerName) > -1; + } + return false; + } + + onClickCheckbox(clickedPermission: PermissionManagement.Permission, value) { + if ( + clickedPermission.isGranted && + this.isGrantedByOtherProviderName(clickedPermission.grantedProviders) + ) + return; + + setTimeout(() => { + this.permissions = this.permissions.map((per) => { + if (clickedPermission.name === per.name) { + return { ...per, isGranted: !per.isGranted }; + } else if (clickedPermission.name === per.parentName && clickedPermission.isGranted) { + return { ...per, isGranted: false }; + } else if (clickedPermission.parentName === per.name && !clickedPermission.isGranted) { + return { ...per, isGranted: true }; + } + + return per; + }); + + this.setTabCheckboxState(); + this.setGrantCheckboxState(); + }, 0); + } + + setTabCheckboxState() { + this.selectedGroupPermissions$.pipe(take(1)).subscribe((permissions) => { + const selectedPermissions = permissions.filter((per) => per.isGranted); + const element = document.querySelector('#select-all-in-this-tabs') as any; + + if (selectedPermissions.length === permissions.length) { + element.indeterminate = false; + this.selectThisTab = true; + } else if (selectedPermissions.length === 0) { + element.indeterminate = false; + this.selectThisTab = false; + } else { + element.indeterminate = true; + } + }); + } + + setGrantCheckboxState() { + const selectedAllPermissions = this.permissions.filter((per) => per.isGranted); + const checkboxElement = document.querySelector('#select-all-in-all-tabs') as any; + + if (selectedAllPermissions.length === this.permissions.length) { + checkboxElement.indeterminate = false; + this.selectAllTab = true; + } else if (selectedAllPermissions.length === 0) { + checkboxElement.indeterminate = false; + this.selectAllTab = false; + } else { + checkboxElement.indeterminate = true; + } + } + + onClickSelectThisTab() { + this.selectedGroupPermissions$.pipe(take(1)).subscribe((permissions) => { + permissions.forEach((permission) => { + if (permission.isGranted && this.isGrantedByOtherProviderName(permission.grantedProviders)) + return; + + const index = this.permissions.findIndex((per) => per.name === permission.name); + + this.permissions = [ + ...this.permissions.slice(0, index), + { ...this.permissions[index], isGranted: !this.selectThisTab }, + ...this.permissions.slice(index + 1), + ]; + }); + }); + + this.setGrantCheckboxState(); + } + + onClickSelectAll() { + this.permissions = this.permissions.map((permission) => ({ + ...permission, + isGranted: + this.isGrantedByOtherProviderName(permission.grantedProviders) || !this.selectAllTab, + })); + + this.selectThisTab = !this.selectAllTab; + } + + onChangeGroup(group: PermissionManagement.Group) { + this.selectedGroup = group; + this.setTabCheckboxState(); + } + + submit() { + this.modalBusy = true; + const unchangedPermissions = getPermissions( + this.store.selectSnapshot(PermissionManagementState.getPermissionGroups) + ); + + const changedPermissions: PermissionManagement.MinimumPermission[] = this.permissions + .filter((per) => + unchangedPermissions.find((unchanged) => unchanged.name === per.name).isGranted === + per.isGranted + ? false + : true + ) + .map(({ name, isGranted }) => ({ name, isGranted })); + + if (changedPermissions.length) { + this.store + .dispatch( + new UpdatePermissions({ + providerKey: this.providerKey, + providerName: this.providerName, + permissions: changedPermissions, + }) + ) + .pipe(finalize(() => (this.modalBusy = false))) + .subscribe(() => { + this.visible = false; + }); + } else { + this.modalBusy = false; + this.visible = false; + } + } + + openModal() { + if (!this.providerKey || !this.providerName) { + throw new Error('Provider Key and Provider Name are required.'); + } + + return this.store + .dispatch( + new GetPermissions({ + providerKey: this.providerKey, + providerName: this.providerName, + }) + ) + .pipe( + pluck('PermissionManagementState', 'permissionRes'), + tap((permissionRes: PermissionManagement.Response) => { + this.selectedGroup = permissionRes.groups[0]; + this.permissions = getPermissions(permissionRes.groups); + }) + ); + } + + initModal() { + this.setTabCheckboxState(); + this.setGrantCheckboxState(); + } + + onVisibleChange(visible: boolean) { + this.visible = visible; + + if (this.replaceableData) { + this.replaceableData.inputs.visible = visible; + this.replaceableData.outputs.visibleChange(visible); + } + } +} + +function findMargin( + permissions: PermissionManagement.Permission[], + permission: PermissionManagement.Permission +) { + const parentPermission = permissions.find((per) => per.name === permission.parentName); + + if (parentPermission && parentPermission.parentName) { + let margin = 20; + return (margin += findMargin(permissions, parentPermission)); + } + + return parentPermission ? 20 : 0; +} + +function getPermissions(groups: PermissionManagement.Group[]): PermissionManagement.Permission[] { + return groups.reduce((acc, val) => [...acc, ...val.permissions], []); +} +``` + +打开 `src/app/permission-management` 文件夹下生成的 `permission-management.component.html` 用以下内容替换它: + +```html + + + +

+ {%{{{ 'AbpPermissionManagement::Permissions' | abpLocalization }}}%} - {%{{{ data.entityName }}}%} +

+
+ +
+ + +
+ +
+
+ +
+

{%{{{ selectedGroup?.displayName }}}%}

+
+
+
+ + +
+
+
+ + +
+
+
+
+
+ + + {%{{{ + 'AbpIdentity::Save' | abpLocalization + }}}%} + +
+
+``` + +打开 `src/app` 文件夹下的 `app.component.ts` 修改为以下内容: + +```js +import { AddReplaceableComponent } from '@abp/ng.core'; +import { ePermissionManagementComponents } from '@abp/ng.permission-management'; +import { Component, OnInit } from '@angular/core'; +import { Store } from '@ngxs/store'; +import { PermissionManagementComponent } from './permission-management/permission-management.component'; + +//... +export class AppComponent implements OnInit { + constructor(private store: Store) {} // injected store + + ngOnInit() { + // added dispatching the AddReplaceableComponent action + this.store.dispatch( + new AddReplaceableComponent({ + component: PermissionManagementComponent, + key: ePermissionManagementComponents.PermissionManagement, + }) + ); + } +} +``` + +## 另请参阅 + +- [组件替换](./Component-Replacement.md) diff --git a/docs/zh-Hans/UI/Angular/images/layout-components.png b/docs/zh-Hans/UI/Angular/images/layout-components.png new file mode 100644 index 0000000000000000000000000000000000000000..3193b47bd12848c0777c4b3f13f995237a3d9766 GIT binary patch literal 76333 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 literal 0 HcmV?d00001 diff --git a/docs/zh-Hans/UI/Angular/images/logo-component.png b/docs/zh-Hans/UI/Angular/images/logo-component.png new file mode 100644 index 0000000000000000000000000000000000000000..5c11fbf617b3a9dfd3201879cfe1de98b727ced8 GIT binary patch literal 79008 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

XB?*(JyGZTZ1!Cl4M8Y(&~iZ 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 literal 0 HcmV?d00001 diff --git a/docs/zh-Hans/UI/Angular/images/nav-items-component.png b/docs/zh-Hans/UI/Angular/images/nav-items-component.png new file mode 100644 index 0000000000000000000000000000000000000000..d3e69916b6b44710143424761fb5c6fa3d21ac3a GIT binary patch literal 72976 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

8PeltPgyYW0;kk#<_( zNda+LOEFS%1~Ao)Lz?b30}fuVeD$D5jOf=gJ@}R19E~!BW0@G^z26>Ka7M~U;IiC( z8!ENUD>`PnA~_LQ(Ap~nt@B4;mKCXzNxEpW&_51!SWUlI(^QU zICFm29UA7zAW5b0{MY5-eO}w6f&q{JDFN$iw%q$J?@@#FP`6`X{;Uo4De*j->YV-$ z`c-vB>ej#Xag$4?4VDg@?iUmq2pyAVnByNnwTzdeMy4d)!`|S}JPNq!pJ?shvxEn- zg!iIop#AucWeKCX*4Xz7|LJ7OZBz3hq*TW`Y#&w{Y`U3l=N1OKni;I`Fws9iBG^MBJELm>av+2~nK zOm5^nO@pgOvkZFZ>Fbk_$Fu4%$sf8$ISpTms$7d^3fSUp%$#{fydU!izfVJ}7kw_VF=sPYAp! zFVQml_;)6FeJ%OK&3pD=&B-IQD^VkP=%{(9#w#c7fUiLU!EKl!T;$ix#F?ll5)R&K zESXdAoR(9zUFFtF8#b>ohwER%$DN5>e%<`@o!g5N=1FNoKNLbw$Z3CQ+E4RyJ5?k0 zHh0)9py~asOdt}6#X#>Z>Gjwld!y{`ZOUY^noiwD2^EQNzmnFWS)HHEA$7a8LhTnr z5VaiTo}z4w_gA86^wWokPW> z9%kF88gyWa^)zoB0l{iwH}Edb8tHARDUQ|3e~Q=-(ctO%g!MaUMcs14TT|?Y#CcqU z`bC9#z_0$WW^C7~LVYUlAFr|26e!kS?Bpv*X*8@vkFO?hyazV7`*ue-@8*3F`;ab_ zP`F}%`IdU5280enq&gJOsG*Xa(;R@cQ{qnPPw#v`w<5|bxYtZWRGi`IyY<@*Q7~Wq z_&kQ0;DLJd3|RXy`d`#i&pAUNqNEGsvk=feq{sW%`kp|C@o+6Bd$-sUfKF`S?sS-0;R-h$DKPA5y^7j?l z!+MjLd|V52^E#049+ zj~dzMncz>Jw_GipXTk_&u&ThBgVm=Xdg0wXY{dW+7j})rILJEm31J`ETTjqw- zS?IPWEZvTqZ%hNLu=yc;(DXJGJx!ZlXMHhBQE<>ZL9kf?PsD5CnTa!HXyTkRC#oH!Da6%IjSdUg#wmRJe8RTwcE9*e&WaBzSZOlf1%%|>bD+7(SiV#e@|`Q+{>HjmL}9nZPgQ@y}L)q!171)_5L;%qZUxO!&B&R>4gN2*bt&JvI*}f4A^S4fr9o z4)gfeQ1IFMyORUon7V($dTU$P&aUOHt2T`4yPUMS^Ahe`gVoh$mIn^s6p4#d#J-9!U)yWOL$# zo{gJJBko{JUskxr05Z#Qrsvv{;e%$%7)pc>YaDYR+_^q;Vz4~`$T*WhfmRPv ztN1Efa{nTS4ylu29->Iy<(L~=t_R|Q9-u121wE{n`4x*Jc>+z8PsWDR^TsdMb`^P} zlox$6%&aXI;sfs(J=5#FU02}SQl6JR`#QIGjU%#drY6Yu^LIvE!WLE2nP|tA!22|~ zi@n(RJmy11<&LlC3QwY*SfXcAjl$a>ORjFh1dw=_PvqW$6@f!yyp)DSp#^?$lCuq4 zr`i1jp_ij{7&H5Ek&!ZvTumuae{3hT>S0Q&b;!3nk7FQgOhH{JEPsHe}K9mC4QybAkTou_=lf4t{>ON=HuemfH*QyfanD*Rd64+8Z+)sJdO4AA;i=y$oxT!NUn(TBHVo~}QjF_yRc zDf7|QJb83gnoXZi;Elo)JZlpBE%hsQ&xdfE0$MjF+DG4YokI{uH6UJuR!tin>ViW? z9}Gc)Vaw-G{$Q^{YJbVn1^W|7`7!D|!v(u}dvpS_sP5d}ufOG6(go!RcfDH;QeUv0 z&#kzRKjJOlc}@@8?*DZf%{{X`8d7G|(KoN@8ogj0niDUTBe8y`W#i`S4eQiH?PthX z_=2XNj;LE;3inx|9eQYJV8W>1^0$(-#AR-~mQ~5mY-eW^oawP)KE)IjQ zsw3%DkeILxTW>k?O!$%0WV^E7c9w^;SNSu9g(&8^ZDNU(h%xFz+2QKx;{1ERBWrDlOAI1lme?*@U#_ypCU zbESYqDL;dG2c+Tyv14!aNk|lHnQP9^cLjUGH$y~FLKUP^#pXAUu$*_xC>948k)(y^ z9t?I>n$r?Y8rU#l>|`+i0Z5idZhPE`1bf2L3^KAe7x}~f0!wl;6oFeHH}6Lw%73?^ zb$52-V7>8CXWdb@mTa?)6}lyt!HCshq%?)i_2o%(+U(d3qu;90M~!S>Khr#=FT660 zXhW-rRnI{qxKcNAj)>G%Cw?Yp2t4mC)~K7H6Ku2{XnYu`O}f<35(dv4?%)H9*!#{t zdC4qf>T@XqGw2d+JG?xE8?3a>ZvyoRpm)@$k%LpL>(W+O;=Z^L@_r$Qbp62ib_@Rx zIw?Vz*dK7IYYdB@Za}TF@n;5zqaUDx z$#9h#$pmE1>|^}>HVZvby>RmU-_C_YS)P=xZRYs7@DbQikD_JK?vMjgUvXaf!P9=$?yV)l)N zaK(HeI*5P!FaPH8SoArVysy63X9u>CNuJRK4)WX%j-u@gs%k+Vly%q-0*zk>T#k4w zpEJNF4UFt=h8#{nKQh)CQ~V=r)D7;=lvq4Oo`YoB!a!`vXE^TcZz@@c_gbf#CtE=*iqyCqS0A_E%>Qxv+2Px{nNEnU%$G7Te)E5t9O337Dcb$bjTE z1)BQVu{7Mpw6wjA4~E9EenG63+<_0V`(D7@%+M8yEq}X#%jH|abl=Ai-Qw$YRgOG; z*Z7g7Y&USfnjqVG;| zn`?Z$ojHPDI&2^_18nGPLCTtyW`#aM-1tE{ZnNRm)~0Uu#p_+~$%hhS4{k;DE!YB@ z>z98X4*! zd%S3;+j+lKsiS0%naLk0fljbjCH~vA8UpuSF#9fH{sJAtZ-*6X*^FEoEdz_iVFipU7YYWv@steW3iTW}b& z!ugLXDZK_}?|3al55r(#Co+xVaXN(&C@`AYv%P7WKB z(UH$^mg}a=47K?ql(bh~(GY=t3ws1uWi#H*(+Z*IMUcm+;b-!-Z^qPbF`?6sm>Q0g zyez6H?zZ`_Iy8ZzpFih%W86mPOkB03a)zTsK#6LP0u^n;IV4{<1z-BWa%(~q8+GqY zZRawh=9&;9{Ba>cf1x9>;Jc1;r`+dTASxJUcL+J98ZW0Cfy|Zh^9%RVy}j3u22-URiLp-{^^v@?TR_3+hPKm?>y^ivyP*8S!W2Q#$%4@_>|#a(XXk1n-O+& zxE;bAci)c>@D0u&&k;vvGygd&u^;k9h<~0g5=|f5mK_O#86MD;j-tam(#NYC?E8b2 z0aY9iOQ*EiNQFe3Uuv%ser!i#5ntg_+|`eoD~#Fl(22XOPVFugc^#4C`XqFc7CzHl z9-JOLj6)5j=RdM13JUA3-N4Oy9JWwh5)~^j{Afd9Y>vVxr2PB|^C(6pl|0}@m3dld zQ2v!{&M!NWPRz1@%SCq>c?1w3l1sjZVA#35Qka4Srf2Fkw4adL`4x@XgW*A(DO+#t zYTFKQG}1~I^o&NTuNx{ZL@#HX&ToS3w%?sRk{G>-_=(P}d7-Ev*$m{_4B>=US`@Lr<$P<8C>VozW4)phs-cK_Ucl1D3ZX! zX$M}9*c|cT&6p3M6X=ov!{I*O`r;EYWpvIEnd3Y#9dC}`05TbI;8E(*eh0?^bSAFF?vT4;TMD2XQmG%~)QJ5tTFE7yj2;gx%*mL~1(GNAVE#t&bA)_${p(4k1%c-4}{FxquDc=OHh*d!m$k6sKWzm(C9 zZAiAjcAV9WNAoQbOlXLh0~;Sm?~sFdPXdv8uZCWZrSb|Si0zZxw&(tg@Ly)R-^g_C zj>N4xrjU@h|VmT%24_2Qe{Ls`9JBKVSqAnYo^erH)|GtZZ)s++Qed;{|}?@N@38kaMVD{ zYI9mM1od&sWwhx`*>ktA@bK5k-(9txlsv4wq$M!Fl5RzH2leL=-ZymQyIR6_( zc-lTf_0OtOH+DW4`3l)0BdZ#%|B_a&2t)psROa2fHre?>c9;t*sXT6vn$w}6Gj3Sa z8d^WK=lUn*>vn60`0I>zi=i?BX8G_A^G*e$fRa}Zo9zwQYgt9;tT=VW0Fl+5qYoYhh@|j zd_n>tKSmT>m5jy+^{f8gWg7CQk0+31`^=j++ z@CB384wY!SVj&1{taV~=f_urPQ3)gLzATY#ZX=Vx=}QSO%UyQ>2H zY&VG4+N%YAMM3M|ds?XV$DeI_R8h~zWga{oTZ zkLgHu9P+C(4pE*Pe8W_Ve=u?zhw9TD5k@ki$LiC1wwxn`MZ2n?kNKKgb4h=cIPU6$ z#rTw{s6%bU-DiDi+;W4E@7>kRA;){@YPgQ78{JMz;lFpJ7SJ*+xyOBmIP4Xnoo zR(F_>sqb~jj2tYpA{}uL$Xlzy%GwZ<_29+)%Z!ZSi&2|AhIq1u!?A>QFa0NGY}Jk? z^M6nw{|=UF$Gt?ZLmWNza}r!&O~Q7y6ZF8YH#K7es&R%x;q|`#DxMG}pRUxCo#OpA z@#?Lp)X+IDp!pKgz~B!3zbpWC#-#+_Ic^Nw+T^5-m9&&2fiDP#bod9`@;0L$2q|!itDL!Nhy)!}f#Yz)^Mc7B|#t zb0#mTl!x&ei_Ux^Uv9vj%Vw*%#Lu>w{}UsHqkXfY`)0o<+~l}iEq`W_uqZn z@wY8E1X#@h9{$%ni&>ze6fm+a73)<`cw_w?3E1rIx3g=+ zbxr5hBBFU_g3D|fZJboO?4^{J#A$zu#N z`JHR#EzH?U*pL$xC>!G--x{V zBt7F1RM6iNm&)`|5&#%*4i}hAbhH`aB1H{auXI%9DNB&!azdZYK&Vw*p z#r>qdM$>7z_POOJ0~601OyUV5+Fbz zA>?K5ow;*oM(_Od)_Uu$HEZRMEWYsVefIgC-OoA1;a;ft8^erX73WY(TJgwaBfW$a zJnPgNloO#OI4)u8CfY*X>$w^&iF^{!sNilrM`@dzcmL!y_AKU$)!UkAw{R159@bk9 z`rT1w6APKsR!#=rooj;al{kq2%&WG6yZF{(JMg#4(31N-B3im7%|7v2R25W|XA?G^ z_7PhHGpN7RH@vOT{b;7q|E^!2n_hhbC&H^%BZXBq+YUu0A1L>S*S;}JE?Qq2X_ISy z*xI(_bIzXXS=OACA{=aTml&`ZtdbFkmX=ciTy_T(EC|+WIw+4vX48Y+J0%_6_zQi= z1~XXBMq->uhV!X#TtfAQ?xpG+{;CTp;gFh7_4bxi?{AlH($5E0z0+9->dsMNYs5a0 zthBBl3!E);4^4kIQPi^z0$xwSyH_IQsH~6nvTc!E2G$Njonf@fp~EkRv&{rKrS}xV za`TYE^6a)(XV8`-7ss-6TIApjb~=)hbNXNS>HDfBi#u8s?W8--pj*k2&{W8srTLMM zh^C6v>-Ce+Qzmkfw?4|0r8?R2;g(8WwTa0-s6*!8LC0W2>OCNgSjx_u34+WwLTiB? zFzKj@n4U?if+rE%R%(l+}-Pfx6SZ<4YkpJBt!*iz&($J>@_>+HXR``){vxu2EENfZjy?|^Vm86?S0TQu{QS^7_P*=oh9q=l~%Tm&+$A8 zM%GwuT*yL(D8O%nxdR=3Q*QshkLY*}xT zU%lC((b`~O@@$wP<1Oc{ve=%Kw?ij3EZEg8ltIKD6 zAE>Mqv+moa4RWysP!GcE`}Cn1v-ggS6l(Wahva1LAi*8C)6`>;yk1qE?d~JWv62Vt z(k-#-48!`ZZh-1BpKF=9qhZjDiN0Ch=_Rx)lv~n6%{RC=@5AxiZ5opFe#~SQX~eEW zdi8Ml7w9~Z|H?0^^nW=cZYKF0;@Q0(yiTGOUL{;5r-?MpYCMmgBfsK3QK--OhZ1yAtgPU4Xg3W3{%p5#L z3{f<#bIpDcGXHo6Un6@L6(&xi6Vm=%h3^@c~V&b%CdKEL8Sz9!}nV%YiT zO*IYHM1e}pM@feeR-zt17Sny?*9Dxz`IF%dE5FR z>{08qqajmTcGm2{JvyzG0W2-bt#3J-a*o-(Oz{Z%AOMtP&Z`3V+i6DImBK2N;Q1r% zSl33R=T4SD+A#y8*jP-?a&lb-%qbnGm}k9N)Xe51?T_%-I}{!Ls3&Ooz=s`Jdic3t zeLfDJY=+9i8I{Ye!yBVtDjk0H<9`wLsuyF;_mz)4G9gx){JivNWJ4 z$6lPFpskD+t*mBB#$J0#m+)K@dJtDGsJA{r$aWe|sy5vVO(}+1Bd2$+%k6Dtu+uy; zYlgPmtr&gJ{hEvZSMdKUNdAQfmqnJ_99s5iRmb&fJi1Yrgu+&1mcVc>qFdPbaHKR+ z@-U5Fo=Ik8{K`Gwm5e#HpqUs4duw4xWBOT@9YGJ%{s%H z10two#EKiAc?@nQz4OgAg`Tw#*uQ_{a=6U*l%WL1-#Ye0wMp337-dFu3J1?Tca7x_}YX?WCI+|opEW0L$W3!G8v~2_J z9xJ|_4ihsG45=WTOVgqJRvi9sDgBEr1CGZ$ahHDiDi`=^c!IE^^8Jhy%MR&Wi&oRp zn+fA4Qo2viCQMm|ud3S4HhAFm^BBy0Q_G8mO^D|1>X(6u33GZuI{l-`LHIKr%mME5jm1b@8=HGS0?`q(`sPgnM zFf1g@tlWO98aqFG+C`f`uiEsHxm?Q6X6P3^6H_g7Q)rntRp)2m`gJyi-=3x8C*wg4 z_%Aa3FBa%;eD{)@Lsy7ceB}_!|Nf=RRc87!VR5JY$8i1lON^YX@I7se$+IKJfBb|0 zSjgub9JdFDH~rL)BYn&{xU9? zFRaY@DLdw8WB-Qo|4Sf#)xZRu|2cy(mxb@_q*=?{uN-CkMb1)42D^M&q~}QWf7z5D zf%07mU7Cj1-7o*0Fmvg@%fQwykN%xB2N^nag_P1x{%jG(xLGLE@4H9Phn|Y$Yk&cjeSDzmIyFrl|;G4}nH0iZDa$kqA@4-Omsva(!HR78>un$Suzo{v8w4>&EM4xKypkQMDwr&|R*RfmTL)|@pMI)rC zVFpVaxcSS@hAXT4;P_T!G@OzvKLaPoYDI6mm2PhKW)unT-#V_Ng?(i&8o62SjyKeH zAUkah>_CD0V?K$}nUom!igDr_dSdlsci>;@0KmYhy<0snO3Z}#wyu@bXrJ{z9*}yP zXaIv$SDU4g^s4j6qoJ~#Y~hZj&UXXSy6l|YGPOG(ryVtD_vP27^^I`p_FO)s&9`~m zWR-NahAAsDirV*(T#?42d1^nJ(!abp96X~PAr1Jct#q?;Y19p^@5tS*4^3-|-ldkT z3(TxTH<#4lM>@@xcr}GmX-8f)+{cE$T@-a13?4UpRYIi_AfbqiwDHL%$7Q7=zFkah zo@LgAuXz@Y^Q5u|QXIBSGhgb=yXm7cH3-8$NQtf)w6d>MbRvyIcSM<`WPV|-$0tTR zLh^qwW|yzAJ=N_)O*J>7iWz2L0M6gClxQRE**0wU`Gy}`m$wz}X*)*#FSqoW^QM5KQ<*7R3GG6l}WHfXzWzV}bdRiZ%46p))BU{ksSte0|;uHSg zatA4OISM9mR-xj=%viSU8EM|TAp_E zbrc9Fo*8GDMJAJx=0$R3X@?McRbUSb-K1!5#0-Q{CYmw5z`~tfY+45hH3e(j>X|ia z!fiprMQ&)WzAMte&nUN@ozfuXQF63eg8D?F5vmUB8j&<=il#|Uo&!HR<8mgVuQkFs zg7-IXhF=h9vck9;EtyaTL(fi9VP7^7Z0#XK6YHp0n zDuwKl5D;aKR6l5)nK!=G+#64s90;4RH;zyLoKw1&_Q4qU+<3f}%tpB_o()9h3U2j+ zNolzah+23_6RsYz_KY1?Y#3pl;#T!g50?dKwknS%P7Lk78Vl=ZH6}tR!O~TtXLN08 zd+f%z?+M1ZfgYo#J+e>THpWfRJWB(AGphw}cM2G8E?y2*->5whv_t?$mrnJgBU%Ec z_YZ~5z|gz(gV7ul@YO=IY_(duTD9;%Z~R)_Kp3F_va{XU&|ppJaWgUcYr6Eh+R7&&r?mglOx0fo`HU+7b4HCVT4Klp~A?N8>b?6=k z9Bs)Y2OL|$U+E1VPQJHYAP~g0TfbJ{kVbB3`-bm^D~okpr7d5D>|~7+?ua)hRz*{n zAzZV=BhWVWUA&a#$rN#OqaX^dFcLRO5cD9@Z)$-95TXowiYM5Q9BM8r6VmQgQ?g*$=# z7PS_JAY7Ht4PVH=M2CJ1E!PbKP;+^VTlR>~b)v>-CbaV@US`45?iVVs0>`}guOwx( zHf~T?7KU#xIz|^guf*AV_w~}G-IJ8cx^fS&%WR@)h~Yw4X9{Zj(ZKe&bxZnCpIXC4 zEB+`XWH!l>$Yi1@QZf-b$8JoFH{owB$-+;Cy)f%ZpM6Hw-fj2t+q=2AGu%+VIJ4&s zZ4Jx>jf+EkVeX4+8(KrETOTSjh*?@%khOW)^p0$l>fJQ2(urF19z<~e#zBab5E#9O z`5Gjcb}pg;RX^z81cAr5eb}o~M3Hj0HoVY-?6e4R*Rja;7iD=hYaRMJr`oAx`n_;V zdDO^K>HL#-4~0?MNI3(O0A#^LyxPC#8S3-xO&XaHrQ<7TuRtj*yeiWCQ8u;l_W8o6Zt#Ih=sTV`LqrWKd}RPji&4fpu=9u-qRNBt8x38 zRh`v!xw4Pi=w_^7*RZ8c<%Og>hOocxplQQ51ZbVEv3H9O=c7aH7pJIQ$2eMBU|ptg zU!PA>7Fq6_ezLWb74NRhG^@^mi z7Nw@o2NpKz3Ug3rz54lVaEj}1L={IV%m$QGU-&bh#O{wqwAzE@(O-5t)gUWx!6U7g zm7Y~LfC^#M_pd8bziy8j#zo#PZ8Ve-?21w#j%nzjNeGoW)xeH{kSgQdIL7FAX}LF-eh6a@gzR0Mfk{b``o%bC z0bNlRj>(~n$n0Yrz_#^y$l5M8qXyM1r@XyUW=tw8$1g(xz~&H&03?K7Q&nhTNlBfu zQc;ou?L+dT8gCmdiK6nhjivD65=fd$Mu63!=Sk)$>i`p$1U zQ=8!>#~cAFTVusp{`h(TC@S7+Ym;u1CBsk-ez1YZ(E98ayji7n%bYW04^BwatiLt} z23y_s(!`EIF6|k-$V!=@-$aEfS1k6mTPnV+vfN(@k{sHj5}xZ+4u)YAj1(Gjrm%St z5v7LQ*t-HM-P=ymSM@eejTFKb#*X8`DEvKP_qx?D6$mM$BFZp6~5dDSvceVP^%~91;K7iT9Lj zq~6_9?W(}5{=oR=*12;K2_d=LdQ_xXs+~oaH-x|Jbld?i1KSlN<8?|6$Bz910X(9Y zgk;&ju@;UJQ2L2-<56KqVvounOrZspIto@In9SlrUNmkv%-D8j- z;tmqfTjrE)f-X8dxYfFw1`%`%Z7^#i@G<9msthH?vPo&>k?#TmqVIvV_ivD^J1u9E z8?5~KSGyl)4cot9jjZh8Op*J<_rhxNaK4H{82EE}Tx6RV!whUez9sEc3(kt1Obxdt z4UPGQ)$`!hrr(*R1XL=_Z_jB7Q7$b~*4XWZatHvl2FmG_^R@#h+V`gpz?QgRGN3hwwpe67*W&s=K< zDD@2u9vQxCPQmAL-ClbxG3R4$D>SF&0aa$3-ius6_7w@G0tE7anw#Pf!a|WzyxQA4X4?yTEnGl{Q^WQ)RSY&b&J7ENHd8iuY( ztvuTZwy5i+oi?kLgT#WA)FxZgGi@T4c4jhp>J^G-Qlt_5+1irR7I2#*7RS4GZ$Cu< zZ|(!fM>-4Y?Qv~^(Cpf6Gyy7bXbm^F@bmE3QrPY>lDcST)qxsQNQ^tV0T`sV`tnn2kVT#^h-XCSu%H90kf108BtU`88RTF(Yy>O@1&>AC)6Wdp${jgT0e$9n@ z1CcAkL$|li-z@wT8ZWrtt~6uX^HRfUKeP>D$+~`rH!9ZNTVqEn7IRLtpww(!A+hl?L$**I9a+O!#!q z&xP&mQrwx=!GszK=HL8QBuNz7D*>SHi`IZPo6yvd#RRL;B&svrF-sBNWiD-Uud~2k zt7SUaDWW7Mp$;F7sNGOmUV@q^Hvr^HFS z=p-eh*`rl}Xwh=U!9vRNGqc%QAxVhH_JmXDhodd`*VJ@cl7y7qS=YqPG1AS%zHq{< zW6<(mei*<5$yXFi3a3iX+Y`%1K6g%Xnw$@UHr0HAQ~Kmd-jZi`N?>*Gmo{=bvqbK6Q-OVK!(GBn%W%o`5mE}Z!hIu%U{JB$!)YxA3hG_qzyQ^ zbu~uT!4d7iERbd;z{;;ff9jj@9A*78aU{)_ll8=c=K&@ z!-k0i;w?UeiBRhWB^SRDG2CNu6z)Zg2!7LEL)+n)h%1A9Yf}lW>>6NZu5DL|5 zsX|UK7)fq6r~@liw}W$FE!fFWXVOMtRx>#ZDxLHuBgR+DS-qt?FT!s`SzRnW6@=9$ zf)%Q@4hC=n}N1x_Rhsd#M?}wGYqp4 z?Qw1qx9PdcXJD!S6mtG7zI5)Gg(VRF7m}0M9)0 zvOK_<)$plkBiuN^*za^~`Pjk8kfABE1MUH*alBk!k5Bm~)@5tOjD{nOH+AVc1tGW_ zin)8Tqn$@!W4WPiEgN@xZC5Y(eN}GOt~RJE^G}jR!CYJlJ)Ok5Ek{uO7sK01i&#nR z%Zi~>u-gFY@b*gOJnt1keBL^IVO(eZncjwv!x}fDB-ORq6B#h3VeWU+dN-#>u$NL1 z)^9Wv5Sj==W$A3g)ZD*8ZDGe47Tj5yLfy}cW|=GVY63prB}NxMH}GtpP2L*(9@1sR zb1uS^N3N1TP0DWnhTch~?);jz5`=7udbEh(%ZITCG1M*I){lxmv2en=F5#R!P)U*k zQeu-pb16tx?99Z22h5EK+DI9#IB?mZ+ZO`)Aa`BtG%Ku{d0N@2KAIu|v!z>p8r2oG zLGLsegMlQKoHyQ^SvkU#nrxin>PoaGrKNq7FG5+JN1j1%X!;uaf~(((NqM!TIM%~k7-o7VOP2} zS{9etcnaHpaX5 zU8YI7uc}Trxx79x`zj^VqCCyF37t_%61m`{K}|GEu)=P>pgH-_c92hfhiU60bU$_@ zn}Vo|9-Hfe>5haM8gJwx!EJt~I?F2qt=rGHHtqnI5IfgPgYWX9604gi z$<)i<+H3J2DxJC=LxX#(l$e5#qN?ixR`np*SRp88PJ1a@y=^J0Ww>7+7Vxf|i~lBW z6e9x8uEg56?@k)v-eemEEmsOIV$%1pHHDWBW!7qJTUv?tVzrCOrF|X2BWdISgv=%o z+%g!rvJ;a!)l7mhEXc`rUXc~pzp)aZzn0vPQPWPYOp)4F>bQY?2l6cITYQ&@!DKhI zELZh`tO`f(eCQjBYptR?AtSAraX{$xl!x)-Nh;D8_+YfX22jo>wkbI{V;)Z#0E>1^ zrOHfpPKk%U`x%sU4=ZY~ww-ot8c}b?3En6TF{nF%zXC?@Z0*KktDSIPYBh$F8*&^? zLuJL2G7zmT*{cgnEhsszh!9q^>IHiJNLZ<1vJfCk59Qkc5smTVraIDab7e`mJHdW#IVEK! zmpWS6Qr!8@qJF)~F>>v(TB#7V7CPT6rsIv;;0d*rX_F<^by79~RV~#{*w=c*SO5s*+k0o6V1|WQ*wb8fpqov-EJrNgZ zzK-ivW;!zuw${sPJ`?j)fDwr;Qk>`v(@4U^^z3fZKC-IpKDM8gRuTa*0-@*Wv6agP zW30Ug?fdAA4xio}3agD6^hXqdcJvjRiIlGr6JsxQd_B#L_c9dQ3chgWDDQAB)OLBN#Cwu4nI}f3h=)6 z@$Eh>WWFl7PoXFqKF=_kF7es;tJ>T#IxzSc3y& zQ-~_?+1+gc?VlOy3w;M`BuV78&I~)ov)rj!Eh}a)FaJtw+80mbrup=NU!nyE?|Cx{ z_8}x{*cKA9-UU&10ATq!wVKyuHfJVOmFdZsxyB`!2HqD}7~uzP_VJb}OaD}Ef*%i| zrbJ7?a3NB?N+VLeRFY&;Xj_pTDs1UQXkrsGgC0DjViKHevijHCxYAf9D9Ht!64_Oer5Y1G_j+E^+7j16 z=%YH?#q>%hHav9jrwYzkxLLUmItj|#+JLT=+9zl@Q?$u5W)ySA38wqSFyE$Evlc10 zDwZa1NZaXnCJ@Rrw)&1XpbVV?udU=(fs2%iBmD5B?`CJhTF#r%GrPvM#l?f_%>q?Z zcl5jRJZk&d@-uvMXz?i-WY;{OhQL0T2pqje60!S5RwT>+Cxu~m*T}2l!8J1njGOkQAv7ukyFBGy2&>o}C(*Y+(3|Y)MLSmjR=3XYC|v6f z93$a?Y?U?~%gNyxa(iIjO;XfLqCCpus59KVRb18SXC+#fNLG4M&O34;mR0#NSH~EG znms`Fypmh%dJ{q$x&fxHLM@j&1xA##!U_YXze2~kZArMM+N&>&>Mi;L-o(A;k!`Kz zTkoKt?a6yvBLkC>#M9+$xzE~>9RM~Nunx^zJhszbuyy_TD}VmIw1LM~#7x9Nh{Qb# zG<1t8z|c<3?mkj$lK`RHSEHa+n?>S|gA$a~<7|a-3UnR1yccOz?x9lnqe2y(cb@D(RfZiqHc0NL z+ek#M{j;}YxE5yTE@@o*i7ei>vd)bnlX%%->_Lrk6%(v+;orj0AfqNin;FQGFnj>mk#giLfGLm)dJ#Zoa*vZV}Ny*%vj zkVOa%rx-F(NsSs+NttTi052S{z^(eU69yYp6=Dl&t2+jWmPQ zf&sZhJ71H6zhufoHmK8&&9q5lW;#m?K9SpZr2^V|90S;Dj_X-8ewORarf&`1l)711 z*x_YfFPg`Pg$E-2r>hzZQ_HIstEM^jFJic|GdlKUak8Ew8#mq#PHM2<9gu(!=-KYs zmu|+?!Sg}=^I++YVB}#2TeTwIPE*U{yfdnH+4iSong|_yMZ2f~!?YxfM>ecRVJ_G^ z(pjFfs0;l*k`Tu~s+wh*y|!B6D#?>1av<*4-FiQ82Ey(#j0up>+o|d_=Ok8}q+Cd+ z@boOMj>Y3i<-=P<-jt|q_M|}kD>drur0kOXGYrg*hCE+eQ)jjOONF9^gz_QLD@*i} z3fVK%ifca9!}gBtFhX|96WEkHzyNO2hO;IAq_odrbA};7{butedFuJl8dU~lio7xF z=GrIT$9S)H#LaNKuiZV(;n+3lZo-$E=^ClIYT|CYeZ}ub-Us$o}+}Df{f(Fh(B* z!Q3GS&1}JJ`^q5zWXvnwBgjEuYgCgr@bXVH{`7EJjk{#X2XeB=p^rVdNwqa#h(U`L zv!WK%y<)reO{GDR%-EliV74Os*W&5#e@WDfv4cB_ZfvBUv|5nn1c@cK^LG!p!~}d} z(BgZAe7SZflXw4yFF038>+DbT$gd3}Qa56(kfWSp*UrDNaw;7x>aS7^Ik@De0!WbY zZ7L*#1@PQ!NZV!TaD`hAJu@>d0~a`&hRIj&9!H zQ1b(%#;gfHmFrOp!lv8SdSqllCp+iFouLO7dJW>=kLX}_UJho6|1a{49Xap5c<+IC6=_(X6|CurWg^!LrU3$PYEw68M`#;oa;5%n3egPm9Q`7AhQ&SUNPiHeEMH({eqbM;~cuy z9KU1d2a1KB2h*iDS4tlGyLSoGTeMCd_@4u!6XKwE@IBf8Kc?wlkC^xGzx(NbER=sg zqW3E{-}<}eCPsRjq@&!Qvw43RGQB$!%Jbvl|Bj^?dQ+(Nk-z-!pCt2-xPBGLKjQig zD*vGC*9G{`V*FKK{iC~nRqy|(`d{tKKbG-Vuizg?;#Vi?|0hS{z_ZK;znul}o7MZ> zFZxIA|D*Q*==1-h_Wx1)zw3uzG{!$_|Nld^{{vN@pTY2lrGA%HF}oMa3p10X24z94 z%7djrikwY(dwwJ!d^5@vU)1ePn)z7avC9pzzZe+Z|#&hL7G!cCTpUk>Dc2ug&+^*Vi}m8^hXdqa|YKU#tVje`0OVT z!#p~)vy${Qc(xtt=bT(0#0HN0o}tUfCbd?~ z^JJE*5K%*i$+>ZiE;K}I$my8ZM@CQYF?Gwd;2lsqQ2owp84H;NmS+v6 zDw8+2P}p$yp)N^JAQ56}=~R+7X4>R>5ooeARh1&Cfq!eBsRY2h?4rES6etPj zzNOVSm%Hh|a)~Z1thcS{H~ziDF9T8${Is}H%9Axt>5ul_^IecHjXDf{1Q|Zxx2^#E zMTCcLB>4b)I%hJ?youc1a|j&u@MW&0XvKvBO-d6D0VnQ5)~KVm^|x|wvp?4z)xYFk zcJKau&J99+->^@{5FRqrTwV$D@q_sc+4)tnO0w~*?laZZ^$?DIpvy1@+RLNtw5jYc zU%hhi<{8o&d6<$zN<^#Wjhw^>=^(w2)2}8zjyOF{DtyUN$+R!9rgk2}oy$%8dZn~V z$`9DCW6@HYYU*ZStm~3LI5aG1b@8s7ThXVQ6lRvxbdNAvK$sr!>oQ1{l$}kcA2X?O zqD^G~ap50)jvZc@Ja|@@;SZmDMmvj_N7>lYn}V?2ZYi4Qiwr!Cg8i=Z@##40bdA#+ zUcpWgcE+{mYW;o z>ZduB`jjc6y4p4bCsF6|?fDBxy-b;3iMDoI4R~2JQ_jsGV`geXBKjck(9!kd=zT(; zF%qwrgUTN@jnFnOw_02wNT*b}9A0_Oc;((-J}&o;FMy@q?N>Kt%l`92woCb!^&cA^ z6_h&8FP%1IIq>=h_ECo@si@tbwo4oWbKNj{zw)OhAVnIM^L{HNL_QHjeiioSYLdHh=L* zc4U2P0+{`HlDk3a5`8aLgl)~nfvZMV+%5L0hAkW;tm}twqr}Akdz-@T1^c=FNd9-6 zaPOz%gXIt4pkpPUQP@JIJYRr|OVoRjw}Y|ZW6nTfQ~!%^$LHYZ2;Fb4XMaQ@O{TuW zdp_ZC<$ZTfqG>xR*t6&SN}7;4TRGNsyc}GWGv6DoT)&=%+4C2QH7^#cQd3hiGdFvE zzbRv$BNV?j5|E%sZxpFLd*)1`iP~^Z{kG8`LHZkJomCjXl#G{Ed zLQnUx{NZztX+Lwfh+%T-+n0jy^@%)67nk^!Ksj#kIDHqT zAI~GtQ#v>7pWSEkul{l2u$_#t3eI8j_FoMT!hY@(Q2So4_918B>!`44HOu<&^K)jF zmgls|jwS+=cN#{9hq~(h>?@n__@Ka|D#uzYBV*%U9Lf>w8Cf#ByevsyK0VyaDpy== zQUw{jLi;}i$Xq}9{F%1J_gmk2+otw+TK|~6JDmCV`YL~$&;NkUpMj%^Zzx!hOHf8E z_s)ICO(M~6_FKhHSFELjGjTDn6k3L_2JyYG&vU-#i)y`U6}et|R+Rl1a&^^Dpb@R8 zsA!kG5v{pa!Lrb%jdNSD86nn+E_3OdTs2sc@>ie;2v;`u=%r(abkiBI|7el!1k= zbUoPj^HDQ3Cbiff1d#eQF=vLJ=jDyKRr9$4`rDp7c~Wr>cvLQ>{?+$HYDtmkR@h1( zJo)XygItmoNox`xHm!BIEoe#Lkb0fM2GuD?PJQ-rUzn$M*eB9<-;Q7&yQQ~KLb=Jt zY$60u&!i$)jD$LA^bM6_SKn=~>IOgyZkQN%Zbh~_?E2B7SSB^L&;isn-e9tPL$17w z)?df`Aww4=_5MR>B0ujRvA&Nb(wkBE`;dy_=g+1^^qa%f)=?TlR|B&!`aqu=In{9F z2+&51l}kpkp!e9DmQ!aR_&$hqrtX|7|Ng+MlWEQdIDBFGa|0f`JR%zQ0hhdv0ug!! zOTXc$F}cFKme$riaYA4(%bDAuPf}7EP7tJ@&3fiYxw^Vau+?jP%TdpPU%d3dW~nIX zo#e;8W^zPnMak3V<_P%Zpn3{rqF^8Yk$d-2_*brzy{tUgs`|$FYO2)ERI$8M7kV(= z8CI^C2fprCskqS0wBYbw|BopoQ;Pc1SWxX3|>V|9bYUc*B4@$8p{w+ieN&DZ$fyE;U^ zy7a*CGx@0Vl`9;Vyi}VU{ro4IhdvJGGB@yOFm{<(M@c-ZUK72gAwslvecSAt@=6g@ z|MBBT8^lz6Oftu*lGDoo%Ry-iYs$KN&skX&Yol(X+k{*#Gb=0q`{ECf3k&DtpCqTN z;zG%Zyw6|0Jb${NV3?h83{MX12s`gAC&b(t_Ryup`Z8R z`>iqa8f&9X`d;WT-NrYZj~ORQ&bw&@lkZ+Nt1sy02PDDAv#XB`#2(0t-fLPxIleY! zTQy<0aXwns+u!?nf03bay5Y#*y+dWuX=tfN5$;S$4{S(>iRgD z_}?rPJPVlZ7~2itnROxEG-hRsSRgM0G6nb9H2CKP+DOks+|BBWN1Xy5pSf~y_lmn< z(IWf%4HdP;g{$%rUwHVKR7XbK{Gk@i%C_3i{sNIm9P>?G+PJj1*rh)j)vr2?cJ!E` zbbY%h<+Ct*`w_KI&pzzJ*|k$wR{Z2cR#Z<8Ej6E%JKcJ6r8}cS+S$vW=(=<_m}TM4 zLv9Qq6;Rc3L%1($x4lJP)#r6n!D$}Rvykp}6CH(WZr72PWv2HRUg0%Z51&;5#$kNe z6{~rqrUT>dJ$|10>ehQ{{ys;RDlgXWGOzlCqBowkZog+;pW{T9=9d>jJ=fSd^-fU6 z*+w=8Y*~>nh)50RH`lTy^d#OFA(9KrJk8^lv@rL>$rL6dC#PhoaEf0zIkVWEnuXk2 z9*|VMXjj&=)uQb?XQM`F4VwSR>DjftHroqB+0Tr7pO|egVC2``zO!f+PQS8fKBs|O z!?^(w@?mT68**UnmDo3rYu42&WfS0jlnbS$Qz+VDZ*zka$E}Id+8aci6&JtSy75-8 zI(cn##OZ~h5Xhq5-+^EXpf$|&uLV*!(HRd}k~b(*9a%QjhHzT`-Xi)76y?>^(@0=L9yA6l;vSCTc{!<%JE^#JTOI5ihVM=DoIjJTK{0b4Y*|1iE>eEBVOK% z0}9G)j9(6G-9>Y6uC+Quj->^DII7b9^t8TIYpY1vcv9Rp%j^Nr+>7Y>w2WUu&(wU0<^>oJZ5k3zDQB0-k!O_NbQy@4&0QYtijNYm>3 zgrR5rrTi^AsxxX@hMzY{>`yK8z!DAUkZdV1$#0E4Vc^7mUS)$7wZY}*mC2l^KXD_7 zxl&FWHLv7pN9darqt9@P-B?Le&=!7&ew425`&w<(ontGx$`{?-wH1*sh}r(0AUmg` zLbXF#wX2<0yZ-1%uZ2Z(hrj6C&IzYGME#dU^d6bJW_$BfAQDdM`ut2}{L)?3u?$&f z85Qc1bq%@pIeTTG+%vLn;f0HS*b;kzPse6wxT-44pQUbGV;OQ7;MI@o z9$hmuHeGW%dE7C&?DSow?&jcSC6gdn{9s5yg4kT4jMS(%IwF~+@OEk6X)S5T57A<_ z(51cyI?N3*r!Hz6f9RmyochRt{1%t=^fYf~gh}n;j-&{i{65U&=;-V3uPb$Uk>?$|+r>Pd1b}Auq-%Nb zQ%_B`khi_FNi?`bkVo&cPYK-iANTQd={hq>+z@!{{nd*(DGAC?Xq3Gv!cBL1ZJ}*s z2~MPfVRAL*9diZ0==6LSyW6KotH{>DVZMUBoC})-?`@I-w)fd}TYFfa7XUeCJe-S{ zO#I+Fy;O9SVMr;NY@)UIG7>uufZQ4J&n{Mo0+b|(4ekeC3JkLuq1jtU>6Zb@lK7(d z7LdcdfC{RcPUBW!EzWhsAy~RjknN3&EMeg07WW?dV))i#G0x>sl)e_PF}MDl`wx7@ z)O`mxKHPOxmHOken5yJ`59A)BNvEX23s#F0_E3@ zLal_M?cjvTeo1Xxae9OzG1zn|Ku0Hf%<`>%p9aYxJ~1)%!8ZL^l#oP=bguFP$QthuGlNFiw~;W;cJjfbjhuH@7>dkF@gV6MEeW|g7&-c3YB?b2}H;qiO#;CA}i zd6a0Hm@#TMFTNu`bTtj5*0O=*q{;Pc=kBjFBEgAz%A#T^TI3GBLl0Uy zx2e0}G`)M5d6)+S)DQOEp6m240V?W|dPlgsU=j=dJ>BviQ}GKt2`m#5bvk!wd2?Ci zGB4)ZpM{(+FdI2hSZRKNEAar^oz>0F;DAp`vZ}RH2LY`0-b;s5OrE3}%cxrCMyy{A z>JJUM@V=>Pwp;|}7NyE~8dZ=!BFMz1T;b>!R9R7R!dXYijp0W7sT|>(L7AZBPH%3t zxzmcku|})CyEGx`_wPHB_~!3RLhHc%8mi-gxgU0LKCHN=QMWb$R<<$=E9+%dib*@9oU+R>A01){U^_a9v)uEXI`OkFWoz(&1C#Xw?&sB z?$N$Ws>~m{#IFwPB|Hjzlz*t2-XU#Sc=5hFF})XaMn$Yhy!y>$tMuW$Z|}uMOjsQ%wbI<&;cKjWGJ&J&az|y1#*h_8$_7hpYwT4CV**__4^oe zlN&ei%89K?Q5+_H>bpDbOj2>+H<$}?jmx$U#5IKxQoVGxCc+2A9&_q+>&y*<_Hk!(PWF@5gJOSqN`0gWo<} z=5-y^kc=1ihN?Fr9p8<0j&v3>?#>yG^h}TPsL^jFeO*>>*P3$_W1;;{^1*Im;@NOZ z{V7?~&M+VH1r5b}yPG*l;%Z7$Y<|;E4ek5kW{^UqEwqkcw8agb*=x3S3zpBikFz8v zRD)wa?01iNds-(HG~pLETg7B{Ja~6=JQus4DKZZBVgF-8!QB_vv_ooMMGa>{V@VdebEvT z|77C)9isYs(aE-xC)4Buzc8MhE`nHoiZ+?y+LW_?kPy95Z3wxbGx4$8CwR$D>*T%D z@AU5=QT4W>COM~BxpGBHOTFb)4TukyLqCC@+%`n9h2vl&bMOZA*Hs)ZX8iKw&^kx^ za{tATVVt*wqF3a0K2=5gjr4~`b2AUCeqGfO=!uPPMe_Gk9%IQ`fv-Rm7j65qmLt<6 zDrkvk-J*($77uZDrO=A>SFQZv+c6ZsFb*?;cFiW|ZAq^)eVlOVIkI79> zdnXt$(tQ+7duE>s?bn)fIzSZ+{|FxR&Mk7gI@~&m*uxRdDvMg3xnpw?Av>gWd0`c? ziv!jK879YnOFDX8bnh0JLtWsUcKBoZ#ZGdO503QkLuYZ}Q6ZBlb^C`RMrVrLg^X|8 zyzDKmE4=8_z11Dg?I2}nl69NHb-FinZocaqQd@Qi(juLq3Wc5A^;et(`H*k!bfrW~ zopX0ruPWHGf1i1jd6+XLM?&Z8hZB13dLi%f>t0_=m$nxrAc${1ik=0W-G@-_A0Ho5 z&e1;tY=zliUdcC@qe>FI_O-XSulH#f&!v#2+?LUzxkU`amqespWQ%sEJA`@~Sq!hf zl4oaO=|>wqTyxr46k9J*M}hB)oK@4dBE4N7gvBi+qZPx@fjyP-uJ0MO!Y?jRq3}v3uO%X3t8E=| ztA%$Za6-EQC`t&HU6CI%_QKd*=nff7X^kz-%ct zVIIYZn=^hmkP1nVI*Es^o$8syi1cHch68W)iM*N1-D|`4A&VY)Np2l~g+I1o8$Pyf zct%;=njT!Y->3pDDuJp=K{_&SKfeHkL~~Tl`BX)4aBx&O@Z|&tPynk^Jp z2R1F~HHQL-;o5YBHi0RN-%@#ra<`zp{8iz;eyIhK&lw@{^Nneaes82?l|b0@TmvZ< z88-LQ32V0E1k5A*Ab7%5dV%}usEN&Z!U^O+lLU{mjL3gz0WXjtLo?p6Cynd@Q z+0}b7IC@(HY!-K!OorqX-+#BewTmi5hfx~UJ8vyVBc$@{eXS>Fua@cl9ju{nz!!A2 zG(hN#U&<3KjeqZ)vX5>x(ERC-^ag)8*S}oI@Xt}a19GQ+a6|TqD)P*2q_kt`G`ugj zj0{_hUgyv~+Y_WuH>nD=0V|#3z^QBf^xUz9lFC z3}2gK2j(o6l>fP?+c+Ng6jx#x5J(>_QxC&Ez58-^Js0jav@qcR2)whvWgac`k`TL% z8yi%}QxLWZT{pe=P)0Rw!=;gOFUE-n^Ki;vv_0OBc9P&>l^3Yr`si`juBQrQ`n6|B zH$iQLEY#f6khzW9)fMQPU6?k?KbDr3EB8V136`V5U{XrT+QIb4y|V=tJUZ!@-PS3w z|L`8~-o5Jspqd(59k)pR84JQsiPhcmJs2eFt}47PT+2!O>NTB$S%a#heVytHkszXH zmc>36HG#Gp-G+!Pkpr7krfb*?8KEmSH5&;|hM%EgoyjGBybA%&o}LLoP4}&jiBx8&s)L! zM!@CQM;EIaO37jSUEN5UU`7~bRBL0&$H?D2P0juTxP<6Z_j909&voI@NSfW5!JM4O zLYp;Vo0In!*)G?6kggvk77q5*j|so~m9;YM(L?5(kD5}M;-2d$bzWg%Y|(3-NCwV! zqK9!YUgvq8{k6W5oH?&r|I=mt-{tm2DeV{`hP9$9_UYl^mh~fIW)^>Si4AJI>23}< z5w;-%Lp-;N%!Q`HhfPC(M)OF``6vaiB}6Vo!c^Dn`F<_#7Ee#6Y}&CdOl*7Q3vf$8 zXX}m4`w|*fUivw$Xp+*q<3Y4=d^)F`nX^-}q7_0Tvr7tbXs15;vT4K(_-vK9p z!sR*%u+88^)EVM_^>IvU{JemKZ6-Evq|t=a&Au)O2a*&%>SSuduuvmjbJRTYo0O5k z&Oc|<9L>~}>FLnWE^$6;Rl3sgzS8bPUp@CS!w06bVO^X~E;57E0ctL86uH28#x4TF zzt8rpyX*GfBH;|z`2;h8)c4IJ=MECsb#OcNFFQ0X#{rQyY6B+4O;c|4c+_-u4Ml~8 z6G?+qCSE0T9)nEmg3!e90wi7bm}oV|l_-_qMEx?4EA;Dl?&v%(A@$g{4^4vj2cOHG zMg3psVKO!UuW#mu1kmxHP;X8;m}D;0dQf2rO$k zzbgVcPb?BXv7hBR9@OWa{QCtv(4+Gzg8(M9Aekzp7$xN0s%}<&+J|ckg-}J_XFt)5}fIBq}%~K0b zdVZ^Q3Qm_yC+u00W%E+=JzMbb`ycLGPt%rBDWzq}@riZ{uM6$Ss|U}K{NFMo6Kx%l zl-TQz%Y={S+d|2#ZrUt<{VF#K0>m%PthvSc9=5;fjVEj#db>wf{!dfg(A8^>!RutV zB)v_^a?sf{-dZ2#<_9`r!Q_>YwBGN6&xglqIxicGik8qsz28qz8dSK{w7pWCr4`?k zlNuaPIz@Hs{?-RrC&zmlxnH}(loWmKRV)smiC+E9O2uQ|I0sAj;(&|_=!l&PQ zn|*PZk^#-5`tf*0gLCT>k4waTiPZ8y{cv__@Vz1-vW)UBwQuy~(NyRowvJGV2Vi9mwLiHT1? zi)xuVtJ7hL3%oRHli_gt61UVDPt=G=rn+4UO{{-iL$?RW70mXXNusgZPUj6`ivVxt?QPNT7XILTFGs1Zo2aB zy1bR>fue%Cd<>VpM%3b0r-Pav4gx>p$fgA}CH-Pu-kmNJft7_>ZlgiMVh25UCi=fW zo*_A**QzTnmi=C&FCd*B?J(eI$|Uo2w$AVqO70BWbu;R$rg~&vj$7KQTb#%J)V4Qo zF2_Qa@KkicD8KMSzd4d6&4RC*3h7F2O5rw}glt?WZ2UAJ3@K-m&0y@n?i6rwEz%T{ zWR)X zB9N+gk9f<2Xd^x?k@OfBHC04B+hp=OXqJY%pG+FdDY?>DhA69k!y)6e#lB8CY?clS z2`kN_o7W;s@`=)5v_feWq>Kw?9;~j?M)#eJ&~kEeRG9Vc%(v1{3I0w;$I{VjaPdo- zx~aXs6S$ZuX%U@}uW1j(7%i4BzJHvw#^9sirp=}CnTiiS&P^UbCW68!cS#3_N=45^ zIOG;gkG`*M%h7;t>ds}k)DB7iiy_fihVJ6G&}g2)lplsdrkv>5fxybFEW#2;K!At> z_Zx%S69rJO1S>c4@cpo3QP`-;qPHQc7?`S=qOq90*2wc<+EvO0?aVau8zov3`(u4AG@&*9vi1~&L0i!LHhEds%d9Q+LPJOHO90&&yROPU(TgZ&dpF1B=BTDG>LA{bv@E@F&FF=^cD z{Kxe&>_xi-3>MtGu4lx;WygJvH(6z0OslWbP``u?GUtV%sL5ZI? zFN(^TXvRM``)e9t3Ef3Qg{6O~~g*%iFQ;ff z(ankcfLh9ILfd-ys*eH$BU*QIowymnPnf=MrwYa6`xc0_}`)X5U6` zo)UZr%WIVZwJ8~t?4r2TVc_W%6Ye`aC9@yQR8oXMGXl>M*d((ayPw!RuXztqdM~sE z8$_hlENR4aNkOsUIk{&GZ7}Ghp{23&uO}N$oAuy%a+4)r!N1uQR+S|Mbn2}%lx)RZ zrX6tkrK3bAQP01Q=7R;sj%Fg~2vt_DWTaMc3PgUVOoj<7E2)+Wxfkl?W!cDf_x6H= ze(YbqoALHy{ddTKa@UF7pk!5lG4klI}8Nzgi} zLes?i5)qRit=c~O2CQF)F(5_p#!#o+o|k9pn_c4xKoZ2^y@j1Sey7Fk$+mfZNoC4I zqwt*X#8pwQTsf$@!&5H@#5MN<`MTP9F-qy_sGF(#AtpgHym7X*E>j(XnHj)rm~COB z#WIcKu{XE6=SHEYo2xXd0XN3ZsDtc(pE+s}78B0sKO_>Gb*WQ{`h~AtQQ_J#9IwYE z*s$4f|z-=EZ{j_sSRu3=L0-V7IZKdK>RYd-MewuU0# z_-nArVzlWJWpjyJGOTPrU(nh?;<_-;PK?>i`c+(o^%u>ER#LgQ$ii2WkiGX*szslvkdH z@4rhVajB>|gyUrX{{7qEjwPXvzR;E2mjKgLuS9RY^O!@EVVWVinRqclhc8lV@*ogL z@uwd$bGeBnEwd0Ks5eaGeb<10@-`p*1(n2H39rm;+sq=@V5MQ7DqV~td;t#s81lDb zTUcO7YL7eRa*)JPl2h17+T^Z;&u5S0y0J*3B=l)VD@`KXT}Fc^xC=65bUhQXPO(_l zxt?`SUejFuMj*cK`TSeqJ4Ae7E$C&|2wSwzE zo!T1QPIGNAJLy25&2_4Gj}h;6P0#(jre5Kdca5Y6%=}T%>`YekXm%)gkY z#6!Q^OYm_&Gn?CR+XGm>82@t~vD##ob~PS@W>8{8hfaj20i~ zUEJX2ji^};4=a~15N~&8ZVrS0RyH1S?zSN%rL{FbWS}&zs=OB!7=CY01iqnMyxh8b z)qL0DL;rbQcH^MXtq<8^T$o$y8=G?6A?F`go=*GS-~^_m+msSZWh==}W=&Gn=5E}obt=0;F#ca1DM;4D z*c`i}S`xQS>zhB%U{SlowbvlUh~ z4}&KA6E9(lrkZLpM<>iS@QRAK*eVR|k1Fg3T~B7WT15H0X_kuSt(U?5@X8THuAw#a zKDTzR1qs_?3Hb!(fo`R~M<7y}Cs>&z!=CFwivn^BoT8?-KKHi6x6r+x4%{T^(H{T_ zKbxhBnI9VN`pKJmZXuwA?J^Rszcuy+791X91;8=Ah;bfyOkbDACz6~Q)14kJKxCjc zwn1hD+L15(ng-+_hIs7H4seFPNFPi_J%8Y?7Hh*`_Mga$N=}JpIo?QOACx{OqKS!q z+P{4e#7y;E?5(u>xdR!HjEqc8>E7};Z@vVE8@Urf4SxiMuv?!#IFd^_IY4gl_WZt%@akdpB^P;JcB_ z)YG3PmA7L7ew}?IUX*cBICu*ys3~!Znp-^ zMi3LAx35;kaqTT=oTN(9Eqn*tdOxsyKXTzL^)y~`^6rO%Z~5@JkH7muKI{cLJ_--ce%SkeafT|yCq)z!&gQbxu?dG`wO=Dmz-95`q$ zHa~r7(yR7uXTl%W%pDbM_$jTelyOmzZH{yGkaGbdtSGhi$XQ9Y{q~MW44;^m)V5z- z-P^0_>H-6%@=Z8L6XqFs^h~q_cN+Gm+!ouvIRMM>*nOWoNe=tqJoaP%xQWSo0TUa~ z9C;%wz9b2NCz$CIQ2uNcEpWB=Wy#chcKjP|v6#22_FvT|K}EDg^9Yu!S%$)4>ZPmm zn>(}1rJ*<8#tm&;ZRe|kYi5e=*AHyFD9bTna8vZ@Zl% z40QRr`nU}o7b$b2w2>@qT3Y#O+B#4W5~!w^EGKL;!cGxchb!+;^|Klu%l)HEsqyE} zuLSG__p)^}*jg>ednk_DsdjYBRieNq=OgY`;;)xw@=v=a(&d3@cN;qXXg^$l7ZY9Q>22 z5PTS`X#MTN{Jo&qyC0yG2j3R^0hnDD{dTANPZHU`7j6>^3!3$Dv3VhE@D1t(a6eOuSs^O` zIQ8%Cl3UMVCNMF8g17Rv8*)bWbi}vxx=w*(=Xyeu5c~2Mn_rojfB-RW&6nOK@7*XU zdy4z|9FGSfqKq2WQ0r5A7W&f_i&fXu9R0=J9u3FqS5Cs;uRa(Um}6l}*kyA~E@dnx zRE+=e9H7eZa&Sn-X9B!!Uy)5jJTFWsm(<+BA9>6fic{FI`}bKVx_?tK_tUY8qI|x| z5d5pz@kK3b8$3ccccZeDQzF)YTs1mO8Uvde^4%aBp4#z9WmknsVA^SYiVKOvk*3uJ+cX`{S71N zFPEk#nIq}ZD>C61pPnuSZK{K4+1Mq+RQMcX{)t$aZh2q(~Cz4#W=zpwu4e4XH!mA^o%=o?+%UBbcWhNJX zN|?~IIF+|9F~8B97Np+2)$F=^iv9t7r$t-oJKw?o&ZN-%xS;_odG5nxu?VS%Ox{t% zwH}Cl_!TxHF}7syYm1(3D*pS-K{+(XDhRab#M`Y^Q&}`*4u6E^5|@*F06c3l1sPKH zYHQpnxE#BEE<9>>K(2Oh298lGzg5=yQf6&l#}dQJcRgk^x@)3{?O<;oGu1{;p&=7D z^+O+rh+s5okHDd&I9?)3D{JtFdC@#T&Xo`szmf-z7D)tDQ|#pI*&cka{Q7m!tJjJu zc2x3S=X-VYJH|TlskiGh6$fWp!=wx(xrE18-YqSXFv5QnRqG_@tP3oRAJjA2hqN$) zo7=~0tC2EsDDqLcrL|>m2qO!V3#0~)pa=CiyIlRv{>e<}Oozo797!#Zr&knRJVZ=D zhs6DDQj{Ui`lSA9JI|##h)Nk1QuUG)?99jdm&kSrPS;Jo!^8-Do%dq_xppqcjti*^{r3ps(i>K7aoF(dqM^rg*!+ zpO9(6wR*ZGl&L#q2l+OeCY8c`^&;oMXKt-q*uIVXDL=nn^weSp{<4sWi2h3lecs-9 z!FWtOO8sj0PR#vb)hZ_zu@)9ny(+}$hr0NwDSfgsqW7;v(aUO-{T2MzlY*>!nfB`x zgL6QLg=9ARN1iB0p$GD(ZccyBX_bNl)2d&W2Y5hMq&_#X6H?Q{KcM6m&IBZ~x*>mpfi|LN~!#*~|aBh7P`wZe5vbH;$N>fF7zxD8Me8qcG*LMk%8V`nqX@4R)dkP4>ST zC7$gg!4J|8SD7swo||p$cfgP5nGx3%($a6ASX$CFa6dDk6kZq{q~N3{)DPLBpjf}I zHYX9560Ooy2khB{0abOsBzN%kT9cEa;@B0L0Lo{S6uHGy(gKPh-ntBvC<<>S)4W%x zDusNktbYGea%}}qFs`@JIoHT-`u7omcLRMzbNtBI#g}xJcg1g!wPI&xY66pWePwVZB zrpH~XMmNg1$tPNGy>OADN`rv?W1`I3`4a17;vKYSwY!;DRQs-of$iS#B%#1r#(q5o z9|rz!78N1OKQNG3An~Cz<4NL2je{;FEc|vvm^sO|aPKj8oC%L>W?zzcuL<;c4VQ+A zr;`zsKfjU9TB*&Pz-n1xeF$q>(BXIvPh|xIFO(Ak8f;7#% zN4L9zlWwdbIa>UkiN{||kBy(!e4C;(wqO|R`R?Q~VCEGdq-9X%I=^OWN2gfe=~JzE zXlPunSyF{nKwC%qhm^A{Mn>*~-ORG{Ei!crdYvCq;9&CI1qc61ZL0MB<+r|Pxm@cN zlP1qMB^!6ttAo430v?Z#e>?htJHZXCXdQ+tg0#ydVpOcQ4u&_fVD1slO}VCqhIWM~ zWrIJtF2!fTe0#n=Y`)0kCMvgNfa zE}{PJTr`_?igN;T_%j|a{E!|8^SEvKyK*c%T4*(L#A}n{de@sOn7L-Pa`snovF0OP zdncQbq4W799CXka4i3(@ioEyTsUoFv?`%s^`49F`n(LaZtha}iJzFIfu0>n>T0}<0 z4|YP-CBFTmJ>O=cT@T>Nf1<75B!0XeS7U!Cn2a`4+D8e#M(w~y!EGU`6ephNT+~R# zuKl$!ozSl;rO&n(7#&dU)880}40CsPcMFK-Z#LC>$atRUE5C<1{tkW$J8*bS(Me13 zMSB$1^AFi@qy5@7&=Tc1An(gteLQ(9QZF{QsR6hQoIAg+vs8MM6^cZsU6?avYL+WZ z+8Gt8f|{9`A=V>;{czFgKr+r7s=54vB&ZzMoDu5pHRW_Wbh>D2@pcH0p!$=Q@R#qu zQt@tyQ<3HAVh~{u9sa%b^|&ziI4VKBof%plNn5GXCiXTPL_X>ll`#$`q^r~r0F|Rh zyKU@Fzn`aqG0j;t2hG$&###6AU^j<|NWtkMJDLj1e+Ss<1~VK zowJ7V;Z|bq>=e&Gfq&?ju%5x={7;>R9}_6yJyZD^PfoS%V`qB*q(406rHFy_)sk_| ztsBMgiwxP~tf$n!q8~{dby(*!`QYW0p)B~9(}O-)19$EK`eh5dFSlRkwkf{p3Y(9V zpi*qMW_lTSoPQN>N*+<^YXe?fF8`M=J5djqNrTSgI znx&Xtc6o+owS??CQOp&uhOl2H5MMb>8*KXDP71 z*>d%o@H>skHlN-frXLeExd$k#(Pb3^!M1tK)4OgPFY9Pf!ln)d+idINd9Vru%tD(A zxx?I+PvM4+pAur#XzNhEXciX`(rpB?*cA!GJtE2l3|TtyTy&alx0@gKUe{(9T- zx0k~NGI4eL)w(0PQbhq~d*l@Q{m%KRg0)*8362|mL!e?Sn}afH>N0le_OqqRm>#~H zj?f^@#Hcu)#hMLUE4N5XySHfMbXXlLKC+O(o}L&($J>IN8!pit;-p+hJ3SMpIyqhp z+Y>*Oh_)W)9IyhyJS-zg|SzgeR zpHZ=9Ow2paZ@oTf78^tVnQuFdCI|kDnZZ~x_6N-N7az8vj1>cS_i9wKgQ|x`cU?>j zv7N_vNw=jPH;_hxh;l||hU(BxK@JXAJ_3RGO7r}^33R>PyX77946CHU%PBf3ZFzRN zWlyaT9EdKnx?5&7ePnes=qu&8+)m<8pTYL3n-hH2qI{Tv1AXjEah? z*E+Qz#`k{5=G-WFZ|7{HCh$*JE%^9J%^7sEcglIy71hBqpP0 z-N@WrM$JxxYO!K#{}q6cWXZ3^8?sm!30)6nGA@EW7oo34GCT{&^Bmu_TT8#*x1;No zUa2t&iZa!MeMbN3(qDz(m#gIzqaIGRFF07Fnp;D$le)`?29Q{i(f#Ga2u=1#$r-inwf+2b|FfBb!atse$&VUy5*bVo&^ z1f2`4zSZaI*|WDMEKd~r&dCRLjmx7}hzB*20EzEW+R35>z;RZ1f=#t=Ai6mL&HpK97{T$X18GzVPfrm~6uJ$R)AU3a<+i zt9sUKI#KNcj2-;F6u9bzC__pzJK^81_iMC$4wCIeOs|xBGaWM;eIlRT6sQ%vq^wRL zIcqFi0alcVQN;1i9l6_2O6_P!ALm_KBYO&Mi9Og1SzX{v z!ZIHIw#VwodDUvJ`jCga4zpSspGJIgb!BDj1)wjf-GnCxx*?+&yMP=*u8t}16)d+w zN0|cU#s>T71q2b5N{!C#-(r$041|RhKQOwM?}u!;6JZI?oknbLyisxsIR~n?<~qWj zXm%Svn;`CIYp`1NBpdYg-S^&DfN9TRC}*#*xZffnja=ip<40An`+SQ55iGHeul_(J zkerQKdhUog{WRw9n%V5skY%A~-mXszE$oj9&A>59W@qpG`Hcz6TGxL&|II8y{H3i7 z9wlGY$Ovi8rJhW@JHaeG=g}4urhW1`q2Zbd%+kp&(_?Z6pint$oWZjE_}2%_D+ck| zwJ%sq(XktS6;b!b5$)cylXsX1jr`3BnY&OOJJ-O?luKB!Ba`{%&Y>ZuKD}AfdnNU+ zqpfVYXHb7lIDsFunNfUWM7Y@RD?db*%*z)Hrc9_QC23vz_|ERLRY zHvK84%7mYTs050ow(h#Lky>6}^;VI=Nz$K=Tti1R5BYg)R~r||#}pe+|BhzcEo{bH zB6G8Q&k7Q%41*SADF_-=rClqqwMyOvDTmbd_ZNJRq)P>~gVr#Jw6b5iyit&nIo<`W zYY<6s=jJN#^?5pVPR`aa>qxqMxPPNiv*zi((c);dMEv*bMcMkokwd+4 zo!R<7cD8Ev;O!;gqm4%c#DkHk9x?yqDp;*`4HrHp@cfaH=kL+7y#L#LwWtQw5|Y$c z-R+yM3i7Ogl%70C{;JXLZ*kBwlix(JGV5#oSmt?c@!86)A2(~L7MCyeeDi`sVD4VO zs8IY}SJzjL4b$a$?-Vc*ilTJ55^g!2qD2lvdrj@g>h-G+-27MJF+ss0I zaCUlJ;l`X2aCtMTF1ZH1R5Dc=_zz3fh>HqSU-(colxaM~h17l+%tLba3R@fLG&C`Z ziPny0@nrK~`@UvVKPtV;GAtJ!d@zmV)J z7|^?2S1hEGQh8jLvI4_3Cz<;j zJdStm(^pqBj0`$W`pg+s+ZGEqmq!yB@oVr|r&!3s2YZJWhR775NhB_zjVv<^2roUD zJ6^w@yw~io4RH@FfJ{LqpEN#))jEZQo=YRUFzGtG!jDwl5jiZ;w)UHI03mKzHV zv-yMuyrWhFI&V(-+d%Yu&E}+W`?pI^YL+s>U+^nrjoIY5pS1p0 zl{q+N9lAzXB211q?H?k`Gz|=9%c~q0G4Qsl$9ns{lJ0bh`mD05>TWFe-)ZVswZXxj zy}u)N=q8I!Z)*3v-}VsW$ru+A9ya1aiS>3~KqN6%Om9~7TzZ}!ul0*AMp@sV)~{{W z1kP3x)_H(>Y^-e=x2J`nXWcOpZR-+>KQ2;&sRa3Fp1Qlf_hidZsD9&fG@U>O?fc=3 z$|czEvJ0o|PAo#q7>p*HNPg;Zr7$mwMS*&`j>uFq)|b@ht^%LO42VJsKd%<~LUp7s z%yRim>ZjztLS~$)s03?nc*IY~JcPYF@FNI`hd5IpTHc7>itV@y_m}AFITeCWB%-eBy62<@gMaD(laB zSW)ThRT6c-N9|hQM0}$YysGI-0vN(mM7l>rmqb_cZL&rGdo)Eg`EfkU$*S~8J)U^% z#+i&y@B1r0PS5R#K=45#LsU~U8TGG^Ah7PY-TAuCqyZqYWOMy;^J|lXW?Ikr$yvRK zLI6me>9bByP!R1)V+DUmPRIm{CoHFTb{!3=nI6x?Fif_*$?}JCf0|8vwyJmgMV^(S zNlJ~=@{+@_xJ6116*+yrz$J;xTuJ9!9oM*5L~t$ivf-qrKQGUefEd~*dMJAssI6XV zGi-1;081q*SZBXqN{GpcAsZo)5FQ?0a9fdD6djTHQrSQ`^bPsvck%Awp({Q-Z(%&0 z%@TLH+S#@#$K;{I^d|u)Mb_Ba+*oWWANhbCY%a2>@;nh%qgfH9ZhM~7+U311{&c>m zQYap?iu21jhoK3=X7yibh2%598n0iy`T>M{HZb5#l$r#2b*@KTmh-GpQnUns37V_2 z?MqAuc-*KcsQv=3k-qtK6TIrvmlfip!-nUW_C06FZ%1Lcha<(80p-TlOiL8vJr))g z&=*d?7VoLYP}f_?-VBG`M1C~C;mcWCW(nCcq_x<WQ{yx;@NP*yiAmj_>L1!_$q4o?9YU3ta1MA#)M{;b>P zd};|W+DQOnr+bLGhjrIm@3+CRj%d}HPYSglqmKlYpz-s-K*i=4sJa*ar*=a|NbZK@ z@cFTJvMKqYb|Xpn?^S+vgjqPiYWeRsZPT!_@5%Gw3M5^43yCgir`vl@XggnoJUu)h z68OdP@Z*K=m8X*mB8omLyG!+~h+< zgD)m(aq<<3>Rc5V_9#Fr;vOgXXKK zCAwqG literal 0 HcmV?d00001 diff --git a/docs/zh-Hans/UI/Angular/images/permission-management-modal.png b/docs/zh-Hans/UI/Angular/images/permission-management-modal.png new file mode 100644 index 0000000000000000000000000000000000000000..05cee8a2e1d00bb28a6ee29d33fadf211f4dd9bd GIT binary patch literal 257876 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\z(~cJ-2i8=t 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 literal 0 HcmV?d00001 diff --git a/docs/zh-Hans/UI/Angular/images/replaced-logo-component.png b/docs/zh-Hans/UI/Angular/images/replaced-logo-component.png new file mode 100644 index 0000000000000000000000000000000000000000..4661b390a853b3e018667164f84a9939ccd92b1b GIT binary patch literal 9345 zcmdUTbzGF&xA(x%IW*D?(w)+cbSO0fqJT8R07G}DQVK|eAV^4e3kXOfN_W@L9dhv; z^_=^A@B6ub-)HuoXFY4L@7ina-YY^&LlGB?0t)~D;3_N0KL!AhA$PPm2HM?!Lt1A& z0Dz-xEhnd?EGI{&%vJ!!vW2TC zA!9Oj24|TnCh9sMz*t+6C6O!*q|#%N4O?69Caz3n6rPYhEzdq=LUle#*h}9NbNi7d za+Dcge>R9Jou9~@u$I#RAXbWeff<+Ge_*|-_EpXw2`CNhYK!PjQk^_F;05$9oNIdc zkkIuW#HYq@PhZ@!c_L@0;R6Wq9TTMox&7T~0q(5N*w~T%djegj3lttR4*E|>qY(u| z3Ohw?jPg34*cg30R90D#ZUO@MUUk1-1!T=4Bl=B!@m5A!@X8zI=@J21a-qWE+)J2r z(Sh#nGBVkOa#9O#PEa)mrGzU(g*}?m=!;7f7*}}8jZ%hEfB4lb`>D#bnDT@IbyAc_ z6S9i$ogzGqO{xe->2~8@eD0Dd#y>DDmtMu^RUu)07ytdo2a#uk0TRH6phj$WlMzs= z92NbSm{%hcl@*@}jKUZ3Wbz}T>XcKev4aoy<#8=P7W2^CgDm@m?FObEW~hyDO#Cs4wJN3Qdr+57GuCL%RV9d!+@;Z+{6Tfr96{`lb@>V1 z)lnE1G{b|XC9Ak}1ldtO5C3rNDQsy7u={RTZlgfsj^c3`9Mn?R3T?EgYf`pf6hW4_6ohD zXKuK6WaVRV`UPx@s&FAH!}gkGm-vmT8fLbzPxIqxg=w#Fg~<`_tDHeW+Yd!)*~z8L z@Rp5AK=jBnFH`KY<_Xpva#u95a6urGD~j!>L6fjI?pF8`I*9B~R+xp}hjcOLsqW(H zYUa$VySTfvyR-uEEG1#}3vZM(*-htUVMU$J7ah#4v0oDQ6>%&*8@w8TS>7=pXtkTy zb@$Lab@nQuCG3D4Odt@5E;((=4zNlA!j6(Mp&AakLnsT!;w`dz#Wjn)*hrGN&I{D$ zSR4VI4uK>d$h07Uth6vWa7mg_3HbVXrhUNFL5=8ZyC963*N%8yM?wA5B^MYpmLR z^f)@K7fgJ#1@eguwsEhNBo6tV03xAjGNQ4RJrcQ;9uZB7yl+A&vPeGwMG4Kb?F1;) zWtrcJY!FwWaLSS8e7B-*077MBvMop0t(Y%y5FLQLkb5R$Zz;Rlg&|al(dK4+c0zgq zx+X3VhB2($O;rf z+JeeHvjgTbrbuu>u#+r_3ATyU;{B%728_}O`F8{(aU0lsT>_?Dj%bbqj?|812Q1}5 z=l&Cl;5aqql3eM>R1u17;Dpy>v97Vvv0U*DO0X{mFW4)XMFP__5@S`r=&m4EI#!}q zx>tN7xjttsX-4E=u#B>*vZS(pd~@`MOGQdIW=jb-m+29_;ON8mZx6SWx1d||1_lN~ z2EGQ%RhcVPQ+w`%9{FCTBO?bAW)ja`JC@+*9!Gb_Tz(mt`rSY@#N24~PHcyV1 zj~kC`r*IGiQ%2B$Qz`@nf(a2dHRQq~dMav{t}MzZsw?W{GPr%b@z|N#S)@UHcCtaR z0o}QD^K_HX%LyF0(Mfwg6hW?&U;kIvJRh?EbBf2?fU8G%h zX4wa_%MX{Mx?pOd$-!?i)Y;TrlZ|*iV7&sk4+i+3T1?q_cH=yN^HN$0eYb0#RIbc0 zLF+&cJqXjqndaZg6S3Jf&3G=^;r;qTnVp<+>OnZ_9={tiuy5ii<_0J`;ygCj|+#RokJ5s-VMt& zWl3kNjRmHz5}n;x?I^^ zZ57^R6BfkzA48lhvT&od}JuHM*t;IEaW$kJ5N)Oz9)l#rTkP zRFsrj%wi|9yw(h1##lb!NEc063*OaeGP{0r{;Z3j`*Tduy)%|i3?>%s1@aGUiNPZ#2>i0GKi|A{Q*Jl=leA@iAmc9$054PNWp3D?a6&p*2 zwWi#vfxr;f4N^3$By3tsbPMhw-*}?8mEe3sVva(>lW>ux>Ls%JNA;9W^DCcMp#zjX zngjE?(p)_p!gM1^E6N(g2BaG7JFyKaeect?uk(vjzOqLpLgN??BMuY6K=^z~gWT>pP zs2wOz*A~jRwO^Tm9(_1ET)Q#eGHz%({(k-K;-fjKIlPa?o9yDLT)k_3@%7Xh(mV{} z&kf?XdbUyRFwm|^5*RtpHp^bbCdIMDeThJip)K?yhom*v`9uuGpQuKtGOCtxVH?*# z>*o&RSMl{;J{_rwudgs&Ez*6hpI$(rTWuofQf=yD>7wS+N6{##I_?c&H}HDTRAr(6 z(F4&w^$$Z@>Q@Pd9GpR_wrWRf&GwpP_r{9^D@|M(Ng!1hqPl&ejFF7p? z*=oIK*e0jyIZdV`Jm)Vj5o^;)0$I3`p}W-g#JF~FrYFB{jMX_Njg<7xKCd-B8_neR zYiVHi)SNaRo9ps9y|OvuKh+nYS07FFOjQ_2=d|XeM(?7svco5;PkA6e7DaIx-1?O0w2&(x4t&NV6^1bM+BSJ9eXlDEnTpC}_pU96+!xQ(} ze|eh>Y%TY-mE4BcY^I&n-?Vz&wzSUXH*YrWT_j@rk{O6Sbfan^_db|-U#8k>yk;!v z#dxaH{e7iqywu!iyNRpr$I8PWugD%m!A|E>yiy$+m!fym3mezmwtqPMFw@W1T+jA0 zIUAhSZ1USiy8Tocb{Iz6&`UEyt1D6CX>{9p^ySlT_%604vpB+&$!Ba{`$zsFxosY;xa2Y@?0!mk&Jv#7(?+FwZ+}$k_%^}Jb z>goWtI~oIkibMzi-cd+*KL8R10QD~#08l}q{6jxRV)-S53;={#15kd+7~H*oKCyTC z4*ly5j1L8%-+d9@<=`yj-_ppCEZ}b%AbwW{kkOV?R=#^{n>m@A+rzD3&gW@@({~I^ z2c;))0DzS7XGT(fe1HG$a^!5S1966^tBIPypj;*|V5a6=?ofxHdH~|?qIV?J+}VWA z9cpI}7j>5a|0N-MNB?AVgX#VfakiBJL)5kCe(E(bg}FFOfWbd2`t$s4r@6cJKQ-CIf4Oz%AotG_ZeA`P?*9qq zY;E!Xf&DD`8}^r9e^)2|Q<?r(#Wc3 z|5S-_t|pD#XPL#v{M#@(WI{*-`akk*mUj$EV1mdW8wg_CzDoRYgbrDfD7NkJ-iQ8( zf7GHR?*3yl!G5woO5%{TxyC=P-7j;-|Ci@ODEG^}(b(YsxOUeRUccMn&Y1tLDO!l$ zhAG(NvmYHj8@nufl&sAikRSqo&rb5U838ZpW0O*CXA()b3U_wwu+fkc6B4ScJib$@ zKL40f@QwC&*F3{VCe|pAfV& zRDt=AP;Ohpne?N6s0d}$)n@JQUT8Z+i7$AgtFKGm;cvD~WUo1*z?-1P^s(&uE8SvF zI1~zD_^hb{SU9 zNwb7m{MqG_^LH=pe@EF!e^;0MHmzp4JEI~$)AOs7larl&bVeaZFwRl2pH*j#oqZV* zwtW!TEWoxQW(^8lg48vwmk!R ziJwI)_l7+kSYsm&ITlWTs+2G0KdQtuK<=Nd5D3GZ;vNhD1B80=VJ`9MKC3GYFW$TBkVT3ZLmVfu6GrGjNeTV zFJ)?qtBV3T?JHuDMMc<@lQG};f!j6rGAe1l6COZy(e%1I&V(|o!iRyd+T(*ZR^F4U zgdD_P_d}eNu{kV74m{LtOzuN7sYouYBFnt|VrSPe4U!N}jp~;T?-ylH*WWDGI4(P! zXAPHF4iP!cz>id>Ue{c^m&Tm_@-{XOWxp*a%!+jAtB%c_NAzJ3l6&0Y%wD8YHlwz3 zYI1V9Ja|)FWpuQ1FsBMOF2v5xso>M@xqD*Zr5_VQ|JEu$+m)e7$75`663R{GhkS}W z_I=iD95!3s@JiS9{J;l~Y}?awuaW0ILQ_MtvHbgX(TvM%&}?HF!O}_FoJvITOEQRt zJd(9AujPEROGn-z@@XHnmmS9&d>QkxQ0O!7G2da&fxJU(#0lp#2fB1+b|{fO+t=)l z`@sK<*d0mV{LQ;vl-^bJG8F3b1Z6HiYqr_((~@FL zohx(a5?oK`vDFZjm<{Cvdq~fCZ)h!>y?*J_T6~R6IL*hWVy=+Y1{F#w@~YlmtOvf+ zW8K9yYeF^ZdPYV&O^?Jz_D0t%#Kyh9L}Fp@Y%=3b52lM5`ANdgc9Ux@Vl;C6 zYOs|LJ#V<~ahLf5@Ao;;mtfHwyK1OUB})%K)*3dcyA>K#GvpQR3X)+?BuC?DCp97$ z5Ar!{hjqokK@7$Q!mPmx=*!Su`sl*4XJN0vk=h-uQ!NofKT1Nv8_+Lwg63_@%I85f z(^i&~FHgf)63nu1|6U;VFpAh0qH(86+kVl3|=J13_{?D?D& zp9yout%R-3lwEVPkL&g+v~OtWL1aGg>TGghA@*kJn3*(~j01~65PN9+0-KCJ0}IN2 zDen8c6&DY8GP#o0@X3=1#6$~lTIlL*+}Ff!9|4<~^YNm6xhRO3s~&ZgarkV?d$q8W zulMxPZpnAp2)G%s_h6OkIe_brYr-s6y=u^`yoH(Scx9SqEs?gCc9s zubw=c`OTtr_|Jk_8q4z9JgVch=A*FjHDrB!){dE`wc*1zL`P}G#Qyon>{PJ zH|~UvrfJ*YCaY9S%N-{BK40Uc ziFzs}qWZxc{N|pXxX)=?^N&oa@~wf!9qv9AC}OJmbnc3FLQKkQmcot3p_?9~>M}*8 zsHjM$M6aazX0CMSRpyVd4zDG#(h1dh&rdeCwmUiSbxyp4^(JT?jZ|MD2!d0I%Iib4 zFYcqKWhMC5zy0FPtjrCPds#1Cp*@L0F~x3|1E0zCeL68_^Dh6L(SRnqjg4AIs!=&r6&sa zUT+));0<}Ww{L8kwu>py3@PG6tcfqiFdmT-ue6UH_Q_t??C6KIy<5u-i%{M?LxNMw z29ki}%A2xuWs?)7>7U6tT{TP;pS&w6t?Q(rq;_1C3&k5(SBDTHN*6zd=D>UE+H*Zj zyWtkqIrA~h-O$km|EDE$7(==NHx3Ie&=80h4)W&rYpScLk+&qW^3Bh*VdJsuC*3`( zrdA*~RN&Xso&79Shu7&dIx#C=mGfZ}Q?!&ddPYaYm+M@j++hX3jup~*1pcjU7W4*b zZ7C@gx1QU%C$2aKo0q289hKk4oId@yR`fF$>`65}m|MzGWDoB=qH3bUQ;1Rf|sWaq3X6 zh~+6>Z!~Z3N1fe`DjJ-2+Q4xuKs|(#rvUd;til4P>5>-?DGK?&MB*%{`1GiUZ20+=c0mju+ZY#?YJ@ZL}X%PXdZTg0ig|+9#ZzF#l zOkRj0VNr4uLt3+Y$3CSJW1-F(27kGjC2i+_(;kLw?QF+Et-%pJOlI<6*Lk9?CpTT# zcbId1I41XWaS?OfW9jIPYe8b2=4~iGa0rs0MY_e3*u|8W<`&5zb-nR2UGySvRZpM} zE?K?KtJmln$z>chZ?213%)v737`%1K>u9);U=yfVi1jXyng+b~%pA^#)J$X=9%xJH zlr1_!nx;908_w0EAH2(B0%|4J!&!FBl%9PUUI5bBW8WC$wwLBUSTb9;h%%8Kgq}uL z+}u1{A&bqOIg+LSH6L<3b3B+lc(8<=N1dMD(@|J$nIXB=WQOx(cec5Yf&ygS;M*}L z?$JAzkWaKLQNEUZ`}C|x^|{O^jU~MO1_7E?Eg3USnK8^q3I2`o z%lArhd6q-5&is&!1aEJPl;Z8T zLEYK<1*@aa?0UMo=C~&=r-!QZPU9r<(E>@HR_s49A$*u45noSHovnHk~rBNfqM)2J4c~9X7(URjdI;9YxyByWghUmR6uozX!Vh6-{gwjUps zj5=kBRs?}_2c!bgq2w@$E{6enD()Hn^Y_0`_sNQFn5^Pa*m2k{7rnYkata6SL!(-^ zJQvLk;x_3|XSp_;YfFb1Q_kl0YBSTX>!I@vpTX`Aop7d0j9@ZS#aq!ZvYM(n=RRQ` zleq}~h57)aLgW?sBWNdxaD21H${MO5%(p@~XBpRiG+1y}oS)y##y0kjgjEWXv3U4> zTj*sisVYHYF1b-e1)Dg8m`UgJwVBhwvM9Qu7oaHIZ>IL)Piirlif-IH6=?!aGcXp(Z`&=!DrUxd`+LbVJM`0 zH)t^AmV?tq>_N0*Kn$;UUyL$>*k~ZBWJ*9Xzp^Hm{2eG%HI5|Zg^4Fh)ok8+>*zg;k;}sVuZXTp zpgA{k*2&*XK307^YbZt%T7G-1S+3SW9bRxleg?l^R~n{o>t>k>?N}LFreJd5?7su|+evZr{U4_aTG&-yctH2lGN#P7mFTASA?QOOkWn$@@2 zWd}Px3;7oD80q-)&`U-Iy{9C<$PQmp^4$$xZiggD1io5sZinGL2D-OLoJ4I~CD}UZ z>L=z)=x+3{f@ehZd*G{24K==prnDa6@wsI7VFIfhi(Oo>-&v5pv!HmFkG`}j9zR$~ z{v#;L5hE(*v4eWH1ljO5y=xwQym3sT0l?)wAhy$&YWE9G6Jk7K<|EfmV_7R|sSafq zAFD5#Q1|nw`lowjr0-jIUX@dmPoveo5GpYPsmd4yDn`uTAy zPX?X7W;AytQr<%{YW=-~6f+?cD?HQnWk{$?8EGGB7Z!cMGAJ%KI7OJc*)f!9X-y5) z@_&!WO@cn3RY`hz_MCvAS?y+D>4rbJAMM(L_!KL+uV~`DhPJi9hv-7Pl`GV=i}&+) z8jku{^b=1CqR1{EAteOWohs1zXggu5LA{ zx(@Y*SndWjIKOw>INjuW=3U{Nj2ODNze#s@eG~yP+{U75nHN&TVDDdnPQ~-yX4g#y zL$Q{&%rUZIwX-$8!N+r<=xoUKsUaxmBEl3M^{GI)Q3}U4GaHLDJ-V(V ze$kMg*{S(3Zog$Wc5$oj^0EyUd1JAr7juL-#5$XMKKb)}MxHb{y1zCiB!V6XASqqL=2!HLt^ha_aUKDO@-g#m**!0JyU)w>V-Lf$Pg738E(V6R4>jmP~#G+>qDIP*`C zqmXG|39Gm&tDO={GK$7C&vgHVBQ9s6sNEwB;V~&EwnV`1DzC z@QTxuWrpPg-gC|AjIzTkah{LA=M{Kg@TXD^tc(Og3F0Tjdi|pYUyjGn+BVuL3#rzB^1+!}Z2~dEgf5x`(|F6Zizzh5V aw`eS|EsupK*Cjur<;n^g@+Gp*1OE%5)3RXz literal 0 HcmV?d00001 diff --git a/docs/zh-Hans/UI/Angular/images/replaced-nav-items-component.png b/docs/zh-Hans/UI/Angular/images/replaced-nav-items-component.png new file mode 100644 index 0000000000000000000000000000000000000000..e4cc0339aee1773338c7e0b9a015d5368920ad50 GIT binary patch literal 11519 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 literal 0 HcmV?d00001 diff --git a/docs/zh-Hans/UI/Angular/images/replaced-routes-component.png b/docs/zh-Hans/UI/Angular/images/replaced-routes-component.png new file mode 100644 index 0000000000000000000000000000000000000000..3a6336afe0f28cec34f213a940ed28daf44928d5 GIT binary patch literal 14733 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 literal 0 HcmV?d00001 diff --git a/docs/zh-Hans/UI/Angular/images/routes-component.png b/docs/zh-Hans/UI/Angular/images/routes-component.png new file mode 100644 index 0000000000000000000000000000000000000000..b708e86d36f071a9af6eacf13ad677f7b4054c71 GIT binary patch literal 72262 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 literal 0 HcmV?d00001 diff --git a/docs/zh-Hans/docs-nav.json b/docs/zh-Hans/docs-nav.json index d105400184..07c27016e1 100644 --- a/docs/zh-Hans/docs-nav.json +++ b/docs/zh-Hans/docs-nav.json @@ -283,7 +283,8 @@ "path": "Application-Services.md" }, { - "text": "数据传输对象(DTO)" + "text": "数据传输对象(DTO)", + "path": "Data-Transfer-Objects.md" }, { "text": "工作单元" @@ -330,7 +331,17 @@ }, { "text": "Tag Helpers", - "path": "UI/AspNetCore/Tag-Helpers/Index.md" + "path": "UI/AspNetCore/Tag-Helpers/Index.md", + "items": [ + { + "text": "Form元素", + "path": "UI/AspNetCore/Tag-Helpers/Form-elements.md" + }, + { + "text": "动态表单", + "path": "UI/AspNetCore/Tag-Helpers/Dynamic-Forms.md" + } + ] }, { "text": "仪表板和小部件(Widget)系统", @@ -546,6 +557,10 @@ { "text": "模块", "path": "Startup-Templates/Module.md" + }, + { + "text": "控制台", + "path": "Startup-Templates/Console.md" } ] }, @@ -570,16 +585,21 @@ "text": "微服务架构", "path": "Microservice-Architecture.md" }, - { - "text": "测试" - }, { "text": "每日构建", "path": "Nightly-Builds.md" }, + { + "text": "路线图", + "path": "Road-Map.md" + }, { "text": "贡献指南", "path": "Contribution/Index.md" + }, + { + "text": "API文档", + "path": "{ApiDocumentationUrl}" } ] } From 9a9a8abfc3c76c6d31a3fce57d6d2b1580956913 Mon Sep 17 00:00:00 2001 From: maliming <6908465+maliming@users.noreply.github.com> Date: Mon, 15 Jun 2020 09:38:57 +0800 Subject: [PATCH 78/81] Add InverseQ to Rsa parameters. --- .../Abp/IdentityServer/AbpIdentityServerBuilderExtensions.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerBuilderExtensions.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerBuilderExtensions.cs index 52ff0ac9c5..81f4b8b629 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerBuilderExtensions.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerBuilderExtensions.cs @@ -112,6 +112,7 @@ namespace Volo.Abp.IdentityServer {"DP", Convert.ToBase64String(parameters.DP)}, {"DQ", Convert.ToBase64String(parameters.DQ)}, {"Exponent", Convert.ToBase64String(parameters.Exponent)}, + {"InverseQ", Convert.ToBase64String(parameters.InverseQ)}, {"Modulus", Convert.ToBase64String(parameters.Modulus)}, {"P", Convert.ToBase64String(parameters.P)}, {"Q", Convert.ToBase64String(parameters.Q)} From e173c843cbb93798a6998134b219c7b355eb7f09 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Mon, 15 Jun 2020 10:29:45 +0300 Subject: [PATCH 79/81] chore: add @swimlane/ngx-datatable as a dependency --- templates/app/angular/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/templates/app/angular/package.json b/templates/app/angular/package.json index 8df33e4323..efc61110a0 100644 --- a/templates/app/angular/package.json +++ b/templates/app/angular/package.json @@ -24,6 +24,7 @@ "@angular/platform-browser": "~9.1.0", "@angular/platform-browser-dynamic": "~9.1.0", "@angular/router": "~9.1.0", + "@swimlane/ngx-datatable": "^17.0.0", "rxjs": "~6.5.4", "tslib": "^1.10.0", "zone.js": "~0.10.2" From ee3b4315f34d6a81a6967b358141f417736ead3a Mon Sep 17 00:00:00 2001 From: Erol Arkat <46989033+erolarkat@users.noreply.github.com> Date: Mon, 15 Jun 2020 10:49:01 +0300 Subject: [PATCH 80/81] docfx improve this doc test --- ...icrosoft_AspNetCore_Routing_AbpEndpointRouterOptions.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 apiSpec/Microsoft_AspNetCore_Routing_AbpEndpointRouterOptions.md diff --git a/apiSpec/Microsoft_AspNetCore_Routing_AbpEndpointRouterOptions.md b/apiSpec/Microsoft_AspNetCore_Routing_AbpEndpointRouterOptions.md new file mode 100644 index 0000000000..7747d776e2 --- /dev/null +++ b/apiSpec/Microsoft_AspNetCore_Routing_AbpEndpointRouterOptions.md @@ -0,0 +1,7 @@ +--- +uid: Microsoft.AspNetCore.Routing.AbpEndpointRouterOptions +summary: '*Summary test' +--- + +*Information Test* + From 2b3ea53bf6336cb319f492b5c31d77f207ededb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Mon, 15 Jun 2020 11:09:52 +0300 Subject: [PATCH 81/81] Resolved #4351: Remove ObjectExtensionPropertyInfo.ValidationAttributes. --- .../Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfo.cs | 5 ----- .../ObjectExtending/ObjectExtensionPropertyInfoExtensions.cs | 1 - 2 files changed, 6 deletions(-) diff --git a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfo.cs b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfo.cs index ddd8fbbc3c..b54d64477f 100644 --- a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfo.cs +++ b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfo.cs @@ -18,10 +18,6 @@ namespace Volo.Abp.ObjectExtending [NotNull] public Type Type { get; } - [NotNull] - [Obsolete("Add validation attributes to the Attributes list instead! ValidationAttributes property will be removed in future versions.")] - public List ValidationAttributes { get; } - [NotNull] public List Attributes { get; } @@ -71,7 +67,6 @@ namespace Volo.Abp.ObjectExtending Name = Check.NotNull(name, nameof(name)); Configuration = new Dictionary(); - ValidationAttributes = new List(); Attributes = new List(); Validators = new List>(); diff --git a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfoExtensions.cs b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfoExtensions.cs index 4eac846314..d51bf5b13a 100644 --- a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfoExtensions.cs +++ b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfoExtensions.cs @@ -10,7 +10,6 @@ namespace Volo.Abp.ObjectExtending return propertyInfo .Attributes .OfType() - .Union(propertyInfo.ValidationAttributes) .ToArray(); } }