From d8ad85b2aa2651c3be06d081631e8e9ab8d9a258 Mon Sep 17 00:00:00 2001 From: Berkan Sasmaz Date: Fri, 24 Jun 2022 13:25:33 +0300 Subject: [PATCH] cli: add ChangeToLeptonTheme method to ChangeThemeStep --- .../Commands/ProjectCreationCommandBase.cs | 29 ++ .../Building/Steps/ChangeThemeStep.cs | 251 +++++++++++++++++- .../Templates/App/AppTemplateBase.cs | 22 +- 3 files changed, 295 insertions(+), 7 deletions(-) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ProjectCreationCommandBase.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ProjectCreationCommandBase.cs index 469eba3089..364289f60a 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ProjectCreationCommandBase.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ProjectCreationCommandBase.cs @@ -518,6 +518,16 @@ public abstract class ProjectCreationCommandBase case Theme.Basic: ConfigureNpmPackagesForBasicTheme(projectArgs); break; + case Theme.Lepton: + ConfigureNpmPackagesForLeptonTheme(projectArgs); + break; + case Theme.NotSpecified: + case Theme.LeptonXLite: + case Theme.LeptonX: + case null: + break; + default: + throw new CliUsageException(ExceptionMessageHelper.GetInvalidArgExceptionMessage(Options.Theme.Long)); } } @@ -538,6 +548,25 @@ public abstract class ProjectCreationCommandBase ThemePackageAdder.AddAngularPackage(projectArgs.OutputFolder, "@abp/ng.theme.basic", projectArgs.Version); } } + + private void ConfigureNpmPackagesForLeptonTheme(ProjectBuildArgs projectArgs) + { + if (projectArgs.UiFramework is not UiFramework.None or UiFramework.Angular) + { + ThemePackageAdder.AddNpmPackage(projectArgs.OutputFolder, "@volo/abp.aspnetcore.mvc.ui.theme.lepton", projectArgs.Version); + } + + if (projectArgs.UiFramework is UiFramework.BlazorServer) + { + ThemePackageAdder.AddNpmPackage(projectArgs.OutputFolder, "@volo/abp.aspnetcore.components.server.leptontheme", projectArgs.Version); + ThemePackageAdder.AddNpmPackage(projectArgs.OutputFolder, "@volo/abp.aspnetcore.mvc.ui.theme.lepton", projectArgs.Version); + } + + if (projectArgs.UiFramework is UiFramework.Angular) + { + ThemePackageAdder.AddAngularPackage(projectArgs.OutputFolder, "@volo/abp.ng.theme.lepton", projectArgs.Version); + } + } public static class Options { diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ChangeThemeStep.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ChangeThemeStep.cs index 4409f258b3..cc2cbd7411 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ChangeThemeStep.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ChangeThemeStep.cs @@ -1,5 +1,9 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; +using System.Xml; +using Volo.Abp.Cli.ProjectBuilding.Files; +using Volo.Abp.Cli.Utils; namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps; @@ -17,6 +21,9 @@ public class ChangeThemeStep : ProjectBuildPipelineStep case Theme.Basic: ChangeToBasicTheme(context); break; + case Theme.Lepton: + ChangeToLeptonTheme(context); + break; } } @@ -457,6 +464,156 @@ public class ChangeThemeStep : ProjectBuildPipelineStep #endregion } + protected void ChangeToLeptonTheme(ProjectBuildContext context) + { + #region Common + + RenameLeptonXFoldersToLepton(context); + AddLeptonThemeManagementReferenceToProjects(context); + + #endregion + + #region MyCompanyName.MyProjectName.Web + + ChangeThemeToLeptonForMvcPresentationLayer(context, "Web"); + + #endregion + + #region MyCompanyName.MyProjectName.HttpApi.Host + + ChangeThemeToLeptonForMvcPresentationLayer(context, "HttpApi.Host"); + + #endregion + + // Blazor + + #region MyCompanyName.MyProjectName.AuthServer + + ChangeThemeToLeptonForMvcPresentationLayer(context, "AuthServer"); + + #endregion + + #region Angular + + ReplaceImportPackage( + context, + "/angular/src/app/app.module.ts", + "@volosoft/abp.ng.theme.lepton-x", + "@volo/abp.ng.theme.lepton" + ); + + RemoveLinesByStatement( + context, + "/angular/src/app/app.module.ts", + "SideMenuLayoutModule" + ); + + ReplaceMethodNames( + context, + "/angular/src/app/app.module.ts", + "ThemeLeptonXModule", + "ThemeLeptonModule" + ); + + RemoveLinesByStatement( + context, + "/angular/angular.json", + "node_modules/bootstrap-icons/font/bootstrap-icons.css" + ); + + #endregion + + // SingleLayers + // Microservices + } + + private void ChangeThemeToLeptonForMvcPresentationLayer(ProjectBuildContext context, string projectName) + { + var projectPath = $"/MyCompanyName.MyProjectName.{projectName}/MyCompanyName.MyProjectName.{projectName}.csproj"; + var projectFile = context.Files.FirstOrDefault(x => x.Name.Contains(projectPath)); + if (projectFile is null) + { + return; + } + var moduleFile = ConvertProjectFileToModuleFile(context, projectFile); + + ReplacePackageReferenceWithProjectReference( + context, + projectFile.Name, + "Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonX", + @"..\..\..\..\..\lepton-theme\src\Volo.Abp.AspNetCore.Mvc.UI.Theme.Lepton\Volo.Abp.AspNetCore.Mvc.UI.Theme.Lepton.csproj" + ); + + ChangeNamespaceAndKeyword( + context, + moduleFile.Name, + "Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonX.Bundling", + "Volo.Abp.AspNetCore.Mvc.UI.Theme.Lepton.Bundling", + "LeptonXThemeBundles.Styles.Global", + "LeptonThemeBundles.Styles.Global" + ); + + ChangeNamespaceAndKeyword( + context, + moduleFile.Name, + "Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonX", + "Volo.Abp.AspNetCore.Mvc.UI.Theme.Lepton", + "AbpAspNetCoreMvcUiLeptonXThemeModule", + "AbpAspNetCoreMvcUiLeptonThemeModule" + ); + } + + private void AddLeptonThemeManagementReferenceToProjects(ProjectBuildContext context) + { + var relatedProjectsNames = new Dictionary(); + relatedProjectsNames.Add("Domain", "MyCompanyName.MyProjectName.Domain.csproj"); + relatedProjectsNames.Add("Domain.Shared", "MyCompanyName.MyProjectName.Domain.Shared.csproj"); + relatedProjectsNames.Add("Application", "MyCompanyName.MyProjectName.Application.csproj"); + relatedProjectsNames.Add("Application.Contracts", "MyCompanyName.MyProjectName.Application.Contracts.csproj"); + relatedProjectsNames.Add("Blazor", "MyCompanyName.MyProjectName.Blazor.csproj"); + relatedProjectsNames.Add("Blazor.Server", "MyCompanyName.MyProjectName.Blazor.Server"); + relatedProjectsNames.Add("HttpApi", "MyCompanyName.MyProjectName.HttpApi.csproj"); + relatedProjectsNames.Add("HttpApi.Client", "MyCompanyName.MyProjectName.HttpApi.Client.csproj"); + relatedProjectsNames.Add("Web.Host", "MyCompanyName.MyProjectName.Web.Host.csproj"); + relatedProjectsNames.Add("Web", "MyCompanyName.MyProjectName.Web.csproj"); + + foreach (var relatedProjectName in relatedProjectsNames) + { + var reference = $@"..\..\..\..\..\lepton-theme\src\Volo.Abp.LeptonTheme.Management.{relatedProjectName.Key}\Volo.Abp.LeptonTheme.Management.{relatedProjectName.Key}.csproj"; + var projectFile = context.Files.FirstOrDefault(f => !f.Name.Contains("Test") && f.Name.Contains(relatedProjectName.Value) && f.Name.Contains(".csproj")); + if (projectFile is null) + { + continue; + } + relatedProjectsNames[relatedProjectName.Key] = projectFile.Name; + + AddProjectReference(projectFile, reference); + + AddModuleDependency(ConvertProjectFileToModuleFile(context, projectFile), + $"LeptonThemeManagement{ConvertProjectNameToModuleName(relatedProjectName.Key)}Module"); + } + } + + private void AddModuleDependency(FileEntry moduleFile, string dependency) + { + var lines = moduleFile.GetLines(); + + for (var i = 0; i < lines.Length; i++) + { + if (lines[i].Contains("namespace MyCompanyName.MyProjectName")) + { + lines[i - 1] = lines[i - 1] + "using Volo.Abp.LeptonTheme.Management;" + Environment.NewLine; + } + + if (lines[i].Contains("public class MyProjectName") && lines[i-1].Contains(")]")) + { + lines[i - 2] = lines[i - 2] + "," + Environment.NewLine + $"\ttypeof({dependency})"; + } + } + + moduleFile.SetLines(lines); + } + protected void ReplacePackageReferenceWithProjectReference( ProjectBuildContext context, string targetProjectFilePath, @@ -620,4 +777,96 @@ public class ChangeThemeStep : ProjectBuildPipelineStep file.SetLines(lines); } + + private static void AddProjectReference(FileEntry file, string reference) + { + if (!file.Name.Contains(".csproj")) + { + return; + } + + var doc = new XmlDocument() { PreserveWhitespace = true }; + using (var stream = StreamHelper.GenerateStreamFromString(file.Content)) + { + doc.Load(stream); + + var itemGroupNodes = doc.SelectNodes("/Project/ItemGroup"); + XmlNode itemGroupNode = null; + + if (itemGroupNodes == null || itemGroupNodes.Count < 1) + { + var projectNodes = doc.SelectNodes("/Project"); + var projectNode = projectNodes![0]; + + itemGroupNode = doc.CreateElement("ItemGroup"); + projectNode.AppendChild(itemGroupNode); + } + else + { + for (var i = 0; i < itemGroupNodes.Count; i++) + { + if (itemGroupNode is not null) + { + break; + } + for (var j = 0; j < itemGroupNodes[i].ChildNodes.Count; j++) + { + if (itemGroupNodes[i].ChildNodes[j].Name != "ProjectReference" || itemGroupNodes[i].ChildNodes[j].NodeType != XmlNodeType.Element) + { + continue; + } + + itemGroupNode = itemGroupNodes[i]; + break; + } + } + } + + itemGroupNode ??= itemGroupNodes[0]; + + var packageReferenceNode = doc.CreateElement("ProjectReference"); + + var includeAttr = doc.CreateAttribute("Include"); + includeAttr.Value = reference; + packageReferenceNode.Attributes.Append(includeAttr); + + itemGroupNode.AppendChild(doc.CreateTextNode("\t")); + itemGroupNode.AppendChild(packageReferenceNode); + itemGroupNode.AppendChild(doc.CreateTextNode(Environment.NewLine)); + file.SetContent(doc.OuterXml); + } + } + + private static FileEntry ConvertProjectFileToModuleFile(ProjectBuildContext context, FileEntry projectFile) + { + var splittedProjectFileName = projectFile.Name.RemovePostFix("/").Split("/"); + var fileName = splittedProjectFileName.Last(); + + splittedProjectFileName = splittedProjectFileName.Take(splittedProjectFileName.Length - 1).ToArray(); + + fileName = fileName + .Replace("MyCompanyName.", "") + .Replace(".csproj", "Module") + .Replace(".", ""); + + fileName = ConvertProjectNameToModuleName(fileName); + + return context.Files.First(f => f.Name.Contains(splittedProjectFileName.Last() + "/" + fileName)); + } + + private static string ConvertProjectNameToModuleName(string moduleName) + { + moduleName = moduleName.Replace(".", ""); + + return moduleName; + } + + private static void RenameLeptonXFoldersToLepton(ProjectBuildContext context) + { + var leptonXFiles = context.Files.Where(x => x.Name.Contains("LeptonX") && x.IsDirectory); + foreach (var file in leptonXFiles) + { + new MoveFolderStep(file.Name, file.Name.Replace("LeptonX", "Lepton")).Execute(context); + } + } } \ No newline at end of file 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 2dc0d43da1..e1dc2f6018 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 @@ -187,11 +187,11 @@ public abstract class AppTemplateBase : TemplateInfo if (context.BuildArgs.Theme != AppTemplate.DefaultTheme || context.BuildArgs.Theme != AppProTemplate.DefaultTheme) { steps.Add(new ChangeThemeStep()); - RemoveLeptonXThemePackagesFromPackageJsonFiles(steps, context.BuildArgs.Theme.Value); + RemoveLeptonXThemePackagesFromPackageJsonFiles(steps, this.IsPro()); } } - private void RemoveLeptonXThemePackagesFromPackageJsonFiles(List steps, Theme theme) + private static void RemoveLeptonXThemePackagesFromPackageJsonFiles(List steps, bool isPro) { var packageJsonFilePaths = new List() { @@ -218,20 +218,30 @@ public abstract class AppTemplateBase : TemplateInfo "/angular/package.json" }; + var mvcUiPackageName = "@abp/aspnetcore.mvc.ui.theme.leptonxlite"; + var blazorServerUiPackageName = "@abp/aspnetcore.components.server.leptonxlitetheme"; + var ngUiPackageName = "@abp/ng.theme.lepton-x"; + if (isPro) + { + mvcUiPackageName = "@volo/abp.aspnetcore.mvc.ui.theme.leptonx"; + blazorServerUiPackageName = "@volo/aspnetcore.components.server.leptonxtheme"; + ngUiPackageName = "@volosoft/abp.ng.theme.lepton-x"; + } + foreach (var packageJsonFilePath in packageJsonFilePaths) { - steps.Add(new RemoveDependencyFromPackageJsonFileStep(packageJsonFilePath, "@abp/aspnetcore.mvc.ui.theme.leptonxlite")); + steps.Add(new RemoveDependencyFromPackageJsonFileStep(packageJsonFilePath, mvcUiPackageName)); } foreach (var blazorServerPackageJsonFilePath in blazorServerPackageJsonFilePaths) { - steps.Add(new RemoveDependencyFromPackageJsonFileStep(blazorServerPackageJsonFilePath, "@abp/aspnetcore.mvc.ui.theme.leptonxlite")); - steps.Add(new RemoveDependencyFromPackageJsonFileStep(blazorServerPackageJsonFilePath, "@abp/aspnetcore.components.server.leptonxlitetheme")); + steps.Add(new RemoveDependencyFromPackageJsonFileStep(blazorServerPackageJsonFilePath, mvcUiPackageName)); + steps.Add(new RemoveDependencyFromPackageJsonFileStep(blazorServerPackageJsonFilePath, blazorServerUiPackageName)); } foreach (var angularPackageJsonFilePath in angularPackageJsonFilePaths) { - steps.Add(new RemoveDependencyFromPackageJsonFileStep(angularPackageJsonFilePath, "@abp/ng.theme.lepton-x")); + steps.Add(new RemoveDependencyFromPackageJsonFileStep(angularPackageJsonFilePath, ngUiPackageName)); steps.Add(new RemoveDependencyFromPackageJsonFileStep(angularPackageJsonFilePath, "bootstrap-icons")); } }