From cc3515cd7f4119be0d47459bb210fa27b8309b83 Mon Sep 17 00:00:00 2001 From: Yunus Emre Kalkan Date: Mon, 21 Dec 2020 11:25:39 +0300 Subject: [PATCH 01/35] =?UTF-8?q?=C4=B0nitial=20DatabaseManagementSystemCh?= =?UTF-8?q?angeStep?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Volo/Abp/Cli/Commands/NewCommand.cs | 40 +++++++++++++++++++ .../Services/SourceCodeDownloadService.cs | 1 + .../Building/DatabaseManagementSystem.cs | 12 ++++++ .../DatabaseManagementSystemChangeStep.cs | 40 +++++++++++++++++++ .../TemplateProjectBuildPipelineBuilder.cs | 2 + .../Cli/ProjectBuilding/ProjectBuildArgs.cs | 6 ++- 6 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/DatabaseManagementSystem.cs create mode 100644 framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/DatabaseManagementSystemChangeStep.cs diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs index 75d2651cbc..f998a6c09e 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs @@ -84,6 +84,12 @@ namespace Volo.Abp.Cli.Commands Logger.LogInformation("Database provider: " + databaseProvider); } + var databaseManagementSystem = GetDatabaseManagementSystem(commandLineArgs); + if (databaseManagementSystem != DatabaseManagementSystem.NotSpecified) + { + Logger.LogInformation("DBSM: " + databaseManagementSystem); + } + var uiFramework = GetUiFramework(commandLineArgs); if (uiFramework != UiFramework.NotSpecified) { @@ -147,6 +153,7 @@ namespace Volo.Abp.Cli.Commands template, version, databaseProvider, + databaseManagementSystem, uiFramework, mobileApp, gitHubAbpLocalRepositoryPath, @@ -267,6 +274,7 @@ namespace Volo.Abp.Cli.Commands sb.AppendLine("-ts|--template-source (your local or network abp template source)"); sb.AppendLine("-csf|--create-solution-folder (default: true)"); sb.AppendLine("-cs|--connection-string (your database connection string)"); + sb.AppendLine("--dbms (your database management system)"); sb.AppendLine("--tiered (if supported by the template)"); sb.AppendLine("--no-ui (if supported by the template)"); sb.AppendLine("--no-random-port (Use template's default ports)"); @@ -289,6 +297,7 @@ namespace Volo.Abp.Cli.Commands sb.AppendLine(" abp new Acme.BookStore -ts \"D:\\localTemplate\\abp\""); sb.AppendLine(" abp new Acme.BookStore -csf false"); sb.AppendLine(" abp new Acme.BookStore --local-framework-ref --abp-path \"D:\\github\\abp\""); + sb.AppendLine(" abp new Acme.BookStore --dbms mysql"); sb.AppendLine(" abp new Acme.BookStore --connection-string \"Server=myServerName\\myInstanceName;Database=myDatabase;User Id=myUsername;Password=myPassword\""); sb.AppendLine(""); sb.AppendLine("See the documentation for more info: https://docs.abp.io/en/abp/latest/CLI"); @@ -315,6 +324,32 @@ namespace Volo.Abp.Cli.Commands } } + protected virtual DatabaseManagementSystem GetDatabaseManagementSystem(CommandLineArgs commandLineArgs) + { + var optionValue = commandLineArgs.Options.GetOrNull(Options.DatabaseManagementSystem.Long); + + if (optionValue == null) + { + return DatabaseManagementSystem.NotSpecified; + } + + switch (optionValue.ToLowerInvariant()) + { + case "sqlserver": + return DatabaseManagementSystem.SQLServer; + case "mysql": + return DatabaseManagementSystem.MySQL; + case "postgresql": + return DatabaseManagementSystem.PostgreSQL; + case "oracle": + return DatabaseManagementSystem.Oracle; + case "sqlite": + return DatabaseManagementSystem.SQLite; + default: + return DatabaseManagementSystem.NotSpecified; + } + } + protected virtual UiFramework GetUiFramework(CommandLineArgs commandLineArgs) { var optionValue = commandLineArgs.Options.GetOrNull(Options.UiFramework.Short, Options.UiFramework.Long); @@ -362,6 +397,11 @@ namespace Volo.Abp.Cli.Commands public const string Long = "database-provider"; } + public static class DatabaseManagementSystem + { + public const string Long = "dbsm"; + } + public static class OutputFolder { public const string Short = "o"; diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/SourceCodeDownloadService.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/SourceCodeDownloadService.cs index 78a95996bd..28f41e55d8 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/SourceCodeDownloadService.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/SourceCodeDownloadService.cs @@ -37,6 +37,7 @@ namespace Volo.Abp.Cli.Commands.Services moduleName, version, DatabaseProvider.NotSpecified, + DatabaseManagementSystem.NotSpecified, UiFramework.NotSpecified, null, gitHubAbpLocalRepositoryPath, diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/DatabaseManagementSystem.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/DatabaseManagementSystem.cs new file mode 100644 index 0000000000..edf30abce1 --- /dev/null +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/DatabaseManagementSystem.cs @@ -0,0 +1,12 @@ +namespace Volo.Abp.Cli.ProjectBuilding.Building +{ + public enum DatabaseManagementSystem + { + NotSpecified, + SQLServer, + MySQL, + PostgreSQL, + Oracle, + SQLite + } +} diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/DatabaseManagementSystemChangeStep.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/DatabaseManagementSystemChangeStep.cs new file mode 100644 index 0000000000..cbbaa8d64a --- /dev/null +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/DatabaseManagementSystemChangeStep.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using Volo.Abp.Cli.ProjectBuilding.Files; +using Volo.Abp.Text; + +namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps +{ + public class DatabaseManagementSystemChangeStep : ProjectBuildPipelineStep + { + public override void Execute(ProjectBuildContext context) + { + switch (context.BuildArgs.DatabaseManagementSystem) + { + case DatabaseManagementSystem.NotSpecified: + return; + + case DatabaseManagementSystem.SQLServer: + return; + + case DatabaseManagementSystem.MySQL: + return; + + case DatabaseManagementSystem.PostgreSQL: + return; + + case DatabaseManagementSystem.Oracle: + return; + + case DatabaseManagementSystem.SQLite: + return; + } + } + } +} diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateProjectBuildPipelineBuilder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateProjectBuildPipelineBuilder.cs index ad5da58a8e..c7cf29de20 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateProjectBuildPipelineBuilder.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateProjectBuildPipelineBuilder.cs @@ -18,6 +18,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building pipeline.Steps.Add(new ProjectReferenceReplaceStep()); pipeline.Steps.Add(new TemplateCodeDeleteStep()); pipeline.Steps.Add(new SolutionRenameStep()); + pipeline.Steps.Add(new DatabaseManagementSystemChangeStep()); if (context.Template.Name == AppProTemplate.TemplateName || context.Template.Name == ModuleProTemplate.TemplateName) @@ -31,6 +32,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building pipeline.Steps.Add(new RemoveRootFolderStep()); } + if (context.BuildArgs.ConnectionString != null) { pipeline.Steps.Add(new ConnectionStringChangeStep()); diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ProjectBuildArgs.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ProjectBuildArgs.cs index 52fa76e551..1022f5f10e 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ProjectBuildArgs.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ProjectBuildArgs.cs @@ -17,6 +17,8 @@ namespace Volo.Abp.Cli.ProjectBuilding public DatabaseProvider DatabaseProvider { get; set; } + public DatabaseManagementSystem DatabaseManagementSystem { get; set; } + public UiFramework UiFramework { get; set; } public MobileApp? MobileApp { get; set; } @@ -41,6 +43,7 @@ namespace Volo.Abp.Cli.ProjectBuilding [CanBeNull] string templateName = null, [CanBeNull] string version = null, DatabaseProvider databaseProvider = DatabaseProvider.NotSpecified, + DatabaseManagementSystem databaseManagementSystem = DatabaseManagementSystem.NotSpecified, UiFramework uiFramework = UiFramework.NotSpecified, MobileApp? mobileApp = null, [CanBeNull] string abpGitHubLocalRepositoryPath = null, @@ -53,6 +56,7 @@ namespace Volo.Abp.Cli.ProjectBuilding TemplateName = templateName; Version = version; DatabaseProvider = databaseProvider; + DatabaseManagementSystem = databaseManagementSystem; UiFramework = uiFramework; MobileApp = mobileApp; AbpGitHubLocalRepositoryPath = abpGitHubLocalRepositoryPath; @@ -62,4 +66,4 @@ namespace Volo.Abp.Cli.ProjectBuilding ConnectionString = connectionString; } } -} \ No newline at end of file +} From 83f9d34120fe14c15ae77c3820ea0841324656b4 Mon Sep 17 00:00:00 2001 From: Yunus Emre Kalkan Date: Mon, 21 Dec 2020 15:57:57 +0300 Subject: [PATCH 02/35] =?UTF-8?q?=C4=B0mplement=20DatabaseManagementSystem?= =?UTF-8?q?ChangeStep=20&=20migration=20recreater?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Volo/Abp/Cli/Commands/NewCommand.cs | 58 ++++++++++++---- .../Building/DatabaseManagementSystem.cs | 1 + .../DatabaseManagementSystemChangeStep.cs | 68 ++++++++++++++----- .../TemplateProjectBuildPipelineBuilder.cs | 1 - .../EfCoreMigrationRecreater.cs | 46 +++++++++++++ 5 files changed, 144 insertions(+), 30 deletions(-) create mode 100644 framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/EfCoreMigrationRecreater.cs diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs index f998a6c09e..c3b9302d3b 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs @@ -1,6 +1,7 @@ using System; using System.Diagnostics; using System.IO; +using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Text.Json; @@ -16,6 +17,7 @@ using Volo.Abp.Cli.ProjectBuilding; using Volo.Abp.Cli.ProjectBuilding.Building; using Volo.Abp.Cli.ProjectBuilding.Templates.App; using Volo.Abp.Cli.ProjectBuilding.Templates.Console; +using Volo.Abp.Cli.ProjectModification; using Volo.Abp.Cli.Utils; using Volo.Abp.DependencyInjection; using Volo.Abp.Threading; @@ -24,14 +26,17 @@ namespace Volo.Abp.Cli.Commands { public class NewCommand : IConsoleCommand, ITransientDependency { + private readonly EfCoreMigrationRecreater _efCoreMigrationRecreater; public ILogger Logger { get; set; } protected TemplateProjectBuilder TemplateProjectBuilder { get; } public ITemplateInfoProvider TemplateInfoProvider { get; } public NewCommand(TemplateProjectBuilder templateProjectBuilder - , ITemplateInfoProvider templateInfoProvider) + , ITemplateInfoProvider templateInfoProvider, + EfCoreMigrationRecreater efCoreMigrationRecreater) { + _efCoreMigrationRecreater = efCoreMigrationRecreater; TemplateProjectBuilder = templateProjectBuilder; TemplateInfoProvider = templateInfoProvider; @@ -84,22 +89,29 @@ namespace Volo.Abp.Cli.Commands Logger.LogInformation("Database provider: " + databaseProvider); } + var connectionString = GetConnectionString(commandLineArgs); + if (connectionString != null) + { + Logger.LogInformation("Connection string: " + connectionString); + } + var databaseManagementSystem = GetDatabaseManagementSystem(commandLineArgs); if (databaseManagementSystem != DatabaseManagementSystem.NotSpecified) { - Logger.LogInformation("DBSM: " + databaseManagementSystem); + Logger.LogInformation("DBMS: " + databaseManagementSystem); } - var uiFramework = GetUiFramework(commandLineArgs); - if (uiFramework != UiFramework.NotSpecified) + if (databaseManagementSystem != DatabaseManagementSystem.NotSpecified + && databaseManagementSystem != DatabaseManagementSystem.SQLServer + && connectionString == null) { - Logger.LogInformation("UI Framework: " + uiFramework); + throw new CliUsageException($"Connection string must be set if a Database Management System other than SQLServer is set. Use \"--{Options.ConnectionString.Long}\" parameter to set connection string"); } - var connectionString = GetConnectionString(commandLineArgs); - if (connectionString != null) + var uiFramework = GetUiFramework(commandLineArgs); + if (uiFramework != UiFramework.NotSpecified) { - Logger.LogInformation("Connection string: " + connectionString); + Logger.LogInformation("UI Framework: " + uiFramework); } var mobileApp = GetMobilePreference(commandLineArgs); @@ -203,6 +215,8 @@ namespace Volo.Abp.Cli.Commands } } + ReCreateMigrationsIfNeeded(databaseProvider, databaseManagementSystem, outputFolder); + Logger.LogInformation($"'{projectName}' has been successfully created to '{outputFolder}'"); if (AppTemplateBase.IsAppTemplate(template ?? (await TemplateInfoProvider.GetDefaultAsync()).Name)) @@ -212,6 +226,23 @@ namespace Volo.Abp.Cli.Commands } } + private void ReCreateMigrationsIfNeeded(DatabaseProvider databaseProvider, DatabaseManagementSystem databaseManagementSystem, string outputFolder) + { + if (databaseManagementSystem == DatabaseManagementSystem.NotSpecified || databaseManagementSystem == DatabaseManagementSystem.SQLServer) + { + return; + } + + if (databaseProvider != DatabaseProvider.NotSpecified && databaseProvider != DatabaseProvider.EntityFrameworkCore) + { + return; + } + + Logger.LogInformation($"Re-creating migrations... ({databaseManagementSystem})"); + + _efCoreMigrationRecreater.Recreate(outputFolder); + } + private void OpenThanksPage(UiFramework uiFramework, DatabaseProvider databaseProvider, bool tiered, bool commercial) { uiFramework = uiFramework == UiFramework.NotSpecified || uiFramework == UiFramework.None ? UiFramework.Mvc : uiFramework; @@ -274,7 +305,7 @@ namespace Volo.Abp.Cli.Commands sb.AppendLine("-ts|--template-source (your local or network abp template source)"); sb.AppendLine("-csf|--create-solution-folder (default: true)"); sb.AppendLine("-cs|--connection-string (your database connection string)"); - sb.AppendLine("--dbms (your database management system)"); + sb.AppendLine("--dbms (your database management system. Requires --connection-string to be set)"); sb.AppendLine("--tiered (if supported by the template)"); sb.AppendLine("--no-ui (if supported by the template)"); sb.AppendLine("--no-random-port (Use template's default ports)"); @@ -297,7 +328,7 @@ namespace Volo.Abp.Cli.Commands sb.AppendLine(" abp new Acme.BookStore -ts \"D:\\localTemplate\\abp\""); sb.AppendLine(" abp new Acme.BookStore -csf false"); sb.AppendLine(" abp new Acme.BookStore --local-framework-ref --abp-path \"D:\\github\\abp\""); - sb.AppendLine(" abp new Acme.BookStore --dbms mysql"); + sb.AppendLine(" abp new Acme.BookStore --dbms mysql --connection-string \"Server=myServerName\\myInstanceName;Database=myDatabase;User Id=myUsername;Password=myPassword\""); sb.AppendLine(" abp new Acme.BookStore --connection-string \"Server=myServerName\\myInstanceName;Database=myDatabase;User Id=myUsername;Password=myPassword\""); sb.AppendLine(""); sb.AppendLine("See the documentation for more info: https://docs.abp.io/en/abp/latest/CLI"); @@ -326,7 +357,7 @@ namespace Volo.Abp.Cli.Commands protected virtual DatabaseManagementSystem GetDatabaseManagementSystem(CommandLineArgs commandLineArgs) { - var optionValue = commandLineArgs.Options.GetOrNull(Options.DatabaseManagementSystem.Long); + var optionValue = commandLineArgs.Options.GetOrNull(Options.DatabaseManagementSystem.Short, Options.DatabaseManagementSystem.Long); if (optionValue == null) { @@ -343,6 +374,8 @@ namespace Volo.Abp.Cli.Commands return DatabaseManagementSystem.PostgreSQL; case "oracle": return DatabaseManagementSystem.Oracle; + case "oracle-devart": + return DatabaseManagementSystem.OracleDevart; case "sqlite": return DatabaseManagementSystem.SQLite; default: @@ -399,7 +432,8 @@ namespace Volo.Abp.Cli.Commands public static class DatabaseManagementSystem { - public const string Long = "dbsm"; + public const string Short = "dbms"; + public const string Long = "database-management-system"; } public static class OutputFolder diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/DatabaseManagementSystem.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/DatabaseManagementSystem.cs index edf30abce1..fcb3130854 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/DatabaseManagementSystem.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/DatabaseManagementSystem.cs @@ -7,6 +7,7 @@ MySQL, PostgreSQL, Oracle, + OracleDevart, SQLite } } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/DatabaseManagementSystemChangeStep.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/DatabaseManagementSystemChangeStep.cs index cbbaa8d64a..f0f7c12872 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/DatabaseManagementSystemChangeStep.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/DatabaseManagementSystemChangeStep.cs @@ -1,13 +1,6 @@ using System; -using System.Collections.Generic; -using System.IO; using System.Linq; -using System.Text; -using System.Text.RegularExpressions; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using Volo.Abp.Cli.ProjectBuilding.Files; -using Volo.Abp.Text; namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps { @@ -17,24 +10,65 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps { switch (context.BuildArgs.DatabaseManagementSystem) { - case DatabaseManagementSystem.NotSpecified: - return; - - case DatabaseManagementSystem.SQLServer: - return; - case DatabaseManagementSystem.MySQL: - return; + ChangeEntityFrameworkCoreDependency(context,"Volo.Abp.EntityFrameworkCore.MySQL", + "Volo.Abp.EntityFrameworkCore.MySQL", + "AbpEntityFrameworkCoreMySQLModule"); + ChangeUseSqlServer(context,"UseMySql"); + break; case DatabaseManagementSystem.PostgreSQL: - return; + ChangeEntityFrameworkCoreDependency(context,"Volo.Abp.EntityFrameworkCore.PostgreSql", + "Volo.Abp.EntityFrameworkCore.PostgreSql", + "AbpEntityFrameworkCorePostgreSqlModule"); + ChangeUseSqlServer(context,"UseNpgsql"); + break; case DatabaseManagementSystem.Oracle: - return; + ChangeEntityFrameworkCoreDependency(context,"Volo.Abp.EntityFrameworkCore.Oracle", + "Volo.Abp.EntityFrameworkCore.Oracle", + "AbpEntityFrameworkCoreOracleModule"); + ChangeUseSqlServer(context,"UseOracle"); + break; + + case DatabaseManagementSystem.OracleDevart: + ChangeEntityFrameworkCoreDependency(context,"Volo.Abp.EntityFrameworkCore.Oracle.Devart", + "Volo.Abp.EntityFrameworkCore.Oracle.Devart", + "AbpEntityFrameworkCoreOracleDevartModule"); + ChangeUseSqlServer(context,"UseOracle"); + break; case DatabaseManagementSystem.SQLite: - return; + ChangeEntityFrameworkCoreDependency(context,"Volo.Abp.EntityFrameworkCore.Sqlite", + "Volo.Abp.EntityFrameworkCore.Sqlite", + "AbpEntityFrameworkCoreSqliteModule"); + ChangeUseSqlServer(context,"UseSqlite"); + break; + + default: + return; } } + + private void ChangeEntityFrameworkCoreDependency(ProjectBuildContext context, string newPackageName, string newModuleNamespace, string newModuleClass) + { + var efCoreProjectFile = context.Files.First(f => f.Name.EndsWith("EntityFrameworkCore.csproj", StringComparison.OrdinalIgnoreCase)); + efCoreProjectFile.ReplaceText("Volo.Abp.EntityFrameworkCore.SqlServer", newPackageName); + + var efCoreModuleClass = context.Files.First(f => f.Name.EndsWith("EntityFrameworkCoreModule.cs", StringComparison.OrdinalIgnoreCase)); + efCoreModuleClass.ReplaceText("Volo.Abp.EntityFrameworkCore.SqlServer", newModuleNamespace); + efCoreModuleClass.ReplaceText("AbpEntityFrameworkCoreSqlServerModule", newModuleClass); + } + + private void ChangeUseSqlServer(ProjectBuildContext context, string newUseMethod) + { + var oldUseMethod = "UseSqlServer"; + + var efCoreModuleClass = context.Files.First(f => f.Name.EndsWith("EntityFrameworkCoreModule.cs", StringComparison.OrdinalIgnoreCase)); + efCoreModuleClass.ReplaceText(oldUseMethod, newUseMethod); + + var dbContextFactoryFile = context.Files.First(f => f.Name.EndsWith("MigrationsDbContextFactory.cs", StringComparison.OrdinalIgnoreCase)); + dbContextFactoryFile.ReplaceText(oldUseMethod, newUseMethod); + } } } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateProjectBuildPipelineBuilder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateProjectBuildPipelineBuilder.cs index c7cf29de20..40ba54a3c0 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateProjectBuildPipelineBuilder.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateProjectBuildPipelineBuilder.cs @@ -32,7 +32,6 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building pipeline.Steps.Add(new RemoveRootFolderStep()); } - if (context.BuildArgs.ConnectionString != null) { pipeline.Steps.Add(new ConnectionStringChangeStep()); diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/EfCoreMigrationRecreater.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/EfCoreMigrationRecreater.cs new file mode 100644 index 0000000000..1f9dc7d93d --- /dev/null +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/EfCoreMigrationRecreater.cs @@ -0,0 +1,46 @@ +using System; +using System.IO; +using System.Linq; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Volo.Abp.Cli.Utils; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Cli.ProjectModification +{ + public class EfCoreMigrationRecreater : ITransientDependency + { + public ILogger Logger { get; set; } + + public EfCoreMigrationRecreater() + { + Logger = NullLogger.Instance; + } + + public void Recreate(string solutionFolder) + { + if (Directory.Exists(Path.Combine(solutionFolder, "aspnet-core"))) + { + solutionFolder = Path.Combine(solutionFolder, "aspnet-core"); + } + + var srcFolder = Path.Combine(solutionFolder, "src"); + + try + { + var migrationsFolder = Directory.GetDirectories(srcFolder).First(d => d.EndsWith(".EntityFrameworkCore.DbMigrations")); + Directory.Delete(Path.Combine(migrationsFolder, "Migrations"), true); + + var migratorFolder = Directory.GetDirectories(srcFolder).First(d => d.EndsWith(".DbMigrator")); + var migratorProjectFile = Directory.GetFiles(migratorFolder).First(d => d.EndsWith(".DbMigrator.csproj")); + var addMigrationCommand = $"dotnet ef migrations add Initial --startup-project {migratorProjectFile}"; + CmdHelper.RunCmd($"cd {migrationsFolder} && {addMigrationCommand}"); + } + catch (Exception e) + { + Logger.LogWarning($"\"Re-creating migrations process failed."); + throw e; + } + } + } +} From a8be0b76111f186cebb1cedebbafa9fd8f47da7f Mon Sep 17 00:00:00 2001 From: Yunus Emre Kalkan Date: Mon, 21 Dec 2020 16:25:28 +0300 Subject: [PATCH 03/35] DatabaseManagementSystemChangeStep improvements & remove connection string requirement --- .../Volo/Abp/Cli/Commands/NewCommand.cs | 11 ++-------- .../DatabaseManagementSystemChangeStep.cs | 22 +++++++++++++++---- .../EfCoreMigrationRecreater.cs | 2 +- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs index c3b9302d3b..0fd3360f15 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs @@ -101,13 +101,6 @@ namespace Volo.Abp.Cli.Commands Logger.LogInformation("DBMS: " + databaseManagementSystem); } - if (databaseManagementSystem != DatabaseManagementSystem.NotSpecified - && databaseManagementSystem != DatabaseManagementSystem.SQLServer - && connectionString == null) - { - throw new CliUsageException($"Connection string must be set if a Database Management System other than SQLServer is set. Use \"--{Options.ConnectionString.Long}\" parameter to set connection string"); - } - var uiFramework = GetUiFramework(commandLineArgs); if (uiFramework != UiFramework.NotSpecified) { @@ -305,7 +298,7 @@ namespace Volo.Abp.Cli.Commands sb.AppendLine("-ts|--template-source (your local or network abp template source)"); sb.AppendLine("-csf|--create-solution-folder (default: true)"); sb.AppendLine("-cs|--connection-string (your database connection string)"); - sb.AppendLine("--dbms (your database management system. Requires --connection-string to be set)"); + sb.AppendLine("--dbms (your database management system)"); sb.AppendLine("--tiered (if supported by the template)"); sb.AppendLine("--no-ui (if supported by the template)"); sb.AppendLine("--no-random-port (Use template's default ports)"); @@ -328,7 +321,7 @@ namespace Volo.Abp.Cli.Commands sb.AppendLine(" abp new Acme.BookStore -ts \"D:\\localTemplate\\abp\""); sb.AppendLine(" abp new Acme.BookStore -csf false"); sb.AppendLine(" abp new Acme.BookStore --local-framework-ref --abp-path \"D:\\github\\abp\""); - sb.AppendLine(" abp new Acme.BookStore --dbms mysql --connection-string \"Server=myServerName\\myInstanceName;Database=myDatabase;User Id=myUsername;Password=myPassword\""); + sb.AppendLine(" abp new Acme.BookStore --dbms mysql"); sb.AppendLine(" abp new Acme.BookStore --connection-string \"Server=myServerName\\myInstanceName;Database=myDatabase;User Id=myUsername;Password=myPassword\""); sb.AppendLine(""); sb.AppendLine("See the documentation for more info: https://docs.abp.io/en/abp/latest/CLI"); diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/DatabaseManagementSystemChangeStep.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/DatabaseManagementSystemChangeStep.cs index f0f7c12872..f215d37954 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/DatabaseManagementSystemChangeStep.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/DatabaseManagementSystemChangeStep.cs @@ -14,7 +14,8 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps ChangeEntityFrameworkCoreDependency(context,"Volo.Abp.EntityFrameworkCore.MySQL", "Volo.Abp.EntityFrameworkCore.MySQL", "AbpEntityFrameworkCoreMySQLModule"); - ChangeUseSqlServer(context,"UseMySql"); + AddMySqlServerVersion(context); + ChangeUseSqlServer(context,"UseMySQL", "UseMySql"); break; case DatabaseManagementSystem.PostgreSQL: @@ -50,6 +51,14 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps } } + private void AddMySqlServerVersion(ProjectBuildContext context) + { + var dbContextFactoryFile = context.Files.First(f => f.Name.EndsWith("MigrationsDbContextFactory.cs", StringComparison.OrdinalIgnoreCase)); + + dbContextFactoryFile.ReplaceText("configuration.GetConnectionString(\"Default\")", + "configuration.GetConnectionString(\"Default\"), MySqlServerVersion.LatestSupportedServerVersion"); + } + private void ChangeEntityFrameworkCoreDependency(ProjectBuildContext context, string newPackageName, string newModuleNamespace, string newModuleClass) { var efCoreProjectFile = context.Files.First(f => f.Name.EndsWith("EntityFrameworkCore.csproj", StringComparison.OrdinalIgnoreCase)); @@ -60,15 +69,20 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps efCoreModuleClass.ReplaceText("AbpEntityFrameworkCoreSqlServerModule", newModuleClass); } - private void ChangeUseSqlServer(ProjectBuildContext context, string newUseMethod) + private void ChangeUseSqlServer(ProjectBuildContext context, string newUseMethodForEfModule, string newUseMethodForDbContext = null) { + if (newUseMethodForDbContext == null) + { + newUseMethodForDbContext = newUseMethodForEfModule; + } + var oldUseMethod = "UseSqlServer"; var efCoreModuleClass = context.Files.First(f => f.Name.EndsWith("EntityFrameworkCoreModule.cs", StringComparison.OrdinalIgnoreCase)); - efCoreModuleClass.ReplaceText(oldUseMethod, newUseMethod); + efCoreModuleClass.ReplaceText(oldUseMethod, newUseMethodForEfModule); var dbContextFactoryFile = context.Files.First(f => f.Name.EndsWith("MigrationsDbContextFactory.cs", StringComparison.OrdinalIgnoreCase)); - dbContextFactoryFile.ReplaceText(oldUseMethod, newUseMethod); + dbContextFactoryFile.ReplaceText(oldUseMethod, newUseMethodForDbContext); } } } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/EfCoreMigrationRecreater.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/EfCoreMigrationRecreater.cs index 1f9dc7d93d..3abdaf9392 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/EfCoreMigrationRecreater.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/EfCoreMigrationRecreater.cs @@ -38,7 +38,7 @@ namespace Volo.Abp.Cli.ProjectModification } catch (Exception e) { - Logger.LogWarning($"\"Re-creating migrations process failed."); + Logger.LogWarning("Re-creating migrations process failed."); throw e; } } From 9e00d351c8243062d73d5e539bf709a53a0b454e Mon Sep 17 00:00:00 2001 From: Yunus Emre Kalkan Date: Mon, 21 Dec 2020 16:57:43 +0300 Subject: [PATCH 04/35] DatabaseManagementSystemChangeStep improvements & revert connectionString requirement revert --- .../Volo/Abp/Cli/Commands/NewCommand.cs | 15 +++++++++++---- .../Steps/DatabaseManagementSystemChangeStep.cs | 9 +++++++++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs index 0fd3360f15..94a690deb9 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs @@ -101,6 +101,13 @@ namespace Volo.Abp.Cli.Commands Logger.LogInformation("DBMS: " + databaseManagementSystem); } + if (databaseManagementSystem != DatabaseManagementSystem.NotSpecified + && databaseManagementSystem != DatabaseManagementSystem.SQLServer + && connectionString == null) + { + throw new CliUsageException($"Connection string must be set if a Database Management System other than SQLServer is set. Use \"--{Options.ConnectionString.Long}\" parameter to set connection string"); + } + var uiFramework = GetUiFramework(commandLineArgs); if (uiFramework != UiFramework.NotSpecified) { @@ -298,7 +305,7 @@ namespace Volo.Abp.Cli.Commands sb.AppendLine("-ts|--template-source (your local or network abp template source)"); sb.AppendLine("-csf|--create-solution-folder (default: true)"); sb.AppendLine("-cs|--connection-string (your database connection string)"); - sb.AppendLine("--dbms (your database management system)"); + sb.AppendLine("--dbms (your database management system. Requires --connection-string to be set)"); sb.AppendLine("--tiered (if supported by the template)"); sb.AppendLine("--no-ui (if supported by the template)"); sb.AppendLine("--no-random-port (Use template's default ports)"); @@ -321,7 +328,7 @@ namespace Volo.Abp.Cli.Commands sb.AppendLine(" abp new Acme.BookStore -ts \"D:\\localTemplate\\abp\""); sb.AppendLine(" abp new Acme.BookStore -csf false"); sb.AppendLine(" abp new Acme.BookStore --local-framework-ref --abp-path \"D:\\github\\abp\""); - sb.AppendLine(" abp new Acme.BookStore --dbms mysql"); + sb.AppendLine(" abp new Acme.BookStore --dbms mysql --connection-string \"Server=myServerName\\myInstanceName;Database=myDatabase;User Id=myUsername;Password=myPassword\""); sb.AppendLine(" abp new Acme.BookStore --connection-string \"Server=myServerName\\myInstanceName;Database=myDatabase;User Id=myUsername;Password=myPassword\""); sb.AppendLine(""); sb.AppendLine("See the documentation for more info: https://docs.abp.io/en/abp/latest/CLI"); @@ -365,12 +372,12 @@ namespace Volo.Abp.Cli.Commands return DatabaseManagementSystem.MySQL; case "postgresql": return DatabaseManagementSystem.PostgreSQL; - case "oracle": - return DatabaseManagementSystem.Oracle; case "oracle-devart": return DatabaseManagementSystem.OracleDevart; case "sqlite": return DatabaseManagementSystem.SQLite; + case "oracle": // Currently disabled. See https://github.com/abpframework/abp/issues/6513 + // return DatabaseManagementSystem.Oracle; default: return DatabaseManagementSystem.NotSpecified; } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/DatabaseManagementSystemChangeStep.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/DatabaseManagementSystemChangeStep.cs index f215d37954..4286710899 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/DatabaseManagementSystemChangeStep.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/DatabaseManagementSystemChangeStep.cs @@ -36,6 +36,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps ChangeEntityFrameworkCoreDependency(context,"Volo.Abp.EntityFrameworkCore.Oracle.Devart", "Volo.Abp.EntityFrameworkCore.Oracle.Devart", "AbpEntityFrameworkCoreOracleDevartModule"); + AdjustOracleDbContextOptionsBuilder(context); ChangeUseSqlServer(context,"UseOracle"); break; @@ -51,6 +52,14 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps } } + private void AdjustOracleDbContextOptionsBuilder(ProjectBuildContext context) + { + var dbContextFactoryFile = context.Files.First(f => f.Name.EndsWith("MigrationsDbContextFactory.cs", StringComparison.OrdinalIgnoreCase)); + + dbContextFactoryFile.ReplaceText("new DbContextOptionsBuilder", + $"(DbContextOptionsBuilder<{context.BuildArgs.SolutionName.ProjectName}MigrationsDbContext>) new DbContextOptionsBuilder"); + } + private void AddMySqlServerVersion(ProjectBuildContext context) { var dbContextFactoryFile = context.Files.First(f => f.Name.EndsWith("MigrationsDbContextFactory.cs", StringComparison.OrdinalIgnoreCase)); From f6f7c7ca7081078f7b6a0941989296681c39bc4c Mon Sep 17 00:00:00 2001 From: Yunus Emre Kalkan Date: Mon, 21 Dec 2020 17:06:22 +0300 Subject: [PATCH 05/35] Cli DBMS selection documentation --- docs/en/CLI.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/en/CLI.md b/docs/en/CLI.md index 2e7b117799..4f4da1d90a 100644 --- a/docs/en/CLI.md +++ b/docs/en/CLI.md @@ -106,6 +106,12 @@ abp new Acme.BookStore * `--template-source` or `-ts`: Specifies a custom template source to use to build the project. Local and network sources can be used(Like `D:\local-template` or `https://.../my-template-file.zip`). * `--create-solution-folder` or `-csf`: Specifies if the project will be in a new folder in the output folder or directly the output folder. * `--connection-string` or `-cs`: Overwrites the default connection strings in all `appsettings.json` files. The default connection string is `Server=localhost;Database=MyProjectName;Trusted_Connection=True;MultipleActiveResultSets=true` for EF Core and it is configured to use the SQL Server. If you want to use the EF Core, but need to change the DBMS, you can change it as [described here](Entity-Framework-Core-Other-DBMS.md) (after creating the solution). +* `--database-management-system` or `dbms`: Sets the database management system. Default is **SQL Server**. `--connection-string` parameter should be set along with this parameter if you want to set any DBMS other than **SQL Server**. Supported DBMS's: + * `SqlServer` + * `MySQL` + * `SQLite` + * `Oracle-Devart` + * `PostgreSQL` * `--local-framework-ref --abp-path`: Uses local projects references to the ABP framework instead of using the NuGet packages. This can be useful if you download the ABP Framework source code and have a local reference to the framework from your application. * `--no-random-port`: Uses template's default ports. From 2f824c20449752ba9500cba19d841d198a840908 Mon Sep 17 00:00:00 2001 From: Yunus Emre Kalkan Date: Tue, 22 Dec 2020 11:33:05 +0300 Subject: [PATCH 06/35] Update TemplateProjectBuildPipelineBuilder.cs --- .../Building/TemplateProjectBuildPipelineBuilder.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateProjectBuildPipelineBuilder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateProjectBuildPipelineBuilder.cs index 40ba54a3c0..9590001ea4 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateProjectBuildPipelineBuilder.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateProjectBuildPipelineBuilder.cs @@ -18,7 +18,6 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building pipeline.Steps.Add(new ProjectReferenceReplaceStep()); pipeline.Steps.Add(new TemplateCodeDeleteStep()); pipeline.Steps.Add(new SolutionRenameStep()); - pipeline.Steps.Add(new DatabaseManagementSystemChangeStep()); if (context.Template.Name == AppProTemplate.TemplateName || context.Template.Name == ModuleProTemplate.TemplateName) @@ -26,6 +25,12 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building pipeline.Steps.Add(new LicenseCodeReplaceStep()); } + if (context.Template.Name == AppTemplate.TemplateName || + context.Template.Name == AppProTemplate.TemplateName) + { + pipeline.Steps.Add(new DatabaseManagementSystemChangeStep()); + } + if ((context.BuildArgs.UiFramework == UiFramework.Mvc || context.BuildArgs.UiFramework == UiFramework.Blazor) && context.BuildArgs.MobileApp == MobileApp.None) { From fe3628cca02c1ef363179e384d2a3afeb9a374ef Mon Sep 17 00:00:00 2001 From: Yunus Emre Kalkan Date: Wed, 23 Dec 2020 12:15:38 +0300 Subject: [PATCH 07/35] Update CLI.md --- docs/en/CLI.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/en/CLI.md b/docs/en/CLI.md index 4f4da1d90a..373b07e3d7 100644 --- a/docs/en/CLI.md +++ b/docs/en/CLI.md @@ -106,7 +106,7 @@ abp new Acme.BookStore * `--template-source` or `-ts`: Specifies a custom template source to use to build the project. Local and network sources can be used(Like `D:\local-template` or `https://.../my-template-file.zip`). * `--create-solution-folder` or `-csf`: Specifies if the project will be in a new folder in the output folder or directly the output folder. * `--connection-string` or `-cs`: Overwrites the default connection strings in all `appsettings.json` files. The default connection string is `Server=localhost;Database=MyProjectName;Trusted_Connection=True;MultipleActiveResultSets=true` for EF Core and it is configured to use the SQL Server. If you want to use the EF Core, but need to change the DBMS, you can change it as [described here](Entity-Framework-Core-Other-DBMS.md) (after creating the solution). -* `--database-management-system` or `dbms`: Sets the database management system. Default is **SQL Server**. `--connection-string` parameter should be set along with this parameter if you want to set any DBMS other than **SQL Server**. Supported DBMS's: +* `--database-management-system` or `-dbms`: Sets the database management system. Default is **SQL Server**. `--connection-string` parameter should be set along with this parameter if you want to set any DBMS other than **SQL Server**. Supported DBMS's: * `SqlServer` * `MySQL` * `SQLite` @@ -425,4 +425,4 @@ abp bundle [options] * ```--working-directory``` or ```-wd```: Specifies the working directory. This option is useful when executing directory doesn't contain a Blazor project file. * ```--force``` or ```-f```: Forces to build project before generating references. -`bundle` command reads the `appsettings.json` file inside the Blazor project for bundling options. For more details about managing style and script references in Blazor apps, see [Managing Global Scripts & Styles](UI/Blazor/Global-Scripts-Styles.md) \ No newline at end of file +`bundle` command reads the `appsettings.json` file inside the Blazor project for bundling options. For more details about managing style and script references in Blazor apps, see [Managing Global Scripts & Styles](UI/Blazor/Global-Scripts-Styles.md) From a2642ab08a500f8437a5e0622988fa6f1885d649 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Thu, 24 Dec 2020 10:21:37 +0800 Subject: [PATCH 08/35] Fix the wrong document --- docs/en/UI/Blazor/Theming.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/UI/Blazor/Theming.md b/docs/en/UI/Blazor/Theming.md index cbc6341dab..00bf911ff9 100644 --- a/docs/en/UI/Blazor/Theming.md +++ b/docs/en/UI/Blazor/Theming.md @@ -63,7 +63,7 @@ A theme is simply a Razor Class Library. ### The Easy Way -The easiest way to create a new theme is to copy the [Basic Theme Source Code](https://github.com/abpframework/abp/tree/dev/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme) and customize it. Once you get a copy of the theme in your solution, remove the `Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic` NuGet package and reference to the local project. +The easiest way to create a new theme is to copy the [Basic Theme Source Code](https://github.com/abpframework/abp/tree/dev/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme) and customize it. Once you get a copy of the theme in your solution, remove the `Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme` NuGet package and reference to the local project. ### Global Styles / Scripts From 11cfe4fc0a743259f5dae0997e0ce4751395b856 Mon Sep 17 00:00:00 2001 From: maliming Date: Thu, 24 Dec 2020 10:46:32 +0800 Subject: [PATCH 09/35] Update Branding.md --- docs/en/UI/AspNetCore/Branding.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/docs/en/UI/AspNetCore/Branding.md b/docs/en/UI/AspNetCore/Branding.md index e4a9ee0f3b..aa1500401d 100644 --- a/docs/en/UI/AspNetCore/Branding.md +++ b/docs/en/UI/AspNetCore/Branding.md @@ -20,13 +20,15 @@ namespace MyProject.Web public class MyProjectBrandingProvider : DefaultBrandingProvider { public override string AppName => "Book Store"; + + public override string LogoUrl => "logo.png"; } } ```` The result will be like shown below: -![branding-appname](../../images/branding-appname.png) +![bookstore-added-logo](../../images/bookstore-added-logo.png) `IBrandingProvider` has the following properties: @@ -38,8 +40,4 @@ The result will be like shown below: ## Overriding the Branding Area -The [Basic Theme](Basic-Theme.md) doesn't implement the logos. However, you can see the [UI Customization Guide](Customization-User-Interface.md) to learn how you can replace the branding area with a custom view component. - -An example screenshot with an image is used in the branding area: - -![bookstore-added-logo](../../images/bookstore-added-logo.png) \ No newline at end of file +You can see the [UI Customization Guide](Customization-User-Interface.md) to learn how you can replace the branding area with a custom view component. From be906177ab4e98adff8f8a1792cb64a7f3afaca7 Mon Sep 17 00:00:00 2001 From: maliming Date: Thu, 24 Dec 2020 11:40:32 +0800 Subject: [PATCH 10/35] Add modal container at the beginning of the body. Resolve #6715 --- .../aspnetcore-mvc-ui-theme-shared/bootstrap/modal-manager.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/modal-manager.js b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/modal-manager.js index 3e60d5f9c2..a4d32550f8 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/modal-manager.js +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/modal-manager.js @@ -55,7 +55,8 @@ $.validator.defaults.ignore = ''; //TODO: Would be better if we can apply only f function _createContainer() { _removeContainer(); - _$modalContainer = $('
').appendTo('body'); + _$modalContainer = $('
'); + $('body').prepend(_$modalContainer); return _$modalContainer; } From e646718fbe60a372893b94e88c9e142dd5a3fb60 Mon Sep 17 00:00:00 2001 From: muhammedaltug Date: Thu, 24 Dec 2020 11:03:37 +0300 Subject: [PATCH 11/35] - add wait services - remove ngxs from api interceptor and loader-bar component - remove filter input from loader bar component --- .../src/lib/interceptors/api.interceptor.ts | 10 ++-- .../src/lib/services/http-wait.service.ts | 44 +++++++++++++++ .../packages/core/src/lib/services/index.ts | 2 + .../src/lib/services/lazy-load.service.ts | 10 +++- .../src/lib/services/resource-wait.service.ts | 41 ++++++++++++++ .../src/lib/services/router-wait.service.ts | 53 +++++++++++++++++++ .../loader-bar/loader-bar.component.ts | 51 ++++++------------ 7 files changed, 168 insertions(+), 43 deletions(-) create mode 100644 npm/ng-packs/packages/core/src/lib/services/http-wait.service.ts create mode 100644 npm/ng-packs/packages/core/src/lib/services/resource-wait.service.ts create mode 100644 npm/ng-packs/packages/core/src/lib/services/router-wait.service.ts diff --git a/npm/ng-packs/packages/core/src/lib/interceptors/api.interceptor.ts b/npm/ng-packs/packages/core/src/lib/interceptors/api.interceptor.ts index a2b08c07db..ad60178a98 100644 --- a/npm/ng-packs/packages/core/src/lib/interceptors/api.interceptor.ts +++ b/npm/ng-packs/packages/core/src/lib/interceptors/api.interceptor.ts @@ -1,10 +1,9 @@ import { HttpHandler, HttpHeaders, HttpInterceptor, HttpRequest } from '@angular/common/http'; import { Injectable } from '@angular/core'; -import { Store } from '@ngxs/store'; import { OAuthService } from 'angular-oauth2-oidc'; import { finalize } from 'rxjs/operators'; -import { StartLoader, StopLoader } from '../actions/loader.actions'; import { SessionStateService } from '../services/session-state.service'; +import { HttpWaitService } from '../services/http-wait.service'; @Injectable({ providedIn: 'root', @@ -12,20 +11,19 @@ import { SessionStateService } from '../services/session-state.service'; export class ApiInterceptor implements HttpInterceptor { constructor( private oAuthService: OAuthService, - private store: Store, private sessionState: SessionStateService, + private httpWaitService: HttpWaitService, ) {} intercept(request: HttpRequest, next: HttpHandler) { - this.store.dispatch(new StartLoader(request)); - + this.httpWaitService.addRequest(request); return next .handle( request.clone({ setHeaders: this.getAdditionalHeaders(request.headers), }), ) - .pipe(finalize(() => this.store.dispatch(new StopLoader(request)))); + .pipe(finalize(() => this.httpWaitService.deleteRequest(request))); } getAdditionalHeaders(existingHeaders?: HttpHeaders) { diff --git a/npm/ng-packs/packages/core/src/lib/services/http-wait.service.ts b/npm/ng-packs/packages/core/src/lib/services/http-wait.service.ts new file mode 100644 index 0000000000..96427594ae --- /dev/null +++ b/npm/ng-packs/packages/core/src/lib/services/http-wait.service.ts @@ -0,0 +1,44 @@ +import { Injectable } from '@angular/core'; +import { HttpRequest } from '@angular/common/http'; +import { InternalStore } from '../utils/internal-store-utils'; + +export interface HttpWaitState { + requests: Set>; +} + +@Injectable({ + providedIn: 'root', +}) +export class HttpWaitService { + protected store = new InternalStore({ requests: new Set() }); + + getLoading() { + return !!this.store.state.requests.size; + } + + getLoading$() { + return this.store.sliceState(({ requests }) => !!requests.size); + } + + updateLoading$() { + return this.store.sliceUpdate(({ requests }) => !!requests.size); + } + + clearLoading() { + this.store.patch({ requests: new Set() }); + } + + addRequest(request: HttpRequest) { + const requests = this.store.state.requests; + requests.add(request); + this.store.patch({ requests }); + } + + deleteRequest(request: HttpRequest) { + const requests = this.store.state.requests; + requests.delete(request); + this.store.patch({ requests }); + } + + // TODO: Add filter function +} diff --git a/npm/ng-packs/packages/core/src/lib/services/index.ts b/npm/ng-packs/packages/core/src/lib/services/index.ts index 5b294c4905..47b146ea9f 100644 --- a/npm/ng-packs/packages/core/src/lib/services/index.ts +++ b/npm/ng-packs/packages/core/src/lib/services/index.ts @@ -4,6 +4,7 @@ export * from './config-state.service'; export * from './content-projection.service'; export * from './dom-insertion.service'; export * from './environment.service'; +export * from './http-wait.service'; export * from './lazy-load.service'; export * from './list.service'; export * from './localization.service'; @@ -13,6 +14,7 @@ export * from './profile-state.service'; export * from './profile.service'; export * from './replaceable-components.service'; export * from './rest.service'; +export * from './router-wait.service'; export * from './routes.service'; export * from './session-state.service'; export * from './subscription.service'; diff --git a/npm/ng-packs/packages/core/src/lib/services/lazy-load.service.ts b/npm/ng-packs/packages/core/src/lib/services/lazy-load.service.ts index 5d44bb0879..0aca94c94a 100644 --- a/npm/ng-packs/packages/core/src/lib/services/lazy-load.service.ts +++ b/npm/ng-packs/packages/core/src/lib/services/lazy-load.service.ts @@ -2,6 +2,7 @@ import { Injectable } from '@angular/core'; import { concat, Observable, of, throwError } from 'rxjs'; import { delay, retryWhen, shareReplay, take, tap } from 'rxjs/operators'; import { LoadingStrategy } from '../strategies'; +import { ResourceWaitService } from './resource-wait.service'; @Injectable({ providedIn: 'root', @@ -9,9 +10,11 @@ import { LoadingStrategy } from '../strategies'; export class LazyLoadService { readonly loaded = new Map(); + constructor(private resourceWaitService: ResourceWaitService) {} + load(strategy: LoadingStrategy, retryTimes?: number, retryDelay?: number): Observable { if (this.loaded.has(strategy.path)) return of(new CustomEvent('load')); - + this.resourceWaitService.addResource(strategy.path); return strategy.createStream().pipe( retryWhen(error$ => concat( @@ -19,7 +22,10 @@ export class LazyLoadService { throwError(new CustomEvent('error')), ), ), - tap(() => this.loaded.set(strategy.path, strategy.element)), + tap(() => { + this.loaded.set(strategy.path, strategy.element); + this.resourceWaitService.deleteResource(strategy.path); + }), delay(100), shareReplay({ bufferSize: 1, refCount: true }), ); diff --git a/npm/ng-packs/packages/core/src/lib/services/resource-wait.service.ts b/npm/ng-packs/packages/core/src/lib/services/resource-wait.service.ts new file mode 100644 index 0000000000..16351837a2 --- /dev/null +++ b/npm/ng-packs/packages/core/src/lib/services/resource-wait.service.ts @@ -0,0 +1,41 @@ +import { Injectable } from '@angular/core'; +import { InternalStore } from '../utils/internal-store-utils'; + +export interface ResourceWaitState { + resources: Set; +} + +@Injectable({ + providedIn: 'root', +}) +export class ResourceWaitService { + private store = new InternalStore({ resources: new Set() }); + + getLoading() { + return !!this.store.state.resources.size; + } + + getLoading$() { + return this.store.sliceState(({ resources }) => !!resources.size); + } + + updateLoading$() { + return this.store.sliceUpdate(({ resources }) => !!resources.size); + } + + clearLoading() { + this.store.patch({ resources: new Set() }); + } + + addResource(resource: string) { + const resources = this.store.state.resources; + resources.add(resource); + this.store.patch({ resources }); + } + + deleteResource(resource: string) { + const resources = this.store.state.resources; + resources.delete(resource); + this.store.patch({ resources }); + } +} diff --git a/npm/ng-packs/packages/core/src/lib/services/router-wait.service.ts b/npm/ng-packs/packages/core/src/lib/services/router-wait.service.ts new file mode 100644 index 0000000000..d1306e63c9 --- /dev/null +++ b/npm/ng-packs/packages/core/src/lib/services/router-wait.service.ts @@ -0,0 +1,53 @@ +import { Injectable } from '@angular/core'; +import { + NavigationCancel, + NavigationEnd, + NavigationError, + NavigationStart, + Router, +} from '@angular/router'; +import { filter } from 'rxjs/operators'; +import { InternalStore } from '../utils/internal-store-utils'; + +export interface RouterWaitState { + loading: boolean; +} + +@Injectable({ + providedIn: 'root', +}) +export class RouterWaitService { + private store = new InternalStore({ loading: false }); + constructor(private router: Router) { + this.router.events + .pipe( + filter( + event => + event instanceof NavigationStart || + event instanceof NavigationEnd || + event instanceof NavigationError || + event instanceof NavigationCancel, + ), + ) + .subscribe(event => { + if (event instanceof NavigationStart) this.setLoading(true); + else this.setLoading(false); + }); + } + + getLoading() { + return this.store.state.loading; + } + + getLoading$() { + return this.store.sliceState(({ loading }) => loading); + } + + updateLoading$() { + return this.store.sliceUpdate(({ loading }) => loading); + } + + setLoading(loading: boolean) { + this.store.patch({ loading }); + } +} diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/loader-bar/loader-bar.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/loader-bar/loader-bar.component.ts index f94b6b3656..729a844440 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/loader-bar/loader-bar.component.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/loader-bar/loader-bar.component.ts @@ -1,9 +1,9 @@ -import { StartLoader, StopLoader, SubscriptionService } from '@abp/ng.core'; +import { SubscriptionService } from '@abp/ng.core'; import { ChangeDetectorRef, Component, Input, OnDestroy, OnInit } from '@angular/core'; -import { NavigationEnd, NavigationError, NavigationStart, Router } from '@angular/router'; -import { Actions, ofActionSuccessful } from '@ngxs/store'; -import { Subscription, timer } from 'rxjs'; -import { filter } from 'rxjs/operators'; +import { Router } from '@angular/router'; +import { combineLatest, Subscription, timer } from 'rxjs'; +import { RouterWaitService } from '../../../../../core/src/lib/services/router-wait.service'; +import { HttpWaitService } from '../../../../../core/src/lib/services/http-wait.service'; @Component({ selector: 'abp-loader-bar', @@ -51,10 +51,6 @@ export class LoaderBarComponent implements OnDestroy, OnInit { stopDelay = 800; - @Input() - filter = (action: StartLoader | StopLoader) => - action.payload.url.indexOf('openid-configuration') < 0; - private readonly clearProgress = () => { this.progressLevel = 0; this.cdRef.detectChanges(); @@ -78,44 +74,27 @@ export class LoaderBarComponent implements OnDestroy, OnInit { } constructor( - private actions: Actions, private router: Router, private cdRef: ChangeDetectorRef, private subscription: SubscriptionService, + private httpWaitService: HttpWaitService, + private routerWaiterService: RouterWaitService, ) {} - private subscribeToLoadActions() { - this.subscription.addOne( - this.actions.pipe(ofActionSuccessful(StartLoader, StopLoader), filter(this.filter)), - action => { - if (action instanceof StartLoader) this.startLoading(); - else this.stopLoading(); - }, - ); + ngOnInit() { + this.subscribeLoading(); } - private subscribeToRouterEvents() { + subscribeLoading() { this.subscription.addOne( - this.router.events.pipe( - filter( - event => - event instanceof NavigationStart || - event instanceof NavigationEnd || - event instanceof NavigationError, - ), - ), - event => { - if (event instanceof NavigationStart) this.startLoading(); + combineLatest([this.httpWaitService.getLoading$(), this.routerWaiterService.getLoading$()]), + ([httpLoading, routerLoading]) => { + if (httpLoading || routerLoading) this.startLoading(); else this.stopLoading(); }, ); } - ngOnInit() { - this.subscribeToLoadActions(); - this.subscribeToRouterEvents(); - } - ngOnDestroy() { if (this.interval) this.interval.unsubscribe(); } @@ -124,8 +103,10 @@ export class LoaderBarComponent implements OnDestroy, OnInit { if (this.isLoading || (this.interval && !this.interval.closed)) return; this.isLoading = true; - + this.progressLevel = 0; this.interval = timer(0, this.intervalPeriod).subscribe(this.reportProgress); + this.timer.unsubscribe(); + this.cdRef.detectChanges(); } stopLoading() { From 57f5205228c597708b13e77f5f9800944eef5fb4 Mon Sep 17 00:00:00 2001 From: muhammedaltug Date: Thu, 24 Dec 2020 11:05:54 +0300 Subject: [PATCH 12/35] - add resource-waiter service to index --- npm/ng-packs/packages/core/src/lib/services/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/npm/ng-packs/packages/core/src/lib/services/index.ts b/npm/ng-packs/packages/core/src/lib/services/index.ts index 47b146ea9f..37bc78d606 100644 --- a/npm/ng-packs/packages/core/src/lib/services/index.ts +++ b/npm/ng-packs/packages/core/src/lib/services/index.ts @@ -13,6 +13,7 @@ export * from './permission.service'; export * from './profile-state.service'; export * from './profile.service'; export * from './replaceable-components.service'; +export * from './resource-wait.service'; export * from './rest.service'; export * from './router-wait.service'; export * from './routes.service'; From e30f08e6d521966fda6bab0c04457b85f2986825 Mon Sep 17 00:00:00 2001 From: muhammedaltug Date: Thu, 24 Dec 2020 11:08:45 +0300 Subject: [PATCH 13/35] - remove detect changes --- .../src/lib/components/loader-bar/loader-bar.component.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/loader-bar/loader-bar.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/loader-bar/loader-bar.component.ts index 729a844440..a3afd9fba0 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/loader-bar/loader-bar.component.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/loader-bar/loader-bar.component.ts @@ -106,7 +106,6 @@ export class LoaderBarComponent implements OnDestroy, OnInit { this.progressLevel = 0; this.interval = timer(0, this.intervalPeriod).subscribe(this.reportProgress); this.timer.unsubscribe(); - this.cdRef.detectChanges(); } stopLoading() { From b4bcc2519a0a3602495f9d937af07b8c4a698e00 Mon Sep 17 00:00:00 2001 From: muhammedaltug Date: Thu, 24 Dec 2020 11:23:03 +0300 Subject: [PATCH 14/35] - service import fix --- .../src/lib/components/loader-bar/loader-bar.component.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/loader-bar/loader-bar.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/loader-bar/loader-bar.component.ts index a3afd9fba0..62f3c077b6 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/loader-bar/loader-bar.component.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/loader-bar/loader-bar.component.ts @@ -1,9 +1,7 @@ -import { SubscriptionService } from '@abp/ng.core'; +import { SubscriptionService, HttpWaitService, RouterWaitService } from '@abp/ng.core'; import { ChangeDetectorRef, Component, Input, OnDestroy, OnInit } from '@angular/core'; import { Router } from '@angular/router'; import { combineLatest, Subscription, timer } from 'rxjs'; -import { RouterWaitService } from '../../../../../core/src/lib/services/router-wait.service'; -import { HttpWaitService } from '../../../../../core/src/lib/services/http-wait.service'; @Component({ selector: 'abp-loader-bar', From a0a1a1c8c9d38f08b0fdbe97731aa3d945b68e02 Mon Sep 17 00:00:00 2001 From: muhammedaltug Date: Thu, 24 Dec 2020 11:23:44 +0300 Subject: [PATCH 15/35] - fix import order --- .../src/lib/components/loader-bar/loader-bar.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/loader-bar/loader-bar.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/loader-bar/loader-bar.component.ts index 62f3c077b6..b0d626cf71 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/loader-bar/loader-bar.component.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/loader-bar/loader-bar.component.ts @@ -1,4 +1,4 @@ -import { SubscriptionService, HttpWaitService, RouterWaitService } from '@abp/ng.core'; +import { HttpWaitService, RouterWaitService, SubscriptionService } from '@abp/ng.core'; import { ChangeDetectorRef, Component, Input, OnDestroy, OnInit } from '@angular/core'; import { Router } from '@angular/router'; import { combineLatest, Subscription, timer } from 'rxjs'; From 99b323c7b5abfd3167e07cdf6203c7c7bd8d503c Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Thu, 24 Dec 2020 17:06:16 +0800 Subject: [PATCH 16/35] Add reset password localized text --- .../Volo/Abp/Account/Localization/Resources/de-DE.json | 4 +++- .../Volo/Abp/Account/Localization/Resources/en.json | 4 +++- .../Volo/Abp/Account/Localization/Resources/es.json | 4 +++- .../Volo/Abp/Account/Localization/Resources/sl.json | 4 +++- .../Volo/Abp/Account/Localization/Resources/tr.json | 4 +++- .../Volo/Abp/Account/Localization/Resources/zh-Hans.json | 4 +++- .../Volo/Abp/Account/Localization/Resources/zh-Hant.json | 4 +++- 7 files changed, 21 insertions(+), 7 deletions(-) diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/de-DE.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/de-DE.json index 714e7f69c2..0c880c3910 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/de-DE.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/de-DE.json @@ -57,6 +57,8 @@ "ProfileTab:Password": "Passwort ändern", "ProfileTab:PersonalInfo": "Persönliche Informationen", "ReturnToApplication": "Zur Anwendung zurückkehren", - "Volo.Account:InvalidEmailAddress": "Die angegebene E-Mail-Adresse kann nicht gefunden werden: {0}" + "Volo.Account:InvalidEmailAddress": "Die angegebene E-Mail-Adresse kann nicht gefunden werden: {0}", + "PasswordReset": "Passwort zurücksetzen", + "PasswordResetInfoInEmail": "Wir haben eine Anfrage zur Wiederherstellung des Kontos erhalten! Wenn Sie diese Anforderung initiiert haben, klicken Sie auf den folgenden Link, um Ihr Passwort zurückzusetzen." } } diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/en.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/en.json index e7cdc64c43..54d3cfd98d 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/en.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/en.json @@ -57,6 +57,8 @@ "ProfileTab:Password": "Change password", "ProfileTab:PersonalInfo": "Personal info", "ReturnToApplication": "Return to application", - "Volo.Account:InvalidEmailAddress": "Can not find the given email address: {0}" + "Volo.Account:InvalidEmailAddress": "Can not find the given email address: {0}", + "PasswordReset": "Password reset", + "PasswordResetInfoInEmail": "We received an account recovery request! If you initiated this request, click the following link to reset your password." } } diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/es.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/es.json index 5f7d824ca0..95b35b3426 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/es.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/es.json @@ -57,6 +57,8 @@ "ProfileTab:Password": "Cambiar contraseña", "ProfileTab:PersonalInfo": "Información personal", "ReturnToApplication": "Volver a la aplicación", - "Volo.Account:InvalidEmailAddress": "No se puede encontrar la dirección de e-mail solicitada: {0}" + "Volo.Account:InvalidEmailAddress": "No se puede encontrar la dirección de e-mail solicitada: {0}", + "PasswordReset": "Restablecer contraseña", + "PasswordResetInfoInEmail": "Recibimos una solicitud de recuperación de cuenta. Si inició esta solicitud, haga clic en el siguiente enlace para restablecer su contraseña." } } diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/sl.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/sl.json index 4cd3d801fc..4bde5fe84d 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/sl.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/sl.json @@ -49,6 +49,8 @@ "ResetPassword_Information": "Prosimo vnesite vaše novo geslo.", "YourPasswordIsSuccessfullyReset": "Vaše geslo je uspešno ponastavljeno.", "BackToLogin": "Nazaj na prijavo", - "Volo.Account:InvalidEmailAddress": "Navedenega e-poštnega naslova ni mogoče najti: {0}" + "Volo.Account:InvalidEmailAddress": "Navedenega e-poštnega naslova ni mogoče najti: {0}", + "PasswordReset": "Ponastavitev gesla", + "PasswordResetInfoInEmail": "Prejeta je bila zahteva za obnovitev računa! V kolikor ste vi sprožili zahtevo, kliknite na sledečo povezavo, da ponastavite geslo." } } diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/tr.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/tr.json index 3be2997f68..758689f068 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/tr.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/tr.json @@ -57,6 +57,8 @@ "ProfileTab:Password": "Şifre değiştir", "ProfileTab:PersonalInfo": "Kişisel bilgiler", "ReturnToApplication": "Uygulamaya geri dön", - "Volo.Account:InvalidEmailAddress": "Email adresi bulunamadı: {0}" + "Volo.Account:InvalidEmailAddress": "Email adresi bulunamadı: {0}", + "PasswordReset": "Şifre Sıfırlama", + "PasswordResetInfoInEmail": "Şifrenizi sıfırlamanız için bir talep aldık! Eğer bu talebi siz gerçekleştirmişseniz, şifrenizi sıfırlamak için bağlantıya tıklayın." } } diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/zh-Hans.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/zh-Hans.json index f5995c6e28..f07e63edc6 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/zh-Hans.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/zh-Hans.json @@ -57,6 +57,8 @@ "ProfileTab:Password": "更改密码", "ProfileTab:PersonalInfo": "个人信息", "ReturnToApplication": "返回到应用程序", - "Volo.Account:InvalidEmailAddress": "找不到给定的电子邮件地址:{0}" + "Volo.Account:InvalidEmailAddress": "找不到给定的电子邮件地址:{0}", + "PasswordReset": "重设密码", + "PasswordResetInfoInEmail": "我们收到了帐户恢复请求!如果你发起了此请求,请单击以下链接以重置密码." } } diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/zh-Hant.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/zh-Hant.json index f4fd2d65b1..566781e2fa 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/zh-Hant.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/zh-Hant.json @@ -55,6 +55,8 @@ "BackToLogin": "返回登錄", "ProfileTab:Password": "更改密碼", "ProfileTab:PersonalInfo": "個人信息", - "ReturnToApplication": "返回到應用程序" + "ReturnToApplication": "返回到應用程序", + "PasswordReset": "重設密碼", + "PasswordResetInfoInEmail": "我們收到了帳戶恢復請求!如果你發起了此請求,請單擊以下鏈接以重置密碼." } } From 4f215e0799655e6c8536624d43657e3a63df7945 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Thu, 24 Dec 2020 17:16:18 +0800 Subject: [PATCH 17/35] Improved --- .../Volo/Abp/Account/Localization/Resources/de-DE.json | 3 ++- .../Volo/Abp/Account/Localization/Resources/en.json | 3 ++- .../Volo/Abp/Account/Localization/Resources/es.json | 3 ++- .../Volo/Abp/Account/Localization/Resources/sl.json | 3 ++- .../Volo/Abp/Account/Localization/Resources/tr.json | 3 ++- .../Volo/Abp/Account/Localization/Resources/zh-Hans.json | 3 ++- .../Volo/Abp/Account/Localization/Resources/zh-Hant.json | 3 ++- 7 files changed, 14 insertions(+), 7 deletions(-) diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/de-DE.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/de-DE.json index 0c880c3910..2ae7c2c53f 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/de-DE.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/de-DE.json @@ -59,6 +59,7 @@ "ReturnToApplication": "Zur Anwendung zurückkehren", "Volo.Account:InvalidEmailAddress": "Die angegebene E-Mail-Adresse kann nicht gefunden werden: {0}", "PasswordReset": "Passwort zurücksetzen", - "PasswordResetInfoInEmail": "Wir haben eine Anfrage zur Wiederherstellung des Kontos erhalten! Wenn Sie diese Anforderung initiiert haben, klicken Sie auf den folgenden Link, um Ihr Passwort zurückzusetzen." + "PasswordResetInfoInEmail": "Wir haben eine Anfrage zur Wiederherstellung des Kontos erhalten! Wenn Sie diese Anforderung initiiert haben, klicken Sie auf den folgenden Link, um Ihr Passwort zurückzusetzen.", + "ResetMyPassword": "Mein Passwort zurücksetzen" } } diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/en.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/en.json index 54d3cfd98d..755cd5674b 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/en.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/en.json @@ -59,6 +59,7 @@ "ReturnToApplication": "Return to application", "Volo.Account:InvalidEmailAddress": "Can not find the given email address: {0}", "PasswordReset": "Password reset", - "PasswordResetInfoInEmail": "We received an account recovery request! If you initiated this request, click the following link to reset your password." + "PasswordResetInfoInEmail": "We received an account recovery request! If you initiated this request, click the following link to reset your password.", + "ResetMyPassword": "Reset my password" } } diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/es.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/es.json index 95b35b3426..f451cff366 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/es.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/es.json @@ -59,6 +59,7 @@ "ReturnToApplication": "Volver a la aplicación", "Volo.Account:InvalidEmailAddress": "No se puede encontrar la dirección de e-mail solicitada: {0}", "PasswordReset": "Restablecer contraseña", - "PasswordResetInfoInEmail": "Recibimos una solicitud de recuperación de cuenta. Si inició esta solicitud, haga clic en el siguiente enlace para restablecer su contraseña." + "PasswordResetInfoInEmail": "Recibimos una solicitud de recuperación de cuenta. Si inició esta solicitud, haga clic en el siguiente enlace para restablecer su contraseña.", + "ResetMyPassword": "Restablecer mi contraseña" } } diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/sl.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/sl.json index 4bde5fe84d..13a8fd4848 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/sl.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/sl.json @@ -51,6 +51,7 @@ "BackToLogin": "Nazaj na prijavo", "Volo.Account:InvalidEmailAddress": "Navedenega e-poštnega naslova ni mogoče najti: {0}", "PasswordReset": "Ponastavitev gesla", - "PasswordResetInfoInEmail": "Prejeta je bila zahteva za obnovitev računa! V kolikor ste vi sprožili zahtevo, kliknite na sledečo povezavo, da ponastavite geslo." + "PasswordResetInfoInEmail": "Prejeta je bila zahteva za obnovitev računa! V kolikor ste vi sprožili zahtevo, kliknite na sledečo povezavo, da ponastavite geslo.", + "ResetMyPassword": "Ponastavi geslo" } } diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/tr.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/tr.json index 758689f068..d8cf5dd74f 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/tr.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/tr.json @@ -59,6 +59,7 @@ "ReturnToApplication": "Uygulamaya geri dön", "Volo.Account:InvalidEmailAddress": "Email adresi bulunamadı: {0}", "PasswordReset": "Şifre Sıfırlama", - "PasswordResetInfoInEmail": "Şifrenizi sıfırlamanız için bir talep aldık! Eğer bu talebi siz gerçekleştirmişseniz, şifrenizi sıfırlamak için bağlantıya tıklayın." + "PasswordResetInfoInEmail": "Şifrenizi sıfırlamanız için bir talep aldık! Eğer bu talebi siz gerçekleştirmişseniz, şifrenizi sıfırlamak için bağlantıya tıklayın.", + "ResetMyPassword": "Şifremi sıfırla" } } diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/zh-Hans.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/zh-Hans.json index f07e63edc6..53fe6135f2 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/zh-Hans.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/zh-Hans.json @@ -59,6 +59,7 @@ "ReturnToApplication": "返回到应用程序", "Volo.Account:InvalidEmailAddress": "找不到给定的电子邮件地址:{0}", "PasswordReset": "重设密码", - "PasswordResetInfoInEmail": "我们收到了帐户恢复请求!如果你发起了此请求,请单击以下链接以重置密码." + "PasswordResetInfoInEmail": "我们收到了帐户恢复请求!如果你发起了此请求,请单击以下链接以重置密码.", + "ResetMyPassword": "重置我的密码" } } diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/zh-Hant.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/zh-Hant.json index 566781e2fa..a67ea8d63f 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/zh-Hant.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/zh-Hant.json @@ -57,6 +57,7 @@ "ProfileTab:PersonalInfo": "個人信息", "ReturnToApplication": "返回到應用程序", "PasswordReset": "重設密碼", - "PasswordResetInfoInEmail": "我們收到了帳戶恢復請求!如果你發起了此請求,請單擊以下鏈接以重置密碼." + "PasswordResetInfoInEmail": "我們收到了帳戶恢復請求!如果你發起了此請求,請單擊以下鏈接以重置密碼.", + "ResetMyPassword": "重置我的密碼" } } From a5cc3375f527d8e26656f465da116b8bfcc21c65 Mon Sep 17 00:00:00 2001 From: Yunus Emre Kalkan Date: Thu, 24 Dec 2020 12:29:22 +0300 Subject: [PATCH 18/35] Fix databaseProvider parameter of thanks page url --- .../src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs index 75d2651cbc..b76d4de5b5 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs @@ -208,6 +208,7 @@ namespace Volo.Abp.Cli.Commands private void OpenThanksPage(UiFramework uiFramework, DatabaseProvider databaseProvider, bool tiered, bool commercial) { uiFramework = uiFramework == UiFramework.NotSpecified || uiFramework == UiFramework.None ? UiFramework.Mvc : uiFramework; + databaseProvider = databaseProvider == DatabaseProvider.NotSpecified ? DatabaseProvider.EntityFrameworkCore : databaseProvider; var urlPrefix = commercial ? "commercial" : "www"; var tieredYesNo = tiered ? "yes" : "no"; From 1a92a83481ca46510c42d07510e2cdc3b0a82a31 Mon Sep 17 00:00:00 2001 From: Yunus Emre Kalkan Date: Thu, 24 Dec 2020 14:26:40 +0300 Subject: [PATCH 19/35] Added RemoveUnnecessaryPortsStep resolves https://github.com/abpframework/abp/issues/6767 --- .../Templates/App/AppTemplateBase.cs | 6 +++ .../Templates/RemoveUnnecessaryPortsStep.cs | 46 +++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/RemoveUnnecessaryPortsStep.cs diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateBase.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateBase.cs index a598d3483c..a351589881 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateBase.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateBase.cs @@ -24,6 +24,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Templates.App SwitchDatabaseProvider(context, steps); DeleteUnrelatedProjects(context, steps); + RemoveUnnecessaryPorts(context, steps); RandomizeSslPorts(context, steps); RandomizeStringEncryption(context, steps); UpdateNuGetConfig(context, steps); @@ -176,6 +177,11 @@ namespace Volo.Abp.Cli.ProjectBuilding.Templates.App } } + private static void RemoveUnnecessaryPorts(ProjectBuildContext context, List steps) + { + steps.Add(new RemoveUnnecessaryPortsStep()); + } + private static void RandomizeSslPorts(ProjectBuildContext context, List steps) { if (context.BuildArgs.ExtraProperties.ContainsKey("no-random-port")) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/RemoveUnnecessaryPortsStep.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/RemoveUnnecessaryPortsStep.cs new file mode 100644 index 0000000000..4d44cf0b05 --- /dev/null +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/RemoveUnnecessaryPortsStep.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using Volo.Abp.Cli.ProjectBuilding.Building; + +namespace Volo.Abp.Cli.ProjectBuilding.Templates +{ + public class RemoveUnnecessaryPortsStep : ProjectBuildPipelineStep + { + public override void Execute(ProjectBuildContext context) + { + var httpApiHostAppSettings = context.Files.FirstOrDefault(f => f.Name.EndsWith(".HttpApi.Host/appsettings.json")); + + if (httpApiHostAppSettings == null) + { + return; + } + + var portsToRemoveFromCors = new List(); + + var appSettingsJson = JObject.Parse(httpApiHostAppSettings.Content); + var appJson = (JObject) appSettingsJson["App"]; + + if (context.BuildArgs.UiFramework != UiFramework.Angular) + { + appJson.Property("ClientUrl")?.Remove(); + portsToRemoveFromCors.Add("4200"); + } + if (context.BuildArgs.UiFramework != UiFramework.Blazor) + { + portsToRemoveFromCors.Add("44307"); + } + + if (appJson["CorsOrigins"] != null) + { + appJson["CorsOrigins"] = string.Join(",", + appJson["CorsOrigins"].ToString().Split(",").Where(u=> !portsToRemoveFromCors.Any(u.EndsWith)) + ); + } + + httpApiHostAppSettings.SetContent(JsonConvert.SerializeObject(appSettingsJson, Formatting.Indented)); + } + } +} From cba06c2afb8e855a699617c0c86e82f29eb86669 Mon Sep 17 00:00:00 2001 From: muhammedaltug Date: Thu, 24 Dec 2020 14:54:18 +0300 Subject: [PATCH 20/35] - fix tests --- .../src/lib/tests/api.interceptor.spec.ts | 19 ++++++++------- .../src/lib/tests/lazy-load.service.spec.ts | 7 ++++-- .../lib/tests/loader-bar.component.spec.ts | 23 ++++++++----------- 3 files changed, 23 insertions(+), 26 deletions(-) diff --git a/npm/ng-packs/packages/core/src/lib/tests/api.interceptor.spec.ts b/npm/ng-packs/packages/core/src/lib/tests/api.interceptor.spec.ts index ed42194755..ab289ddd9a 100644 --- a/npm/ng-packs/packages/core/src/lib/tests/api.interceptor.spec.ts +++ b/npm/ng-packs/packages/core/src/lib/tests/api.interceptor.spec.ts @@ -1,31 +1,29 @@ import { HttpRequest } from '@angular/common/http'; import { SpyObject } from '@ngneat/spectator'; import { createServiceFactory, SpectatorService } from '@ngneat/spectator/jest'; -import { Store } from '@ngxs/store'; import { OAuthService } from 'angular-oauth2-oidc'; import { Subject, timer } from 'rxjs'; -import { StartLoader, StopLoader } from '../actions'; import { ApiInterceptor } from '../interceptors'; -import { SessionStateService } from '../services'; +import { HttpWaitService, SessionStateService } from '../services'; describe('ApiInterceptor', () => { let spectator: SpectatorService; let interceptor: ApiInterceptor; - let store: SpyObject; let oauthService: SpyObject; let sessionState: SpyObject; + let httpWaitService: SpyObject; const createService = createServiceFactory({ service: ApiInterceptor, - mocks: [OAuthService, Store, SessionStateService], + mocks: [OAuthService, SessionStateService], }); beforeEach(() => { spectator = createService(); interceptor = spectator.service; - store = spectator.inject(Store); sessionState = spectator.inject(SessionStateService); oauthService = spectator.inject(OAuthService); + httpWaitService = spectator.inject(HttpWaitService); }); it('should add headers to http request', done => { @@ -52,8 +50,9 @@ describe('ApiInterceptor', () => { handleRes$.complete(); }); - it('should dispatch the loader', done => { - const spy = jest.spyOn(store, 'dispatch'); + it('should call http wait services add request and delete request', done => { + const spyAddRequest = jest.spyOn(httpWaitService, 'addRequest'); + const spyDeleteRequest = jest.spyOn(httpWaitService, 'deleteRequest'); const request = new HttpRequest('GET', 'https://abp.io'); const handleRes$ = new Subject(); @@ -70,8 +69,8 @@ describe('ApiInterceptor', () => { handleRes$.complete(); timer(0).subscribe(() => { - expect(spy.mock.calls[0][0] instanceof StartLoader).toBeTruthy(); - expect(spy.mock.calls[1][0] instanceof StopLoader).toBeTruthy(); + expect(spyAddRequest).toHaveBeenCalled(); + expect(spyDeleteRequest).toHaveBeenCalled(); done(); }); }); diff --git a/npm/ng-packs/packages/core/src/lib/tests/lazy-load.service.spec.ts b/npm/ng-packs/packages/core/src/lib/tests/lazy-load.service.spec.ts index dc4d937f17..eb347be80a 100644 --- a/npm/ng-packs/packages/core/src/lib/tests/lazy-load.service.spec.ts +++ b/npm/ng-packs/packages/core/src/lib/tests/lazy-load.service.spec.ts @@ -2,10 +2,12 @@ import { of, throwError } from 'rxjs'; import { switchMap } from 'rxjs/operators'; import { LazyLoadService } from '../services/lazy-load.service'; import { ScriptLoadingStrategy } from '../strategies'; +import { ResourceWaitService } from '../services'; describe('LazyLoadService', () => { describe('#load', () => { - const service = new LazyLoadService(); + const resourceWaitService = new ResourceWaitService(); + const service = new LazyLoadService(resourceWaitService); const strategy = new ScriptLoadingStrategy('http://example.com/'); afterEach(() => { @@ -58,7 +60,8 @@ describe('LazyLoadService', () => { }); describe('#remove', () => { - const service = new LazyLoadService(); + const resourceWaitService = new ResourceWaitService(); + const service = new LazyLoadService(resourceWaitService); it('should remove an already lazy loaded element and return true', () => { const script = document.createElement('script'); diff --git a/npm/ng-packs/packages/theme-shared/src/lib/tests/loader-bar.component.spec.ts b/npm/ng-packs/packages/theme-shared/src/lib/tests/loader-bar.component.spec.ts index 894b5f60d1..00a823f860 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/tests/loader-bar.component.spec.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/tests/loader-bar.component.spec.ts @@ -1,16 +1,10 @@ -import { - Router, - RouteReuseStrategy, - NavigationStart, - NavigationEnd, - NavigationError, -} from '@angular/router'; +import { NavigationEnd, NavigationError, NavigationStart, Router } from '@angular/router'; import { createHostFactory, SpectatorHost, SpyObject } from '@ngneat/spectator/jest'; -import { Actions, NgxsModule, Store } from '@ngxs/store'; -import { Subject, Subscription, Observable, Subscriber, timer } from 'rxjs'; +import { Subject, Subscription, timer } from 'rxjs'; import { LoaderBarComponent } from '../components/loader-bar/loader-bar.component'; -import { StartLoader, StopLoader, SubscriptionService } from '@abp/ng.core'; +import { SubscriptionService } from '@abp/ng.core'; import { HttpRequest } from '@angular/common/http'; +import { HttpWaitService } from '../../../../core/src/lib/services'; describe('LoaderBarComponent', () => { let spectator: SpectatorHost; @@ -20,7 +14,6 @@ describe('LoaderBarComponent', () => { const createHost = createHostFactory({ component: LoaderBarComponent, mocks: [Router], - imports: [NgxsModule.forRoot()], detectChanges: false, providers: [SubscriptionService], }); @@ -41,7 +34,8 @@ describe('LoaderBarComponent', () => { it('should increase the progressLevel', done => { spectator.detectChanges(); - spectator.inject(Store).dispatch(new StartLoader(new HttpRequest('GET', 'test'))); + const httpWaitService = spectator.inject(HttpWaitService); + httpWaitService.addRequest(new HttpRequest('GET', 'test')); spectator.detectChanges(); setTimeout(() => { expect(spectator.component.progressLevel > 0).toBeTruthy(); @@ -51,7 +45,8 @@ describe('LoaderBarComponent', () => { test.skip('should be interval unsubscribed', done => { spectator.detectChanges(); - spectator.inject(Store).dispatch(new StartLoader(new HttpRequest('GET', 'test'))); + const httpWaitService = spectator.inject(HttpWaitService); + httpWaitService.addRequest(new HttpRequest('GET', 'test')); expect(spectator.component.interval.closed).toBe(false); timer(400).subscribe(() => { @@ -80,7 +75,7 @@ describe('LoaderBarComponent', () => { (router as any).events.next(new NavigationStart(1, 'test')); expect(spectator.component.interval.closed).toBe(false); - spectator.inject(Store).dispatch(new StopLoader(new HttpRequest('GET', 'test'))); + (router as any).events.next(new NavigationEnd(1, 'testend', 'testend')); expect(spectator.component.progressLevel).toBe(100); timer(2).subscribe(() => { From 245f59b5a7dcf5d93643efe5f75048f1fa1edf9b Mon Sep 17 00:00:00 2001 From: muhammedaltug Date: Thu, 24 Dec 2020 15:42:22 +0300 Subject: [PATCH 21/35] - fix tests --- .../loader-bar/loader-bar.component.ts | 12 +++---- .../lib/tests/loader-bar.component.spec.ts | 32 ++++++++----------- 2 files changed, 20 insertions(+), 24 deletions(-) diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/loader-bar/loader-bar.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/loader-bar/loader-bar.component.ts index b0d626cf71..1700efafe2 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/loader-bar/loader-bar.component.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/loader-bar/loader-bar.component.ts @@ -41,9 +41,9 @@ export class LoaderBarComponent implements OnDestroy, OnInit { progressLevel = 0; - interval: Subscription; + interval = new Subscription(); - timer: Subscription; + timer = new Subscription(); intervalPeriod = 350; @@ -94,11 +94,11 @@ export class LoaderBarComponent implements OnDestroy, OnInit { } ngOnDestroy() { - if (this.interval) this.interval.unsubscribe(); + this.interval.unsubscribe(); } startLoading() { - if (this.isLoading || (this.interval && !this.interval.closed)) return; + if (this.isLoading || !this.interval.closed) return; this.isLoading = true; this.progressLevel = 0; @@ -107,12 +107,12 @@ export class LoaderBarComponent implements OnDestroy, OnInit { } stopLoading() { - if (this.interval) this.interval.unsubscribe(); + this.interval.unsubscribe(); this.progressLevel = 100; this.isLoading = false; - if (this.timer && !this.timer.closed) return; + if (!this.timer.closed) return; this.timer = timer(this.stopDelay).subscribe(this.clearProgress); } diff --git a/npm/ng-packs/packages/theme-shared/src/lib/tests/loader-bar.component.spec.ts b/npm/ng-packs/packages/theme-shared/src/lib/tests/loader-bar.component.spec.ts index 00a823f860..6d1ab85a46 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/tests/loader-bar.component.spec.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/tests/loader-bar.component.spec.ts @@ -1,33 +1,29 @@ import { NavigationEnd, NavigationError, NavigationStart, Router } from '@angular/router'; -import { createHostFactory, SpectatorHost, SpyObject } from '@ngneat/spectator/jest'; -import { Subject, Subscription, timer } from 'rxjs'; +import { createComponentFactory, Spectator, SpyObject } from '@ngneat/spectator/jest'; +import { Subject, timer } from 'rxjs'; import { LoaderBarComponent } from '../components/loader-bar/loader-bar.component'; -import { SubscriptionService } from '@abp/ng.core'; +import { HttpWaitService, SubscriptionService } from '@abp/ng.core'; import { HttpRequest } from '@angular/common/http'; -import { HttpWaitService } from '../../../../core/src/lib/services'; describe('LoaderBarComponent', () => { - let spectator: SpectatorHost; + let spectator: Spectator; let router: SpyObject; const events$ = new Subject(); - const createHost = createHostFactory({ + const createComponent = createComponentFactory({ component: LoaderBarComponent, - mocks: [Router], detectChanges: false, - providers: [SubscriptionService], + providers: [SubscriptionService, { provide: Router, useValue: { events: events$ } }], }); beforeEach(() => { - spectator = createHost(''); + spectator = createComponent({}); spectator.component.intervalPeriod = 1; spectator.component.stopDelay = 1; router = spectator.inject(Router); - (router as any).events = events$; }); it('should initial variable values are correct', () => { - spectator.component.interval = new Subscription(); expect(spectator.component.containerClass).toBe('abp-loader-bar'); expect(spectator.component.color).toBe('#77b6ff'); }); @@ -57,11 +53,11 @@ describe('LoaderBarComponent', () => { it('should start and stop the loading with navigation', done => { spectator.detectChanges(); - (router as any).events.next(new NavigationStart(1, 'test')); + events$.next(new NavigationStart(1, 'test')); expect(spectator.component.interval.closed).toBe(false); - (router as any).events.next(new NavigationEnd(1, 'test', 'test')); - (router as any).events.next(new NavigationError(1, 'test', 'test')); + events$.next(new NavigationEnd(1, 'test', 'test')); + events$.next(new NavigationError(1, 'test', 'test')); expect(spectator.component.progressLevel).toBe(100); timer(2).subscribe(() => { @@ -72,10 +68,10 @@ describe('LoaderBarComponent', () => { it('should stop the loading with navigation', done => { spectator.detectChanges(); - (router as any).events.next(new NavigationStart(1, 'test')); + events$.next(new NavigationStart(1, 'test')); expect(spectator.component.interval.closed).toBe(false); - (router as any).events.next(new NavigationEnd(1, 'testend', 'testend')); + events$.next(new NavigationEnd(1, 'testend', 'testend')); expect(spectator.component.progressLevel).toBe(100); timer(2).subscribe(() => { @@ -87,8 +83,8 @@ describe('LoaderBarComponent', () => { describe('#startLoading', () => { it('should return when isLoading is true', done => { spectator.detectChanges(); - (router as any).events.next(new NavigationStart(1, 'test')); - (router as any).events.next(new NavigationStart(1, 'test')); + events$.next(new NavigationStart(1, 'test')); + events$.next(new NavigationStart(1, 'test')); done(); }); }); From c6cac9b948e0a4a484101e24ca8defbb8343bf0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Thu, 24 Dec 2020 16:16:19 +0300 Subject: [PATCH 22/35] Use local packages for the tests. --- .../AbpPerfTest.WithAbp/AbpPerfTest.WithAbp.csproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/AbpPerfTest/AbpPerfTest.WithAbp/AbpPerfTest.WithAbp.csproj b/test/AbpPerfTest/AbpPerfTest.WithAbp/AbpPerfTest.WithAbp.csproj index b270d019a4..3c738143b7 100644 --- a/test/AbpPerfTest/AbpPerfTest.WithAbp/AbpPerfTest.WithAbp.csproj +++ b/test/AbpPerfTest/AbpPerfTest.WithAbp/AbpPerfTest.WithAbp.csproj @@ -5,9 +5,9 @@ - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive From fbbd40e3cdacc3ba59a88ea7aad3a78d31a79566 Mon Sep 17 00:00:00 2001 From: Arman Ozak Date: Thu, 24 Dec 2020 16:41:44 +0300 Subject: [PATCH 23/35] fix: use string as baseHref type in ABP.Test interface --- npm/ng-packs/packages/core/src/lib/models/common.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/npm/ng-packs/packages/core/src/lib/models/common.ts b/npm/ng-packs/packages/core/src/lib/models/common.ts index 88bd75c027..7e828c9d2a 100644 --- a/npm/ng-packs/packages/core/src/lib/models/common.ts +++ b/npm/ng-packs/packages/core/src/lib/models/common.ts @@ -1,5 +1,5 @@ import { EventEmitter, Type } from '@angular/core'; -import { Router, Routes } from '@angular/router'; +import { Routes } from '@angular/router'; import { Subject } from 'rxjs'; import { eLayoutType } from '../enums/common'; import { Environment } from './environment'; @@ -13,7 +13,7 @@ export namespace ABP { } export interface Test extends Partial { - baseHref?: Router; + baseHref?: string; routes?: Routes; } From 02e0ec5989cc363822e95448afb891ef4c26c368 Mon Sep 17 00:00:00 2001 From: Arman Ozak Date: Thu, 24 Dec 2020 16:44:19 +0300 Subject: [PATCH 24/35] use withConfig instead of forTest in CoreTestingModule --- .../packages/core/testing/src/lib/core-testing.module.ts | 2 +- .../theme-shared/src/lib/tests/confirmation.service.spec.ts | 4 ++-- .../packages/theme-shared/src/lib/tests/error.handler.spec.ts | 2 +- .../theme-shared/src/lib/tests/toaster.service.spec.ts | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/npm/ng-packs/packages/core/testing/src/lib/core-testing.module.ts b/npm/ng-packs/packages/core/testing/src/lib/core-testing.module.ts index 5a43aa9a4c..224992ed23 100644 --- a/npm/ng-packs/packages/core/testing/src/lib/core-testing.module.ts +++ b/npm/ng-packs/packages/core/testing/src/lib/core-testing.module.ts @@ -21,7 +21,7 @@ import { MockLocalizationPipe } from './pipes/mock-localization.pipe'; declarations: [MockLocalizationPipe], }) export class CoreTestingModule { - static forTest( + static withConfig( { baseHref = '/', routes = [], ...options } = {} as ABP.Test, ): ModuleWithProviders { return { diff --git a/npm/ng-packs/packages/theme-shared/src/lib/tests/confirmation.service.spec.ts b/npm/ng-packs/packages/theme-shared/src/lib/tests/confirmation.service.spec.ts index 88813c44de..ab63cb3cb5 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/tests/confirmation.service.spec.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/tests/confirmation.service.spec.ts @@ -13,7 +13,7 @@ import { ConfirmationService } from '../services'; exports: [ConfirmationComponent], entryComponents: [ConfirmationComponent], declarations: [ConfirmationComponent], - imports: [CoreTestingModule.forTest()], + imports: [CoreTestingModule.withConfig()], }) export class MockModule {} @@ -22,7 +22,7 @@ describe('ConfirmationService', () => { let service: ConfirmationService; const createService = createServiceFactory({ service: ConfirmationService, - imports: [NgxsModule.forRoot(), CoreTestingModule.forTest(), MockModule], + imports: [NgxsModule.forRoot(), CoreTestingModule.withConfig(), MockModule], }); beforeEach(() => { diff --git a/npm/ng-packs/packages/theme-shared/src/lib/tests/error.handler.spec.ts b/npm/ng-packs/packages/theme-shared/src/lib/tests/error.handler.spec.ts index 939f87e5ee..a6908e03bf 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/tests/error.handler.spec.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/tests/error.handler.spec.ts @@ -31,7 +31,7 @@ const CONFIRMATION_BUTTONS = { describe('ErrorHandler', () => { const createService = createServiceFactory({ service: ErrorHandler, - imports: [NgxsModule.forRoot([]), CoreTestingModule.forTest(), MockModule], + imports: [NgxsModule.forRoot([]), CoreTestingModule.withConfig(), MockModule], mocks: [OAuthService], providers: [ { provide: APP_BASE_HREF, useValue: '/' }, diff --git a/npm/ng-packs/packages/theme-shared/src/lib/tests/toaster.service.spec.ts b/npm/ng-packs/packages/theme-shared/src/lib/tests/toaster.service.spec.ts index fa6e0e578c..ab885726de 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/tests/toaster.service.spec.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/tests/toaster.service.spec.ts @@ -11,7 +11,7 @@ import { ToasterService } from '../services/toaster.service'; exports: [ToastContainerComponent], entryComponents: [ToastContainerComponent], declarations: [ToastContainerComponent, ToastComponent], - imports: [CoreTestingModule.forTest()], + imports: [CoreTestingModule.withConfig()], }) export class MockModule {} const toastClassPrefix = 'abp-toast'; @@ -21,7 +21,7 @@ describe('ToasterService', () => { let service: ToasterService; const createService = createServiceFactory({ service: ToasterService, - imports: [NgxsModule.forRoot(), CoreTestingModule.forTest(), MockModule], + imports: [NgxsModule.forRoot(), CoreTestingModule.withConfig(), MockModule], }); beforeEach(() => { From 0a98cb6ee1819a924ec488e32fd53c23c8cccff3 Mon Sep 17 00:00:00 2001 From: Arman Ozak Date: Thu, 24 Dec 2020 16:45:27 +0300 Subject: [PATCH 25/35] create a BaseThemeSharedModule --- .../src/lib/theme-shared.module.ts | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) 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 c4647cbcd1..4bafe28925 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 @@ -27,7 +27,7 @@ import { initLazyStyleHandler } from './handlers/lazy-style.handler'; import { RootParams } from './models/common'; import { THEME_SHARED_ROUTE_PROVIDERS } from './providers/route.provider'; import { THEME_SHARED_APPEND_CONTENT } from './tokens/append-content.token'; -import { HTTP_ERROR_CONFIG, httpErrorConfigFactory } from './tokens/http-error.token'; +import { httpErrorConfigFactory, HTTP_ERROR_CONFIG } from './tokens/http-error.token'; import { DateParserFormatter } from './utils/date-parser-formatter'; const declarationsWithExports = [ @@ -48,17 +48,11 @@ const declarationsWithExports = [ LoadingDirective, TableSortDirective, ]; + @NgModule({ imports: [CoreModule, NgxDatatableModule, NgxValidateCoreModule, NgbPaginationModule], - declarations: [ - ...declarationsWithExports, - HttpErrorWrapperComponent, - ModalContainerComponent, - ], - exports: [ - NgxDatatableModule, - ...declarationsWithExports, - ], + declarations: [...declarationsWithExports, HttpErrorWrapperComponent, ModalContainerComponent], + exports: [NgxDatatableModule, ...declarationsWithExports], providers: [DatePipe], entryComponents: [ HttpErrorWrapperComponent, @@ -68,6 +62,12 @@ const declarationsWithExports = [ ConfirmationComponent, ], }) +export class BaseThemeSharedModule {} + +@NgModule({ + imports: [BaseThemeSharedModule], + exports: [BaseThemeSharedModule], +}) export class ThemeSharedModule { constructor(private errorHandler: ErrorHandler) {} From 37954a8c99927833c163e14dea14bd6048b84b39 Mon Sep 17 00:00:00 2001 From: Arman Ozak Date: Thu, 24 Dec 2020 16:46:08 +0300 Subject: [PATCH 26/35] add an entry point for theme shared testing --- npm/ng-packs/packages/theme-shared/testing/ng-package.json | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 npm/ng-packs/packages/theme-shared/testing/ng-package.json diff --git a/npm/ng-packs/packages/theme-shared/testing/ng-package.json b/npm/ng-packs/packages/theme-shared/testing/ng-package.json new file mode 100644 index 0000000000..7fc8d6067d --- /dev/null +++ b/npm/ng-packs/packages/theme-shared/testing/ng-package.json @@ -0,0 +1,7 @@ +{ + "$schema": "../../../node_modules/ng-packagr/ng-package.schema.json", + "dest": "../../dist/theme-shared/testing", + "lib": { + "entryFile": "src/public-api.ts" + } +} From 394692d8a486cc56202fca35a516973af5847ebc Mon Sep 17 00:00:00 2001 From: Arman Ozak Date: Thu, 24 Dec 2020 16:46:50 +0300 Subject: [PATCH 27/35] add ThemeSharedTestingModule --- .../src/lib/theme-shared-testing.module.ts | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 npm/ng-packs/packages/theme-shared/testing/src/lib/theme-shared-testing.module.ts diff --git a/npm/ng-packs/packages/theme-shared/testing/src/lib/theme-shared-testing.module.ts b/npm/ng-packs/packages/theme-shared/testing/src/lib/theme-shared-testing.module.ts new file mode 100644 index 0000000000..323281046a --- /dev/null +++ b/npm/ng-packs/packages/theme-shared/testing/src/lib/theme-shared-testing.module.ts @@ -0,0 +1,27 @@ +import { + BaseThemeSharedModule, + DateParserFormatter, + THEME_SHARED_ROUTE_PROVIDERS, +} from '@abp/ng.theme.shared'; +import { ModuleWithProviders, NgModule } from '@angular/core'; +import { RouterTestingModule } from '@angular/router/testing'; +import { NgbDateParserFormatter } from '@ng-bootstrap/ng-bootstrap'; + +/** + * ThemeSharedTestingModule is the module that will be used in tests + */ +@NgModule({ + exports: [RouterTestingModule, BaseThemeSharedModule], + imports: [RouterTestingModule, BaseThemeSharedModule], +}) +export class ThemeSharedTestingModule { + static withConfig(): ModuleWithProviders { + return { + ngModule: ThemeSharedTestingModule, + providers: [ + THEME_SHARED_ROUTE_PROVIDERS, + { provide: NgbDateParserFormatter, useClass: DateParserFormatter }, + ], + }; + } +} From 98cd7b001bcbb2c97a8975feaefe3a459a1c8776 Mon Sep 17 00:00:00 2001 From: Arman Ozak Date: Thu, 24 Dec 2020 16:46:58 +0300 Subject: [PATCH 28/35] make ThemeSharedTestingModule public --- npm/ng-packs/packages/theme-shared/testing/src/public-api.ts | 1 + 1 file changed, 1 insertion(+) create mode 100644 npm/ng-packs/packages/theme-shared/testing/src/public-api.ts diff --git a/npm/ng-packs/packages/theme-shared/testing/src/public-api.ts b/npm/ng-packs/packages/theme-shared/testing/src/public-api.ts new file mode 100644 index 0000000000..14355a8a28 --- /dev/null +++ b/npm/ng-packs/packages/theme-shared/testing/src/public-api.ts @@ -0,0 +1 @@ +export * from './lib/theme-shared-testing.module'; From 78980ed2731345450fb22cfb4f43a677e267020c Mon Sep 17 00:00:00 2001 From: Arman Ozak Date: Thu, 24 Dec 2020 17:52:10 +0300 Subject: [PATCH 29/35] update yarn lock --- npm/ng-packs/yarn.lock | 106 ++++++++++++++++++++--------------------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/npm/ng-packs/yarn.lock b/npm/ng-packs/yarn.lock index 4ef0c07ef8..a3f300d1c8 100644 --- a/npm/ng-packs/yarn.lock +++ b/npm/ng-packs/yarn.lock @@ -2,12 +2,12 @@ # yarn lockfile v1 -"@abp/ng.core@~4.1.0-rc.1": - version "4.1.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/ng.core/-/ng.core-4.1.0-rc.1.tgz#efbd35e8df0731e75b2195149269b0228ec4ae42" - integrity sha512-WhXHMlDSbYled+mW8faMW8qHUGVErh/E/3eOgfvhx4N2tGGs5w+A4EfjNVBBROcoLDwiX2q1L88WeNnrK1+OIQ== +"@abp/ng.core@~4.1.0-rc.2": + version "4.1.0-rc.2" + resolved "https://registry.yarnpkg.com/@abp/ng.core/-/ng.core-4.1.0-rc.2.tgz#5fe53658965af66fae655dfce4bf6a7ad7105032" + integrity sha512-NcjOn1HYIdLTdHPbWTiLywPp1jQ+zmoeknnb0q/JfUUDn5r5kPrCf85xiZBUo8e+2ViB5vXvkM5lOOD5RfES6A== dependencies: - "@abp/utils" "^4.0.1" + "@abp/utils" "^4.1.0-rc.1" "@angular/localize" "~10.0.10" "@ngxs/store" "^3.7.0" angular-oauth2-oidc "^10.0.0" @@ -17,35 +17,35 @@ ts-toolbelt "6.15.4" tslib "^2.0.0" -"@abp/ng.feature-management@~4.1.0-rc.1": - version "4.1.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/ng.feature-management/-/ng.feature-management-4.1.0-rc.1.tgz#5237db2e5a0ea5a6511941864fa721a303b5612c" - integrity sha512-/9GP6ze127uMkHB2QxWJC2MXiEMTLtBhM0DXYlPZKI+Y+FrVOBoUTI3gNz+AqWFwbBAA4PqfVuThhoja5b29Sg== +"@abp/ng.feature-management@~4.1.0-rc.2": + version "4.1.0-rc.2" + resolved "https://registry.yarnpkg.com/@abp/ng.feature-management/-/ng.feature-management-4.1.0-rc.2.tgz#02e760bfa913276e694dbff545e39210a69b21bd" + integrity sha512-vf//thBD3ve8tkmAIan2FqQeHrO/sP8NVV83noGVMTpqKIAWIu7PBuSL3YqcNVOVxHLsO6EIwr63OAJytlvH6A== dependencies: - "@abp/ng.theme.shared" "~4.1.0-rc.1" + "@abp/ng.theme.shared" "~4.1.0-rc.2" tslib "^2.0.0" -"@abp/ng.identity@~4.1.0-rc.1": - version "4.1.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/ng.identity/-/ng.identity-4.1.0-rc.1.tgz#932fd10482e82400a87927d200c2d3c850cccef4" - integrity sha512-uh7Fy+X2qGiNZ58g2c1GkmJL9VnMPLsKzg9EugNV2VxbGYg4/sNmVvAeIV66x2hpDXETHCjm+7lYuZsqI/5Vew== +"@abp/ng.identity@~4.1.0-rc.2": + version "4.1.0-rc.2" + resolved "https://registry.yarnpkg.com/@abp/ng.identity/-/ng.identity-4.1.0-rc.2.tgz#381d956cebe2f3c272c59567ff424d3729adb6aa" + integrity sha512-4Wnx/iXAOgdexDYuNTV+DBdnjyfhcgca1ZiUSuEnSVDKePq0xvpGeKvpXzhhm9T3uXNsqYwqNq/X5jK3jd6mZg== dependencies: - "@abp/ng.permission-management" "~4.1.0-rc.1" - "@abp/ng.theme.shared" "~4.1.0-rc.1" + "@abp/ng.permission-management" "~4.1.0-rc.2" + "@abp/ng.theme.shared" "~4.1.0-rc.2" tslib "^2.0.0" -"@abp/ng.permission-management@~4.1.0-rc.1": - version "4.1.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/ng.permission-management/-/ng.permission-management-4.1.0-rc.1.tgz#de810f1d50f901cffb15f59756127e83109e79f7" - integrity sha512-AgPpmBKDYnMKmMXoiU9ewGKtn5hH9frO5tV0wjz46BjmO9kIwyap3BBeCFcZjhgVLxZnXi8D0WuzZW7mgQARIQ== +"@abp/ng.permission-management@~4.1.0-rc.2": + version "4.1.0-rc.2" + resolved "https://registry.yarnpkg.com/@abp/ng.permission-management/-/ng.permission-management-4.1.0-rc.2.tgz#b74402241886e156a0e72baddfbc0ebebb7576aa" + integrity sha512-6/Z/8KGKkAflfk6CoXk92StEELuP0xkwj2dvvFvnGpr2od9ELGWWqtiJ5Pjz6i5FQvrLdqcHqPh8x/vgr7QV9w== dependencies: - "@abp/ng.theme.shared" "~4.1.0-rc.1" + "@abp/ng.theme.shared" "~4.1.0-rc.2" tslib "^2.0.0" -"@abp/ng.schematics@~4.1.0-rc.1": - version "4.1.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/ng.schematics/-/ng.schematics-4.1.0-rc.1.tgz#42173b847cfc2f293245a96fe4732a9049b8ab7c" - integrity sha512-FU5Mat3ki6ARDmOK5WC4/AMXJC+61EknuH44SE9Y9PraXAYkJk+2Ha+1qAg+VLBQcEEVWLxIqMp+2Soc6d6oow== +"@abp/ng.schematics@~4.1.0-rc.2": + version "4.1.0-rc.2" + resolved "https://registry.yarnpkg.com/@abp/ng.schematics/-/ng.schematics-4.1.0-rc.2.tgz#31dada6fc1f69d0198f4fb3801b6009d6a0a0c09" + integrity sha512-yVi/C1IbwcOQfXUAe8FSlekdNfoqi/UQvTBQ19h/HGBBDxhqbv6QKjhkaVs/+EOAW8WHWCufyVtQ2/y/jrCeog== dependencies: "@angular-devkit/core" "~11.0.2" "@angular-devkit/schematics" "~11.0.2" @@ -53,37 +53,37 @@ jsonc-parser "^2.3.0" typescript "~3.9.2" -"@abp/ng.setting-management@~4.1.0-rc.1": - version "4.1.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/ng.setting-management/-/ng.setting-management-4.1.0-rc.1.tgz#d35083c211089683c4fb07f88523c01e3e5d8ce0" - integrity sha512-qKLV2IWkHbK5ohHMxbdzPqE1pvPPatmV0EidE79Rk4j5+WZXOXtNz5GEA2vLmF3CsuVjX90cJQdtY1bdZpvdVQ== +"@abp/ng.setting-management@~4.1.0-rc.2": + version "4.1.0-rc.2" + resolved "https://registry.yarnpkg.com/@abp/ng.setting-management/-/ng.setting-management-4.1.0-rc.2.tgz#4b61bff63fa9d68be5f1c7b8c47049cc1bd8b5a8" + integrity sha512-Df2QS0bsytytUSkQ0KrI/m4pVTpQS708fwl8t3KcpeQ4hlgdg6LtTmhUaY/j6k8M1RJHaKvjPE9Jg6R2daLNGg== dependencies: - "@abp/ng.theme.shared" "~4.1.0-rc.1" + "@abp/ng.theme.shared" "~4.1.0-rc.2" tslib "^2.0.0" -"@abp/ng.tenant-management@~4.1.0-rc.1": - version "4.1.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/ng.tenant-management/-/ng.tenant-management-4.1.0-rc.1.tgz#be6740c8a7ac844c7100a46fb88bc96ce386e17d" - integrity sha512-OymGkg5BzHiraUC0FcWPm6JN84FgYNZ3YuLTAZd/iHmqQVoj51ymTK8dBOn7sw49vWlAj/WvGN4Z9tT/JS40zg== +"@abp/ng.tenant-management@~4.1.0-rc.2": + version "4.1.0-rc.2" + resolved "https://registry.yarnpkg.com/@abp/ng.tenant-management/-/ng.tenant-management-4.1.0-rc.2.tgz#b75b60db124e5246476821da2bfeebd5e5da09b6" + integrity sha512-AnDiMa/M4xSwiSXjyIsBY13BNxm+JMhWiIEb9WAPlk8IUaNDJZH9zHJH/HQSUHdy6dFCmutl5Ezi6U1J9ZHpPQ== dependencies: - "@abp/ng.feature-management" "~4.1.0-rc.1" - "@abp/ng.theme.shared" "~4.1.0-rc.1" + "@abp/ng.feature-management" "~4.1.0-rc.2" + "@abp/ng.theme.shared" "~4.1.0-rc.2" tslib "^2.0.0" -"@abp/ng.theme.basic@~4.1.0-rc.1": - version "4.1.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/ng.theme.basic/-/ng.theme.basic-4.1.0-rc.1.tgz#311e1ee4490803d43b1b1286620f1efa0fe3f459" - integrity sha512-nTf9UaupTxT0UgBx/SwaVuhtutUXFqGGq2dBKI0JNxltgfykLhDXUOTlUnymLlsyu09DJv8OIZbCX6PJAMV1GA== +"@abp/ng.theme.basic@~4.1.0-rc.2": + version "4.1.0-rc.2" + resolved "https://registry.yarnpkg.com/@abp/ng.theme.basic/-/ng.theme.basic-4.1.0-rc.2.tgz#4c0ccb5386a09cf7d89efaee59c8920265032361" + integrity sha512-2NjHymzE/sgbZ8e+CJ4iMemB+mD6e/VSKA2EkCaekPpXDlp0Z3f2yyhm0jwYqCQPsmCjykdtTpR266yLQOs7ug== dependencies: - "@abp/ng.theme.shared" "~4.1.0-rc.1" + "@abp/ng.theme.shared" "~4.1.0-rc.2" tslib "^2.0.0" -"@abp/ng.theme.shared@~4.1.0-rc.1": - version "4.1.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/ng.theme.shared/-/ng.theme.shared-4.1.0-rc.1.tgz#08c051cafd1364563943f7f8b6d067955227cc7e" - integrity sha512-oNPGXI6gyesDnzHq/x7QuXKr0ISwgz9YaKg2bvzZOCvyZ0usL2P4h/4sQvV9ThCYjDdkVKN+cdW+KNvalJ415w== +"@abp/ng.theme.shared@~4.1.0-rc.2": + version "4.1.0-rc.2" + resolved "https://registry.yarnpkg.com/@abp/ng.theme.shared/-/ng.theme.shared-4.1.0-rc.2.tgz#eaf524ef26f5433ec7ea01d402ba071c42ce1aa6" + integrity sha512-d6dVhV2wer7eeHoT8Y91Bqf7m2r3FVexUp7R+/f93564swuceZGZWSsgntwpHkNdDJaxhLUJ8tG5XMe2deEGTQ== dependencies: - "@abp/ng.core" "~4.1.0-rc.1" + "@abp/ng.core" "~4.1.0-rc.2" "@fortawesome/fontawesome-free" "^5.14.0" "@ng-bootstrap/ng-bootstrap" "^7.0.0" "@ngx-validate/core" "^0.0.13" @@ -92,13 +92,6 @@ chart.js "^2.9.3" tslib "^2.0.0" -"@abp/utils@^4.0.1": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-4.0.1.tgz#9a4cb420266c49d8084776bd31c86681d4d4d125" - integrity sha512-nI2ZyaNpvohr75p8jeMPWze+hX+mV47EHI+Zloa4GgGmJqrULdG71kYh45R+jGmMTbQL6huaXGnpz4gNF9TGyQ== - dependencies: - just-compare "^1.3.0" - "@abp/utils@^4.1.0-rc.1": version "4.1.0-rc.1" resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-4.1.0-rc.1.tgz#2863867985db9d178a5ce4347309f060f1ce6142" @@ -106,6 +99,13 @@ dependencies: just-compare "^1.3.0" +"@abp/utils@^4.1.0-rc.2": + version "4.1.0-rc.2" + resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-4.1.0-rc.2.tgz#eb6dbf0ee493d0f050b37347d2d6d283098aedae" + integrity sha512-V2k5I89lVBoeGIKgg4p2H9GlMAcDWbctwKZPVwBEMVEVm1uTR2xQAWdTdSFd5Q8I8Xsf/aIG8ELM7l5j2h7/zQ== + dependencies: + just-compare "^1.3.0" + "@angular-builders/jest@^10.0.0": version "10.0.1" resolved "https://registry.yarnpkg.com/@angular-builders/jest/-/jest-10.0.1.tgz#a1a6fb5d11b5d54c051bdaa2012b5f046371560c" From ca96318427be3b734637fc46d2cca90c376e4bd1 Mon Sep 17 00:00:00 2001 From: Arman Ozak Date: Thu, 24 Dec 2020 17:52:44 +0300 Subject: [PATCH 30/35] inject ApplicationRef at runtime in ErrorHandler --- .../theme-shared/src/lib/handlers/error.handler.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts b/npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts index 46652f8b25..97f9533cf7 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts @@ -74,7 +74,6 @@ export class ErrorHandler { private actions: Actions, private router: Router, private confirmationService: ConfirmationService, - private appRef: ApplicationRef, private cfRes: ComponentFactoryResolver, private rendererFactory: RendererFactory2, private injector: Injector, @@ -281,14 +280,16 @@ export class ErrorHandler { } this.componentRef.instance.hideCloseIcon = this.httpErrorConfig.errorScreen.hideCloseIcon; + const appRef = this.injector.get(ApplicationRef); + if (this.canCreateCustomError(instance.status as ErrorScreenErrorCodes)) { this.componentRef.instance.cfRes = this.cfRes; - this.componentRef.instance.appRef = this.appRef; + this.componentRef.instance.appRef = appRef; this.componentRef.instance.injector = this.injector; this.componentRef.instance.customComponent = this.httpErrorConfig.errorScreen.component; } - this.appRef.attachView(this.componentRef.hostView); + appRef.attachView(this.componentRef.hostView); renderer.appendChild(host, (this.componentRef.hostView as EmbeddedViewRef).rootNodes[0]); const destroy$ = new Subject(); From 0897bd30f9aeb99605e72e15971660fa567a75bd Mon Sep 17 00:00:00 2001 From: Arman Ozak Date: Thu, 24 Dec 2020 17:53:15 +0300 Subject: [PATCH 31/35] use APP_INITIALIZER to instantiate ErrorHandler --- .../packages/theme-shared/src/lib/theme-shared.module.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) 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 4bafe28925..6775c15e5a 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 @@ -69,12 +69,16 @@ export class BaseThemeSharedModule {} exports: [BaseThemeSharedModule], }) export class ThemeSharedModule { - constructor(private errorHandler: ErrorHandler) {} - static forRoot(options = {} as RootParams): ModuleWithProviders { return { ngModule: ThemeSharedModule, providers: [ + { + provide: APP_INITIALIZER, + multi: true, + deps: [ErrorHandler], + useFactory: noop, + }, THEME_SHARED_ROUTE_PROVIDERS, { provide: APP_INITIALIZER, From f37b52480a2b4aaf7a52424e21bcf454176e3492 Mon Sep 17 00:00:00 2001 From: Arman Ozak Date: Thu, 24 Dec 2020 18:46:33 +0300 Subject: [PATCH 32/35] change private props and methods to protected in RestService --- .../packages/core/src/lib/services/rest.service.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/npm/ng-packs/packages/core/src/lib/services/rest.service.ts b/npm/ng-packs/packages/core/src/lib/services/rest.service.ts index 204118aa56..d880c94e5a 100644 --- a/npm/ng-packs/packages/core/src/lib/services/rest.service.ts +++ b/npm/ng-packs/packages/core/src/lib/services/rest.service.ts @@ -15,13 +15,13 @@ import { EnvironmentService } from './environment.service'; }) export class RestService { constructor( - @Inject(CORE_OPTIONS) private options: ABP.Root, - private http: HttpClient, - private store: Store, - private environment: EnvironmentService, + @Inject(CORE_OPTIONS) protected options: ABP.Root, + protected http: HttpClient, + protected environment: EnvironmentService, + protected store: Store, ) {} - private getApiFromStore(apiName: string): string { + protected getApiFromStore(apiName: string): string { return this.environment.getApiUrl(apiName); } From ab0116cca7d19841e3973e11c068de4a84e8583d Mon Sep 17 00:00:00 2001 From: Arman Ozak Date: Thu, 24 Dec 2020 18:47:07 +0300 Subject: [PATCH 33/35] create a mock rest service which doesn't report errors --- .../core/testing/src/lib/services/index.ts | 1 + .../src/lib/services/mock-rest.service.ts | 21 +++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 npm/ng-packs/packages/core/testing/src/lib/services/index.ts create mode 100644 npm/ng-packs/packages/core/testing/src/lib/services/mock-rest.service.ts diff --git a/npm/ng-packs/packages/core/testing/src/lib/services/index.ts b/npm/ng-packs/packages/core/testing/src/lib/services/index.ts new file mode 100644 index 0000000000..24206d7c5d --- /dev/null +++ b/npm/ng-packs/packages/core/testing/src/lib/services/index.ts @@ -0,0 +1 @@ +export * from './mock-rest.service'; diff --git a/npm/ng-packs/packages/core/testing/src/lib/services/mock-rest.service.ts b/npm/ng-packs/packages/core/testing/src/lib/services/mock-rest.service.ts new file mode 100644 index 0000000000..b7b4066a4c --- /dev/null +++ b/npm/ng-packs/packages/core/testing/src/lib/services/mock-rest.service.ts @@ -0,0 +1,21 @@ +import { ABP, CORE_OPTIONS, EnvironmentService, RestService } from '@abp/ng.core'; +import { HttpClient } from '@angular/common/http'; +import { Inject, Injectable } from '@angular/core'; +import { Observable, throwError } from 'rxjs'; + +@Injectable({ + providedIn: 'root', +}) +export class MockRestService extends RestService { + constructor( + @Inject(CORE_OPTIONS) protected options: ABP.Root, + protected http: HttpClient, + protected environment: EnvironmentService, + ) { + super(options, http, environment, null); + } + + handleError(err: any): Observable { + return throwError(err); + } +} From 4fc4172b514f2fcd6950874fd02a3e5c334a6312 Mon Sep 17 00:00:00 2001 From: Arman Ozak Date: Thu, 24 Dec 2020 18:47:23 +0300 Subject: [PATCH 34/35] provide mock rest service in CoreTestingModule --- .../packages/core/testing/src/lib/core-testing.module.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/npm/ng-packs/packages/core/testing/src/lib/core-testing.module.ts b/npm/ng-packs/packages/core/testing/src/lib/core-testing.module.ts index 224992ed23..9a7fc3eec0 100644 --- a/npm/ng-packs/packages/core/testing/src/lib/core-testing.module.ts +++ b/npm/ng-packs/packages/core/testing/src/lib/core-testing.module.ts @@ -4,12 +4,14 @@ import { coreOptionsFactory, CORE_OPTIONS, LocalizationPipe, + RestService, } from '@abp/ng.core'; import { APP_BASE_HREF } from '@angular/common'; import { ModuleWithProviders, NgModule } from '@angular/core'; import { provideRoutes } from '@angular/router'; import { RouterTestingModule } from '@angular/router/testing'; import { MockLocalizationPipe } from './pipes/mock-localization.pipe'; +import { MockRestService } from './services/mock-rest.service'; /** * CoreTestingModule is the module that will be used in tests @@ -41,6 +43,10 @@ export class CoreTestingModule { provide: LocalizationPipe, useClass: MockLocalizationPipe, }, + { + provide: RestService, + useClass: MockRestService, + }, provideRoutes(routes), ], }; From e6eedd7164d61008f6c974f223f9ab3e9c357aa8 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Fri, 25 Dec 2020 14:24:33 +0800 Subject: [PATCH 35/35] Fix typo --- docs/zh-Hans/Domain-Driven-Design-Implementation-Guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/zh-Hans/Domain-Driven-Design-Implementation-Guide.md b/docs/zh-Hans/Domain-Driven-Design-Implementation-Guide.md index 8a6ec1de9b..db434ab365 100644 --- a/docs/zh-Hans/Domain-Driven-Design-Implementation-Guide.md +++ b/docs/zh-Hans/Domain-Driven-Design-Implementation-Guide.md @@ -1920,7 +1920,7 @@ public class OrganizationAppService : ApplicationService 你可能想知道为什么付款逻辑代码不在`OrganizationManager`中.付款是非常**重要的事情**,我们不能**遗漏任何一次付款**. -它确实非常重要,但是,它不能放到领域服务中.我们可能还又**其它用例**来创建组织但不收取任何费用.例如: +它确实非常重要,但是,它不能放到领域服务中.我们可能还有**其它用例**来创建组织但不收取任何费用.例如: * 管理员可以在后台管理系统创建新组织,而无需支付任何费用. * 后台作业系统导入,集成,同步组织而无需支付费用.