Browse Source

Merge remote-tracking branch 'abpframework/master'

pull/1144/head
liangshiwei 7 years ago
parent
commit
332f06850b
  1. 4
      abp_io/src/Volo.Utils.SolutionTemplating/Volo/Utils/SolutionTemplating/Building/Steps/SwitchEntityFrameworkCoreToMongoDbStep.cs
  2. 4
      docs/en/AspNetCore/Auto-API-Controllers.md
  3. 16
      docs/en/AspNetCore/Client-Side-Package-Management.md
  4. 2
      docs/en/Best-Practices/Entities.md
  5. 2
      docs/en/Module-Development-Basics.md
  6. 2
      docs/en/Modules/Index.md
  7. 2
      docs/en/Multi-Tenancy.md
  8. 4
      docs/en/Repositories.md
  9. 4
      docs/en/Samples/Microservice-Demo.md
  10. 44
      framework/Volo.Abp.sln
  11. 5
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpDynamicformTagHelperService.cs
  12. 19
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs
  13. 9
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/DynamicFormIgnore.cs
  14. 3
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/AbpAspNetCoreMvcUiBundlingModule.cs
  15. 27
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Dashboards/Properties/launchSettings.json
  16. 34
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Dashboards/Volo.Abp.AspNetCore.Mvc.UI.Dashboards.csproj
  17. 20
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Dashboards/Volo/Abp/AspNetCore/Mvc/UI/Dashboards/AbpAspNetCoreMvcUiDashboardsModule.cs
  18. 17
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Dashboards/Volo/Abp/AspNetCore/Mvc/UI/Dashboards/Components/Dashboard/DashboardViewComponent.cshtml.cs
  19. 27
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Dashboards/Volo/Abp/AspNetCore/Mvc/UI/Dashboards/Components/Dashboard/DashboardViewModel.cs
  20. 21
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Dashboards/Volo/Abp/AspNetCore/Mvc/UI/Dashboards/Components/Dashboard/Default.cshtml
  21. 49
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Dashboards/Volo/Abp/AspNetCore/Mvc/UI/Dashboards/DashboardDefinition.cs
  22. 14
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Dashboards/Volo/Abp/AspNetCore/Mvc/UI/Dashboards/DashboardOptions.cs
  23. 15
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Dashboards/Volo/Abp/AspNetCore/Mvc/UI/Dashboards/DashboardRenderer.cs
  24. 28
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Dashboards/Volo/Abp/AspNetCore/Mvc/UI/Dashboards/DashboardWidgetConfiguration.cs
  25. 15
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Dashboards/Volo/Abp/AspNetCore/Mvc/UI/Dashboards/IDashboardRenderer.cs
  26. 15
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Dashboards/Volo/Abp/AspNetCore/Mvc/UI/Dashboards/WidgetLocation.cs
  27. 3
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Dashboards/Volo/Abp/AspNetCore/Mvc/UI/Dashboards/_ViewImports.cshtml
  28. 3
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/AbpAspNetCoreMvcUiPackagesModule.cs
  29. 16
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Widgets/Volo.Abp.AspNetCore.Mvc.UI.Widgets.csproj
  30. 13
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Widgets/Volo/Abp/AspNetCore/Mvc/UI/Widgets/AbpAspNetCoreMvcUiWidgetsModule.cs
  31. 12
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Widgets/Volo/Abp/AspNetCore/Mvc/UI/Widgets/IWidgetRenderer.cs
  32. 44
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Widgets/Volo/Abp/AspNetCore/Mvc/UI/Widgets/WidgetDefinition.cs
  33. 15
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Widgets/Volo/Abp/AspNetCore/Mvc/UI/Widgets/WidgetDimensions.cs
  34. 14
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Widgets/Volo/Abp/AspNetCore/Mvc/UI/Widgets/WidgetOptions.cs
  35. 25
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Widgets/Volo/Abp/AspNetCore/Mvc/UI/Widgets/WidgetRenderer.cs
  36. 9
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AbpAuditingOptions.cs
  37. 2
      framework/src/Volo.Abp.Cli.Core/Volo.Abp.Cli.Core.csproj
  38. 3
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs
  39. 6
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Args/CommandLineArgumentParser.cs
  40. 2
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Auth/AuthService.cs
  41. 4
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliOptions.cs
  42. 2
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliPaths.cs
  43. 135
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliService.cs
  44. 19
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliUsageException.cs
  45. 55
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddCommand.cs
  46. 20
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddCommandHelper.cs
  47. 121
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddModuleCommand.cs
  48. 110
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddPackageCommand.cs
  49. 11
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/CommandSelector.cs
  50. 23
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/HelpCommand.cs
  51. 4
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LoginCommand.cs
  52. 5
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs
  53. 63
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/NuGet/NuGetService.cs
  54. 159
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/AbpIoTemplateStore.cs
  55. 2
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/DatabaseProvider.cs
  56. 2
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/GithubRepositoryInfo.cs
  57. 14
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ProjectBuildContext.cs
  58. 4
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ProjectBuildContextExtensions.cs
  59. 2
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ProjectBuildPipeline.cs
  60. 4
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ProjectBuildPipelineBuilder.cs
  61. 2
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ProjectBuildPipelineStep.cs
  62. 2
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ProjectResult.cs
  63. 35
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ChangeLocalhostPortStep.cs
  64. 6
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/CreateProjectResultZipStep.cs
  65. 6
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/FileEntryListReadStep.cs
  66. 6
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/NugetReferenceReplaceStep.cs
  67. 2
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/RemoveProjectFromSolutionStep.cs
  68. 4
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/SolutionRenameStep.cs
  69. 8
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/SwitchEntityFrameworkCoreToMongoDbStep.cs
  70. 4
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/TemplateCodeDeleteStep.cs
  71. 2
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateInfo.cs
  72. 4
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/DownloadInfo.cs
  73. 2
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Files/FileEntry.cs
  74. 2
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Files/FileEntryExtensions.cs
  75. 2
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Files/FileEntryList.cs
  76. 2
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Files/FileEntryListExtensions.cs
  77. 2
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Github/GithubRelease.cs
  78. 2
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/IProjectBuilder.cs
  79. 4
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ITemplateInfoProvider.cs
  80. 16
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ITemplateStore.cs
  81. 4
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ProjectBuildArgs.cs
  82. 2
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ProjectBuildResult.cs
  83. 17
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ProjectBuilder.cs
  84. 2
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/SolutionName.cs
  85. 15
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateFile.cs
  86. 12
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateInfoProvider.cs
  87. 4
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/MvcModuleTemplate.cs
  88. 22
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/MvcTemplate.cs
  89. 4
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/ServiceTemplate.cs
  90. 4
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Zipping/ZipFileExtensions.cs
  91. 84
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/DbContextFileBuilderConfigureAdder.cs
  92. 83
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/DerivedClassFinder.cs
  93. 46
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/EfCoreMigrationAdder.cs
  94. 78
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ModuleClassDependcyAdder.cs
  95. 17
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ModuleInfo.cs
  96. 10
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NpmApplicationType.cs
  97. 9
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NpmPackageInfo.cs
  98. 11
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NuGetPackageInfo.cs
  99. 15
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NuGetPackageTarget.cs
  100. 133
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ProjectFinder.cs

4
abp_io/src/Volo.Utils.SolutionTemplating/Volo/Utils/SolutionTemplating/Building/Steps/SwitchEntityFrameworkCoreToMongoDbStep.cs

@ -21,9 +21,9 @@ namespace Volo.Utils.SolutionTemplating.Building.Steps
var lines = file.GetLines();
for (var i = 0; i < lines.Length; i++)
{
if (lines[i].Contains("ProjectReference") && lines[i].Contains("MyCompanyName.MyProjectName.EntityFrameworkCore"))
if (lines[i].Contains("ProjectReference") && lines[i].Contains("MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations"))
{
lines[i] = lines[i].Replace("EntityFrameworkCore", "MongoDB");
lines[i] = lines[i].Replace("EntityFrameworkCore.DbMigrations", "MongoDB");
file.SetLines(lines);
return;
}

4
docs/en/AspNetCore/Auto-API-Controllers.md

@ -1,6 +1,6 @@
# Auto API Controllers
Once you create an [application service](Application-Services.md), you generally want to create an API controller to expose this service as an HTTP (REST) API endpoint. A typical API controller does nothing but redirects method calls to the application service and configures the REST API using attributes like [HttpGet], [HttpPost], [Route]... etc.
Once you create an [application service](../Application-Services.md), you generally want to create an API controller to expose this service as an HTTP (REST) API endpoint. A typical API controller does nothing but redirects method calls to the application service and configures the REST API using attributes like [HttpGet], [HttpPost], [Route]... etc.
ABP can **automagically** configures your application services as MVC API Controllers by convention. Most of time you don't care about its detailed configuration, but it's possible fully customize it.
@ -106,7 +106,7 @@ public class PersonAppService : ApplicationService
### TypePredicate Option
You can further filter classes to become an API controller by providing the `TypePedicate` option:
You can further filter classes to become an API controller by providing the `TypePredicate` option:
````csharp
services.Configure<AbpAspNetCoreMvcOptions>(options =>

16
docs/en/AspNetCore/Client-Side-Package-Management.md

@ -22,14 +22,14 @@ The benefit of a **standard package** is:
Depending on a standard package is easy. Just add it to your **package.json** file like you normally do. Example:
{
...
"dependencies": {
"@abp/bootstrap": "^1.0.0"
}
}
````
{
...
"dependencies": {
"@abp/bootstrap": "^1.0.0"
}
}
````
It's suggested to depend on a standard package instead of directly depending on a third-party package.

2
docs/en/Best-Practices/Entities.md

@ -63,7 +63,7 @@ public class Issue : FullAuditedAggregateRoot<Guid> //Using Guid as the key/iden
protected Issue()
{
/* This conctructor is for ORMs to be used while getting the entity from database.
/* This constructor is for ORMs to be used while getting the entity from database.
* - No need to initialize the Labels collection
since it will be overrided from the database.
- It's protected since proxying and deserialization tools

2
docs/en/Module-Development-Basics.md

@ -112,7 +112,7 @@ Lastly, you can override ``OnApplicationShutdown`` method if you want to execute
## Module Dependencies
In a modular application, it's not unusual for one module to depend upon another module(s). An Abp module must declare ``[DependsOn]`` attribute if it does have a dependcy upon another module, as shown below:
In a modular application, it's not unusual for one module to depend upon another module(s). An Abp module must declare ``[DependsOn]`` attribute if it does have a dependency upon another module, as shown below:
````C#
[DependsOn(typeof(AbpAspNetCoreMvcModule))]

2
docs/en/Modules/Index.md

@ -21,6 +21,6 @@ There are some **free and open source** application modules developed and mainta
* **Permission Management**: Used to persist permissions.
* **Setting Management**: Used to persist settings.
* **Tenant Management**: Used to manage tenants for a [multi-tenant](../Multi-Tenancy.md) application.
* **Users**: Used the abstract users, so other modules can depend on this instead of the Identity module.
* **Users**: Used to abstract users, so other modules can depend on this instead of the Identity module.
Documenting the modules is in the progress. See [this repository](https://github.com/abpframework/abp/tree/master/modules) for source code of all modules.

2
docs/en/Multi-Tenancy.md

@ -56,7 +56,7 @@ namespace MyCompany.MyProject
}
````
IMultiTenant requires to define a **TenantId** property in the implementing entity (See entity documentation (TODO: link) for more about entities).
IMultiTenant requires to define a **TenantId** property in the implementing entity (See [entity documentation](Entities.md) for more about entities).
#### Obtain Current Tenant's Id

4
docs/en/Repositories.md

@ -48,8 +48,8 @@ In this example;
Generic Repositories provides some standard CRUD features out of the box:
* Providers `Insert` method to save a new entity.
* Providers `Update` and `Delete` methods to update or delete an entity by entity object or it's id.
* Provides `Insert` method to save a new entity.
* Provides `Update` and `Delete` methods to update or delete an entity by entity object or it's id.
* Provides `Delete` method to delete multiple entities by a filter.
* Implements `IQueryable<TEntity>`, so you can use LINQ and extension methods like `FirstOrDefault`, `Where`, `OrderBy`, `ToList` and so on...
* Have **sync** and **async** versions for all methods.

4
docs/en/Samples/Microservice-Demo.md

@ -168,7 +168,7 @@ These are the actual applications those have user interfaces to interact to the
- **AuthServer.Host**: Host the IdentityServer4 to provide an authentication service to other services and applications. It is a single-sign server and contains the login page.
- **BackendAdminApp.Host**: This is a backend admin application that host UI for Identity and Product management modules.
- **PubicWebSite.Host**: As public web site that contains a simple product list page and blog module UI.
- **PublicWebSite.Host**: As public web site that contains a simple product list page and blog module UI.
- **ConsoleClientDemo**: A simple console application to demonstrate the usage of services from a C# application.
### Gateways / BFFs (Backend for Frontend)
@ -1471,4 +1471,4 @@ ABP provides automatic audit logging which saves every request in detail (who is
All of the services and applications are configured to write audit logs. Audit logs are saved to the MsDemo_Identity SQL database. So, you can query all audit logs of all applications from a single point.
An Audit Log record has a `CorrelationId` property that can be used to track a request. When a service calls another service in a single web request, they both save audit logs with the same `CorrelationId`. See the `AbpAuditLogs` table in the database.
An Audit Log record has a `CorrelationId` property that can be used to track a request. When a service calls another service in a single web request, they both save audit logs with the same `CorrelationId`. See the `AbpAuditLogs` table in the database.

44
framework/Volo.Abp.sln

@ -224,11 +224,19 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.FluentValidation",
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.FluentValidation.Tests", "test\Volo.Abp.FluentValidation.Tests\Volo.Abp.FluentValidation.Tests.csproj", "{E9E1714F-7ED2-4BD1-BA4A-BA06E398288A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Cli.Tests", "test\Volo.Abp.Cli.Tests\Volo.Abp.Cli.Tests.csproj", "{92B70EFF-C1B1-4D1D-8BCE-D116908FC6FF}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.EntityFrameworkCore.Sqlite", "src\Volo.Abp.EntityFrameworkCore.Sqlite\Volo.Abp.EntityFrameworkCore.Sqlite.csproj", "{58CF8957-5045-4F81-884D-72DF48F721CC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Cli.Core", "src\Volo.Abp.Cli.Core\Volo.Abp.Cli.Core.csproj", "{3DA9923E-048E-4FE7-9748-3A0194F5D196}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Cli.Core", "src\Volo.Abp.Cli.Core\Volo.Abp.Cli.Core.csproj", "{3DA9923E-048E-4FE7-9748-3A0194F5D196}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Specifications", "src\Volo.Abp.Specifications\Volo.Abp.Specifications.csproj", "{2C621EED-563C-4F81-A75E-50879E173544}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Specifications.Tests", "test\Volo.Abp.Specifications.Tests\Volo.Abp.Specifications.Tests.csproj", "{D078553A-C70C-4F56-B3E2-9C5BA6384C72}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Cli.Core.Tests", "test\Volo.Abp.Cli.Core.Tests\Volo.Abp.Cli.Core.Tests.csproj", "{F006B0B4-F25D-4511-9FB3-F17AA44BDCEA}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore.Mvc.UI.Widgets", "src\Volo.Abp.AspNetCore.Mvc.UI.Widgets\Volo.Abp.AspNetCore.Mvc.UI.Widgets.csproj", "{EE1AAB08-3FBD-487F-B0B4-BEBA4B69528A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore.Mvc.UI.Dashboards", "src\Volo.Abp.AspNetCore.Mvc.UI.Dashboards\Volo.Abp.AspNetCore.Mvc.UI.Dashboards.csproj", "{054D766D-5992-460E-A4D8-936D80BE2C1A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -672,10 +680,6 @@ Global
{E9E1714F-7ED2-4BD1-BA4A-BA06E398288A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E9E1714F-7ED2-4BD1-BA4A-BA06E398288A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E9E1714F-7ED2-4BD1-BA4A-BA06E398288A}.Release|Any CPU.Build.0 = Release|Any CPU
{92B70EFF-C1B1-4D1D-8BCE-D116908FC6FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{92B70EFF-C1B1-4D1D-8BCE-D116908FC6FF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{92B70EFF-C1B1-4D1D-8BCE-D116908FC6FF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{92B70EFF-C1B1-4D1D-8BCE-D116908FC6FF}.Release|Any CPU.Build.0 = Release|Any CPU
{58CF8957-5045-4F81-884D-72DF48F721CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{58CF8957-5045-4F81-884D-72DF48F721CC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{58CF8957-5045-4F81-884D-72DF48F721CC}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -684,6 +688,26 @@ Global
{3DA9923E-048E-4FE7-9748-3A0194F5D196}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3DA9923E-048E-4FE7-9748-3A0194F5D196}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3DA9923E-048E-4FE7-9748-3A0194F5D196}.Release|Any CPU.Build.0 = Release|Any CPU
{2C621EED-563C-4F81-A75E-50879E173544}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2C621EED-563C-4F81-A75E-50879E173544}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2C621EED-563C-4F81-A75E-50879E173544}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2C621EED-563C-4F81-A75E-50879E173544}.Release|Any CPU.Build.0 = Release|Any CPU
{D078553A-C70C-4F56-B3E2-9C5BA6384C72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D078553A-C70C-4F56-B3E2-9C5BA6384C72}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D078553A-C70C-4F56-B3E2-9C5BA6384C72}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D078553A-C70C-4F56-B3E2-9C5BA6384C72}.Release|Any CPU.Build.0 = Release|Any CPU
{F006B0B4-F25D-4511-9FB3-F17AA44BDCEA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F006B0B4-F25D-4511-9FB3-F17AA44BDCEA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F006B0B4-F25D-4511-9FB3-F17AA44BDCEA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F006B0B4-F25D-4511-9FB3-F17AA44BDCEA}.Release|Any CPU.Build.0 = Release|Any CPU
{EE1AAB08-3FBD-487F-B0B4-BEBA4B69528A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EE1AAB08-3FBD-487F-B0B4-BEBA4B69528A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EE1AAB08-3FBD-487F-B0B4-BEBA4B69528A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EE1AAB08-3FBD-487F-B0B4-BEBA4B69528A}.Release|Any CPU.Build.0 = Release|Any CPU
{054D766D-5992-460E-A4D8-936D80BE2C1A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{054D766D-5992-460E-A4D8-936D80BE2C1A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{054D766D-5992-460E-A4D8-936D80BE2C1A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{054D766D-5992-460E-A4D8-936D80BE2C1A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -798,9 +822,13 @@ Global
{69168816-4394-4DDA-BB6B-C21983D37F0B} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{43D5FE61-ECBF-4B16-AD95-0043E18EB93A} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{E9E1714F-7ED2-4BD1-BA4A-BA06E398288A} = {447C8A77-E5F0-4538-8687-7383196D04EA}
{92B70EFF-C1B1-4D1D-8BCE-D116908FC6FF} = {447C8A77-E5F0-4538-8687-7383196D04EA}
{58CF8957-5045-4F81-884D-72DF48F721CC} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{3DA9923E-048E-4FE7-9748-3A0194F5D196} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{2C621EED-563C-4F81-A75E-50879E173544} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{D078553A-C70C-4F56-B3E2-9C5BA6384C72} = {447C8A77-E5F0-4538-8687-7383196D04EA}
{F006B0B4-F25D-4511-9FB3-F17AA44BDCEA} = {447C8A77-E5F0-4538-8687-7383196D04EA}
{EE1AAB08-3FBD-487F-B0B4-BEBA4B69528A} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{054D766D-5992-460E-A4D8-936D80BE2C1A} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5}

5
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpDynamicformTagHelperService.cs

@ -205,6 +205,11 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
protected virtual List<ModelExpression> ExploreModelsRecursively(List<ModelExpression> list, ModelExplorer model)
{
if (model.GetAttribute<DynamicFormIgnore>() != null)
{
return list;
}
if (IsCsharpClassOrPrimitive(model.ModelType) || IsListOfCsharpClassOrPrimitive(model.ModelType))
{
list.Add(ModelExplorerToModelExpressionConverter(model));

19
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs

@ -187,8 +187,23 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
{
var localizer = _tagHelperLocalizer.GetLocalizer(explorer);
var selectItems = explorer.Metadata.IsEnum ? explorer.ModelType.GetTypeInfo().GetMembers(BindingFlags.Public | BindingFlags.Static)
.Select((t, i) => new SelectListItem { Value = i.ToString(), Text = GetLocalizedPropertyName(localizer, explorer.ModelType, t.Name) }).ToList() : null;
var selectItems = new List<SelectListItem>();
var isNullableType = Nullable.GetUnderlyingType(explorer.ModelType) != null;
var enumType = explorer.ModelType;
if (isNullableType)
{
enumType = Nullable.GetUnderlyingType(explorer.ModelType);
selectItems.Add(new SelectListItem());
}
selectItems.AddRange(enumType.GetTypeInfo().GetMembers(BindingFlags.Public | BindingFlags.Static)
.Select((t, i) =>
new SelectListItem
{
Value = ((int) Enum.Parse(enumType, t.Name)).ToString(),
Text = GetLocalizedPropertyName(localizer, enumType, t.Name)
}).ToList());
return selectItems;
}

9
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/DynamicFormIgnore.cs

@ -0,0 +1,9 @@
using System;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
{
[AttributeUsage(AttributeTargets.Property)]
public class DynamicFormIgnore : Attribute
{
}
}

3
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/AbpAspNetCoreMvcUiBundlingModule.cs

@ -1,5 +1,4 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap;
using Volo.Abp.Modularity;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling

27
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Dashboards/Properties/launchSettings.json

@ -0,0 +1,27 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:57333/",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Volo.Abp.AspNetCore.Mvc.UI.Dashboards": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:57343/"
}
}
}

34
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Dashboards/Volo.Abp.AspNetCore.Mvc.UI.Dashboards.csproj

@ -0,0 +1,34 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Abp.AspNetCore.Mvc.UI.Dashboards</AssemblyName>
<PackageId>Volo.Abp.AspNetCore.Mvc.UI.Dashboards</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<IsPackable>true</IsPackable>
<OutputType>Library</OutputType>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="Volo\Abp\AspNetCore\Mvc\UI\Dashboards\Components\**\*.cshtml" />
<Content Remove="Volo\Abp\AspNetCore\Mvc\UI\Dashboards\Components\**\*.cshtml" />
</ItemGroup>
<ItemGroup>
<Content Remove="Volo\Abp\AspNetCore\Mvc\UI\Dashboards\_ViewImports.cshtml" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Volo\Abp\AspNetCore\Mvc\UI\Dashboards\_ViewImports.cshtml" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.AspNetCore.Mvc.UI.Widgets\Volo.Abp.AspNetCore.Mvc.UI.Widgets.csproj" />
</ItemGroup>
</Project>

20
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Dashboards/Volo/Abp/AspNetCore/Mvc/UI/Dashboards/AbpAspNetCoreMvcUiDashboardsModule.cs

@ -0,0 +1,20 @@
using Volo.Abp.AspNetCore.Mvc.UI.Widgets;
using Volo.Abp.Modularity;
using Volo.Abp.VirtualFileSystem;
namespace Volo.Abp.AspNetCore.Mvc.UI.Dashboards
{
[DependsOn(
typeof(AbpAspNetCoreMvcUiWidgetsModule)
)]
public class AbpAspNetCoreMvcUiDashboardsModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<VirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<AbpAspNetCoreMvcUiDashboardsModule>();
});
}
}
}

17
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Dashboards/Volo/Abp/AspNetCore/Mvc/UI/Dashboards/Components/Dashboard/DashboardViewComponent.cshtml.cs

@ -0,0 +1,17 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.AspNetCore.Mvc.UI.Widgets;
namespace Volo.Abp.AspNetCore.Mvc.UI.Dashboards.Components.Dashboard
{
public class DashboardViewComponent : AbpViewComponent
{
public async Task<IViewComponentResult> InvokeAsync(string dashboardName, DashboardOptions dashboardOptions, WidgetOptions widgetOptions)
{
var model = new DashboardViewModel(dashboardName, dashboardOptions, widgetOptions);
return View("~/Volo/Abp/AspNetCore/Mvc/UI/Dashboards/Components/Dashboard/Default.cshtml", model);
}
}
}

27
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Dashboards/Volo/Abp/AspNetCore/Mvc/UI/Dashboards/Components/Dashboard/DashboardViewModel.cs

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.AspNetCore.Mvc.UI.Widgets;
namespace Volo.Abp.AspNetCore.Mvc.UI.Dashboards.Components.Dashboard
{
public class DashboardViewModel
{
public DashboardDefinition Dashboard { get; set; }
public DashboardOptions DashboardOptions { get; set; }
public WidgetOptions WidgetOptions { get; set; }
public DashboardViewModel(string dashboardName, DashboardOptions dashboardOptions, WidgetOptions widgetOptions)
{
Dashboard = dashboardOptions.Dashboards.Single(d => d.Name.Equals(dashboardName));
DashboardOptions = dashboardOptions;
WidgetOptions = widgetOptions;
}
public WidgetDefinition GetWidget(string name)
{
return WidgetOptions.Widgets.Single(d => d.Name.Equals(name));
}
}
}

21
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Dashboards/Volo/Abp/AspNetCore/Mvc/UI/Dashboards/Components/Dashboard/Default.cshtml

@ -0,0 +1,21 @@
@using Microsoft.Extensions.Localization
@using Volo.Abp.AspNetCore.Mvc.UI.Widgets
@inject IWidgetRenderer WidgetRenderer
@inject IStringLocalizerFactory localizer
@model Volo.Abp.AspNetCore.Mvc.UI.Dashboards.Components.Dashboard.DashboardViewModel
@{
}
<abp-row>
@foreach (var widgetConfiguration in Model.Dashboard.AvailableWidgets)
{
var widgetDefinition = Model.GetWidget(widgetConfiguration.WidgetName);
widgetDefinition.DefaultDimensions = widgetConfiguration.Dimensions ?? widgetDefinition.DefaultDimensions ?? new WidgetDimensions(5, 5);
<abp-column class="col-@widgetDefinition.DefaultDimensions.Width"
style="height: @(widgetDefinition.DefaultDimensions.Height * 100)px"
abp-border="Danger">
@await WidgetRenderer.RenderAsync(Component, widgetDefinition.Name)
</abp-column>
}
</abp-row>

49
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Dashboards/Volo/Abp/AspNetCore/Mvc/UI/Dashboards/DashboardDefinition.cs

@ -0,0 +1,49 @@
using System.Collections.Generic;
using JetBrains.Annotations;
using Volo.Abp.AspNetCore.Mvc.UI.Widgets;
using Volo.Abp.Localization;
namespace Volo.Abp.AspNetCore.Mvc.UI.Dashboards
{
public class DashboardDefinition
{
/// <summary>
/// Unique name of the dashboard.
/// </summary>
[NotNull]
public string Name { get; }
/// <summary>
/// A list of Widgets available for this dashboard.
/// </summary>
public List<DashboardWidgetConfiguration> AvailableWidgets { get; }
/// <summary>
/// Display name of the widget.
/// </summary>
[NotNull]
public ILocalizableString DisplayName
{
get => _displayName;
set => _displayName = Check.NotNull(value, nameof(value));
}
private ILocalizableString _displayName;
public DashboardDefinition(
[NotNull] string name,
[CanBeNull] ILocalizableString displayName)
{
Name = Check.NotNullOrWhiteSpace(name, nameof(name));
DisplayName = displayName ?? new FixedLocalizableString(name);
AvailableWidgets = new List<DashboardWidgetConfiguration>();
}
public DashboardDefinition WithWidget(string widgetName, WidgetLocation location = null, WidgetDimensions dimensions = null)
{
AvailableWidgets.Add( new DashboardWidgetConfiguration(widgetName, dimensions, location));
return this;
}
}
}

14
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Dashboards/Volo/Abp/AspNetCore/Mvc/UI/Dashboards/DashboardOptions.cs

@ -0,0 +1,14 @@
using System.Collections.Generic;
namespace Volo.Abp.AspNetCore.Mvc.UI.Dashboards
{
public class DashboardOptions
{
public List<DashboardDefinition> Dashboards { get; }
public DashboardOptions()
{
Dashboards = new List<DashboardDefinition>();
}
}
}

15
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Dashboards/Volo/Abp/AspNetCore/Mvc/UI/Dashboards/DashboardRenderer.cs

@ -0,0 +1,15 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.Dashboards.Components.Dashboard;
namespace Volo.Abp.AspNetCore.Mvc.UI.Dashboards
{
public class DashboardRenderer : IDashboardRenderer
{
public async Task<IHtmlContent> RenderAsync(IViewComponentHelper componentHelper, object args = null)
{
return await componentHelper.InvokeAsync(typeof(DashboardViewComponent), args ?? new object());
}
}
}

28
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Dashboards/Volo/Abp/AspNetCore/Mvc/UI/Dashboards/DashboardWidgetConfiguration.cs

@ -0,0 +1,28 @@
using JetBrains.Annotations;
using Volo.Abp.AspNetCore.Mvc.UI.Widgets;
namespace Volo.Abp.AspNetCore.Mvc.UI.Dashboards
{
public class DashboardWidgetConfiguration
{
[NotNull]
public string WidgetName { get; }
[CanBeNull]
public WidgetDimensions Dimensions { get; set; }
[CanBeNull]
public WidgetLocation Location { get; set; }
public DashboardWidgetConfiguration(
[NotNull] string widgetName,
[CanBeNull] WidgetDimensions dimensions = null,
[CanBeNull] WidgetLocation location = null
)
{
WidgetName = Check.NotNullOrWhiteSpace(widgetName, nameof(widgetName));
Dimensions = dimensions;
Location = location;
}
}
}

15
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Dashboards/Volo/Abp/AspNetCore/Mvc/UI/Dashboards/IDashboardRenderer.cs

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.Mvc.UI.Dashboards
{
public interface IDashboardRenderer : ITransientDependency
{
Task<IHtmlContent> RenderAsync(IViewComponentHelper componentHelper, object args = null);
}
}

15
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Dashboards/Volo/Abp/AspNetCore/Mvc/UI/Dashboards/WidgetLocation.cs

@ -0,0 +1,15 @@
namespace Volo.Abp.AspNetCore.Mvc.UI.Dashboards
{
public class WidgetLocation
{
public int X { get; set; }
public int Y { get; set; }
public WidgetLocation(int x, int y)
{
X = x;
Y = y;
}
}
}

3
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Dashboards/Volo/Abp/AspNetCore/Mvc/UI/Dashboards/_ViewImports.cshtml

@ -0,0 +1,3 @@
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bootstrap
@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bundling

3
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/AbpAspNetCoreMvcUiPackagesModule.cs

@ -1,5 +1,4 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
using Volo.Abp.Modularity;
namespace Volo.Abp.AspNetCore.Mvc.UI.Packages

16
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Widgets/Volo.Abp.AspNetCore.Mvc.UI.Widgets.csproj

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Abp.AspNetCore.Mvc.UI.Widgets</AssemblyName>
<PackageId>Volo.Abp.AspNetCore.Mvc.UI.Widgets</PackageId>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.AspNetCore.Mvc.UI.Bootstrap\Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.csproj" />
</ItemGroup>
</Project>

13
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Widgets/Volo/Abp/AspNetCore/Mvc/UI/Widgets/AbpAspNetCoreMvcUiWidgetsModule.cs

@ -0,0 +1,13 @@
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap;
using Volo.Abp.Modularity;
namespace Volo.Abp.AspNetCore.Mvc.UI.Widgets
{
[DependsOn(
typeof(AbpAspNetCoreMvcUiBootstrapModule)
)]
public class AbpAspNetCoreMvcUiWidgetsModule : AbpModule
{
}
}

12
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Widgets/Volo/Abp/AspNetCore/Mvc/UI/Widgets/IWidgetRenderer.cs

@ -0,0 +1,12 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.Mvc.UI.Widgets
{
public interface IWidgetRenderer : ITransientDependency
{
Task<IHtmlContent> RenderAsync(IViewComponentHelper componentHelper, string widgetName, object args = null);
}
}

44
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Widgets/Volo/Abp/AspNetCore/Mvc/UI/Widgets/WidgetDefinition.cs

@ -0,0 +1,44 @@
using System;
using JetBrains.Annotations;
using Volo.Abp.Localization;
namespace Volo.Abp.AspNetCore.Mvc.UI.Widgets
{
public class WidgetDefinition
{
/// <summary>
/// Unique name of the widget.
/// </summary>
[NotNull]
public string Name { get; }
/// <summary>
/// Display name of the widget.
/// </summary>
[NotNull]
public ILocalizableString DisplayName
{
get => _displayName;
set => _displayName = Check.NotNull(value, nameof(value));
}
private ILocalizableString _displayName;
[NotNull]
public Type ViewComponentType { get; }
[CanBeNull]
public WidgetDimensions DefaultDimensions { get; set; }
public WidgetDefinition(
[NotNull] string name,
[NotNull] Type viewComponentType,
[CanBeNull] ILocalizableString displayName,
[CanBeNull] WidgetDimensions defaultDimensions = null)
{
DefaultDimensions = defaultDimensions;
Name = Check.NotNullOrWhiteSpace(name, nameof(name));
ViewComponentType = Check.NotNull(viewComponentType, nameof(viewComponentType));
DisplayName = displayName ?? new FixedLocalizableString(name);
}
}
}

15
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Widgets/Volo/Abp/AspNetCore/Mvc/UI/Widgets/WidgetDimensions.cs

@ -0,0 +1,15 @@
namespace Volo.Abp.AspNetCore.Mvc.UI.Widgets
{
public class WidgetDimensions
{
public int Width { get; }
public int Height { get; }
public WidgetDimensions(int width, int height)
{
Width = width;
Height = height;
}
}
}

14
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Widgets/Volo/Abp/AspNetCore/Mvc/UI/Widgets/WidgetOptions.cs

@ -0,0 +1,14 @@
using System.Collections.Generic;
namespace Volo.Abp.AspNetCore.Mvc.UI.Widgets
{
public class WidgetOptions
{
public List<WidgetDefinition> Widgets { get; }
public WidgetOptions()
{
Widgets = new List<WidgetDefinition>();
}
}
}

25
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Widgets/Volo/Abp/AspNetCore/Mvc/UI/Widgets/WidgetRenderer.cs

@ -0,0 +1,25 @@
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
namespace Volo.Abp.AspNetCore.Mvc.UI.Widgets
{
public class WidgetRenderer : IWidgetRenderer
{
private readonly WidgetOptions _widgetOptions;
public WidgetRenderer(IOptions<WidgetOptions> widgetOptions)
{
_widgetOptions = widgetOptions.Value;
}
public async Task<IHtmlContent> RenderAsync(IViewComponentHelper componentHelper, string widgetName, object args = null)
{
var componentType = _widgetOptions.Widgets.Single(w=>w.Name.Equals(widgetName)).ViewComponentType;
return await componentHelper.InvokeAsync(componentType, args ?? new object());
}
}
}

9
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AbpAuditingOptions.cs

@ -9,6 +9,12 @@ namespace Volo.Abp.Auditing
{
//TODO: Consider to add an option to disable auditing for application service methods?
/// <summary>
/// If this value is true, auditing will not throw an exceptions and it will log it when an error occurred while saving AuditLog.
/// Default: true.
/// </summary>
public bool HideErrors { get; set; }
/// <summary>
/// Default: true.
/// </summary>
@ -36,11 +42,12 @@ namespace Volo.Abp.Auditing
/// Default: false.
/// </summary>
public bool IsEnabledForGetRequests { get; set; }
public AbpAuditingOptions()
{
IsEnabled = true;
IsEnabledForAnonymousUsers = true;
HideErrors = true;
Contributors = new List<AuditLogContributor>();

2
framework/src/Volo.Abp.Cli.Core/Volo.Abp.Cli.Core.csproj

@ -17,10 +17,12 @@
<PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="2.2.0" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="4.5.1" />
<PackageReference Include="System.Security.Permissions" Version="4.5.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Ddd.Domain\Volo.Abp.Ddd.Domain.csproj" />
<ProjectReference Include="..\Volo.Abp.Http\Volo.Abp.Http.csproj" />
<ProjectReference Include="..\Volo.Abp.IdentityModel\Volo.Abp.IdentityModel.csproj" />
<ProjectReference Include="..\Volo.Abp.Json\Volo.Abp.Json.csproj" />
</ItemGroup>

3
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs

@ -22,7 +22,8 @@ namespace Volo.Abp.Cli
{
options.Commands["help"] = typeof(HelpCommand);
options.Commands["new"] = typeof(NewCommand);
options.Commands["add"] = typeof(AddCommand);
options.Commands["add-package"] = typeof(AddPackageCommand);
options.Commands["add-module"] = typeof(AddModuleCommand);
options.Commands["login"] = typeof(LoginCommand);
options.Commands["logout"] = typeof(LogoutCommand);
});

6
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Args/CommandLineArgumentParser.cs

@ -16,7 +16,7 @@ namespace Volo.Abp.Cli.Args
var argumentList = args.ToList();
//Get command
//Command
var command = argumentList[0];
argumentList.RemoveAt(0);
@ -26,7 +26,7 @@ namespace Volo.Abp.Cli.Args
return new CommandLineArgs(command);
}
//Get target
//Target
var target = argumentList[0];
if (target.StartsWith("-"))
@ -43,7 +43,7 @@ namespace Volo.Abp.Cli.Args
return new CommandLineArgs(command, target);
}
//Get options
//Options
var commandLineArgs = new CommandLineArgs(command, target);

2
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Auth/AuthService.cs

@ -22,7 +22,7 @@ namespace Volo.Abp.Cli.Auth
var accessToken = await AuthenticationService.GetAccessTokenAsync(
new IdentityClientConfiguration(
"https://localhost:44333", //TODO: Configure
"role email abpio_www",
"role email abpio_www abpio_commercial",
"abp-cli",
"1q2w3e*",
OidcConstants.GrantTypes.Password,

4
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliOptions.cs

@ -7,6 +7,10 @@ namespace Volo.Abp.Cli
{
public Dictionary<string, Type> Commands { get; }
public string AbpIoWwwUrlRoot { get; set; } = "https://abp.io/";
public string AbpIoAccountUrlRoot { get; set; } = "https://account.abp.io/";
public CliOptions()
{
Commands = new Dictionary<string, Type>(StringComparer.OrdinalIgnoreCase);

2
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliPaths.cs

@ -12,4 +12,4 @@ namespace Volo.Abp.Cli
private static readonly string AbpRootPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".abp");
}
}
}

135
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliService.cs

@ -1,42 +1,51 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using Microsoft.Extensions.DependencyInjection;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Volo.Abp.Cli.Args;
using Volo.Abp.Cli.Commands;
using Volo.Abp.Cli.NuGet;
using Volo.Abp.Cli.Utils;
using Volo.Abp.DependencyInjection;
using Volo.Abp.ProjectBuilding;
namespace Volo.Abp.Cli
{
public class CliService : ITransientDependency
{
public static string Version => typeof(AbpCliCoreModule).Assembly.GetFileVersion();
public ILogger<CliService> Logger { get; set; }
protected ICommandLineArgumentParser CommandLineArgumentParser { get; }
protected ICommandSelector CommandSelector { get; }
public IHybridServiceScopeFactory ServiceScopeFactory { get; }
protected IHybridServiceScopeFactory ServiceScopeFactory { get; }
protected NuGetService NuGetService { get; }
public CliService(
ICommandLineArgumentParser commandLineArgumentParser,
ICommandSelector commandSelector,
IHybridServiceScopeFactory serviceScopeFactory)
IHybridServiceScopeFactory serviceScopeFactory,
NuGetService nugetService)
{
CommandLineArgumentParser = commandLineArgumentParser;
CommandSelector = commandSelector;
ServiceScopeFactory = serviceScopeFactory;
NuGetService = nugetService;
Logger = NullLogger<CliService>.Instance;
}
public async Task RunAsync(string[] args)
{
Logger.LogInformation("ABP CLI (abp.io)");
Logger.LogInformation("Version: " + Version);
Logger.LogInformation($"ABP CLI, version {GetCliVersion()}.");
Logger.LogInformation("https://abp.io");
await CheckForNewVersion();
CheckDependencies();
var commandLineArgs = CommandLineArgumentParser.Parse(args);
var commandType = CommandSelector.Select(commandLineArgs);
@ -44,8 +53,118 @@ namespace Volo.Abp.Cli
using (var scope = ServiceScopeFactory.CreateScope())
{
var command = (IConsoleCommand)scope.ServiceProvider.GetRequiredService(commandType);
await command.ExecuteAsync(commandLineArgs);
try
{
await command.ExecuteAsync(commandLineArgs);
}
catch (CliUsageException usageException)
{
Logger.LogWarning(usageException.Message);
}
catch (Exception ex)
{
Logger.LogException(ex);
}
}
}
private void CheckDependencies()
{
var installedNpmPackages = GetInstalledNpmPackages();
if (!installedNpmPackages.Contains(" yarn@"))
{
InstallYarn();
}
if (!installedNpmPackages.Contains(" gulp@"))
{
InstallGulp();
}
}
private string GetInstalledNpmPackages()
{
var output = "";
using (var process = new Process())
{
process.StartInfo = new ProcessStartInfo(CmdHelper.GetFileName())
{
Arguments = CmdHelper.GetArguments("npm list -g --depth 0"),
UseShellExecute = false,
CreateNoWindow = true,
RedirectStandardOutput = true,
RedirectStandardError = true
};
process.Start();
using (var stdOut = process.StandardOutput)
{
using (var stdErr = process.StandardError)
{
output = stdOut.ReadToEnd();
output += stdErr.ReadToEnd();
}
}
}
return output;
}
private void InstallYarn()
{
Logger.LogInformation("Installing yarn...");
CmdHelper.RunCmd("npm install yarn -g");
}
private void InstallGulp()
{
Logger.LogInformation("Installing gulp...");
CmdHelper.RunCmd("npm install gulp -g");
}
private async Task CheckForNewVersion()
{
try
{
var currentVersion = GetCliVersion();
var latestVersion = await NuGetService.GetLatestVersionOrNullAsync("Volo.Abp.Cli");
if (!latestVersion.IsNullOrEmpty() && currentVersion != latestVersion)
{
Logger.LogInformation("");
Logger.LogWarning("ABP CLI has a newer version (" + latestVersion + "). Please update to get the latest features and fixes.");
Logger.LogWarning("");
Logger.LogWarning("Update Command: ");
Logger.LogWarning(" dotnet tool update -g Volo.Abp.Cli");
Logger.LogWarning("");
}
}
catch (Exception e)
{
Logger.LogWarning("Could not get the latest version infom from NuGet.org:");
Logger.LogWarning(e.Message);
}
}
private static string GetCliVersion()
{
var version = typeof(CliService)
.Assembly
.GetFileVersion();
/* Assembly versions are like "2.4.0.0", but NuGet removes the last "0" here,
* like "2.4.0".
* So, we need to remove it from the assembly version to match to the NuGet version.
*/
if (version.Split('.').Length == 4)
{
version = version.RemovePostFix(".0");
}
return version;
}
}
}

19
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliUsageException.cs

@ -0,0 +1,19 @@
using System;
namespace Volo.Abp.Cli
{
public class CliUsageException : Exception
{
public CliUsageException(string message)
: base(message)
{
}
public CliUsageException(string message, Exception innerException)
: base(message, innerException)
{
}
}
}

55
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddCommand.cs

@ -1,55 +0,0 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using System.Threading.Tasks;
using Volo.Abp.Cli.Args;
using Volo.Abp.DependencyInjection;
using Volo.Abp.ProjectModification;
namespace Volo.Abp.Cli.Commands
{
public class AddCommand : IConsoleCommand, ITransientDependency
{
public ILogger<AddCommand> Logger { get; set; }
protected ModuleAdder ModuleAdder { get; }
public AddCommand(ModuleAdder moduleAdder)
{
ModuleAdder = moduleAdder;
Logger = NullLogger<AddCommand>.Instance;
}
public async Task ExecuteAsync(CommandLineArgs commandLineArgs)
{
if (commandLineArgs.Target == null)
{
Logger.LogWarning("Module name is missing.");
AddCommandHelper.WriteUsage(Logger);
return;
}
await ModuleAdder.AddModuleAsync(
new AddModuleArgs(
commandLineArgs.Target,
commandLineArgs.Options.GetOrNull(Options.Solution.Short, Options.Solution.Long),
commandLineArgs.Options.GetOrNull(Options.Project.Short, Options.Project.Long)
)
);
}
public static class Options
{
public static class Solution
{
public const string Short = "s";
public const string Long = "solution";
}
public static class Project
{
public const string Short = "p";
public const string Long = "project";
}
}
}
}

20
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddCommandHelper.cs

@ -4,24 +4,6 @@ namespace Volo.Abp.Cli.Commands
{
public static class AddCommandHelper
{
public static void WriteUsage(ILogger logger)
{
logger.LogWarning("");
logger.LogWarning("'add' command is used to add a module to a solution or to a project.");
logger.LogWarning("Use in a solution folder to add a multi-package module to a solution.");
logger.LogWarning("Use in a project folder to add a single-package module to a project.");
logger.LogWarning("");
logger.LogWarning("Usage:");
logger.LogWarning(" abp add <module-name> [-s|--solution] [-p|--project]");
logger.LogWarning("");
logger.LogWarning("Options:");
logger.LogWarning(" -s|--solution <solution-file> Specify solution file explicitly.");
logger.LogWarning(" -p|--project <project-file> Specify project file explicitly.");
logger.LogWarning("");
logger.LogWarning("Examples:");
logger.LogWarning(" abp add Volo.Abp.TenantManagement Adds tenant management module packages to the solution.");
logger.LogWarning(" abp add Volo.Abp.FluentValidation Adds a single module package to the project.");
logger.LogWarning("");
}
}
}

121
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddModuleCommand.cs

@ -0,0 +1,121 @@
using System;
using System.IO;
using System.Text;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using System.Threading.Tasks;
using Volo.Abp.Cli.Args;
using Volo.Abp.Cli.ProjectModification;
using Volo.Abp.Cli.Utils;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Cli.Commands
{
public class AddModuleCommand : IConsoleCommand, ITransientDependency
{
public ILogger<AddModuleCommand> Logger { get; set; }
protected SolutionModuleAdder SolutionModuleAdder { get; }
public AddModuleCommand(SolutionModuleAdder solutionModuleAdder)
{
SolutionModuleAdder = solutionModuleAdder;
Logger = NullLogger<AddModuleCommand>.Instance;
}
public async Task ExecuteAsync(CommandLineArgs commandLineArgs)
{
if (commandLineArgs.Target == null)
{
throw new CliUsageException("Module name is missing!" + Environment.NewLine + Environment.NewLine + GetUsageInfo());
}
var skipDbMigrations = Convert.ToBoolean(
commandLineArgs.Options.GetOrNull(Options.DbMigrations.Skip) ?? "false");
await SolutionModuleAdder.AddAsync(
GetSolutionFile(commandLineArgs),
commandLineArgs.Target,
skipDbMigrations
);
}
protected virtual string GetSolutionFile(CommandLineArgs commandLineArgs)
{
var providedSolutionFile = PathHelper.NormalizePath(
commandLineArgs.Options.GetOrNull(
AddPackageCommand.Options.Project.Short,
AddPackageCommand.Options.Project.Long
)
);
if (!providedSolutionFile.IsNullOrWhiteSpace())
{
return providedSolutionFile;
}
var foundSolutionFiles = Directory.GetFiles(Directory.GetCurrentDirectory(), "*.sln");
if (foundSolutionFiles.Length == 1)
{
return foundSolutionFiles[0];
}
if (foundSolutionFiles.Length == 0)
{
throw new CliUsageException("'abp add-module' command should be used inside a folder contaning a .sln file!");
}
//foundSolutionFiles.Length > 1
var sb = new StringBuilder("There are multiple solution (.sln) files in the current directory. Please specify one of the files below:");
foreach (var foundSolutionFile in foundSolutionFiles)
{
sb.AppendLine("* " + foundSolutionFile);
}
sb.AppendLine("Example:");
sb.AppendLine($"abp add-module {commandLineArgs.Target} -p {foundSolutionFiles[0]}");
throw new CliUsageException(sb.ToString());
}
protected virtual string GetUsageInfo()
{
var sb = new StringBuilder();
sb.AppendLine("");
sb.AppendLine("'add-module' command is used to add a multi-package ABP module to a solution.");
sb.AppendLine("It should be used in a folder containing a .sln file.");
sb.AppendLine("");
sb.AppendLine("Usage:");
sb.AppendLine(" abp add-module <module-name> [-s|--solution]");
sb.AppendLine("");
sb.AppendLine("Options:");
sb.AppendLine(" -s|--solution <solution-file> Specify the solution file explicitly.");
sb.AppendLine(" --skip-db-migrations <boolean> Specify if a new migration will be added or not.");
sb.AppendLine("");
sb.AppendLine("Examples:");
sb.AppendLine(" abp add-module Volo.Blogging Adds the module to the current soluton.");
sb.AppendLine(" abp add-module Volo.Blogging -s Acme.BookStore Adds the module to the given soluton.");
sb.AppendLine(" abp add-module Volo.Blogging -s Acme.BookStore --skip-db-migrations false Adds the module to the given soluton but doesn't add-migration.");
sb.AppendLine("");
return sb.ToString();
}
public static class Options
{
public static class Solution
{
public const string Short = "s";
public const string Long = "solution";
}
public static class DbMigrations
{
public const string Skip = "skip-db-migrations";
}
}
}
}

110
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddPackageCommand.cs

@ -0,0 +1,110 @@
using System;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Volo.Abp.Cli.Args;
using Volo.Abp.Cli.ProjectModification;
using Volo.Abp.Cli.Utils;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Cli.Commands
{
public class AddPackageCommand : IConsoleCommand, ITransientDependency
{
public ILogger<AddPackageCommand> Logger { get; set; }
protected ProjectNugetPackageAdder ProjectNugetPackageAdder { get; }
public AddPackageCommand(ProjectNugetPackageAdder projectNugetPackageAdder)
{
ProjectNugetPackageAdder = projectNugetPackageAdder;
Logger = NullLogger<AddPackageCommand>.Instance;
}
public virtual async Task ExecuteAsync(CommandLineArgs commandLineArgs)
{
if (commandLineArgs.Target == null)
{
throw new CliUsageException("Package name is missing!" + Environment.NewLine + Environment.NewLine + GetUsageInfo());
}
await ProjectNugetPackageAdder.AddAsync(
GetProjectFile(commandLineArgs),
commandLineArgs.Target
);
}
protected virtual string GetProjectFile(CommandLineArgs commandLineArgs)
{
var providedProjectFile = PathHelper.NormalizePath(
commandLineArgs.Options.GetOrNull(
Options.Project.Short,
Options.Project.Long
)
);
if (!providedProjectFile.IsNullOrWhiteSpace())
{
return providedProjectFile;
}
var foundProjectFiles = Directory.GetFiles(Directory.GetCurrentDirectory(), "*.csproj");
if (foundProjectFiles.Length == 1)
{
return foundProjectFiles[0];
}
if (foundProjectFiles.Length == 0)
{
throw new CliUsageException("'abp add-package' command should be used inside a folder contaning a .csproj file!");
}
//foundProjectFiles.Length > 1
var sb = new StringBuilder("There are multiple project (.csproj) files in the current directory. Please specify one of the files below:");
foreach (var foundProjectFile in foundProjectFiles)
{
sb.AppendLine("* " + foundProjectFile);
}
sb.AppendLine("Example:");
sb.AppendLine($"abp add-package {commandLineArgs.Target} -p {foundProjectFiles[0]}");
throw new CliUsageException(sb.ToString());
}
protected virtual string GetUsageInfo()
{
var sb = new StringBuilder();
sb.AppendLine("");
sb.AppendLine("'add-package' command is used to add an ABP package to a project.");
sb.AppendLine("It should be used in a folder containing a .csproj file.");
sb.AppendLine("");
sb.AppendLine("Usage:");
sb.AppendLine(" abp add-package <package-name> [-p|--project]");
sb.AppendLine("");
sb.AppendLine("Options:");
sb.AppendLine(" -p|--project <project-file> Specify the project file explicitly.");
sb.AppendLine("");
sb.AppendLine("Examples:");
sb.AppendLine(" abp add-package Volo.Abp.FluentValidation Adds the package to the current project.");
sb.AppendLine(" abp add-package Volo.Abp.FluentValidation -p Acme.BookStore.Application Adds the package to the given project.");
sb.AppendLine("");
return sb.ToString();
}
public static class Options
{
public static class Project
{
public const string Short = "p";
public const string Long = "project";
}
}
}
}

11
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/CommandSelector.cs

@ -1,6 +1,6 @@
using System;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using Microsoft.Extensions.Options;
using Volo.Abp.Cli.Args;
using Volo.Abp.DependencyInjection;
@ -17,7 +17,12 @@ namespace Volo.Abp.Cli.Commands
public Type Select(CommandLineArgs commandLineArgs)
{
return Options.Commands.GetOrDefault(commandLineArgs.Command)
if (commandLineArgs.Command.IsNullOrWhiteSpace())
{
return typeof(HelpCommand);
}
return Options.Commands.GetOrDefault(commandLineArgs.Command)
?? typeof(HelpCommand);
}
}

23
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/HelpCommand.cs

@ -1,5 +1,6 @@
using System;
using System.Threading.Tasks;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Volo.Abp.Cli.Args;
using Volo.Abp.DependencyInjection;
@ -7,13 +8,21 @@ namespace Volo.Abp.Cli.Commands
{
public class HelpCommand : IConsoleCommand, ITransientDependency
{
public ILogger<HelpCommand> Logger { get; set; }
public HelpCommand()
{
Logger = NullLogger<HelpCommand>.Instance;
}
public Task ExecuteAsync(CommandLineArgs commandLineArgs)
{
Console.WriteLine("*********** ABP CLI ****************");
Console.WriteLine();
Console.WriteLine("Usage:");
Console.WriteLine();
Console.WriteLine(" abp <command> <target> [options]");
Logger.LogInformation("");
Logger.LogInformation("Usage:");
Logger.LogInformation("");
Logger.LogInformation(" abp <command> <target> [options]");
Logger.LogInformation("");
return Task.CompletedTask;
}
}

4
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LoginCommand.cs

@ -25,6 +25,7 @@ namespace Volo.Abp.Cli.Commands
{
if (commandLineArgs.Target.IsNullOrEmpty())
{
Logger.LogInformation("");
Logger.LogWarning("Username is missing.");
LogHelp();
return;
@ -34,6 +35,7 @@ namespace Volo.Abp.Cli.Commands
var password = ConsoleHelper.ReadSecret();
if (password.IsNullOrWhiteSpace())
{
Logger.LogInformation("");
Logger.LogWarning("Password is missing.");
LogHelp();
return;
@ -41,7 +43,7 @@ namespace Volo.Abp.Cli.Commands
await AuthService.LoginAsync(commandLineArgs.Target, password);
Console.WriteLine($"Successfully logged in as '{commandLineArgs.Target}'");
Logger.LogInformation($"Successfully logged in as '{commandLineArgs.Target}'");
}
private void LogHelp()

5
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs

@ -4,9 +4,9 @@ using Ionic.Zip;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Volo.Abp.Cli.Args;
using Volo.Abp.Cli.ProjectBuilding;
using Volo.Abp.Cli.ProjectBuilding.Building;
using Volo.Abp.DependencyInjection;
using Volo.Abp.ProjectBuilding;
using Volo.Abp.ProjectBuilding.Building;
namespace Volo.Abp.Cli.Commands
{
@ -27,6 +27,7 @@ namespace Volo.Abp.Cli.Commands
{
if (commandLineArgs.Target == null)
{
Logger.LogInformation("");
Logger.LogWarning("Project name is missing.");
Logger.LogWarning("");
Logger.LogWarning("Usage:");

63
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/NuGet/NuGetService.cs

@ -0,0 +1,63 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Json;
using Volo.Abp.Threading;
namespace Volo.Abp.Cli.NuGet
{
public class NuGetService : ISingletonDependency
{
protected IJsonSerializer JsonSerializer { get; }
protected ICancellationTokenProvider CancellationTokenProvider { get; }
public NuGetService(
IJsonSerializer jsonSerializer,
ICancellationTokenProvider cancellationTokenProvider)
{
JsonSerializer = jsonSerializer;
CancellationTokenProvider = cancellationTokenProvider;
}
public async Task<string> GetLatestVersionOrNullAsync(string packageId, bool includePreviews = false)
{
using (var client = new HttpClient())
{
client.Timeout = TimeSpan.FromSeconds(30);
var responseMessage = await client.GetAsync(
$"https://api.nuget.org/v3-flatcontainer/{packageId.ToLowerInvariant()}/index.json",
CancellationTokenProvider.Token
);
if (!responseMessage.IsSuccessStatusCode)
{
throw new Exception("Remote server returns error! HTTP status code: " + responseMessage.StatusCode);
}
var result = await responseMessage.Content.ReadAsStringAsync();
var versions = JsonSerializer.Deserialize<NuGetVersionResultDto>(result).Versions;
if (!includePreviews)
{
versions = versions
.Where(x => !x.Contains("beta") && !x.Contains("preview") && !x.Contains("alpha") && !x.Contains("rc"))
.ToList();
}
return versions.Count > 0 ? versions.Last() : null;
}
}
public class NuGetVersionResultDto
{
[JsonProperty("versions")]
public List<string> Versions { get; set; }
}
}
}

159
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/AbpIoTemplateStore.cs

@ -0,0 +1,159 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using System;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Cli.ProjectBuilding.Building;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Http;
using Volo.Abp.IO;
using Volo.Abp.Json;
using Volo.Abp.Threading;
namespace Volo.Abp.Cli.ProjectBuilding
{
public class AbpIoTemplateStore : ITemplateStore, ITransientDependency
{
public ILogger<AbpIoTemplateStore> Logger { get; set; }
protected CliOptions Options { get; }
protected IJsonSerializer JsonSerializer { get; }
protected ICancellationTokenProvider CancellationTokenProvider { get; }
public AbpIoTemplateStore(
IOptions<CliOptions> options,
IJsonSerializer jsonSerializer,
ICancellationTokenProvider cancellationTokenProvider)
{
JsonSerializer = jsonSerializer;
CancellationTokenProvider = cancellationTokenProvider;
Options = options.Value;
Logger = NullLogger<AbpIoTemplateStore>.Instance;
}
public async Task<TemplateFile> GetAsync(
string name,
DatabaseProvider databaseProvider,
string projectName,
string version = null)
{
if (version == null)
{
version = await GetLatestTemplateVersionAsync(name);
}
DirectoryHelper.CreateIfNotExists(CliPaths.TemplateCache);
var localCacheFile = Path.Combine(CliPaths.TemplateCache, name + "-" + version + ".zip");
if (File.Exists(localCacheFile))
{
Logger.LogInformation("Using cached template: " + name + ", version: " + version);
return new TemplateFile(File.ReadAllBytes(localCacheFile), version);
}
Logger.LogInformation("Downloading template: " + name + ", version: " + version);
var fileContent = await DownloadTemplateFileContentAsync(
new TemplateDownloadInputDto
{
Name = name,
Version = version,
DatabaseProvider = databaseProvider.ToString(),
ProjectName = projectName
}
);
File.WriteAllBytes(localCacheFile, fileContent);
return new TemplateFile(fileContent, version);
}
private async Task<string> GetLatestTemplateVersionAsync(string name)
{
var postData = JsonSerializer.Serialize(new GetLatestTemplateVersionDto { Name = name });
using (var client = new HttpClient())
{
client.Timeout = TimeSpan.FromSeconds(30);
AddAuthentication(client);
var responseMessage = await client.PostAsync(
Options.AbpIoWwwUrlRoot + "api/download/template/get-version/",
new StringContent(postData, Encoding.UTF8, MimeTypes.Application.Json),
CancellationTokenProvider.Token
);
if (!responseMessage.IsSuccessStatusCode)
{
throw new Exception("Remote server returns error! HTTP status code: " + responseMessage.StatusCode);
}
var result = await responseMessage.Content.ReadAsStringAsync();
return JsonSerializer.Deserialize<GetLatestTemplateVersionResultDto>(result).Version;
}
}
private async Task<byte[]> DownloadTemplateFileContentAsync(TemplateDownloadInputDto input)
{
var postData = JsonSerializer.Serialize(input);
using (var client = new HttpClient())
{
client.Timeout = TimeSpan.FromMinutes(3);
AddAuthentication(client);
var responseMessage = await client.PostAsync(
Options.AbpIoWwwUrlRoot + "api/download/template/",
new StringContent(postData, Encoding.UTF8, MimeTypes.Application.Json),
CancellationTokenProvider.Token
);
if (!responseMessage.IsSuccessStatusCode)
{
throw new Exception("Remote server returns error! HTTP status code: " + responseMessage.StatusCode);
}
return await responseMessage.Content.ReadAsByteArrayAsync();
}
}
private static void AddAuthentication(HttpClient client)
{
if (File.Exists(CliPaths.AccessToken))
{
var accessToken = File.ReadAllText(CliPaths.AccessToken, Encoding.UTF8);
if (!accessToken.IsNullOrEmpty())
{
client.SetBearerToken(accessToken);
}
}
}
public class TemplateDownloadInputDto
{
public string Name { get; set; }
public string Version { get; set; }
public string DatabaseProvider { get; set; }
public string ProjectName { get; set; }
}
public class GetLatestTemplateVersionDto
{
public string Name { get; set; }
}
public class GetLatestTemplateVersionResultDto
{
public string Version { get; set; }
}
}
}

2
framework/src/Volo.Abp.Cli.Core/Volo/Abp/ProjectBuilding/Building/DatabaseProvider.cs → framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/DatabaseProvider.cs

@ -1,4 +1,4 @@
namespace Volo.Abp.ProjectBuilding.Building
namespace Volo.Abp.Cli.ProjectBuilding.Building
{
public enum DatabaseProvider
{

2
framework/src/Volo.Abp.Cli.Core/Volo/Abp/ProjectBuilding/Building/GithubRepositoryInfo.cs → framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/GithubRepositoryInfo.cs

@ -1,6 +1,6 @@
using System;
namespace Volo.Abp.ProjectBuilding.Building
namespace Volo.Abp.Cli.ProjectBuilding.Building
{
public class GithubRepositoryInfo
{

14
framework/src/Volo.Abp.Cli.Core/Volo/Abp/ProjectBuilding/Building/ProjectBuildContext.cs → framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ProjectBuildContext.cs

@ -1,16 +1,13 @@
using JetBrains.Annotations;
using Volo.Abp.ProjectBuilding.Files;
using Volo.Abp.Cli.ProjectBuilding.Files;
namespace Volo.Abp.ProjectBuilding.Building
namespace Volo.Abp.Cli.ProjectBuilding.Building
{
public class ProjectBuildContext
{
[NotNull]
public TemplateFile TemplateFile { get; }
[NotNull]
public string Version { get; }
[NotNull]
public ProjectBuildArgs BuildArgs { get; }
@ -21,15 +18,14 @@ namespace Volo.Abp.ProjectBuilding.Building
public ProjectResult Result { get; set; }
public ProjectBuildContext([NotNull] TemplateInfo template,
public ProjectBuildContext(
[NotNull] TemplateInfo template,
[NotNull] TemplateFile templateFile,
[NotNull] ProjectBuildArgs buildArgs,
[NotNull] string version)
[NotNull] ProjectBuildArgs buildArgs)
{
Template = Check.NotNull(template, nameof(template));
TemplateFile = Check.NotNull(templateFile, nameof(templateFile));
BuildArgs = Check.NotNull(buildArgs, nameof(buildArgs));
Version = Check.NotNullOrWhiteSpace(version, nameof(version));
Result = new ProjectResult();
}

4
framework/src/Volo.Abp.Cli.Core/Volo/Abp/ProjectBuilding/Building/ProjectBuildContextExtensions.cs → framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ProjectBuildContextExtensions.cs

@ -1,8 +1,8 @@
using System;
using System.Linq;
using Volo.Abp.ProjectBuilding.Files;
using Volo.Abp.Cli.ProjectBuilding.Files;
namespace Volo.Abp.ProjectBuilding.Building
namespace Volo.Abp.Cli.ProjectBuilding.Building
{
public static class ProjectBuildContextExtensions
{

2
framework/src/Volo.Abp.Cli.Core/Volo/Abp/ProjectBuilding/Building/ProjectBuildPipeline.cs → framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ProjectBuildPipeline.cs

@ -1,6 +1,6 @@
using System.Collections.Generic;
namespace Volo.Abp.ProjectBuilding.Building
namespace Volo.Abp.Cli.ProjectBuilding.Building
{
public class ProjectBuildPipeline
{

4
framework/src/Volo.Abp.Cli.Core/Volo/Abp/ProjectBuilding/Building/ProjectBuildPipelineBuilder.cs → framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ProjectBuildPipelineBuilder.cs

@ -1,6 +1,6 @@
using Volo.Abp.ProjectBuilding.Building.Steps;
using Volo.Abp.Cli.ProjectBuilding.Building.Steps;
namespace Volo.Abp.ProjectBuilding.Building
namespace Volo.Abp.Cli.ProjectBuilding.Building
{
public static class ProjectBuildPipelineBuilder
{

2
framework/src/Volo.Abp.Cli.Core/Volo/Abp/ProjectBuilding/Building/ProjectBuildPipelineStep.cs → framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ProjectBuildPipelineStep.cs

@ -1,4 +1,4 @@
namespace Volo.Abp.ProjectBuilding.Building
namespace Volo.Abp.Cli.ProjectBuilding.Building
{
public abstract class ProjectBuildPipelineStep
{

2
framework/src/Volo.Abp.Cli.Core/Volo/Abp/ProjectBuilding/Building/ProjectResult.cs → framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ProjectResult.cs

@ -1,4 +1,4 @@
namespace Volo.Abp.ProjectBuilding.Building
namespace Volo.Abp.Cli.ProjectBuilding.Building
{
public class ProjectResult
{

35
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ChangeLocalhostPortStep.cs

@ -0,0 +1,35 @@
namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
{
public class ChangeLocalhostPortStep : ProjectBuildPipelineStep
{
public string LaunchSettingsFilePath { get; }
public int[] PortNumbers { get; }
public ChangeLocalhostPortStep(
string launchSettingsFilePath,
params int[] portNumbers)
{
Check.NotNullOrEmpty(portNumbers, nameof(portNumbers));
LaunchSettingsFilePath = launchSettingsFilePath;
PortNumbers = portNumbers;
}
public override void Execute(ProjectBuildContext context)
{
var launchSettings = context.GetFile(LaunchSettingsFilePath);
var randomPort = RandomHelper.GetRandom(50001, 59990);
var newContent = launchSettings.Content;
for (var i = 0; i < PortNumbers.Length; i++)
{
newContent = newContent.Replace(
PortNumbers[i].ToString(),
(randomPort + i).ToString()
);
}
launchSettings.SetContent(newContent);
}
}
}

6
framework/src/Volo.Abp.Cli.Core/Volo/Abp/ProjectBuilding/Building/Steps/CreateProjectResultZipStep.cs → framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/CreateProjectResultZipStep.cs

@ -1,8 +1,8 @@
using Ionic.Zip;
using Volo.Abp.ProjectBuilding.Files;
using Volo.Abp.ProjectBuilding.Zipping;
using Volo.Abp.Cli.ProjectBuilding.Files;
using Volo.Abp.Cli.ProjectBuilding.Zipping;
namespace Volo.Abp.ProjectBuilding.Building.Steps
namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
{
public class CreateProjectResultZipStep : ProjectBuildPipelineStep
{

6
framework/src/Volo.Abp.Cli.Core/Volo/Abp/ProjectBuilding/Building/Steps/FileEntryListReadStep.cs → framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/FileEntryListReadStep.cs

@ -1,9 +1,9 @@
using System.IO;
using Ionic.Zip;
using Volo.Abp.ProjectBuilding.Files;
using Volo.Abp.ProjectBuilding.Zipping;
using Volo.Abp.Cli.ProjectBuilding.Files;
using Volo.Abp.Cli.ProjectBuilding.Zipping;
namespace Volo.Abp.ProjectBuilding.Building.Steps
namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
{
public class FileEntryListReadStep : ProjectBuildPipelineStep
{

6
framework/src/Volo.Abp.Cli.Core/Volo/Abp/ProjectBuilding/Building/Steps/NugetReferenceReplaceStep.cs → framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/NugetReferenceReplaceStep.cs

@ -2,9 +2,9 @@
using System.IO;
using System.Linq;
using HtmlAgilityPack;
using Volo.Abp.ProjectBuilding.Files;
using Volo.Abp.Cli.ProjectBuilding.Files;
namespace Volo.Abp.ProjectBuilding.Building.Steps
namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
{
public class NugetReferenceReplaceStep : ProjectBuildPipelineStep
{
@ -14,7 +14,7 @@ namespace Volo.Abp.ProjectBuilding.Building.Steps
context.Files,
"MyCompanyName",
"MyProjectName",
context.Version
context.TemplateFile.Version
).Run();
}

2
framework/src/Volo.Abp.Cli.Core/Volo/Abp/ProjectBuilding/Building/Steps/RemoveProjectFromSolutionStep.cs → framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/RemoveProjectFromSolutionStep.cs

@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.Linq;
namespace Volo.Abp.ProjectBuilding.Building.Steps
namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
{
public class RemoveProjectFromSolutionStep : ProjectBuildPipelineStep
{

4
framework/src/Volo.Abp.Cli.Core/Volo/Abp/ProjectBuilding/Building/Steps/SolutionRenameStep.cs → framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/SolutionRenameStep.cs

@ -1,9 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Volo.Abp.ProjectBuilding.Files;
using Volo.Abp.Cli.ProjectBuilding.Files;
namespace Volo.Abp.ProjectBuilding.Building.Steps
namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
{
public class SolutionRenameStep : ProjectBuildPipelineStep
{

8
framework/src/Volo.Abp.Cli.Core/Volo/Abp/ProjectBuilding/Building/Steps/SwitchEntityFrameworkCoreToMongoDbStep.cs → framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/SwitchEntityFrameworkCoreToMongoDbStep.cs

@ -1,7 +1,7 @@
using System;
using Volo.Abp.ProjectBuilding.Files;
using Volo.Abp.Cli.ProjectBuilding.Files;
namespace Volo.Abp.ProjectBuilding.Building.Steps
namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
{
public class SwitchEntityFrameworkCoreToMongoDbStep : ProjectBuildPipelineStep
{
@ -21,9 +21,9 @@ namespace Volo.Abp.ProjectBuilding.Building.Steps
var lines = file.GetLines();
for (var i = 0; i < lines.Length; i++)
{
if (lines[i].Contains("ProjectReference") && lines[i].Contains("MyCompanyName.MyProjectName.EntityFrameworkCore"))
if (lines[i].Contains("ProjectReference") && lines[i].Contains("MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations"))
{
lines[i] = lines[i].Replace("EntityFrameworkCore", "MongoDB");
lines[i] = lines[i].Replace("EntityFrameworkCore.DbMigrations", "MongoDB");
file.SetLines(lines);
return;
}

4
framework/src/Volo.Abp.Cli.Core/Volo/Abp/ProjectBuilding/Building/Steps/TemplateCodeDeleteStep.cs → framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/TemplateCodeDeleteStep.cs

@ -1,6 +1,6 @@
using Volo.Abp.ProjectBuilding.Files;
using Volo.Abp.Cli.ProjectBuilding.Files;
namespace Volo.Abp.ProjectBuilding.Building.Steps
namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
{
public class TemplateCodeDeleteStep : ProjectBuildPipelineStep
{

2
framework/src/Volo.Abp.Cli.Core/Volo/Abp/ProjectBuilding/Building/TemplateInfo.cs → framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateInfo.cs

@ -2,7 +2,7 @@
using System.Collections.Generic;
using JetBrains.Annotations;
namespace Volo.Abp.ProjectBuilding.Building
namespace Volo.Abp.Cli.ProjectBuilding.Building
{
public abstract class TemplateInfo
{

4
framework/src/Volo.Abp.Cli.Core/Volo/Abp/ProjectBuilding/DownloadInfo.cs → framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/DownloadInfo.cs

@ -1,9 +1,9 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Volo.Abp.Cli.ProjectBuilding.Building;
using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp.ProjectBuilding.Building;
namespace Volo.Abp.ProjectBuilding
namespace Volo.Abp.Cli.ProjectBuilding
{
[Table("Downloads")]
public class DownloadInfo : CreationAuditedAggregateRoot<int>

2
framework/src/Volo.Abp.Cli.Core/Volo/Abp/ProjectBuilding/Files/FileEntry.cs → framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Files/FileEntry.cs

@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Volo.Abp.ProjectBuilding.Files
namespace Volo.Abp.Cli.ProjectBuilding.Files
{
public class FileEntry
{

2
framework/src/Volo.Abp.Cli.Core/Volo/Abp/ProjectBuilding/Files/FileEntryExtensions.cs → framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Files/FileEntryExtensions.cs

@ -1,6 +1,6 @@
using System.Collections.Generic;
namespace Volo.Abp.ProjectBuilding.Files
namespace Volo.Abp.Cli.ProjectBuilding.Files
{
public static class FileEntryExtensions
{

2
framework/src/Volo.Abp.Cli.Core/Volo/Abp/ProjectBuilding/Files/FileEntryList.cs → framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Files/FileEntryList.cs

@ -1,6 +1,6 @@
using System.Collections.Generic;
namespace Volo.Abp.ProjectBuilding.Files
namespace Volo.Abp.Cli.ProjectBuilding.Files
{
public class FileEntryList : List<FileEntry>
{

2
framework/src/Volo.Abp.Cli.Core/Volo/Abp/ProjectBuilding/Files/FileEntryListExtensions.cs → framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Files/FileEntryListExtensions.cs

@ -1,7 +1,7 @@
using System;
using Ionic.Zip;
namespace Volo.Abp.ProjectBuilding.Files
namespace Volo.Abp.Cli.ProjectBuilding.Files
{
public static class FileEntryListExtensions
{

2
framework/src/Volo.Abp.Cli.Core/Volo/Abp/ProjectBuilding/Github/GithubRelease.cs → framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Github/GithubRelease.cs

@ -1,7 +1,7 @@
using System;
using Newtonsoft.Json;
namespace Volo.Abp.ProjectBuilding.Github
namespace Volo.Abp.Cli.ProjectBuilding.Github
{
[JsonObject]
public class GithubRelease

2
framework/src/Volo.Abp.Cli.Core/Volo/Abp/ProjectBuilding/IProjectBuilder.cs → framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/IProjectBuilder.cs

@ -1,6 +1,6 @@
using System.Threading.Tasks;
namespace Volo.Abp.ProjectBuilding
namespace Volo.Abp.Cli.ProjectBuilding
{
public interface IProjectBuilder
{

4
framework/src/Volo.Abp.Cli.Core/Volo/Abp/ProjectBuilding/ITemplateInfoProvider.cs → framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ITemplateInfoProvider.cs

@ -1,6 +1,6 @@
using Volo.Abp.ProjectBuilding.Building;
using Volo.Abp.Cli.ProjectBuilding.Building;
namespace Volo.Abp.ProjectBuilding
namespace Volo.Abp.Cli.ProjectBuilding
{
public interface ITemplateInfoProvider
{

16
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ITemplateStore.cs

@ -0,0 +1,16 @@
using System.Threading.Tasks;
using JetBrains.Annotations;
using Volo.Abp.Cli.ProjectBuilding.Building;
namespace Volo.Abp.Cli.ProjectBuilding
{
public interface ITemplateStore
{
Task<TemplateFile> GetAsync(
string name,
DatabaseProvider databaseProvider,
string projectName,
[CanBeNull] string version = null
);
}
}

4
framework/src/Volo.Abp.Cli.Core/Volo/Abp/ProjectBuilding/ProjectBuildArgs.cs → framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ProjectBuildArgs.cs

@ -1,7 +1,7 @@
using JetBrains.Annotations;
using Volo.Abp.ProjectBuilding.Building;
using Volo.Abp.Cli.ProjectBuilding.Building;
namespace Volo.Abp.ProjectBuilding
namespace Volo.Abp.Cli.ProjectBuilding
{
public class ProjectBuildArgs
{

2
framework/src/Volo.Abp.Cli.Core/Volo/Abp/ProjectBuilding/ProjectBuildResult.cs → framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ProjectBuildResult.cs

@ -1,4 +1,4 @@
namespace Volo.Abp.ProjectBuilding
namespace Volo.Abp.Cli.ProjectBuilding
{
public class ProjectBuildResult
{

17
framework/src/Volo.Abp.Cli.Core/Volo/Abp/ProjectBuilding/ProjectBuilder.cs → framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ProjectBuilder.cs

@ -1,10 +1,10 @@
using System;
using System.Threading.Tasks;
using Volo.Abp.Cli;
using Volo.Abp.Cli.ProjectBuilding.Building;
using Volo.Abp.Cli.Utils;
using Volo.Abp.DependencyInjection;
using Volo.Abp.ProjectBuilding.Building;
namespace Volo.Abp.ProjectBuilding
namespace Volo.Abp.Cli.ProjectBuilding
{
public class ProjectBuilder : IProjectBuilder, ITransientDependency
{
@ -31,15 +31,16 @@ namespace Volo.Abp.ProjectBuilding
}
}
var version = CliService.Version;
var templateFile = await TemplateStore.GetAsync(args.TemplateName, version);
var templateFile = await TemplateStore.GetAsync(
args.TemplateName,
args.DatabaseProvider,
args.SolutionName.FullName
);
var context = new ProjectBuildContext(
templateInfo,
templateFile,
args,
version
args
);
ProjectBuildPipelineBuilder.Build(context).Execute(context);

2
framework/src/Volo.Abp.Cli.Core/Volo/Abp/ProjectBuilding/SolutionName.cs → framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/SolutionName.cs

@ -1,6 +1,6 @@
using System;
namespace Volo.Abp.ProjectBuilding
namespace Volo.Abp.Cli.ProjectBuilding
{
public class SolutionName
{

15
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateFile.cs

@ -0,0 +1,15 @@
namespace Volo.Abp.Cli.ProjectBuilding
{
public class TemplateFile
{
public string Version { get; }
public byte[] FileBytes { get; }
public TemplateFile(byte[] fileBytes, string version)
{
FileBytes = fileBytes;
Version = version;
}
}
}

12
framework/src/Volo.Abp.Cli.Core/Volo/Abp/ProjectBuilding/TemplateInfoProvider.cs → framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateInfoProvider.cs

@ -1,23 +1,23 @@
using System;
using Volo.Abp.Cli.ProjectBuilding.Building;
using Volo.Abp.Cli.ProjectBuilding.Templates;
using Volo.Abp.DependencyInjection;
using Volo.Abp.ProjectBuilding.Building;
using Volo.Abp.ProjectBuilding.Templates;
namespace Volo.Abp.ProjectBuilding
namespace Volo.Abp.Cli.ProjectBuilding
{
public class TemplateInfoProvider : ITemplateInfoProvider, ITransientDependency
{
public TemplateInfo GetDefault()
{
return Get(MvcApplicationTemplate.TemplateName);
return Get(MvcTemplate.TemplateName);
}
public TemplateInfo Get(string name)
{
switch (name)
{
case MvcApplicationTemplate.TemplateName:
return new MvcApplicationTemplate();
case MvcTemplate.TemplateName:
return new MvcTemplate();
case MvcModuleTemplate.TemplateName:
return new MvcModuleTemplate();
case ServiceTemplate.TemplateName:

4
framework/src/Volo.Abp.Cli.Core/Volo/Abp/ProjectBuilding/Templates/MvcModuleTemplate.cs → framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/MvcModuleTemplate.cs

@ -1,6 +1,6 @@
using Volo.Abp.ProjectBuilding.Building;
using Volo.Abp.Cli.ProjectBuilding.Building;
namespace Volo.Abp.ProjectBuilding.Templates
namespace Volo.Abp.Cli.ProjectBuilding.Templates
{
public class MvcModuleTemplate : TemplateInfo
{

22
framework/src/Volo.Abp.Cli.Core/Volo/Abp/ProjectBuilding/Templates/MvcApplicationTemplate.cs → framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/MvcTemplate.cs

@ -1,17 +1,17 @@
using System.Collections.Generic;
using Volo.Abp.ProjectBuilding.Building;
using Volo.Abp.ProjectBuilding.Building.Steps;
using Volo.Abp.Cli.ProjectBuilding.Building;
using Volo.Abp.Cli.ProjectBuilding.Building.Steps;
namespace Volo.Abp.ProjectBuilding.Templates
namespace Volo.Abp.Cli.ProjectBuilding.Templates
{
public class MvcApplicationTemplate : TemplateInfo
public class MvcTemplate : TemplateInfo
{
/// <summary>
/// "mvc".
/// </summary>
public const string TemplateName = "mvc";
public MvcApplicationTemplate()
public MvcTemplate()
: base(TemplateName, DatabaseProvider.EntityFrameworkCore)
{
}
@ -21,6 +21,7 @@ namespace Volo.Abp.ProjectBuilding.Templates
var steps = new List<ProjectBuildPipelineStep>();
SwitchDatabaseProvider(context, steps);
RemoveOtherDatabaseProviders(context, steps);
ChangeLocalhostPort(steps);
return steps;
}
@ -47,5 +48,16 @@ namespace Volo.Abp.ProjectBuilding.Templates
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.MongoDB"));
}
}
private void ChangeLocalhostPort(List<ProjectBuildPipelineStep> steps)
{
steps.Add(
new ChangeLocalhostPortStep(
"/src/MyCompanyName.MyProjectName.Web/Properties/launchSettings.json",
53929,
53932
)
);
}
}
}

4
framework/src/Volo.Abp.Cli.Core/Volo/Abp/ProjectBuilding/Templates/ServiceTemplate.cs → framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/ServiceTemplate.cs

@ -1,6 +1,6 @@
using Volo.Abp.ProjectBuilding.Building;
using Volo.Abp.Cli.ProjectBuilding.Building;
namespace Volo.Abp.ProjectBuilding.Templates
namespace Volo.Abp.Cli.ProjectBuilding.Templates
{
public class ServiceTemplate : TemplateInfo
{

4
framework/src/Volo.Abp.Cli.Core/Volo/Abp/ProjectBuilding/Zipping/ZipFileExtensions.cs → framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Zipping/ZipFileExtensions.cs

@ -3,9 +3,9 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using Ionic.Zip;
using Volo.Abp.ProjectBuilding.Files;
using Volo.Abp.Cli.ProjectBuilding.Files;
namespace Volo.Abp.ProjectBuilding.Zipping
namespace Volo.Abp.Cli.ProjectBuilding.Zipping
{
public static class ZipFileExtensions
{

84
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/DbContextFileBuilderConfigureAdder.cs

@ -0,0 +1,84 @@
using System;
using System.IO;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Cli.ProjectModification
{
public class DbContextFileBuilderConfigureAdder : ITransientDependency
{
public ILogger<DbContextFileBuilderConfigureAdder> Logger { get; set; }
protected UsingStatementAdder UsingStatementAdder { get; }
public DbContextFileBuilderConfigureAdder(UsingStatementAdder usingStatementAdder)
{
UsingStatementAdder = usingStatementAdder;
Logger = NullLogger<DbContextFileBuilderConfigureAdder>.Instance;
}
public void Add(string path, string moduleConfiguration)
{
var file = File.ReadAllText(path);
file = UsingStatementAdder.Add(file, GetNamespace(moduleConfiguration));
var stringToAdd = GetLineToAdd(moduleConfiguration);
if (!file.Contains(stringToAdd))
{
var indexToInsert = FindIndexToInsert(file);
if (indexToInsert <= 0 || indexToInsert >= file.Length)
{
Logger.LogWarning($"\"OnModelCreating(ModelBuilder builder)\" method couldn't be found in {path}");
return;
}
file = file.Insert(indexToInsert, " " + stringToAdd + Environment.NewLine + " ");
}
File.WriteAllText(path, file);
}
protected int FindIndexToInsert(string file)
{
var indexOfMethodDeclaration = file.IndexOf("OnModelCreating(", StringComparison.Ordinal);
var indexOfOpeningBracket = indexOfMethodDeclaration + file.Substring(indexOfMethodDeclaration).IndexOf('{');
var stack = 1;
var index = indexOfOpeningBracket;
while (stack > 0)
{
index++;
if (index >= file.Length)
{
break;
}
if (file[index] == '{')
{
stack++;
}
else if (file[index] == '}')
{
stack--;
}
}
return index;
}
protected string GetLineToAdd(string moduleConfiguration)
{
return "builder." + moduleConfiguration.Split(':')[1] + "();";
}
protected string GetNamespace(string moduleConfiguration)
{
return string.Join(".", moduleConfiguration.Split(':')[0]);
}
}
}

83
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/DerivedClassFinder.cs

@ -0,0 +1,83 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Cli.ProjectModification
{
public class DerivedClassFinder : ITransientDependency
{
public ILogger<DerivedClassFinder> Logger { get; set; }
public DerivedClassFinder()
{
Logger = NullLogger<DerivedClassFinder>.Instance;
}
public virtual List<string> Find(string csprojFilePath, string baseClass)
{
var moduleFilePaths = new List<string>();
var csprojFileDirectory = Path.GetDirectoryName(csprojFilePath);
var binFile = Path.Combine(csprojFileDirectory, "bin");
var objFile = Path.Combine(csprojFileDirectory, "obj");
var csFiles = new DirectoryInfo(csprojFileDirectory)
.GetFiles("*.cs", SearchOption.AllDirectories)
.Where(f => !f.DirectoryName.StartsWith(binFile))
.Where(f => !f.DirectoryName.StartsWith(objFile))
.Select(f => f.FullName)
.ToList();
foreach (var csFile in csFiles)
{
try
{
if (IsDerived(csFile, baseClass))
{
moduleFilePaths.Add(csFile);
}
}
catch (Exception)
{
Logger.LogDebug($"Couldn't parse {csFile}.");
}
}
return moduleFilePaths;
}
protected bool IsDerived(string csFile, string baseClass)
{
Logger.LogDebug(csFile);
var root = CSharpSyntaxTree.ParseText(File.ReadAllText(csFile)).GetRoot();
var namespaceSyntax = root.DescendantNodes().OfType<NamespaceDeclarationSyntax>().First();
var classDeclaration = (namespaceSyntax.DescendantNodes().OfType<ClassDeclarationSyntax>()).First();
var baseTypeList = classDeclaration.BaseList?.Types.Select(t => t.ToString()).ToList();
if (baseTypeList == null)
{
return false;
}
foreach (var baseType in baseTypeList)
{
if (baseType.Contains('<') && baseType.Substring(0, baseType.IndexOf('<')) == baseClass)
{
return true;
}
if (baseType == baseClass)
{
return true;
}
}
return false;
}
}
}

46
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/EfCoreMigrationAdder.cs

@ -0,0 +1,46 @@
using System;
using System.Diagnostics;
using System.IO;
using Volo.Abp.Cli.Utils;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Cli.ProjectModification
{
public class EfCoreMigrationAdder : ITransientDependency
{
public void AddMigration(string csprojFile, string module, bool updateDatabase = true)
{
var moduleName = ParseModuleName(module);
var migrationName = "Added_" + moduleName + "_Module" + GetUniquePostFix();
CmdHelper.RunCmd("cd \"" + Path.GetDirectoryName(csprojFile) + "\" & dotnet ef migrations add " + migrationName);
if (updateDatabase)
{
UpdateDatabase(csprojFile);
}
}
protected void UpdateDatabase(string csprojFile)
{
CmdHelper.RunCmd("cd \"" + Path.GetDirectoryName(csprojFile) + "\" & dotnet ef database update");
}
protected virtual string ParseModuleName(string fullModuleName)
{
var words = fullModuleName?.Split('.');
if (words == null || words.Length <= 1)
{
return "";
}
return words[words.Length - 1];
}
protected virtual string GetUniquePostFix()
{
return "_" + new Random().Next(1,99999);
}
}
}

78
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ModuleClassDependcyAdder.cs

@ -0,0 +1,78 @@
using System;
using System.IO;
using System.Linq;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Cli.ProjectModification
{
public class ModuleClassDependcyAdder : ITransientDependency
{
protected UsingStatementAdder UsingStatementAdder { get; }
public ModuleClassDependcyAdder(UsingStatementAdder usingStatementAdder)
{
UsingStatementAdder = usingStatementAdder;
}
public virtual void Add(string path, string module)
{
ParseModuleNameAndNameSpace(module, out var nameSpace, out var moduleName);
var file = File.ReadAllText(path);
file = UsingStatementAdder.Add(file, nameSpace);
if (!file.Contains(moduleName) )
{
file = InsertDependsOnAttribute(file, moduleName);
}
File.WriteAllText(path, file);
}
protected virtual string InsertDependsOnAttribute(string file, string moduleName)
{
var indexOfPublicClassDeclaration = GetIndexOfWhereDependsOnWillBeAdded(file);
var dependsOnAttribute = GetDependsOnAttribute(moduleName);
return file.Insert(indexOfPublicClassDeclaration, dependsOnAttribute);
}
protected virtual int GetIndexOfWhereDependsOnWillBeAdded(string file)
{
var indexOfPublicClassDeclaration = file.IndexOf("public class", StringComparison.Ordinal);
if (indexOfPublicClassDeclaration < 0)
{
throw new Exception("\"public class\" declaration not found!");
}
return indexOfPublicClassDeclaration;
}
protected virtual string GetDependsOnAttribute(string moduleName)
{
return "[DependsOn(typeof(" + moduleName + "))]" + Environment.NewLine + " ";
}
protected virtual string GetUsingStatement(string nameSpace)
{
return "using " + nameSpace + ";";
}
protected virtual void ParseModuleNameAndNameSpace(string module, out string nameSpace, out string moduleName)
{
var words = module?.Split('.');
if (words == null || words.Length <= 1)
{
nameSpace = null;
moduleName = module;
return;
}
moduleName = words[words.Length - 1];
nameSpace = string.Join(".", words.Take(words.Length - 1));
}
}
}

17
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ModuleInfo.cs

@ -0,0 +1,17 @@
using System.Collections.Generic;
namespace Volo.Abp.Cli.ProjectModification
{
public class ModuleInfo
{
public string Name { get; set; }
public string DisplayName { get; set; }
public string EfCoreConfigureMethodName { get; set; }
public List<NugetPackageInfo> NugetPackages { get; set; }
public List<NpmPackageInfo> NpmPackages { get; set; }
}
}

10
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NpmApplicationType.cs

@ -0,0 +1,10 @@
using System;
namespace Volo.Abp.Cli.ProjectModification
{
[Flags]
public enum NpmApplicationType
{
Mvc = 1
}
}

9
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NpmPackageInfo.cs

@ -0,0 +1,9 @@
namespace Volo.Abp.Cli.ProjectModification
{
public class NpmPackageInfo
{
public string Name { get; set; }
public NpmApplicationType ApplicationType { get; set; }
}
}

11
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NuGetPackageInfo.cs

@ -0,0 +1,11 @@
namespace Volo.Abp.Cli.ProjectModification
{
public class NugetPackageInfo
{
public string Name { get; set; }
public string ModuleClass { get; set; }
public NuGetPackageTarget Target { get; set; }
}
}

15
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NuGetPackageTarget.cs

@ -0,0 +1,15 @@
namespace Volo.Abp.Cli.ProjectModification
{
public enum NuGetPackageTarget : byte
{
DomainShared = 1,
Domain = 2,
ApplicationContracts = 3,
Application = 4,
HttpApi = 5,
HttpApiClient = 6,
Web = 7,
EntityFrameworkCore = 8,
MongoDB = 9
}
}

133
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ProjectFinder.cs

@ -0,0 +1,133 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace Volo.Abp.Cli.ProjectModification
{
public static class ProjectFinder
{
public static string FindNuGetTargetProjectFile(string[] projectFiles, NuGetPackageTarget target)
{
if (!projectFiles.Any())
{
return null;
}
var assemblyNames = GetAssemblyNames(projectFiles);
switch (target)
{
case NuGetPackageTarget.Web:
return FindProjectEndsWith(projectFiles, assemblyNames, ".Web");
case NuGetPackageTarget.EntityFrameworkCore:
return FindProjectEndsWith(projectFiles, assemblyNames, ".EntityFrameworkCore");
case NuGetPackageTarget.MongoDB:
return FindProjectEndsWith(projectFiles, assemblyNames, ".MongoDB");
case NuGetPackageTarget.Application:
return FindProjectEndsWith(projectFiles, assemblyNames, ".Application") ??
FindProjectEndsWith(projectFiles, assemblyNames, ".Web");
case NuGetPackageTarget.ApplicationContracts:
return FindProjectEndsWith(projectFiles, assemblyNames, ".Application.Contracts");
case NuGetPackageTarget.Domain:
return FindProjectEndsWith(projectFiles, assemblyNames, ".Domain") ??
FindProjectEndsWith(projectFiles, assemblyNames, ".Application") ??
FindProjectEndsWith(projectFiles, assemblyNames, ".Web");
case NuGetPackageTarget.DomainShared:
return FindProjectEndsWith(projectFiles, assemblyNames, ".Domain.Shared");
case NuGetPackageTarget.HttpApi:
return FindProjectEndsWith(projectFiles, assemblyNames, ".HttpApi");
case NuGetPackageTarget.HttpApiClient:
return FindProjectEndsWith(projectFiles, assemblyNames, ".HttpApi.Client");
default:
throw new ApplicationException($"{nameof(NuGetPackageTarget)}.{target} has not implemented!");
}
}
public static string[] FindNpmTargetProjectFile(string[] projectFiles)
{
if (!projectFiles.Any())
{
return Array.Empty<string>();
}
var assemblyNames = GetAssemblyNames(projectFiles);
var projects = new List<string>();
var project = FindProjectEndsWith(projectFiles, assemblyNames, ".Web.Host");
if (project != null)
{
projects.Add(project);
}
project = FindProjectEndsWith(projectFiles, assemblyNames, ".Host", ".HttpApi.Host");
if (project != null)
{
projects.Add(project);
}
if (projects.Any())
{
return projects.ToArray();
}
project = FindProjectEndsWith(projectFiles, assemblyNames, ".Web");
if (project != null)
{
projects.Add(project);
}
return projects.ToArray();
}
public static string[] GetProjectFiles(string solutionFile)
{
var baseProjectFolder = GetBaseProjectFolder(solutionFile);
return Directory.GetFiles(baseProjectFolder, "*.csproj", SearchOption.AllDirectories);
}
public static string[] GetAssemblyNames(string[] projectFiles)
{
return projectFiles.Select(GetAssemblyName).ToArray();
}
public static string GetAssemblyName(string projectFile)
{
return projectFile
.Substring(projectFile.LastIndexOf(Path.DirectorySeparatorChar) + 1)
.RemovePostFix(StringComparison.OrdinalIgnoreCase, ".csproj");
}
private static string FindProjectEndsWith(
string[] projectFiles,
string[] assemblyNames,
string postfix,
string excludePostfix = null)
{
for (var i = 0; i < assemblyNames.Length; i++)
{
var assemblyName = assemblyNames[i];
if(assemblyName.EndsWith(postfix, StringComparison.OrdinalIgnoreCase) &&
(excludePostfix == null || !assemblyName.EndsWith(excludePostfix)))
{
return projectFiles[i];
}
}
return null;
}
private static string GetBaseProjectFolder(string solutionFile)
{
var baseFolder = Path.GetDirectoryName(solutionFile);
var srcFolder = Path.Combine(baseFolder, "src");
if (Directory.Exists(srcFolder))
{
baseFolder = srcFolder;
}
return baseFolder;
}
}
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save