Browse Source

Merge remote-tracking branch 'abpframework/dev' into Translate

pull/2965/head
liangshiwei 6 years ago
parent
commit
cea4c024ae
  1. 29
      docs/en/CLI.md
  2. 7
      docs/zh-Hans/CLI.md
  3. 39
      framework/Volo.Abp.sln
  4. 6
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpDynamicformTagHelperService.cs
  5. 16
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/AlertsDemo/AlertsDemoViewComponent.cs
  6. 70
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/AlertsDemo/Default.cshtml
  7. 16
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/BadgesDemo/BadgesDemoViewComponent.cs
  8. 49
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/BadgesDemo/Default.cshtml
  9. 16
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/BordersDemo/BordersDemoViewComponent.cs
  10. 46
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/BordersDemo/Default.cshtml
  11. 16
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/BreadcrumbsDemo/BreadcrumbsDemoViewComponent.cs
  12. 18
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/BreadcrumbsDemo/Default.cshtml
  13. 16
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/ButtonGroupsDemo/ButtonGroupsDemoViewComponent.cs
  14. 68
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/ButtonGroupsDemo/Default.cshtml
  15. 16
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/CardsDemo/CardsDemoViewComponent.cs
  16. 156
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/CardsDemo/Default.cshtml
  17. 16
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/CollapseDemo/CollapseDemoViewComponent.cs
  18. 43
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/CollapseDemo/Default.cshtml
  19. 171
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/DropdownsDemo/Default.cshtml
  20. 16
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/DropdownsDemo/DropdownsDemoViewComponent.cs
  21. 223
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/GridsDemo/Default.cshtml
  22. 16
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/GridsDemo/GridsDemoViewComponent.cs
  23. 82
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/ListGroupsDemo/Default.cshtml
  24. 16
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/ListGroupsDemo/ListGroupsDemoViewComponent.cs
  25. 15
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/ModalsDemo/Default.cshtml
  26. 16
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/ModalsDemo/ModalsDemoViewComponent.cs
  27. 53
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/NavsDemo/Default.cshtml
  28. 16
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/NavsDemo/NavsDemoViewComponent.cs
  29. 16
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/PopoversDemo/Default.cshtml
  30. 16
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/PopoversDemo/PopoversDemoViewComponent.cs
  31. 17
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/ProgressBarsDemo/Default.cshtml
  32. 16
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/ProgressBarsDemo/ProgressBarsDemoViewComponent.cs
  33. 134
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/TablesDemo/Default.cshtml
  34. 16
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/TablesDemo/TablesDemoViewComponent.cs
  35. 63
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/TabsDemo/Default.cshtml
  36. 16
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/TabsDemo/TabsDemoViewComponent.cs
  37. 23
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/TooltipsDemo/Default.cshtml
  38. 16
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/TooltipsDemo/TooltipsDemoViewComponent.cs
  39. 6
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Auditing/AbpAuditActionFilter.cs
  40. 2
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Auditing/AbpAuditingMiddleware.cs
  41. 15
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingManager.cs
  42. 0
      framework/src/Volo.Abp.BackgroundJobs.Quartz/FodyWeavers.xml
  43. 0
      framework/src/Volo.Abp.BackgroundJobs.Quartz/FodyWeavers.xsd
  44. 22
      framework/src/Volo.Abp.BackgroundJobs.Quartz/Volo.Abp.BackgroundJobs.Quartz.csproj
  45. 18
      framework/src/Volo.Abp.BackgroundJobs.Quartz/Volo/Abp/BackgroundJobs/Quartz/AbpBackgroundJobsQuartzModule.cs
  46. 27
      framework/src/Volo.Abp.BackgroundJobs.Quartz/Volo/Abp/BackgroundJobs/Quartz/QuartzBackgroundJobManager.cs
  47. 36
      framework/src/Volo.Abp.BackgroundJobs.Quartz/Volo/Abp/BackgroundJobs/Quartz/QuartzJobExecutionAdapter.cs
  48. 0
      framework/src/Volo.Abp.BackgroundWorkers.Quartz/FodyWeavers.xml
  49. 0
      framework/src/Volo.Abp.BackgroundWorkers.Quartz/FodyWeavers.xsd
  50. 24
      framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo.Abp.BackgroundWorkers.Quartz.csproj
  51. 30
      framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/AbpBackgroundWorkersQuartzModule.cs
  52. 27
      framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/AbpQuartzConventionalRegistrar.cs
  53. 11
      framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/IQuartzBackgroundWorker.cs
  54. 14
      framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/QuartzBackgroundWorkerBase.cs
  55. 43
      framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/QuartzBackgroundWorkerManager.cs
  56. 30
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddModuleCommand.cs
  57. 82
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/GetSourceCommand.cs
  58. 19
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs
  59. 84
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/SourceCodeDownloadService.cs
  60. 42
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/AbpIoSourceCodeStore.cs
  61. 1
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ModuleProjectBuildPipelineBuilder.cs
  62. 13
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ProjectReferenceReplaceStep.cs
  63. 13
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ReplaceCommonPropsStep.cs
  64. 75
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ReplaceConfigureAwaitPropsStep.cs
  65. 3
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ISourceCodeStore.cs
  66. 2
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ModuleProjectBuilder.cs
  67. 11
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ProjectBuildArgs.cs
  68. 17
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateProjectBuilder.cs
  69. 9
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/DbContextFileBuilderConfigureAdder.cs
  70. 1
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/DerivedClassFinder.cs
  71. 9
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ModuleWithMastersInfo.cs
  72. 140
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NugetPackageToLocalReferenceConverter.cs
  73. 2
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ProjectNpmPackageAdder.cs
  74. 5
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ProjectNugetPackageAdder.cs
  75. 36
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionAbpVersionFinder.cs
  76. 117
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionFileModifier.cs
  77. 68
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs
  78. 20
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Utils/StreamHelper.cs
  79. 0
      framework/src/Volo.Abp.Http.Client.IdentityModel.Web/FodyWeavers.xml
  80. 0
      framework/src/Volo.Abp.Http.Client.IdentityModel.Web/FodyWeavers.xsd
  81. 27
      framework/src/Volo.Abp.Http.Client.IdentityModel.Web/Properties/launchSettings.json
  82. 23
      framework/src/Volo.Abp.Http.Client.IdentityModel.Web/Volo.Abp.Http.Client.IdentityModel.Web.csproj
  83. 12
      framework/src/Volo.Abp.Http.Client.IdentityModel.Web/Volo/Abp/Http/Client/IdentityModel/Web/AbpHttpClientIdentityModelWebModule.cs
  84. 48
      framework/src/Volo.Abp.Http.Client.IdentityModel.Web/Volo/Abp/Http/Client/IdentityModel/Web/HttpContextIdentityModelRemoteServiceHttpClientAuthenticator.cs
  85. 6
      framework/src/Volo.Abp.Http.Client.IdentityModel/Volo.Abp.Http.Client.IdentityModel.csproj
  86. 28
      framework/src/Volo.Abp.Http.Client.IdentityModel/Volo/Abp/Http/Client/IdentityModel/IdentityModelRemoteServiceHttpClientAuthenticator.cs
  87. 6
      framework/src/Volo.Abp.Http.Client/Volo.Abp.Http.Client.csproj
  88. 19
      framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/ApiDescriptionFinder.cs
  89. 2
      framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/AbpIdentityModelModule.cs
  90. 3
      framework/src/Volo.Abp.Quartz/FodyWeavers.xml
  91. 30
      framework/src/Volo.Abp.Quartz/FodyWeavers.xsd
  92. 25
      framework/src/Volo.Abp.Quartz/Volo.Abp.Quartz.csproj
  93. 41
      framework/src/Volo.Abp.Quartz/Volo/Abp/Quartz/AbpQuartzJobFactory.cs
  94. 34
      framework/src/Volo.Abp.Quartz/Volo/Abp/Quartz/AbpQuartzModule.cs
  95. 14
      framework/src/Volo.Abp.Quartz/Volo/Abp/Quartz/AbpQuartzPreOptions.cs
  96. 7
      framework/src/Volo.Abp.Security/System/Security/Principal/AbpClaimsIdentityExtensions.cs
  97. 1
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditTestController.cs
  98. 59
      framework/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/BasicThemeDemoMenuContributor.cs
  99. 8
      framework/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/Pages/Components/Alerts/Index.cshtml
  100. 12
      framework/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/Pages/Components/Alerts/Index.cshtml.cs

29
docs/en/CLI.md

@ -55,6 +55,7 @@ abp new Acme.BookStore
* `--no-ui`: Specifies to not include the UI. This makes possible to create service-only modules (a.k.a. microservices - without UI).
* `--output-folder` or `-o`: Specifies the output folder. Default value is the current directory.
* `--version` or `-v`: Specifies the ABP & template version. It can be a [release tag](https://github.com/abpframework/abp/releases) or a [branch name](https://github.com/abpframework/abp/branches). Uses the latest release if not specified. Most of the times, you will want to use the latest version.
* `--template-source` or `-ts`: Specifies a custom template source to use to build the project. Local and network sources can be used(Like `D\localTemplate` or `https://<your url>.zip`).
### add-package
@ -128,9 +129,35 @@ abp update [options]
* `--npm`: Only updates NPM packages.
* `--nuget`: Only updates NuGet packages.
### switch-to-preview
You can use this command to switch your project to latest preview version of the ABP framework packages.
Usage:
````bash
abp switch-to-preview [options]
````
#### Options
`--solution-path` or `-sp`: Specifies the solution (.sln) file path. If not specified, CLI tries to find a .sln file in the current directory.
### switch-to-stable
If you're using the ABP Framework preview packages, you can switch back to stable version using this command.
Usage:
````bash
abp switch-to-stable [options]
````
#### Options
`--solution-path` or `-sp`: Specifies the solution (.sln) file path. If not specified, CLI tries to find a .sln file in the current directory.
### login
Some features of the CLI requires to be logged in to abp.io platform. To login with your username write
Some features of the CLI requires to be logged in to abp.io platform. To login with your username write:
```bash
abp login <username>

7
docs/zh-Hans/CLI.md

@ -43,7 +43,7 @@ abp new Acme.BookStore
* `app` (default): [应用程序模板](Startup-Templates/Application.md). 其他选项:
* `--ui` 或者 `-u`: 指定ui框架.默认`mvc`框架.其他选项:
* `mvc`: ASP.NET Core MVC.此模板的其他选项:
* `--tiered`: 创建分层解决方案,Web和Http Api层在物理上是分开的.如果未指定会创建一个分层的解决方案,此解决方案没有那么复杂,适合大多数场景.
* `--tiered`: 创建分层解决方案,Web和Http Api层在物理上是分开的.如果未指定会创建一个分层的解决方案,此解决方案没有那么复杂,适合大多数场景.
* `angular`: Angular. 这个模板还有一些额外的选项:
* `--separate-identity-server`: 将Identity Server应用程序与API host应用程序分开. 如果未指定,则服务器端将只有一个端点.
* `none`: 无UI. 这个模板还有一些额外的选项:
@ -53,8 +53,9 @@ abp new Acme.BookStore
* `mongodb`: MongoDB.
* `module`: [Module template](Startup-Templates/Module.md). 其他选项:
* `--no-ui`: 不包含UI.仅创建服务模块(也称为微服务 - 没有UI).
* `--output-folder` 或者 `-o`: 指定输出文件夹,默认是当前目录.
* `--version` 或者 `-v`: 指定ABP和模板的版本.它可以是 [release tag](https://github.com/abpframework/abp/releases) 或者 [branch name](https://github.com/abpframework/abp/branches). 如果没有指定,则使用最新版本.大多数情况下,您会希望使用最新的版本.
* `--output-folder` 或者 `-o`: 指定输出文件夹,默认是当前目录.
* `--version` 或者 `-v`: 指定ABP和模板的版本.它可以是 [release tag](https://github.com/abpframework/abp/releases) 或者 [branch name](https://github.com/abpframework/abp/branches). 如果没有指定,则使用最新版本.大多数情况下,您会希望使用最新的版本.
* `--template-source` 或者 `-ts`: 指定自定义模板源用于生成项目,可以使用本地源和网络源(例如 `D\localTemplate``https://<your url>.zip`).
### add-package

39
framework/Volo.Abp.sln

@ -261,9 +261,19 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore.Serilog
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore.Serilog.Tests", "test\Volo.Abp.AspNetCore.Serilog.Tests\Volo.Abp.AspNetCore.Serilog.Tests.csproj", "{9CAA07ED-FE5C-4427-A6FA-6C6CB5B4CC62}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo", "src\Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo\Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.csproj", "{29E42ADB-85F8-44AE-A9B0-078F84C1B866}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Http.Client.IdentityModel.Web", "src\Volo.Abp.Http.Client.IdentityModel.Web\Volo.Abp.Http.Client.IdentityModel.Web.csproj", "{925AF101-2203-409C-9C3B-03917316858F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo", "test\Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo\Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo.csproj", "{0C498CF2-D052-4BF7-AD35-509A90F69707}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.BackgroundJobs.Quartz", "src\Volo.Abp.BackgroundJobs.Quartz\Volo.Abp.BackgroundJobs.Quartz.csproj", "{2307198B-5837-4F05-AA84-D6EC2A923D69}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Quartz", "src\Volo.Abp.Quartz\Volo.Abp.Quartz.csproj", "{9467418B-4A9B-4093-9B31-01A9DEF5B372}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.BackgroundWorkers.Quartz", "src\Volo.Abp.BackgroundWorkers.Quartz\Volo.Abp.BackgroundWorkers.Quartz.csproj", "{CD5770BB-2E0C-4B3C-80E0-21B8CC43DBA9}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo", "src\Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo\Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.csproj", "{29E42ADB-85F8-44AE-A9B0-078F84C1B866}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo", "test\Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo\Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo.csproj", "{0C498CF2-D052-4BF7-AD35-509A90F69707}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Http.Client.IdentityModel.Web.Tests", "test\Volo.Abp.Http.Client.IdentityModel.Web.Tests\Volo.Abp.Http.Client.IdentityModel.Web.Tests.csproj", "{E1963439-2BE5-4DB5-8438-2A9A792A1ADA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -779,6 +789,22 @@ Global
{9CAA07ED-FE5C-4427-A6FA-6C6CB5B4CC62}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9CAA07ED-FE5C-4427-A6FA-6C6CB5B4CC62}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9CAA07ED-FE5C-4427-A6FA-6C6CB5B4CC62}.Release|Any CPU.Build.0 = Release|Any CPU
{925AF101-2203-409C-9C3B-03917316858F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{925AF101-2203-409C-9C3B-03917316858F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{925AF101-2203-409C-9C3B-03917316858F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{925AF101-2203-409C-9C3B-03917316858F}.Release|Any CPU.Build.0 = Release|Any CPU
{2307198B-5837-4F05-AA84-D6EC2A923D69}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2307198B-5837-4F05-AA84-D6EC2A923D69}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2307198B-5837-4F05-AA84-D6EC2A923D69}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2307198B-5837-4F05-AA84-D6EC2A923D69}.Release|Any CPU.Build.0 = Release|Any CPU
{9467418B-4A9B-4093-9B31-01A9DEF5B372}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9467418B-4A9B-4093-9B31-01A9DEF5B372}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9467418B-4A9B-4093-9B31-01A9DEF5B372}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9467418B-4A9B-4093-9B31-01A9DEF5B372}.Release|Any CPU.Build.0 = Release|Any CPU
{CD5770BB-2E0C-4B3C-80E0-21B8CC43DBA9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CD5770BB-2E0C-4B3C-80E0-21B8CC43DBA9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CD5770BB-2E0C-4B3C-80E0-21B8CC43DBA9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CD5770BB-2E0C-4B3C-80E0-21B8CC43DBA9}.Release|Any CPU.Build.0 = Release|Any CPU
{29E42ADB-85F8-44AE-A9B0-078F84C1B866}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{29E42ADB-85F8-44AE-A9B0-078F84C1B866}.Debug|Any CPU.Build.0 = Debug|Any CPU
{29E42ADB-85F8-44AE-A9B0-078F84C1B866}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -787,6 +813,10 @@ Global
{0C498CF2-D052-4BF7-AD35-509A90F69707}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0C498CF2-D052-4BF7-AD35-509A90F69707}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0C498CF2-D052-4BF7-AD35-509A90F69707}.Release|Any CPU.Build.0 = Release|Any CPU
{E1963439-2BE5-4DB5-8438-2A9A792A1ADA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E1963439-2BE5-4DB5-8438-2A9A792A1ADA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E1963439-2BE5-4DB5-8438-2A9A792A1ADA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E1963439-2BE5-4DB5-8438-2A9A792A1ADA}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -919,8 +949,13 @@ Global
{E69182B3-350A-43F5-A935-5EBBEBECEF97} = {447C8A77-E5F0-4538-8687-7383196D04EA}
{3B801003-BE74-49ED-9749-DA5E99F45EBF} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{9CAA07ED-FE5C-4427-A6FA-6C6CB5B4CC62} = {447C8A77-E5F0-4538-8687-7383196D04EA}
{925AF101-2203-409C-9C3B-03917316858F} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{2307198B-5837-4F05-AA84-D6EC2A923D69} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{9467418B-4A9B-4093-9B31-01A9DEF5B372} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{CD5770BB-2E0C-4B3C-80E0-21B8CC43DBA9} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{29E42ADB-85F8-44AE-A9B0-078F84C1B866} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{0C498CF2-D052-4BF7-AD35-509A90F69707} = {447C8A77-E5F0-4538-8687-7383196D04EA}
{E1963439-2BE5-4DB5-8438-2A9A792A1ADA} = {447C8A77-E5F0-4538-8687-7383196D04EA}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5}

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

@ -47,7 +47,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
SetFormAttributes(context, output);
SetSubmitButton(context, output);
await SetSubmitButton(context, output);
}
protected virtual async Task ConvertToMvcForm(TagHelperContext context, TagHelperOutput output)
@ -107,14 +107,14 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
output.Content.SetHtmlContent(childContent);
}
protected virtual void SetSubmitButton(TagHelperContext context, TagHelperOutput output)
protected virtual async Task SetSubmitButton(TagHelperContext context, TagHelperOutput output)
{
if (!TagHelper.SubmitButton ?? true)
{
return;
}
var buttonHtml = ProcessSubmitButtonAndGetContentAsync(context, output);
var buttonHtml = await ProcessSubmitButtonAndGetContentAsync(context, output);
output.PostContent.SetHtmlContent(output.PostContent.GetContent() + buttonHtml);
}

16
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/AlertsDemo/AlertsDemoViewComponent.cs

@ -0,0 +1,16 @@
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.Widgets;
namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.Shared.Demos.AlertsDemo
{
[Widget]
public class AlertsDemoViewComponent : AbpViewComponent
{
public const string ViewPath = "/Views/Components/Themes/Shared/Demos/AlertsDemo/Default.cshtml";
public IViewComponentResult Invoke()
{
return View(ViewPath);
}
}
}

70
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/AlertsDemo/Default.cshtml

@ -0,0 +1,70 @@
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.Shared.Demos.AlertsDemo
<abp-component-demo-section title="Examples" view-path="@AlertsDemoViewComponent.ViewPath">
<abp-alert alert-type="Primary">
A simple primary alert—check it out!
</abp-alert>
<abp-alert alert-type="Secondary">
A simple secondary alert—check it out!
</abp-alert>
<abp-alert alert-type="Success">
A simple success alert—check it out!
</abp-alert>
<abp-alert alert-type="Danger">
A simple danger alert—check it out!
</abp-alert>
<abp-alert alert-type="Warning">
A simple warning alert—check it out!
</abp-alert>
<abp-alert alert-type="Info">
A simple info alert—check it out!
</abp-alert>
<abp-alert alert-type="Light">
A simple light alert—check it out!
</abp-alert>
<abp-alert alert-type="Dark">
A simple dark alert—check it out!
</abp-alert>
</abp-component-demo-section>
<abp-component-demo-section title="Link color" view-path="@AlertsDemoViewComponent.ViewPath">
<abp-alert alert-type="Primary">
A simple primary alert with <a abp-alert-link href="#">an example link</a>. Give it a click if you like.
</abp-alert>
<abp-alert alert-type="Secondary">
A simple secondary alert with <a abp-alert-link href="#">an example link</a>. Give it a click if you like.
</abp-alert>
<abp-alert alert-type="Success">
A simple success alert with <a abp-alert-link href="#">an example link</a>. Give it a click if you like.
</abp-alert>
<abp-alert alert-type="Danger">
A simple danger alert with <a abp-alert-link href="#">an example link</a>. Give it a click if you like.
</abp-alert>
<abp-alert alert-type="Warning">
A simple warning alert with <a abp-alert-link href="#">an example link</a>. Give it a click if you like.
</abp-alert>
<abp-alert alert-type="Info">
A simple info alert with <a abp-alert-link href="#">an example link</a>. Give it a click if you like.
</abp-alert>
<abp-alert alert-type="Light">
A simple light alert with <a abp-alert-link href="#">an example link</a>. Give it a click if you like.
</abp-alert>
<abp-alert alert-type="Dark">
A simple dark alert with <a abp-alert-link href="#">an example link</a>. Give it a click if you like.
</abp-alert>
</abp-component-demo-section>
<abp-component-demo-section title="Additional content" view-path="@AlertsDemoViewComponent.ViewPath">
<abp-alert alert-type="Success">
<h4>Well done!</h4>
<p>Aww yeah, you successfully read this important alert message. This example text is going to run a bit longer so that you can see how spacing within an alert works with this kind of content.</p>
<hr>
<p class="mb-0">Whenever you need to, be sure to use margin utilities to keep things nice and tidy.</p>
</abp-alert>
</abp-component-demo-section>
<abp-component-demo-section title="Dismissing" view-path="@AlertsDemoViewComponent.ViewPath">
<abp-alert alert-type="Warning" dismissible="true">
Holy guacamole! You should check in on some of those fields below.
</abp-alert>
</abp-component-demo-section>

16
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/BadgesDemo/BadgesDemoViewComponent.cs

@ -0,0 +1,16 @@
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.Widgets;
namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.Shared.Demos.BadgesDemo
{
[Widget]
public class BadgesDemoViewComponent : AbpViewComponent
{
public const string ViewPath = "/Views/Components/Themes/Shared/Demos/BadgesDemo/Default.cshtml";
public IViewComponentResult Invoke()
{
return View(ViewPath);
}
}
}

49
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/BadgesDemo/Default.cshtml

@ -0,0 +1,49 @@
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.Shared.Demos.BadgesDemo
<abp-component-demo-section title="Example" view-path="@BadgesDemoViewComponent.ViewPath">
<h1>Example heading <span abp-badge="Secondary">New</span></h1>
<h2>Example heading <span abp-badge="Secondary">New</span></h2>
<h3>Example heading <span abp-badge="Secondary">New</span></h3>
<h4>Example heading <span abp-badge="Secondary">New</span></h4>
<h5>Example heading <span abp-badge="Secondary">New</span></h5>
<h6>Example heading <span abp-badge="Secondary">New</span></h6>
</abp-component-demo-section>
<abp-component-demo-section title="Notifications" view-path="@BadgesDemoViewComponent.ViewPath">
<abp-button button-type="Primary">
Notifications <span abp-badge="Light">4</span>
</abp-button>
</abp-component-demo-section>
<abp-component-demo-section title="Contextual variations" view-path="@BadgesDemoViewComponent.ViewPath">
<span abp-badge="Primary">Primary</span>
<span abp-badge="Secondary">Secondary</span>
<span abp-badge="Success">Success</span>
<span abp-badge="Danger">Danger</span>
<span abp-badge="Warning">Warning</span>
<span abp-badge="Info">Info</span>
<span abp-badge="Light">Light</span>
<span abp-badge="Dark">Dark</span>
</abp-component-demo-section>
<abp-component-demo-section title="Pill badges" view-path="@BadgesDemoViewComponent.ViewPath">
<span abp-badge-pill="Primary">Primary</span>
<span abp-badge-pill="Secondary">Secondary</span>
<span abp-badge-pill="Success">Success</span>
<span abp-badge-pill="Danger">Danger</span>
<span abp-badge-pill="Warning">Warning</span>
<span abp-badge-pill="Info">Info</span>
<span abp-badge-pill="Light">Light</span>
<span abp-badge-pill="Dark">Dark</span>
</abp-component-demo-section>
<abp-component-demo-section title="Links" view-path="@BadgesDemoViewComponent.ViewPath">
<a href="#" abp-badge="Primary">Primary</a>
<a href="#" abp-badge="Secondary">Secondary</a>
<a href="#" abp-badge="Success">Success</a>
<a href="#" abp-badge="Danger">Danger</a>
<a href="#" abp-badge="Warning">Warning</a>
<a href="#" abp-badge="Info">Info</a>
<a href="#" abp-badge="Light">Light</a>
<a href="#" abp-badge="Dark">Dark</a>
</abp-component-demo-section>

16
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/BordersDemo/BordersDemoViewComponent.cs

@ -0,0 +1,16 @@
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.Widgets;
namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.Shared.Demos.BordersDemo
{
[Widget]
public class BordersDemoViewComponent : AbpViewComponent
{
public const string ViewPath = "/Views/Components/Themes/Shared/Demos/BordersDemo/Default.cshtml";
public IViewComponentResult Invoke()
{
return View(ViewPath);
}
}
}

46
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/BordersDemo/Default.cshtml

@ -0,0 +1,46 @@
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.Shared.Demos.BordersDemo
<abp-component-demo-section title="Additive" view-path="@BordersDemoViewComponent.ViewPath">
<span abp-border="Default"></span>
<span abp-border="Top"></span>
<span abp-border="Right"></span>
<span abp-border="Bottom"></span>
<span abp-border="Left"></span>
</abp-component-demo-section>
<abp-component-demo-section title="Subtractive" view-path="@BordersDemoViewComponent.ViewPath">
<span abp-border="_0"></span>
<span abp-border="Top_0"></span>
<span abp-border="Right_0"></span>
<span abp-border="Bottom_0"></span>
<span abp-border="Left_0"></span>
</abp-component-demo-section>
<abp-component-demo-section title="Border color" view-path="@BordersDemoViewComponent.ViewPath">
<span abp-border="Primary"></span>
<span abp-border="Secondary"></span>
<span abp-border="Success"></span>
<span abp-border="Danger"></span>
<span abp-border="Info"></span>
<span abp-border="Light"></span>
<span abp-border="Dark"></span>
<span abp-border="White"></span>
<br />
<span abp-border="Left_Primary"></span>
<span abp-border="Top_Secondary"></span>
<span abp-border="Right_Success"></span>
<span abp-border="Bottom_Danger"></span>
<span abp-border="Bottom_Warning"></span>
<span abp-border="Left_Info"></span>
<span abp-border="Top_Light"></span>
<span abp-border="Right_Dark"></span>
</abp-component-demo-section>
<abp-component-demo-section title="Border-radius" view-path="@BordersDemoViewComponent.ViewPath">
<span abp-border="Primary" abp-rounded="Default"></span>
<span abp-border="Primary" abp-rounded="_0"></span>
<span abp-border="Primary" abp-rounded="Top"></span>
<span abp-border="Primary" abp-rounded="Left"></span>
<span abp-border="Primary" abp-rounded="Bottom"></span>
<span abp-border="Primary" abp-rounded="Right"></span>
</abp-component-demo-section>

16
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/BreadcrumbsDemo/BreadcrumbsDemoViewComponent.cs

@ -0,0 +1,16 @@
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.Widgets;
namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.Shared.Demos.BreadcrumbsDemo
{
[Widget]
public class BreadcrumbsDemoViewComponent : AbpViewComponent
{
public const string ViewPath = "/Views/Components/Themes/Shared/Demos/BreadcrumbsDemo/Default.cshtml";
public IViewComponentResult Invoke()
{
return View(ViewPath);
}
}
}

18
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/BreadcrumbsDemo/Default.cshtml

@ -0,0 +1,18 @@
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.Shared.Demos.BreadcrumbsDemo
<abp-component-demo-section title="Example" view-path="@BreadcrumbsDemoViewComponent.ViewPath">
<abp-breadcrumb>
<abp-breadcrumb-item title="Home" />
</abp-breadcrumb>
<abp-breadcrumb>
<abp-breadcrumb-item href="#" title="Home" />
<abp-breadcrumb-item title="Library" />
</abp-breadcrumb>
<abp-breadcrumb>
<abp-breadcrumb-item href="#" title="Home" />
<abp-breadcrumb-item href="#" title="Library" />
<abp-breadcrumb-item title="Page" />
</abp-breadcrumb>
</abp-component-demo-section>

16
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/ButtonGroupsDemo/ButtonGroupsDemoViewComponent.cs

@ -0,0 +1,16 @@
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.Widgets;
namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.Shared.Demos.ButtonGroupsDemo
{
[Widget]
public class ButtonGroupsDemoViewComponent : AbpViewComponent
{
public const string ViewPath = "/Views/Components/Themes/Shared/Demos/ButtonGroupsDemo/Default.cshtml";
public IViewComponentResult Invoke()
{
return View(ViewPath);
}
}
}

68
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/ButtonGroupsDemo/Default.cshtml

@ -0,0 +1,68 @@
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.Shared.Demos.ButtonGroupsDemo
<abp-component-demo-section title="Basic example" view-path="@ButtonGroupsDemoViewComponent.ViewPath">
<abp-button-group>
<abp-button button-type="Secondary">Left</abp-button>
<abp-button button-type="Secondary">Middle</abp-button>
<abp-button button-type="Secondary">Right</abp-button>
</abp-button-group>
</abp-component-demo-section>
<abp-component-demo-section title="Button Toolbar" view-path="@ButtonGroupsDemoViewComponent.ViewPath">
<abp-button-toolbar>
<abp-button-group class="mr-2">
<abp-button button-type="Secondary">1</abp-button>
<abp-button button-type="Secondary">2</abp-button>
<abp-button button-type="Secondary">3</abp-button>
<abp-button button-type="Secondary">4</abp-button>
</abp-button-group>
<abp-button-group class="mr-2">
<abp-button button-type="Secondary">5</abp-button>
<abp-button button-type="Secondary">6</abp-button>
<abp-button button-type="Secondary">7</abp-button>
</abp-button-group>
<abp-button-group>
<abp-button button-type="Secondary">8</abp-button>
</abp-button-group>
</abp-button-toolbar>
</abp-component-demo-section>
<abp-component-demo-section title="Sizing" view-path="@ButtonGroupsDemoViewComponent.ViewPath">
<abp-button-group size="Large">
<abp-button button-type="Secondary">Left</abp-button>
<abp-button button-type="Secondary">Middle</abp-button>
<abp-button button-type="Secondary">Right</abp-button>
</abp-button-group>
<abp-button-group>
<abp-button button-type="Secondary">Left</abp-button>
<abp-button button-type="Secondary">Middle</abp-button>
<abp-button button-type="Secondary">Right</abp-button>
</abp-button-group>
<abp-button-group size="Small">
<abp-button button-type="Secondary">Left</abp-button>
<abp-button button-type="Secondary">Middle</abp-button>
<abp-button button-type="Secondary">Right</abp-button>
</abp-button-group>
</abp-component-demo-section>
<abp-component-demo-section title="Nesting" view-path="@ButtonGroupsDemoViewComponent.ViewPath">
<abp-button-group>
<abp-button button-type="Secondary">1</abp-button>
<abp-button button-type="Secondary">2</abp-button>
<abp-dropdown>
<abp-dropdown-button button-type="Secondary" text="Dropdown" />
<abp-dropdown-menu>
<abp-dropdown-item href="#"> Dropdown link </abp-dropdown-item>
<abp-dropdown-item href="#"> Dropdown link </abp-dropdown-item>
</abp-dropdown-menu>
</abp-dropdown>
</abp-button-group>
</abp-component-demo-section>
<abp-component-demo-section title="Vertical variation" view-path="@ButtonGroupsDemoViewComponent.ViewPath">
<abp-button-group direction="Vertical">
<abp-button button-type="Secondary">Left</abp-button>
<abp-button button-type="Secondary">Middle</abp-button>
<abp-button button-type="Secondary">Right</abp-button>
</abp-button-group>
</abp-component-demo-section>

16
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/CardsDemo/CardsDemoViewComponent.cs

@ -0,0 +1,16 @@
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.Widgets;
namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.Shared.Demos.CardsDemo
{
[Widget]
public class CardsDemoViewComponent : AbpViewComponent
{
public const string ViewPath = "/Views/Components/Themes/Shared/Demos/CardsDemo/Default.cshtml";
public IViewComponentResult Invoke()
{
return View(ViewPath);
}
}
}

156
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/CardsDemo/Default.cshtml

@ -0,0 +1,156 @@
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.Shared.Demos.CardsDemo
<abp-component-demo-section title="Example" view-path="@CardsDemoViewComponent.ViewPath">
<abp-card style="width: 18rem;">
<img abp-card-image="Top" src="~/imgs/demo/300x200.png" />
<abp-card-body>
<abp-card-title>Card Title</abp-card-title>
<abp-card-text>Some quick example text to build on the card title and make up the bulk of the card's content.</abp-card-text>
<a abp-button="Primary" href="#"> Go somewhere</a>
</abp-card-body>
</abp-card>
</abp-component-demo-section>
<abp-component-demo-section title="Titles, text, and links" view-path="@CardsDemoViewComponent.ViewPath">
<abp-card style="width: 18rem;">
<abp-card-body>
<abp-card-title>Card title</abp-card-title>
<abp-card-subtitle class="mb-2 text-muted">Card subtitle</abp-card-subtitle>
<abp-card-text>Some quick example text to build on the card title and make up the bulk of the card's content.</abp-card-text>
<a abp-card-link href="#">Card link</a>
<a abp-card-link href="#">Another link</a>
</abp-card-body>
</abp-card>
</abp-component-demo-section>
<abp-component-demo-section title="List groups" view-path="@CardsDemoViewComponent.ViewPath">
<abp-card style="width: 18rem;">
<abp-list-group flush="true">
<abp-list-group-item>Cras justo odio</abp-list-group-item>
<abp-list-group-item>Dapibus ac facilisis in</abp-list-group-item>
<abp-list-group-item>Vestibulum at eros</abp-list-group-item>
</abp-list-group>
</abp-card>
</abp-component-demo-section>
<abp-component-demo-section title="List Title" view-path="@CardsDemoViewComponent.ViewPath">
<abp-card style="width: 18rem;">
<abp-card-header>Featured</abp-card-header>
<abp-list-group flush="true">
<abp-list-group-item>Cras justo odio</abp-list-group-item>
<abp-list-group-item>Dapibus ac facilisis in</abp-list-group-item>
<abp-list-group-item>Vestibulum at eros</abp-list-group-item>
</abp-list-group>
</abp-card>
</abp-component-demo-section>
<abp-component-demo-section title="Kitchen sink" view-path="@CardsDemoViewComponent.ViewPath">
<abp-card style="width: 18rem;">
<img abp-card-image="Top" src="~/imgs/demo/300x200.png" />
<abp-card-body>
<abp-card-title>Card Title</abp-card-title><abp-card-text>Some quick example text to build on the card title and make up the bulk of the card's content.</abp-card-text>
</abp-card-body>
<abp-list-group flush="true">
<abp-list-group-item>Cras justo odio</abp-list-group-item>
<abp-list-group-item>Dapibus ac facilisis in</abp-list-group-item>
<abp-list-group-item>Vestibulum at eros</abp-list-group-item>
</abp-list-group>
<abp-card-body>
<a abp-card-link href="#">Card link</a>
<a abp-card-link href="#">Another link</a>
</abp-card-body>
</abp-card>
</abp-component-demo-section>
<abp-component-demo-section title="Header and footer" view-path="@CardsDemoViewComponent.ViewPath">
<abp-card style="width: 18rem;">
<abp-card-header>Featured</abp-card-header>
<abp-card-body>
<abp-card-title> Special title treatment</abp-card-title>
<abp-card-text>With supporting text below as a natural lead-in to additional content.</abp-card-text>
<a abp-button="Primary" href="#"> Go somewhere</a>
</abp-card-body>
</abp-card>
</abp-component-demo-section>
<abp-component-demo-section title="Quoate" view-path="@CardsDemoViewComponent.ViewPath">
<abp-card>
<abp-card-header>Quote</abp-card-header>
<abp-card-body>
<abp-blockquote>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.</p>
<footer>Someone famous in Source Title</footer>
</abp-blockquote>
</abp-card-body>
</abp-card>
</abp-component-demo-section>
<abp-component-demo-section title="Featured" view-path="@CardsDemoViewComponent.ViewPath">
<abp-card class="text-center">
<abp-card-header>Featured</abp-card-header>
<abp-card-body>
<abp-card-title> Special title treatment</abp-card-title>
<abp-card-text>With supporting text below as a natural lead-in to additional content.</abp-card-text>
<a abp-button="Primary" href="#"> Go somewhere</a>
</abp-card-body>
<abp-card-footer class="text-muted"> 2 days ago</abp-card-footer>
</abp-card>
</abp-component-demo-section>
<abp-component-demo-section title="Card Styles" view-path="@CardsDemoViewComponent.ViewPath">
<abp-card background="Primary" class="mb-3" style="max-width: 18rem;">
<abp-card-header>Featured</abp-card-header>
<abp-card-body>
<abp-card-title> Special title treatment</abp-card-title>
<abp-card-text>With supporting text below as a natural lead-in to additional content.</abp-card-text>
</abp-card-body>
</abp-card>
<abp-card background="Success" text-color="Danger" border="Dark" class="mb-3" style="max-width: 18rem;">
<abp-card-header>Featured</abp-card-header>
<abp-card-body>
<abp-card-title> Special title treatment</abp-card-title>
<abp-card-text>With supporting text below as a natural lead-in to additional content.</abp-card-text>
</abp-card-body>
</abp-card>
<abp-card background="Warning" text-color="Secondary" class="mb-3" style="max-width: 18rem;">
<abp-card-header>Featured</abp-card-header>
<abp-card-body>
<abp-card-title> Special title treatment</abp-card-title>
<abp-card-text>With supporting text below as a natural lead-in to additional content.</abp-card-text>
</abp-card-body>
</abp-card>
<abp-card background="Light" text-color="Dark" border="Success" class="mb-3" style="max-width: 18rem;">
<abp-card-header>Featured</abp-card-header>
<abp-card-body>
<abp-card-title> Special title treatment</abp-card-title>
<abp-card-text>With supporting text below as a natural lead-in to additional content.</abp-card-text>
</abp-card-body>
</abp-card>
<abp-card background="Dark" text-color="White" border="Danger" class="mb-3" style="max-width: 18rem;">
<abp-card-header>Featured</abp-card-header>
<abp-card-body>
<abp-card-title> Special title treatment</abp-card-title>
<abp-card-text>With supporting text below as a natural lead-in to additional content.</abp-card-text>
</abp-card-body>
</abp-card>
<abp-card background="Danger" class="mb-3" style="max-width: 18rem;">
<abp-card-header text-color="Primary">Featured</abp-card-header>
<abp-card-body>
<abp-card-title> Special title treatment</abp-card-title>
<abp-card-text>With supporting text below as a natural lead-in to additional content.</abp-card-text>
</abp-card-body>
</abp-card>
<abp-card background="Info" border="Danger" class="mb-3" style="max-width: 18rem;">
<abp-card-header>Featured</abp-card-header>
<abp-card-body text-color="Danger">
<abp-card-title> Special title treatment</abp-card-title>
<abp-card-text>With supporting text below as a natural lead-in to additional content.</abp-card-text>
</abp-card-body>
</abp-card>
</abp-component-demo-section>

16
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/CollapseDemo/CollapseDemoViewComponent.cs

@ -0,0 +1,16 @@
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.Widgets;
namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.Shared.Demos.CollapseDemo
{
[Widget]
public class CollapseDemoViewComponent : AbpViewComponent
{
public const string ViewPath = "/Views/Components/Themes/Shared/Demos/CollapseDemo/Default.cshtml";
public IViewComponentResult Invoke()
{
return View(ViewPath);
}
}
}

43
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/CollapseDemo/Default.cshtml

@ -0,0 +1,43 @@
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.Shared.Demos.CollapseDemo
<abp-component-demo-section title="Example" view-path="@CollapseDemoViewComponent.ViewPath">
<abp-button button-type="Primary" abp-collapse-id="collapseExample" text="Button with data-target" />
<a abp-button="Primary" abp-collapse-id="collapseExample"> Link with href </a>
<abp-collapse-body id="collapseExample">
Anim pariatur wolf moon tempor,,, sunt aliqua put a bird on it squid single-origin coffee nulla assumenda shoreditch et. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident. Ad vegan excepteur butcher vice lomo. Leggings occaecat craft beer farm-to-table, raw denim aesthetic synth nesciunt you probably haven't heard of them accusamus labore sustainable VHS.
</abp-collapse-body>
</abp-component-demo-section>
<abp-component-demo-section title="Multiple targets" view-path="@CollapseDemoViewComponent.ViewPath">
<a abp-button="Primary" abp-collapse-id="FirstCollapseExample"> Toggle first element </a>
<abp-button button-type="Primary" abp-collapse-id="SecondCollapseExample" text="Toggle second element" />
<abp-button button-type="Primary" abp-collapse-id="FirstCollapseExample SecondCollapseExample" text="Toggle both elements" />
<abp-row class="mt-3">
<abp-column size-sm="_6">
<abp-collapse-body id="FirstCollapseExample" multi="true">
Curabitur porta porttitor libero eu luctus. Praesent ultrices mattis commodo. Integer sodales massa risus, in molestie enim sagittis blandit
</abp-collapse-body>
</abp-column>
<abp-column size-sm="_6">
<abp-collapse-body id="SecondCollapseExample" multi="true">
Anim pariatur wolf moon tempor,,, sunt aliqua put a bird on it squid single-origin coffee nulla assumenda shoreditch et.
</abp-collapse-body>
</abp-column>
</abp-row>
</abp-component-demo-section>
<abp-component-demo-section title="Accordion example" view-path="@CollapseDemoViewComponent.ViewPath">
<abp-accordion>
<abp-accordion-item title="Collapsible Group Item #1">
Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry rtat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf moon tempor, sunt aliqua put a bird on it squid single-origin coffee nulla assumenda shoreditch et. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident. Ad vegan excepteur butcher vice lomo. Leggings occaecat craft beer farm-to-table, raw denim aesthetic synth nesciunt you probably haven't heard of them accusamus labore sustainable VHS.
</abp-accordion-item>
<abp-accordion-item title="Collapsible Group Item #2">
Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf moon officia aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf moon tempor, sunt aliqua put a bird on it squid single-origin coffee nulla assumenda shoreditch et. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident. Ad vegan excepteur butcher vice lomo. Leggings occaecat craft beer farm-to-table, raw denim aesthetic synth nesciunt you probably haven't heard of them accusamus labore sustainable VHS.
</abp-accordion-item>
<abp-accordion-item title="Collapsible Group Item #3">
Anim pariatur wolf moon tempor, sunt aliqua put a bird on it squid single-origin coffee nulla assumenda shoreditch et. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident. Ad vegan excepteur butcher vice lomo. Leggings occaecat craft beer farm-to-table, raw denim aesthetic synth nesciunt you probably haven't heard of them accusamus labore sustainable VHS.
</abp-accordion-item>
</abp-accordion>
</abp-component-demo-section>

171
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/DropdownsDemo/Default.cshtml

@ -0,0 +1,171 @@
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.Shared.Demos.DropdownsDemo
<abp-component-demo-section title="Single button" view-path="@DropdownsDemoViewComponent.ViewPath">
<abp-dropdown>
<abp-dropdown-button text="Dropdown button" />
<abp-dropdown-menu>
<abp-dropdown-item href="#">Action</abp-dropdown-item>
<abp-dropdown-item href="#">Another action</abp-dropdown-item>
<abp-dropdown-item href="#">Something else here</abp-dropdown-item>
</abp-dropdown-menu>
</abp-dropdown>
</abp-component-demo-section>
<abp-component-demo-section title="Single button 2" view-path="@DropdownsDemoViewComponent.ViewPath">
<abp-dropdown>
<abp-dropdown-button button-type="Secondary" link="true" text="Dropdown button" />
<abp-dropdown-menu>
<abp-dropdown-item href="#">Action</abp-dropdown-item>
<abp-dropdown-item href="#">Another action</abp-dropdown-item>
<abp-dropdown-item href="#">Something else here</abp-dropdown-item>
</abp-dropdown-menu>
</abp-dropdown>
</abp-component-demo-section>
<abp-component-demo-section title="Single button 3" view-path="@DropdownsDemoViewComponent.ViewPath">
<abp-dropdown>
<abp-dropdown-button button-type="Danger" text="Dropdown button" />
<abp-dropdown-menu>
<abp-dropdown-item href="#">Action</abp-dropdown-item>
<abp-dropdown-item href="#">Another action</abp-dropdown-item>
<abp-dropdown-item href="#">Something else here</abp-dropdown-item>
<abp-dropdown-divider />
<abp-dropdown-item href="#">Separated link</abp-dropdown-item>
</abp-dropdown-menu>
</abp-dropdown>
</abp-component-demo-section>
<abp-component-demo-section title="Split button" view-path="@DropdownsDemoViewComponent.ViewPath">
<abp-dropdown>
<abp-dropdown-button button-type="Danger" dropdown-style="Split" text="Dropdown button" />
<abp-dropdown-menu>
<abp-dropdown-item href="#">Action</abp-dropdown-item>
<abp-dropdown-item href="#">Another action</abp-dropdown-item>
<abp-dropdown-item href="#">Something else here</abp-dropdown-item>
<abp-dropdown-divider />
<abp-dropdown-item href="#">Separated link</abp-dropdown-item>
</abp-dropdown-menu>
</abp-dropdown>
</abp-component-demo-section>
<abp-component-demo-section title="Split button 2" view-path="@DropdownsDemoViewComponent.ViewPath">
<abp-dropdown>
<abp-dropdown-button size="Large" button-type="Secondary" text="Large button" />
<abp-dropdown-menu>
<abp-dropdown-item href="#">Action</abp-dropdown-item>
<abp-dropdown-item href="#">Another action</abp-dropdown-item>
<abp-dropdown-item href="#">Something else here</abp-dropdown-item>
<abp-dropdown-divider />
<abp-dropdown-item href="#">Separated link</abp-dropdown-item>
</abp-dropdown-menu>
</abp-dropdown><abp-dropdown>
<abp-dropdown-button size="Large" button-type="Secondary" dropdown-style="Split" text="Large split button" />
<abp-dropdown-menu>
<abp-dropdown-item href="#">Action</abp-dropdown-item>
<abp-dropdown-item href="#">Another action</abp-dropdown-item>
<abp-dropdown-item href="#">Something else here</abp-dropdown-item>
<abp-dropdown-divider />
<abp-dropdown-item href="#">Separated link</abp-dropdown-item>
</abp-dropdown-menu>
</abp-dropdown><abp-dropdown>
<abp-dropdown-button size="Small" button-type="Secondary" text="Small button" />
<abp-dropdown-menu>
<abp-dropdown-item href="#">Action</abp-dropdown-item>
<abp-dropdown-item href="#">Another action</abp-dropdown-item>
<abp-dropdown-item href="#">Something else here</abp-dropdown-item>
<abp-dropdown-divider />
<abp-dropdown-item href="#">Separated link</abp-dropdown-item>
</abp-dropdown-menu>
</abp-dropdown><abp-dropdown>
<abp-dropdown-button size="Small" button-type="Secondary" dropdown-style="Split" text="Small split button" />
<abp-dropdown-menu>
<abp-dropdown-item href="#">Action</abp-dropdown-item>
<abp-dropdown-item href="#">Another action</abp-dropdown-item>
<abp-dropdown-item href="#">Something else here</abp-dropdown-item>
<abp-dropdown-divider />
<abp-dropdown-item href="#">Separated link</abp-dropdown-item>
</abp-dropdown-menu>
</abp-dropdown>
</abp-component-demo-section>
<abp-component-demo-section title="Directions" view-path="@DropdownsDemoViewComponent.ViewPath">
<abp-dropdown direction="Up">
<abp-dropdown-button button-type="Secondary" text="Dropup" />
<abp-dropdown-menu>
<abp-dropdown-item href="#">Action</abp-dropdown-item>
<abp-dropdown-item href="#">Another action</abp-dropdown-item>
<abp-dropdown-item href="#">Something else here</abp-dropdown-item>
</abp-dropdown-menu>
</abp-dropdown><abp-dropdown direction="Right">
<abp-dropdown-button button-type="Secondary" text="dropright" />
<abp-dropdown-menu>
<abp-dropdown-item href="#">Action</abp-dropdown-item>
<abp-dropdown-item href="#">Another action</abp-dropdown-item>
<abp-dropdown-item href="#">Something else here</abp-dropdown-item>
</abp-dropdown-menu>
</abp-dropdown><abp-dropdown direction="Right">
<abp-dropdown-button button-type="Secondary" dropdown-style="Split" text="Split right" />
<abp-dropdown-menu>
<abp-dropdown-item href="#">Action</abp-dropdown-item>
<abp-dropdown-item href="#">Another action</abp-dropdown-item>
<abp-dropdown-item href="#">Something else here</abp-dropdown-item>
</abp-dropdown-menu>
</abp-dropdown>
</abp-component-demo-section>
<abp-component-demo-section title="Menu Items" view-path="@DropdownsDemoViewComponent.ViewPath">
<abp-dropdown>
<abp-dropdown-button button-type="Secondary" text="Dropdown" />
<abp-dropdown-menu>
<abp-dropdown-header>Dropdown Header</abp-dropdown-header>
<abp-dropdown-item href="#">Action</abp-dropdown-item>
<abp-dropdown-item active="true" href="#">Active action</abp-dropdown-item>
<abp-dropdown-item disabled="true" href="#">Disabled action</abp-dropdown-item>
<abp-dropdown-divider />
<abp-dropdown-item-text>Dropdown Item Text</abp-dropdown-item-text>
<abp-dropdown-item href="#">Something else here</abp-dropdown-item>
</abp-dropdown-menu>
</abp-dropdown>
</abp-component-demo-section>
<abp-component-demo-section title="Menu alignment" view-path="@DropdownsDemoViewComponent.ViewPath">
<abp-dropdown>
<abp-dropdown-button button-type="Secondary" text="Right-aligned" />
<abp-dropdown-menu align="Right">
<abp-dropdown-item href="#">Action</abp-dropdown-item>
<abp-dropdown-item active="true" href="#">Active action</abp-dropdown-item>
<abp-dropdown-item disabled="true" href="#">Disabled action</abp-dropdown-item>
</abp-dropdown-menu>
</abp-dropdown>
</abp-component-demo-section>
<abp-component-demo-section title="Custom Content" view-path="@DropdownsDemoViewComponent.ViewPath">
<abp-dropdown>
<abp-dropdown-button button-type="Secondary" text="Dropdown With Only Text" />
<abp-dropdown-menu class="p-4" style="max-width: 200px;">
<p>
Some example text that's free-flowing within the dropdown menu.
</p>
<p class="mb-0">
And this is more example text.
</p>
</abp-dropdown-menu>
</abp-dropdown>
</abp-component-demo-section>
<abp-component-demo-section title="With Form" view-path="@DropdownsDemoViewComponent.ViewPath">
<abp-dropdown>
<abp-dropdown-button button-type="Secondary" text="Dropdown With Form" />
<abp-dropdown-menu>
<form class="px-4 py-3">
<abp-input asp-for="EmailAddress"></abp-input>
<abp-input asp-for="Password"></abp-input>
<abp-input asp-for="RememberMe"></abp-input>
<abp-button button-type="Primary" text="Sign In" type="submit" />
</form>
<abp-dropdown-divider></abp-dropdown-divider>
<abp-dropdown-item href="#">New around here? Sign up</abp-dropdown-item>
<abp-dropdown-item href="#">Forgot password?</abp-dropdown-item>
</abp-dropdown-menu>
</abp-dropdown>
</abp-component-demo-section>

16
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/DropdownsDemo/DropdownsDemoViewComponent.cs

@ -0,0 +1,16 @@
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.Widgets;
namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.Shared.Demos.DropdownsDemo
{
[Widget]
public class DropdownsDemoViewComponent : AbpViewComponent
{
public const string ViewPath = "/Views/Components/Themes/Shared/Demos/DropdownsDemo/Default.cshtml";
public IViewComponentResult Invoke()
{
return View(ViewPath);
}
}
}

223
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/GridsDemo/Default.cshtml

@ -0,0 +1,223 @@
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.Shared.Demos.GridsDemo
<abp-component-demo-section title="Equal-width" view-path="@GridsDemoViewComponent.ViewPath">
<abp-container>
<abp-row>
<abp-column>1 of 2</abp-column>
<abp-column>2 of 2</abp-column>
</abp-row>
<abp-row>
<abp-column>1 of 3</abp-column>
<abp-column>2 of 3</abp-column>
<abp-column>3 of 3</abp-column>
</abp-row>
</abp-container>
</abp-component-demo-section>
<abp-component-demo-section title="Column Breaker" view-path="@GridsDemoViewComponent.ViewPath">
<abp-container>
<abp-row>
<abp-column>column</abp-column>
<abp-column>column</abp-column>
<abp-column-breaker />
<abp-column>column</abp-column>
<abp-column>column</abp-column>
</abp-row>
</abp-container>
</abp-component-demo-section>
<abp-component-demo-section title="Setting one column width" view-path="@GridsDemoViewComponent.ViewPath">
<abp-container>
<abp-row>
<abp-column>1 of 3</abp-column>
<abp-column size="_6">2 of 3 (wider)</abp-column>
<abp-column>3 of 3</abp-column>
</abp-row>
<abp-row>
<abp-column>1 of 3</abp-column>
<abp-column size="_5">2 of 3 (wider)</abp-column>
<abp-column>3 of 3</abp-column>
</abp-row>
</abp-container>
</abp-component-demo-section>
<abp-component-demo-section title="Variable width content" view-path="@GridsDemoViewComponent.ViewPath">
<abp-container>
<abp-row h-align="Center">
<abp-column size-lg="_2">1 of 3</abp-column>
<abp-column size-md="Auto">Variable width content</abp-column>
<abp-column size-lg="_2">3 of 3</abp-column>
</abp-row>
<abp-row>
<abp-column>1 of 3</abp-column>
<abp-column size-md="Auto">Variable width content</abp-column>
<abp-column size-lg="_2">3 of 3</abp-column>
</abp-row>
</abp-container>
</abp-component-demo-section>
<abp-component-demo-section title="Responsive classes" view-path="@GridsDemoViewComponent.ViewPath">
<abp-row>
<abp-column>col</abp-column>
<abp-column>col</abp-column>
<abp-column>col</abp-column>
<abp-column>col</abp-column>
</abp-row>
<abp-row>
<abp-column size="_8">col-8</abp-column>
<abp-column size="_4">col-4</abp-column>
</abp-row>
</abp-component-demo-section>
<abp-component-demo-section title="All breakpoints" view-path="@GridsDemoViewComponent.ViewPath">
<abp-row>
<abp-column size-sm="_8">col-sm-8</abp-column>
<abp-column size-sm="_4">col-sm-4</abp-column>
</abp-row>
<abp-row>
<abp-column size-sm="_">col-sm</abp-column>
<abp-column size-sm="_">col-sm</abp-column>
<abp-column size-sm="_">col-sm</abp-column>
<abp-column size-sm="_">col-sm</abp-column>
</abp-row>
</abp-component-demo-section>
<abp-component-demo-section title="Mix and match" view-path="@GridsDemoViewComponent.ViewPath">
<!-- Stack the columns on mobile by making one full-width and the other half-width -->
<abp-row>
<abp-column size="_12" size-md="_8">.col-12 .col-md-8</abp-column>
<abp-column size="_6" size-md="_4">.col-6 .col-md-4</abp-column>
</abp-row>
<!-- Columns start at 50% wide on mobile and bump up to 33.3% wide on desktop -->
<abp-row>
<abp-column size="_6" size-md="_4">.col-6 .col-md-4</abp-column>
<abp-column size="_6" size-md="_4">.col-6 .col-md-4</abp-column>
<abp-column size="_6" size-md="_4">.col-6 .col-md-4</abp-column>
</abp-row>
<!-- Columns are always 50% wide, on mobile and desktop -->
<abp-row>
<abp-column size="_6">.col-6</abp-column>
<abp-column size="_6">.col-6</abp-column>
</abp-row>
</abp-component-demo-section>
<abp-component-demo-section title="Vertical Alignment" view-path="@GridsDemoViewComponent.ViewPath">
<abp-container>
<abp-row v-align="Start">
<abp-column>column</abp-column>
<abp-column>column</abp-column>
<abp-column>column</abp-column>
</abp-row>
<abp-row v-align="Center">
<abp-column>column</abp-column>
<abp-column>column</abp-column>
<abp-column>column</abp-column>
</abp-row>
<abp-row v-align="End">
<abp-column>column</abp-column>
<abp-column>column</abp-column>
<abp-column>column</abp-column>
</abp-row>
</abp-container>
</abp-component-demo-section>
<abp-component-demo-section title="Vertical Alignment 2" view-path="@GridsDemoViewComponent.ViewPath">
<abp-container>
<abp-row v-align="Start">
<abp-column v-align="Start">column</abp-column>
<abp-column v-align="Center">column</abp-column>
<abp-column v-align="End">column</abp-column>
</abp-row>
</abp-container>
</abp-component-demo-section>
<abp-component-demo-section title="Horizontal alignment" view-path="@GridsDemoViewComponent.ViewPath">
<abp-container>
<abp-row h-align="Start">
<abp-column size="_4">One of two columns</abp-column>
<abp-column size="_4">One of two columns</abp-column>
</abp-row>
<abp-row h-align="Center">
<abp-column size="_4">One of two columns</abp-column>
<abp-column size="_4">One of two columns</abp-column>
</abp-row>
<abp-row h-align="End">
<abp-column size="_4">One of two columns</abp-column>
<abp-column size="_4">One of two columns</abp-column>
</abp-row>
<abp-row h-align="Around">
<abp-column size="_4">One of two columns</abp-column>
<abp-column size="_4">One of two columns</abp-column>
</abp-row>
<abp-row h-align="Between">
<abp-column size="_4">One of two columns</abp-column>
<abp-column size="_4">One of two columns</abp-column>
</abp-row>
</abp-container>
</abp-component-demo-section>
<abp-component-demo-section title="No gutters" view-path="@GridsDemoViewComponent.ViewPath">
<abp-row gutters="false">
<abp-column size="_8">One of two columns</abp-column>
<abp-column size="_4">One of two columns</abp-column>
</abp-row>
</abp-component-demo-section>
<abp-component-demo-section title="Column wrapping" view-path="@GridsDemoViewComponent.ViewPath">
<abp-row>
<abp-column size="_9">.col-9</abp-column>
<abp-column size="_4">.col-4<br>Since 9 + 4 = 13 &gt; 12, this 4-column-wide div gets wrapped onto a new line as one contiguous unit.</abp-column>
<abp-column size="_6">.col-6<br>Subsequent columns continue along the new line.s</abp-column>
</abp-row>
</abp-component-demo-section>
<abp-component-demo-section title="Reordering" view-path="@GridsDemoViewComponent.ViewPath">
<abp-container>
<abp-row>
<abp-column order="_12">First, but Last</abp-column>
<abp-column>Second, but unordered</abp-column>
<abp-column order="_6">Third, but Second</abp-column>
</abp-row>
</abp-container>
</abp-component-demo-section>
<abp-component-demo-section title="Reordering 2" view-path="@GridsDemoViewComponent.ViewPath">
<abp-container>
<abp-row>
<abp-column order="Last">First, but Last</abp-column>
<abp-column>Second, but unordered</abp-column>
<abp-column order="First">Third, but First</abp-column>
</abp-row>
</abp-container>
</abp-component-demo-section>
<abp-component-demo-section title="Offsetting columns" view-path="@GridsDemoViewComponent.ViewPath">
<abp-container>
<abp-row>
<abp-column size-md="_4">.col-md-4</abp-column>
<abp-column size-md="_4" offset-md="_4">.col-md-4 .offset-md-4</abp-column>
</abp-row>
<abp-row>
<abp-column size-md="_3" offset-md="_3">.col-md-3 .offset-md-3</abp-column>
<abp-column size-md="_3" offset-md="_3">.col-md-3 .offset-md-3</abp-column>
</abp-row>
<abp-row>
<abp-column size-md="_6" offset-md="_3">.col-md-6 .offset-md-3</abp-column>
</abp-row>
</abp-container>
</abp-component-demo-section>
<abp-component-demo-section title="Offsetting columns 2" view-path="@GridsDemoViewComponent.ViewPath">
<abp-container>
<abp-row>
<abp-column size-sm="_5" size-md="_6">.col-sm-5 .col-md-6</abp-column>
<abp-column size-sm="_5" offset-sm="_2" size-md="_6" offset-md="_">.col-sm-5 .offset-sm-2 .col-md-6 .offset-md-0</abp-column>
</abp-row>
<abp-row>
<abp-column size-sm="_6" size-md="_5" size-lg="_6">col-sm-6 .col-md-5 .col-lg-6</abp-column>
<abp-column size-sm="_6" size-md="_5" offset-md="_2" size-lg="_6" offset-lg="_">.col-sm-6 .col-md-5 .offset-md-2 .col-lg-6 .offset-lg-0</abp-column>
</abp-row>
</abp-container>
</abp-component-demo-section>

16
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/GridsDemo/GridsDemoViewComponent.cs

@ -0,0 +1,16 @@
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.Widgets;
namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.Shared.Demos.GridsDemo
{
[Widget]
public class GridsDemoViewComponent : AbpViewComponent
{
public const string ViewPath = "/Views/Components/Themes/Shared/Demos/GridsDemo/Default.cshtml";
public IViewComponentResult Invoke()
{
return View(ViewPath);
}
}
}

82
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/ListGroupsDemo/Default.cshtml

@ -0,0 +1,82 @@
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.Shared.Demos.ListGroupsDemo
<abp-component-demo-section title="Basic example" view-path="@ListGroupsDemoViewComponent.ViewPath">
<abp-list-group>
<abp-list-group-item>Cras justo odio</abp-list-group-item>
<abp-list-group-item>Dapibus ac facilisis in</abp-list-group-item>
<abp-list-group-item>Morbi leo risus</abp-list-group-item>
<abp-list-group-item>Vestibulum at eros</abp-list-group-item>
</abp-list-group>
</abp-component-demo-section>
<abp-component-demo-section title="Active & disabled items" view-path="@ListGroupsDemoViewComponent.ViewPath">
<abp-list-group>
<abp-list-group-item>Cras justo odio</abp-list-group-item>
<abp-list-group-item active="true">Dapibus ac facilisis in</abp-list-group-item>
<abp-list-group-item>Morbi leo risus</abp-list-group-item>
<abp-list-group-item disabled="true">Vestibulum at eros</abp-list-group-item>
</abp-list-group>
</abp-component-demo-section>
<abp-component-demo-section title="Links and buttons" view-path="@ListGroupsDemoViewComponent.ViewPath">
<abp-list-group>
<abp-list-group-item href="#" active="true">Cras justo odio</abp-list-group-item>
<abp-list-group-item href="#">Dapibus ac facilisis in</abp-list-group-item>
<abp-list-group-item href="#">Morbi leo risus</abp-list-group-item>
<abp-list-group-item href="#" disabled="true">Vestibulum at eros</abp-list-group-item>
</abp-list-group>
</abp-component-demo-section>
<abp-component-demo-section title="Links and buttons 2" view-path="@ListGroupsDemoViewComponent.ViewPath">
<abp-list-group>
<abp-list-group-item href="#" active="true">Cras justo odio</abp-list-group-item>
<abp-list-group-item href="#">Dapibus ac facilisis in</abp-list-group-item>
<abp-list-group-item href="#">Morbi leo risus</abp-list-group-item>
<abp-list-group-item href="#" disabled="true">Vestibulum at eros</abp-list-group-item>
</abp-list-group>
</abp-component-demo-section>
<abp-component-demo-section title="Flush" view-path="@ListGroupsDemoViewComponent.ViewPath">
<abp-list-group flush="true">
<abp-list-group-item>Cras justo odio</abp-list-group-item>
<abp-list-group-item>Dapibus ac facilisis in</abp-list-group-item>
<abp-list-group-item>Morbi leo risus</abp-list-group-item>
<abp-list-group-item>Vestibulum at eros</abp-list-group-item>
</abp-list-group>
</abp-component-demo-section>
<abp-component-demo-section title="Contextual classes" view-path="@ListGroupsDemoViewComponent.ViewPath">
<abp-list-group>
<abp-list-group-item>Cras justo odio</abp-list-group-item>
<abp-list-group-item type="Primary">A simple Primary list group item</abp-list-group-item>
<abp-list-group-item type="Secondary">A simple Secondary list group item</abp-list-group-item>
<abp-list-group-item type="Success">A simple Success list group item</abp-list-group-item>
<abp-list-group-item type="Danger">A simple Danger list group item</abp-list-group-item>
<abp-list-group-item type="Warning">A simple Warning list group item</abp-list-group-item>
<abp-list-group-item type="Info">A simple Info list group item</abp-list-group-item>
<abp-list-group-item type="Light">A simple Light list group item</abp-list-group-item>
<abp-list-group-item type="Dark">A simple Dark list group item</abp-list-group-item>
</abp-list-group>
</abp-component-demo-section>
<abp-component-demo-section title="Contextual classes 2" view-path="@ListGroupsDemoViewComponent.ViewPath">
<abp-list-group>
<abp-list-group-item href="#">Cras justo odio</abp-list-group-item>
<abp-list-group-item href="#" type="Primary">A simple Primary list group item</abp-list-group-item>
<abp-list-group-item href="#" type="Secondary">A simple Secondary list group item</abp-list-group-item>
<abp-list-group-item href="#" type="Success">A simple Success list group item</abp-list-group-item>
<abp-list-group-item href="#" type="Danger">A simple Danger list group item</abp-list-group-item>
<abp-list-group-item href="#" type="Warning">A simple Warning list group item</abp-list-group-item>
<abp-list-group-item href="#" type="Info">A simple Info list group item</abp-list-group-item>
<abp-list-group-item href="#" type="Light">A simple Light list group item</abp-list-group-item>
<abp-list-group-item href="#" type="Dark">A simple Dark list group item</abp-list-group-item>
</abp-list-group>
</abp-component-demo-section>
<abp-component-demo-section title="With badges" view-path="@ListGroupsDemoViewComponent.ViewPath">
<abp-list-group>
<abp-list-group-item>Cras justo odio <span abp-badge-pill="Primary">14</span></abp-list-group-item>
<abp-list-group-item>Dapibus ac facilisis in <span abp-badge-pill="Primary">2</span></abp-list-group-item>
<abp-list-group-item>Morbi leo risus <span abp-badge-pill="Primary">1</span></abp-list-group-item>
</abp-list-group>
</abp-component-demo-section>

16
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/ListGroupsDemo/ListGroupsDemoViewComponent.cs

@ -0,0 +1,16 @@
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.Widgets;
namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.Shared.Demos.ListGroupsDemo
{
[Widget]
public class ListGroupsDemoViewComponent : AbpViewComponent
{
public const string ViewPath = "/Views/Components/Themes/Shared/Demos/ListGroupsDemo/Default.cshtml";
public IViewComponentResult Invoke()
{
return View(ViewPath);
}
}
}

15
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/ModalsDemo/Default.cshtml

@ -0,0 +1,15 @@
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.Shared.Demos.ModalsDemo
@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal
<abp-component-demo-section title="Example" view-path="@ModalsDemoViewComponent.ViewPath">
<abp-button button-type="Primary" data-toggle="modal" data-target="#myModal">Launch modal</abp-button>
<abp-modal centered="true" size="Large" id="myModal">
<abp-modal-header title="Modal title"></abp-modal-header>
<abp-modal-body>
Woohoo, you're reading this text in a modal!
</abp-modal-body>
<abp-modal-footer buttons="@(AbpModalButtons.Save|AbpModalButtons.Close)"></abp-modal-footer>
</abp-modal>
</abp-component-demo-section>

16
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/ModalsDemo/ModalsDemoViewComponent.cs

@ -0,0 +1,16 @@
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.Widgets;
namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.Shared.Demos.ModalsDemo
{
[Widget]
public class ModalsDemoViewComponent : AbpViewComponent
{
public const string ViewPath = "/Views/Components/Themes/Shared/Demos/ModalsDemo/Default.cshtml";
public IViewComponentResult Invoke()
{
return View(ViewPath);
}
}
}

53
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/NavsDemo/Default.cshtml

@ -0,0 +1,53 @@
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.Shared.Demos.NavsDemo
<abp-component-demo-section title="Base nav" view-path="@NavsDemoViewComponent.ViewPath">
<abp-nav nav-style="Pill" align="Center">
<abp-nav-item>
<a abp-nav-link active="true" href="#">Active</a>
</abp-nav-item>
<abp-nav-item>
<a abp-nav-link href="#">Longer nav link</a>
</abp-nav-item>
<abp-nav-item>
<a abp-nav-link href="#">link</a>
</abp-nav-item>
<abp-nav-item>
<a abp-nav-link disabled="true" href="#">disabled</a>
</abp-nav-item>
</abp-nav>
</abp-component-demo-section>
<abp-component-demo-section title="Base nav 2" view-path="@NavsDemoViewComponent.ViewPath">
<abp-nav-bar size="Lg" navbar-style="Dark_Warning">
<a abp-navbar-brand href="#">Navbar</a>
<abp-navbar-toggle>
<abp-navbar-nav>
<abp-nav-item active="true">
<a abp-nav-link href="#">Home <span class="sr-only">(current)</span></a>
</abp-nav-item>
<abp-nav-item>
<a abp-nav-link href="#">Link</a>
</abp-nav-item>
<abp-nav-item dropdown="true">
<abp-dropdown>
<abp-dropdown-button nav-link="true" text="Dropdown" />
<abp-dropdown-menu>
<abp-dropdown-header>Dropdown header</abp-dropdown-header>
<abp-dropdown-item href="#" active="true">Action</abp-dropdown-item>
<abp-dropdown-item href="#" disabled="true">Another disabled action</abp-dropdown-item>
<abp-dropdown-item href="#">Something else here</abp-dropdown-item>
<abp-dropdown-divider />
<abp-dropdown-item href="#">Separated link</abp-dropdown-item>
</abp-dropdown-menu>
</abp-dropdown>
</abp-nav-item>
<abp-nav-item>
<a abp-nav-link disabled="true" href="#">Disabled</a>
</abp-nav-item>
</abp-navbar-nav>
<span abp-navbar-text>
Sample Text
</span>
</abp-navbar-toggle>
</abp-nav-bar>
</abp-component-demo-section>

16
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/NavsDemo/NavsDemoViewComponent.cs

@ -0,0 +1,16 @@
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.Widgets;
namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.Shared.Demos.NavsDemo
{
[Widget]
public class NavsDemoViewComponent : AbpViewComponent
{
public const string ViewPath = "/Views/Components/Themes/Shared/Demos/NavsDemo/Default.cshtml";
public IViewComponentResult Invoke()
{
return View(ViewPath);
}
}
}

16
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/PopoversDemo/Default.cshtml

@ -0,0 +1,16 @@
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.Shared.Demos.PopoversDemo
<abp-component-demo-section title="Example" view-path="@PopoversDemoViewComponent.ViewPath">
<abp-button abp-popover="Hi, i'm popover content!">
Popover Default
</abp-button>
<abp-button abp-popover-top="Hi, i'm popover content!" title="Popover Title">
Popover With Title
</abp-button>
<abp-button abp-popover-right="Hi, i'm popover content!" title="Popover Title" dismissible="true">
Dismissible Popover
</abp-button>
<abp-button abp-popover-left="Hi, i'm popover content!" title="Popover Title" disabled="true">
Disabled Popover
</abp-button>
</abp-component-demo-section>

16
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/PopoversDemo/PopoversDemoViewComponent.cs

@ -0,0 +1,16 @@
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.Widgets;
namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.Shared.Demos.PopoversDemo
{
[Widget]
public class PopoversDemoViewComponent : AbpViewComponent
{
public const string ViewPath = "/Views/Components/Themes/Shared/Demos/PopoversDemo/Default.cshtml";
public IViewComponentResult Invoke()
{
return View(ViewPath);
}
}
}

17
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/ProgressBarsDemo/Default.cshtml

@ -0,0 +1,17 @@
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.Shared.Demos.ProgressBarsDemo
<abp-component-demo-section title="Example" view-path="@ProgressBarsDemoViewComponent.ViewPath">
<abp-progress-bar value="70" />
<abp-progress-bar type="Warning" value="25"> %25 </abp-progress-bar>
<abp-progress-bar type="Success" value="40" strip="true" />
<abp-progress-bar type="Dark" value="10" min-value="5" max-value="15" strip="true"> %50 </abp-progress-bar>
<abp-progress-group>
<abp-progress-part type="Success" value="25" />
<abp-progress-part type="Danger" value="10" strip="true"> %10 </abp-progress-part>
<abp-progress-part type="Primary" value="50" animation="true" strip="true" />
</abp-progress-group>
</abp-component-demo-section>

16
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/ProgressBarsDemo/ProgressBarsDemoViewComponent.cs

@ -0,0 +1,16 @@
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.Widgets;
namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.Shared.Demos.ProgressBarsDemo
{
[Widget]
public class ProgressBarsDemoViewComponent : AbpViewComponent
{
public const string ViewPath = "/Views/Components/Themes/Shared/Demos/ProgressBarsDemo/Default.cshtml";
public IViewComponentResult Invoke()
{
return View(ViewPath);
}
}
}

134
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/TablesDemo/Default.cshtml

@ -0,0 +1,134 @@
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.Shared.Demos.TablesDemo
<abp-component-demo-section title="Example 1" view-path="@TablesDemoViewComponent.ViewPath">
<abp-table hoverable-rows="true" responsive-sm="true">
<thead>
<tr>
<th scope="Column">#</th>
<th scope="Column">First</th>
<th scope="Column">Last</th>
<th scope="Column">Handle</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="Row">1</th>
<td>Mark</td>
<td>Otto</td>
<td table-style="Danger">mdo</td>
</tr>
<tr table-style="Warning">
<th scope="Row">2</th>
<td>Jacob</td>
<td>Thornton</td>
<td>fat</td>
</tr>
<tr>
<th scope="Row">3</th>
<td table-style="Success">Larry</td>
<td>the Bird</td>
<td>twitter</td>
</tr>
</tbody>
</abp-table>
</abp-component-demo-section>
<abp-component-demo-section title="Example 2" view-path="@TablesDemoViewComponent.ViewPath">
<abp-table small="true" striped-rows="true" border-style="Bordered">
<thead Theme="Dark">
<tr>
<th scope="Column">#</th>
<th scope="Column">First</th>
<th scope="Column">Last</th>
<th scope="Column">Handle</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="Row">1</th>
<td>Mark</td>
<td>Otto</td>
<td>mdo</td>
</tr>
<tr>
<th scope="Row">2</th>
<td>Jacob</td>
<td>Thornton</td>
<td>fat</td>
</tr>
<tr>
<th scope="Row">3</th>
<td>Larry</td>
<td>the Bird</td>
<td>twitter</td>
</tr>
</tbody>
</abp-table>
</abp-component-demo-section>
<abp-component-demo-section title="Example 3" view-path="@TablesDemoViewComponent.ViewPath">
<abp-table striped-rows="true" dark-theme="true">
<caption>List of users</caption>
<thead>
<tr>
<th scope="Column">#</th>
<th scope="Column">First</th>
<th scope="Column">Last</th>
<th scope="Column">Handle</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="Row">1</th>
<td>Mark</td>
<td>Otto</td>
<td>mdo</td>
</tr>
<tr>
<th scope="Row">2</th>
<td>Jacob</td>
<td>Thornton</td>
<td>fat</td>
</tr>
<tr>
<th scope="Row">3</th>
<td>Larry</td>
<td>the Bird</td>
<td>twitter</td>
</tr>
</tbody>
</abp-table>
</abp-component-demo-section>
<abp-component-demo-section title="Example 4" view-path="@TablesDemoViewComponent.ViewPath">
<abp-table border-style="Borderless">
<thead>
<tr>
<th scope="Column">#</th>
<th scope="Column">First</th>
<th scope="Column">Last</th>
<th scope="Column">Handle</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="Row">1</th>
<td>Mark</td>
<td>Otto</td>
<td>mdo</td>
</tr>
<tr>
<th scope="Row">2</th>
<td>Jacob</td>
<td>Thornton</td>
<td>fat</td>
</tr>
<tr>
<th scope="Row">3</th>
<td>Larry</td>
<td>the Bird</td>
<td>twitter</td>
</tr>
</tbody>
</abp-table>
</abp-component-demo-section>

16
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/TablesDemo/TablesDemoViewComponent.cs

@ -0,0 +1,16 @@
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.Widgets;
namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.Shared.Demos.TablesDemo
{
[Widget]
public class TablesDemoViewComponent : AbpViewComponent
{
public const string ViewPath = "/Views/Components/Themes/Shared/Demos/TablesDemo/Default.cshtml";
public IViewComponentResult Invoke()
{
return View(ViewPath);
}
}
}

63
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/TabsDemo/Default.cshtml

@ -0,0 +1,63 @@
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.Shared.Demos.TabsDemo
<abp-component-demo-section title="Example" view-path="@TabsDemoViewComponent.ViewPath">
<abp-tabs>
<abp-tab title="Home">
Content_Home
</abp-tab>
<abp-tab-link title="Link" href="#" />
<abp-tab title="profile">
Content_Profile
</abp-tab>
<abp-tab-dropdown title="Contact" name="ContactDropdown">
<abp-tab title="Contact 1" parent-dropdown-name="ContactDropdown">
Content_1_Content
</abp-tab>
<abp-tab title="Contact 2" parent-dropdown-name="ContactDropdown">
Content_2_Content
</abp-tab>
</abp-tab-dropdown>
</abp-tabs>
</abp-component-demo-section>
<abp-component-demo-section title="Tab attributes" view-path="@TabsDemoViewComponent.ViewPath">
<abp-tabs>
<abp-tab name="nav-home" title="Home">
Content_Home
</abp-tab>
<abp-tab name="nav-profile" active="true" title="profile">
Content_Profile
</abp-tab>
<abp-tab name="nav-contact" title="Contact">
Content_Contact
</abp-tab>
</abp-tabs>
</abp-component-demo-section>
<abp-component-demo-section title="Pill Example" view-path="@TabsDemoViewComponent.ViewPath">
<abp-tabs tab-style="Pill">
<abp-tab title="Home">
Content_Home
</abp-tab>
<abp-tab title="profile">
Content_Profile
</abp-tab>
<abp-tab title="Contact">
Content_Contact
</abp-tab>
</abp-tabs>
</abp-component-demo-section>
<abp-component-demo-section title="Vertical Example" view-path="@TabsDemoViewComponent.ViewPath">
<abp-tabs tab-style="PillVertical" vertical-header-size="_2">
<abp-tab active="true" title="Home">
Content_Home
</abp-tab>
<abp-tab title="profile">
Content_Profile
</abp-tab>
<abp-tab title="Contact">
Content_Contact
</abp-tab>
</abp-tabs>
</abp-component-demo-section>

16
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/TabsDemo/TabsDemoViewComponent.cs

@ -0,0 +1,16 @@
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.Widgets;
namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.Shared.Demos.TabsDemo
{
[Widget]
public class TabsDemoViewComponent : AbpViewComponent
{
public const string ViewPath = "/Views/Components/Themes/Shared/Demos/TabsDemo/Default.cshtml";
public IViewComponentResult Invoke()
{
return View(ViewPath);
}
}
}

23
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/TooltipsDemo/Default.cshtml

@ -0,0 +1,23 @@
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.Shared.Demos.TooltipsDemo
<abp-component-demo-section title="Example" view-path="@TooltipsDemoViewComponent.ViewPath">
<abp-button abp-tooltip="Tooltip">
Tooltip Default
</abp-button>
<abp-button abp-tooltip-top="Tooltip">
Tooltip on top
</abp-button>
<abp-button abp-tooltip-right="Tooltip">
Tooltip on right
</abp-button>
<abp-button abp-tooltip-bottom="Tooltip">
Tooltip on bottom
</abp-button>
<abp-button disabled="true" abp-tooltip="Tooltip">
Disabled button Tooltip
</abp-button>
</abp-component-demo-section>

16
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/TooltipsDemo/TooltipsDemoViewComponent.cs

@ -0,0 +1,16 @@
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.Widgets;
namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.Shared.Demos.TooltipsDemo
{
[Widget]
public class TooltipsDemoViewComponent : AbpViewComponent
{
public const string ViewPath = "/Views/Components/Themes/Shared/Demos/TooltipsDemo/Default.cshtml";
public IViewComponentResult Invoke()
{
return View(ViewPath);
}
}
}

6
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Auditing/AbpAuditActionFilter.cs

@ -84,12 +84,6 @@ namespace Volo.Abp.AspNetCore.Mvc.Auditing
return false;
}
//TODO: This is partially duplication of AuditHelper.ShouldSaveAudit method. Check why it does not work for controllers
if (!AuditingInterceptorRegistrar.ShouldAuditTypeByDefault(context.Controller.GetType()))
{
return false;
}
auditLog = auditLogScope.Log;
auditLogAction = _auditingHelper.CreateAuditLogAction(
auditLog,

2
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Auditing/AbpAuditingMiddleware.cs

@ -1,4 +1,4 @@
using System;
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;

15
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingManager.cs

@ -114,20 +114,7 @@ namespace Volo.Abp.Auditing
{
BeforeSave(saveHandle);
if (ShouldSave(saveHandle.AuditLog))
{
await _auditingStore.SaveAsync(saveHandle.AuditLog);
}
}
protected bool ShouldSave(AuditLogInfo auditLog)
{
if (!auditLog.Actions.Any() && !auditLog.EntityChanges.Any())
{
return false;
}
return true;
await _auditingStore.SaveAsync(saveHandle.AuditLog);
}
protected class DisposableSaveHandle : IAuditLogSaveHandle

0
modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.HangFire/FodyWeavers.xml → framework/src/Volo.Abp.BackgroundJobs.Quartz/FodyWeavers.xml

0
modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.HangFire/FodyWeavers.xsd → framework/src/Volo.Abp.BackgroundJobs.Quartz/FodyWeavers.xsd

22
framework/src/Volo.Abp.BackgroundJobs.Quartz/Volo.Abp.BackgroundJobs.Quartz.csproj

@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Abp.BackgroundJobs.Quartz</AssemblyName>
<PackageId>Volo.Abp.BackgroundJobs.Quartz</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.BackgroundJobs.Abstractions\Volo.Abp.BackgroundJobs.Abstractions.csproj" />
<ProjectReference Include="..\Volo.Abp.Quartz\Volo.Abp.Quartz.csproj" />
</ItemGroup>
</Project>

18
framework/src/Volo.Abp.BackgroundJobs.Quartz/Volo/Abp/BackgroundJobs/Quartz/AbpBackgroundJobsQuartzModule.cs

@ -0,0 +1,18 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Modularity;
using Volo.Abp.Quartz;
namespace Volo.Abp.BackgroundJobs.Quartz
{
[DependsOn(
typeof(AbpBackgroundJobsAbstractionsModule),
typeof(AbpQuartzModule)
)]
public class AbpBackgroundJobsQuartzModule :AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddTransient(typeof(QuartzJobExecutionAdapter<>));
}
}
}

27
framework/src/Volo.Abp.BackgroundJobs.Quartz/Volo/Abp/BackgroundJobs/Quartz/QuartzBackgroundJobManager.cs

@ -0,0 +1,27 @@
using System;
using System.Threading.Tasks;
using Quartz;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.BackgroundJobs.Quartz
{
[Dependency(ReplaceServices = true)]
public class QuartzBackgroundJobManager : IBackgroundJobManager, ITransientDependency
{
private readonly IScheduler _scheduler;
public QuartzBackgroundJobManager(IScheduler scheduler)
{
_scheduler = scheduler;
}
public async Task<string> EnqueueAsync<TArgs>(TArgs args, BackgroundJobPriority priority = BackgroundJobPriority.Normal,
TimeSpan? delay = null)
{
var jobDetail = JobBuilder.Create<QuartzJobExecutionAdapter<TArgs>>().SetJobData(new JobDataMap { { nameof(TArgs), args } }).Build();
var trigger = !delay.HasValue ? TriggerBuilder.Create().StartNow().Build() : TriggerBuilder.Create().StartAt(new DateTimeOffset(DateTime.Now.Add(delay.Value))).Build();
await _scheduler.ScheduleJob(jobDetail, trigger);
return jobDetail.Key.ToString();
}
}
}

36
framework/src/Volo.Abp.BackgroundJobs.Quartz/Volo/Abp/BackgroundJobs/Quartz/QuartzJobExecutionAdapter.cs

@ -0,0 +1,36 @@
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Quartz;
namespace Volo.Abp.BackgroundJobs.Quartz
{
public class QuartzJobExecutionAdapter<TArgs> : IJob
{
protected AbpBackgroundJobOptions Options { get; }
protected IServiceScopeFactory ServiceScopeFactory { get; }
protected IBackgroundJobExecuter JobExecuter { get; }
public QuartzJobExecutionAdapter(
IOptions<AbpBackgroundJobOptions> options,
IBackgroundJobExecuter jobExecuter,
IServiceScopeFactory serviceScopeFactory)
{
JobExecuter = jobExecuter;
ServiceScopeFactory = serviceScopeFactory;
Options = options.Value;
}
public async Task Execute(IJobExecutionContext context)
{
using (var scope = ServiceScopeFactory.CreateScope())
{
var args = (TArgs)context.JobDetail.JobDataMap.Get(nameof(TArgs));
var jobType = Options.GetJob(typeof(TArgs)).JobType;
var jobContext = new JobExecutionContext(scope.ServiceProvider, jobType, args);
await JobExecuter.ExecuteAsync(jobContext);
}
}
}
}

0
modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.RabbitMq/FodyWeavers.xml → framework/src/Volo.Abp.BackgroundWorkers.Quartz/FodyWeavers.xml

0
modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.RabbitMq/FodyWeavers.xsd → framework/src/Volo.Abp.BackgroundWorkers.Quartz/FodyWeavers.xsd

24
framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo.Abp.BackgroundWorkers.Quartz.csproj

@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Abp.BackgroundWorkers.Quartz</AssemblyName>
<PackageId>Volo.Abp.BackgroundWorkers.Quartz</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.BackgroundWorkers\Volo.Abp.BackgroundWorkers.csproj" />
<ProjectReference Include="..\Volo.Abp.Quartz\Volo.Abp.Quartz.csproj" />
</ItemGroup>
</Project>

30
framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/AbpBackgroundWorkersQuartzModule.cs

@ -0,0 +1,30 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Volo.Abp.Modularity;
using Volo.Abp.Quartz;
namespace Volo.Abp.BackgroundWorkers.Quartz
{
[DependsOn(
typeof(AbpBackgroundWorkersModule),
typeof(AbpQuartzModule)
)]
public class AbpBackgroundWorkersQuartzModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddConventionalRegistrar(new AbpQuartzConventionalRegistrar());
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
var backgroundWorkerManager = context.ServiceProvider.GetService<IBackgroundWorkerManager>();
var works = context.ServiceProvider.GetServices<IQuartzBackgroundWorker>();
foreach (var work in works)
{
backgroundWorkerManager.Add(work);
}
}
}
}

27
framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/AbpQuartzConventionalRegistrar.cs

@ -0,0 +1,27 @@
using System;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.BackgroundWorkers.Quartz
{
public class AbpQuartzConventionalRegistrar : DefaultConventionalRegistrar
{
public override void AddType(IServiceCollection services, Type type)
{
if (!typeof(IQuartzBackgroundWorker).IsAssignableFrom(type))
{
return;
}
var dependencyAttribute = GetDependencyAttributeOrNull(type);
var lifeTime = GetLifeTimeOrNull(type, dependencyAttribute);
if (lifeTime == null)
{
return;
}
services.Add(ServiceDescriptor.Describe(typeof(IQuartzBackgroundWorker), type, lifeTime.Value));
}
}
}

11
framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/IQuartzBackgroundWorker.cs

@ -0,0 +1,11 @@
using Quartz;
namespace Volo.Abp.BackgroundWorkers.Quartz
{
public interface IQuartzBackgroundWorker : IBackgroundWorker, IJob
{
ITrigger Trigger { get; set; }
IJobDetail JobDetail { get; set; }
}
}

14
framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/QuartzBackgroundWorkerBase.cs

@ -0,0 +1,14 @@
using System.Threading.Tasks;
using Quartz;
namespace Volo.Abp.BackgroundWorkers.Quartz
{
public abstract class QuartzBackgroundWorkerBase : BackgroundWorkerBase, IQuartzBackgroundWorker
{
public ITrigger Trigger { get; set; }
public IJobDetail JobDetail { get; set; }
public abstract Task Execute(IJobExecutionContext context);
}
}

43
framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/QuartzBackgroundWorkerManager.cs

@ -0,0 +1,43 @@
using System.Threading;
using System.Threading.Tasks;
using Quartz;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Threading;
namespace Volo.Abp.BackgroundWorkers.Quartz
{
[Dependency(ReplaceServices = true)]
public class QuartzBackgroundWorkerManager : IBackgroundWorkerManager, ISingletonDependency
{
private readonly IScheduler _scheduler;
public QuartzBackgroundWorkerManager(IScheduler scheduler)
{
_scheduler = scheduler;
}
public async Task StartAsync(CancellationToken cancellationToken = default)
{
await _scheduler.ResumeAll(cancellationToken);
}
public async Task StopAsync(CancellationToken cancellationToken = default)
{
if (!_scheduler.IsShutdown)
{
await _scheduler.PauseAll(cancellationToken);
}
}
public void Add(IBackgroundWorker worker)
{
if (worker is IQuartzBackgroundWorker quartzWork)
{
Check.NotNull(quartzWork.Trigger, nameof(quartzWork.Trigger));
Check.NotNull(quartzWork.JobDetail, nameof(quartzWork.JobDetail));
AsyncHelper.RunSync(() => _scheduler.ScheduleJob(quartzWork.JobDetail, quartzWork.Trigger));
}
}
}
}

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

@ -16,10 +16,12 @@ namespace Volo.Abp.Cli.Commands
public ILogger<AddModuleCommand> Logger { get; set; }
protected SolutionModuleAdder SolutionModuleAdder { get; }
public SolutionAbpVersionFinder SolutionAbpVersionFinder { get; }
public AddModuleCommand(SolutionModuleAdder solutionModuleAdder)
public AddModuleCommand(SolutionModuleAdder solutionModuleAdder, SolutionAbpVersionFinder solutionAbpVersionFinder)
{
SolutionModuleAdder = solutionModuleAdder;
SolutionAbpVersionFinder = solutionAbpVersionFinder;
Logger = NullLogger<AddModuleCommand>.Instance;
}
@ -34,14 +36,26 @@ namespace Volo.Abp.Cli.Commands
);
}
var withSourceCode = commandLineArgs.Options.ContainsKey("with-source-code");
var skipDbMigrations = Convert.ToBoolean(
commandLineArgs.Options.GetOrNull(Options.DbMigrations.Skip) ?? "false");
var solutionFile = GetSolutionFile(commandLineArgs);
var version = commandLineArgs.Options.GetOrNull(Options.Version.Short, Options.Version.Long);
if (version == null)
{
version = SolutionAbpVersionFinder.Find(solutionFile);
}
await SolutionModuleAdder.AddAsync(
GetSolutionFile(commandLineArgs),
solutionFile,
commandLineArgs.Target,
commandLineArgs.Options.GetOrNull(Options.StartupProject.Short, Options.StartupProject.Long),
skipDbMigrations
version,
skipDbMigrations,
withSourceCode
);
}
@ -57,8 +71,9 @@ namespace Volo.Abp.Cli.Commands
sb.AppendLine(" abp add-module <module-name> [options]");
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(" --with-source-code Downloads the source code of the module and adds it to your solution.");
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(" -sp|--startup-project <startup-project-path> Relative path to the project folder of the startup project. Default value is the current folder.");
sb.AppendLine("");
sb.AppendLine("Examples:");
@ -126,6 +141,11 @@ namespace Volo.Abp.Cli.Commands
public const string Short = "s";
public const string Long = "solution";
}
public static class Version
{
public const string Short = "v";
public const string Long = "version";
}
public static class DbMigrations
{

82
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/GetSourceCommand.cs

@ -7,6 +7,7 @@ using ICSharpCode.SharpZipLib.Zip;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Volo.Abp.Cli.Args;
using Volo.Abp.Cli.Commands.Services;
using Volo.Abp.Cli.ProjectBuilding;
using Volo.Abp.Cli.ProjectBuilding.Building;
using Volo.Abp.DependencyInjection;
@ -15,12 +16,14 @@ namespace Volo.Abp.Cli.Commands
{
public class GetSourceCommand : IConsoleCommand, ITransientDependency
{
private readonly SourceCodeDownloadService _sourceCodeDownloadService;
public ModuleProjectBuilder ModuleProjectBuilder { get; }
public ILogger<NewCommand> Logger { get; set; }
public GetSourceCommand(ModuleProjectBuilder moduleProjectBuilder)
public GetSourceCommand(ModuleProjectBuilder moduleProjectBuilder, SourceCodeDownloadService sourceCodeDownloadService)
{
_sourceCodeDownloadService = sourceCodeDownloadService;
ModuleProjectBuilder = moduleProjectBuilder;
Logger = NullLogger<NewCommand>.Instance;
}
@ -36,29 +39,13 @@ namespace Volo.Abp.Cli.Commands
);
}
Logger.LogInformation("Downloading source code of " + commandLineArgs.Target);
var version = commandLineArgs.Options.GetOrNull(Options.Version.Short, Options.Version.Long);
if (version != null)
{
Logger.LogInformation("Version: " + version);
}
var outputFolder = commandLineArgs.Options.GetOrNull(Options.OutputFolder.Short, Options.OutputFolder.Long);
if (outputFolder != null)
{
if (!Directory.Exists(outputFolder))
{
Directory.CreateDirectory(outputFolder);
}
outputFolder = Path.GetFullPath(outputFolder);
}
else
{
outputFolder = Directory.GetCurrentDirectory();
}
var outputFolder = GetOutPutFolder(commandLineArgs);
Logger.LogInformation("Output folder: " + outputFolder);
var gitHubLocalRepositoryPath = commandLineArgs.Options.GetOrNull(Options.GitHubLocalRepositoryPath.Long);
@ -68,54 +55,29 @@ namespace Volo.Abp.Cli.Commands
}
commandLineArgs.Options.Add(CliConsts.Command, commandLineArgs.Command);
await _sourceCodeDownloadService.DownloadAsync(
commandLineArgs.Target, outputFolder, version, gitHubLocalRepositoryPath, commandLineArgs.Options);
}
var result = await ModuleProjectBuilder.BuildAsync(
new ProjectBuildArgs(
SolutionName.Parse(commandLineArgs.Target),
commandLineArgs.Target,
version,
DatabaseProvider.NotSpecified,
UiFramework.NotSpecified,
MobileApp.None,
gitHubLocalRepositoryPath,
commandLineArgs.Options
)
);
using (var templateFileStream = new MemoryStream(result.ZipContent))
private static string GetOutPutFolder(CommandLineArgs commandLineArgs)
{
var outputFolder = commandLineArgs.Options.GetOrNull(Options.OutputFolder.Short, Options.OutputFolder.Long);
if (outputFolder != null)
{
using (var zipInputStream = new ZipInputStream(templateFileStream))
if (!Directory.Exists(outputFolder))
{
var zipEntry = zipInputStream.GetNextEntry();
while (zipEntry != null)
{
var fullZipToPath = Path.Combine(outputFolder, zipEntry.Name);
var directoryName = Path.GetDirectoryName(fullZipToPath);
if (!string.IsNullOrEmpty(directoryName))
{
Directory.CreateDirectory(directoryName);
}
var fileName = Path.GetFileName(fullZipToPath);
if (fileName.Length == 0)
{
zipEntry = zipInputStream.GetNextEntry();
continue;
}
var buffer = new byte[4096]; // 4K is optimum
using (var streamWriter = File.Create(fullZipToPath))
{
StreamUtils.Copy(zipInputStream, streamWriter, buffer);
}
zipEntry = zipInputStream.GetNextEntry();
}
Directory.CreateDirectory(outputFolder);
}
outputFolder = Path.GetFullPath(outputFolder);
}
else
{
outputFolder = Directory.GetCurrentDirectory();
}
Logger.LogInformation($"'{commandLineArgs.Target}' has been successfully downloaded to '{outputFolder}'");
return outputFolder;
}
public string GetUsageInfo()

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

@ -30,7 +30,7 @@ namespace Volo.Abp.Cli.Commands
public async Task ExecuteAsync(CommandLineArgs commandLineArgs)
{
var projectName = NamespaceHelper.NormalizeNamespace(commandLineArgs.Target);
if (projectName == null)
{
throw new CliUsageException(
@ -39,7 +39,7 @@ namespace Volo.Abp.Cli.Commands
GetUsageInfo()
);
}
Logger.LogInformation("Creating your project...");
Logger.LogInformation("Project name: " + projectName);
@ -79,6 +79,12 @@ namespace Volo.Abp.Cli.Commands
Logger.LogInformation("GitHub Local Repository Path: " + gitHubLocalRepositoryPath);
}
var templateSource = commandLineArgs.Options.GetOrNull(Options.TemplateSource.Short, Options.TemplateSource.Long);
if (templateSource != null)
{
Logger.LogInformation("Template Source: " + templateSource);
}
var outputFolder = commandLineArgs.Options.GetOrNull(Options.OutputFolder.Short, Options.OutputFolder.Long);
outputFolder = Path.Combine(outputFolder != null ? Path.GetFullPath(outputFolder) : Directory.GetCurrentDirectory(),
@ -102,6 +108,7 @@ namespace Volo.Abp.Cli.Commands
uiFramework,
mobileApp,
gitHubLocalRepositoryPath,
templateSource,
commandLineArgs.Options
)
);
@ -158,6 +165,7 @@ namespace Volo.Abp.Cli.Commands
sb.AppendLine("-d|--database-provider <database-provider> (if supported by the template)");
sb.AppendLine("-o|--output-folder <output-folder> (default: current folder)");
sb.AppendLine("-v|--version <version> (default: latest version)");
sb.AppendLine("-ts|--template-source <template-source> (your local or network abp template source)");
sb.AppendLine("--tiered (if supported by the template)");
sb.AppendLine("--no-ui (if supported by the template)");
sb.AppendLine("--separate-identity-server (if supported by the template)");
@ -173,6 +181,7 @@ namespace Volo.Abp.Cli.Commands
sb.AppendLine(" abp new Acme.BookStore -d mongodb -o d:\\my-project");
sb.AppendLine(" abp new Acme.BookStore -t module");
sb.AppendLine(" abp new Acme.BookStore -t module --no-ui");
sb.AppendLine(" abp new Acme.BookStore -ts \"D:\\localTemplate\\abp\"");
sb.AppendLine(" abp new Acme.BookStore --local-framework-ref --abp-path \"D:\\github\\abp\"");
sb.AppendLine("");
sb.AppendLine("See the documentation for more info: https://docs.abp.io/en/abp/latest/CLI");
@ -271,6 +280,12 @@ namespace Volo.Abp.Cli.Commands
public const string Short = "m";
public const string Long = "mobile";
}
public static class TemplateSource
{
public const string Short = "ts";
public const string Long = "template-source";
}
}
}
}

84
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/SourceCodeDownloadService.cs

@ -0,0 +1,84 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using ICSharpCode.SharpZipLib.Core;
using ICSharpCode.SharpZipLib.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;
namespace Volo.Abp.Cli.Commands.Services
{
public class SourceCodeDownloadService : ITransientDependency
{
public ModuleProjectBuilder ModuleProjectBuilder { get; }
public ILogger<SourceCodeDownloadService> Logger { get; set; }
public SourceCodeDownloadService(ModuleProjectBuilder moduleProjectBuilder)
{
ModuleProjectBuilder = moduleProjectBuilder;
Logger = NullLogger<SourceCodeDownloadService>.Instance;
}
public async Task DownloadAsync(string moduleName, string outputFolder, string version, string gitHubLocalRepositoryPath, AbpCommandLineOptions options)
{
Logger.LogInformation("Downloading source code of " + moduleName);
Logger.LogInformation("Version: " + version);
Logger.LogInformation("Output folder: " + outputFolder);
var result = await ModuleProjectBuilder.BuildAsync(
new ProjectBuildArgs(
SolutionName.Parse(moduleName),
moduleName,
version,
DatabaseProvider.NotSpecified,
UiFramework.NotSpecified,
null,
gitHubLocalRepositoryPath,
null,
options
)
);
using (var templateFileStream = new MemoryStream(result.ZipContent))
{
using (var zipInputStream = new ZipInputStream(templateFileStream))
{
var zipEntry = zipInputStream.GetNextEntry();
while (zipEntry != null)
{
var fullZipToPath = Path.Combine(outputFolder, zipEntry.Name);
var directoryName = Path.GetDirectoryName(fullZipToPath);
if (!string.IsNullOrEmpty(directoryName))
{
Directory.CreateDirectory(directoryName);
}
var fileName = Path.GetFileName(fullZipToPath);
if (fileName.Length == 0)
{
zipEntry = zipInputStream.GetNextEntry();
continue;
}
var buffer = new byte[4096]; // 4K is optimum
using (var streamWriter = File.Create(fullZipToPath))
{
StreamUtils.Copy(zipInputStream, streamWriter, buffer);
}
zipEntry = zipInputStream.GetNextEntry();
}
}
}
Logger.LogInformation($"'{moduleName}' has been successfully downloaded to '{outputFolder}'");
}
}
}

42
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/AbpIoSourceCodeStore.cs

@ -2,9 +2,7 @@ using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
@ -46,7 +44,8 @@ namespace Volo.Abp.Cli.ProjectBuilding
public async Task<TemplateFile> GetAsync(
string name,
string type,
string version = null)
string version = null,
string templateSource = null)
{
var latestVersion = await GetLatestSourceCodeVersionAsync(name, type);
@ -57,8 +56,14 @@ namespace Volo.Abp.Cli.ProjectBuilding
DirectoryHelper.CreateIfNotExists(CliPaths.TemplateCache);
if (!string.IsNullOrWhiteSpace(templateSource) && !IsNetworkSource(templateSource))
{
Logger.LogInformation("Using local " + type + ": " + name + ", version: " + version);
return new TemplateFile(File.ReadAllBytes(Path.Combine(templateSource, name + "-" + version + ".zip")), version, latestVersion);
}
var localCacheFile = Path.Combine(CliPaths.TemplateCache, name + "-" + version + ".zip");
if (Options.CacheTemplates && File.Exists(localCacheFile))
if (Options.CacheTemplates && File.Exists(localCacheFile) && templateSource.IsNullOrWhiteSpace())
{
Logger.LogInformation("Using cached " + type + ": " + name + ", version: " + version);
return new TemplateFile(File.ReadAllBytes(localCacheFile), version, latestVersion);
@ -71,11 +76,12 @@ namespace Volo.Abp.Cli.ProjectBuilding
{
Name = name,
Type = type,
TemplateSource = templateSource,
Version = version
}
);
if (Options.CacheTemplates)
if (Options.CacheTemplates && templateSource.IsNullOrWhiteSpace())
{
File.WriteAllBytes(localCacheFile, fileContent);
}
@ -114,11 +120,20 @@ namespace Volo.Abp.Cli.ProjectBuilding
using (var client = new CliHttpClient(TimeSpan.FromMinutes(10)))
{
var responseMessage = await client.PostAsync(
$"{CliUrls.WwwAbpIo}api/download/{input.Type}/",
new StringContent(postData, Encoding.UTF8, MimeTypes.Application.Json),
CancellationTokenProvider.Token
);
HttpResponseMessage responseMessage;
if (input.TemplateSource.IsNullOrWhiteSpace())
{
responseMessage = await client.PostAsync(
$"{CliUrls.WwwAbpIo}api/download/{input.Type}/",
new StringContent(postData, Encoding.UTF8, MimeTypes.Application.Json),
CancellationTokenProvider.Token
);
}
else
{
responseMessage = await client.GetAsync(input.TemplateSource, CancellationTokenProvider.Token);
}
await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(responseMessage);
@ -126,6 +141,11 @@ namespace Volo.Abp.Cli.ProjectBuilding
}
}
private bool IsNetworkSource(string source)
{
return source.ToLower().StartsWith("http");
}
public class SourceCodeDownloadInputDto
{
public string Name { get; set; }
@ -133,6 +153,8 @@ namespace Volo.Abp.Cli.ProjectBuilding
public string Version { get; set; }
public string Type { get; set; }
public string TemplateSource { get; set; }
}
public class GetLatestSourceCodeVersionDto

1
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ModuleProjectBuildPipelineBuilder.cs

@ -11,6 +11,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building
pipeline.Steps.Add(new FileEntryListReadStep());
pipeline.Steps.Add(new ProjectReferenceReplaceStep());
pipeline.Steps.Add(new ReplaceCommonPropsStep());
pipeline.Steps.Add(new ReplaceConfigureAwaitPropsStep());
pipeline.Steps.Add(new CreateProjectResultZipStep());
return pipeline;

13
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ProjectReferenceReplaceStep.cs

@ -4,6 +4,7 @@ using System.IO;
using System.Text.RegularExpressions;
using System.Xml;
using Volo.Abp.Cli.ProjectBuilding.Files;
using Volo.Abp.Cli.Utils;
namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
{
@ -92,7 +93,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
var doc = new XmlDocument() { PreserveWhitespace = true };
doc.Load(GenerateStreamFromString(content));
doc.Load(StreamHelper.GenerateStreamFromString(content));
return ProcessReferenceNodes(doc, content);
}
@ -125,16 +126,6 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
protected abstract XmlElement GetNewReferenceNode(XmlDocument doc, string oldNodeIncludeValue);
private static Stream GenerateStreamFromString(string s)
{
var stream = new MemoryStream();
var writer = new StreamWriter(stream);
writer.Write(s);
writer.Flush();
stream.Position = 0;
return stream;
}
public class NugetReferenceReplacer : ProjectReferenceReplacer
{

13
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ReplaceCommonPropsStep.cs

@ -4,6 +4,7 @@ using System.IO;
using System.Text.RegularExpressions;
using System.Xml;
using Volo.Abp.Cli.ProjectBuilding.Files;
using Volo.Abp.Cli.Utils;
namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
{
@ -41,7 +42,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
var doc = new XmlDocument() { PreserveWhitespace = true };
doc.Load(GenerateStreamFromString(content));
doc.Load(StreamHelper.GenerateStreamFromString(content));
return ProcessReferenceNodes(doc, content);
}
@ -81,16 +82,6 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
return doc.OuterXml;
}
private static Stream GenerateStreamFromString(string s)
{
var stream = new MemoryStream();
var writer = new StreamWriter(stream);
writer.Write(s);
writer.Flush();
stream.Position = 0;
return stream;
}
}
}
}

75
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ReplaceConfigureAwaitPropsStep.cs

@ -0,0 +1,75 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using System.Xml;
using Volo.Abp.Cli.ProjectBuilding.Files;
using Volo.Abp.Cli.Utils;
namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
{
public class ReplaceConfigureAwaitPropsStep : ProjectBuildPipelineStep
{
public override void Execute(ProjectBuildContext context)
{
new ConfigureAwaitPropsReplacer(context.Files).Run();
}
private class ConfigureAwaitPropsReplacer
{
private readonly List<FileEntry> _entries;
public ConfigureAwaitPropsReplacer(
List<FileEntry> entries)
{
_entries = entries;
}
public void Run()
{
foreach (var fileEntry in _entries)
{
if (fileEntry.Name.EndsWith(".csproj"))
{
fileEntry.SetContent(ProcessFileContent(fileEntry.Content));
}
}
}
private string ProcessFileContent(string content)
{
Check.NotNull(content, nameof(content));
var doc = new XmlDocument() { PreserveWhitespace = true };
doc.Load(StreamHelper.GenerateStreamFromString(content));
return ProcessReferenceNodes(doc, content);
}
private string ProcessReferenceNodes(XmlDocument doc, string content)
{
Check.NotNull(content, nameof(content));
var importNodes = doc.SelectNodes("/Project/Import[@Project]");
if (importNodes == null)
{
return doc.OuterXml;
}
foreach (XmlNode node in importNodes)
{
if (!(node.Attributes?["Project"]?.Value?.EndsWith("\\configureawait.props") ?? false))
{
continue;
}
node.ParentNode?.RemoveChild(node);
}
return doc.OuterXml;
}
}
}
}

3
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ISourceCodeStore.cs

@ -8,7 +8,8 @@ namespace Volo.Abp.Cli.ProjectBuilding
Task<TemplateFile> GetAsync(
string name,
string type,
[CanBeNull] string version = null
[CanBeNull] string version = null,
[CanBeNull] string templateSource = null
);
}
}

2
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ModuleProjectBuilder.cs

@ -83,6 +83,8 @@ namespace Volo.Abp.Cli.ProjectBuilding
!x.Key.Equals(NewCommand.Options.OutputFolder.Short, StringComparison.InvariantCultureIgnoreCase))
.Where(x => !x.Key.Equals(NewCommand.Options.Version.Long, StringComparison.InvariantCultureIgnoreCase) &&
!x.Key.Equals(NewCommand.Options.Version.Short, StringComparison.InvariantCultureIgnoreCase))
.Where(x => !x.Key.Equals(NewCommand.Options.TemplateSource.Short, StringComparison.InvariantCultureIgnoreCase) &&
!x.Key.Equals(NewCommand.Options.TemplateSource.Long, StringComparison.InvariantCultureIgnoreCase))
.Select(x => x.Key).ToList();
await CliAnalyticsCollect.CollectAsync(new CliAnalyticsCollectInputDto

11
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ProjectBuildArgs.cs

@ -19,22 +19,26 @@ namespace Volo.Abp.Cli.ProjectBuilding
public UiFramework UiFramework { get; set; }
public MobileApp MobileApp { get; set; }
public MobileApp? MobileApp { get; set; }
[CanBeNull]
public string AbpGitHubLocalRepositoryPath { get; set; }
[CanBeNull]
public string TemplateSource { get; set; }
[NotNull]
public Dictionary<string, string> ExtraProperties { get; set; }
public ProjectBuildArgs(
[NotNull] SolutionName solutionName,
[NotNull] SolutionName solutionName,
[CanBeNull] string templateName = null,
[CanBeNull] string version = null,
DatabaseProvider databaseProvider = DatabaseProvider.NotSpecified,
UiFramework uiFramework = UiFramework.NotSpecified,
MobileApp mobileApp = MobileApp.ReactNative,
MobileApp? mobileApp = null,
[CanBeNull] string abpGitHubLocalRepositoryPath = null,
[CanBeNull] string templateSource = null,
Dictionary<string, string> extraProperties = null)
{
SolutionName = Check.NotNull(solutionName, nameof(solutionName));
@ -44,6 +48,7 @@ namespace Volo.Abp.Cli.ProjectBuilding
UiFramework = uiFramework;
MobileApp = mobileApp;
AbpGitHubLocalRepositoryPath = abpGitHubLocalRepositoryPath;
TemplateSource = templateSource;
ExtraProperties = extraProperties ?? new Dictionary<string, string>();
}
}

17
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateProjectBuilder.cs

@ -24,11 +24,11 @@ namespace Volo.Abp.Cli.ProjectBuilding
protected IJsonSerializer JsonSerializer { get; }
protected IApiKeyService ApiKeyService { get; }
public TemplateProjectBuilder(ISourceCodeStore sourceCodeStore,
public TemplateProjectBuilder(ISourceCodeStore sourceCodeStore,
ITemplateInfoProvider templateInfoProvider,
ICliAnalyticsCollect cliAnalyticsCollect,
ICliAnalyticsCollect cliAnalyticsCollect,
IOptions<AbpCliOptions> options,
IJsonSerializer jsonSerializer,
IJsonSerializer jsonSerializer,
IApiKeyService apiKeyService)
{
SourceCodeStore = sourceCodeStore;
@ -40,7 +40,7 @@ namespace Volo.Abp.Cli.ProjectBuilding
Logger = NullLogger<TemplateProjectBuilder>.Instance;
}
public async Task<ProjectBuildResult> BuildAsync(ProjectBuildArgs args)
{
var templateInfo = GetTemplateInfo(args);
@ -50,9 +50,10 @@ namespace Volo.Abp.Cli.ProjectBuilding
var templateFile = await SourceCodeStore.GetAsync(
args.TemplateName,
SourceCodeTypes.Template,
args.Version
args.Version,
args.TemplateSource
);
var apiKeyResult = await ApiKeyService.GetApiKeyOrNullAsync();
if (apiKeyResult?.ApiKey != null)
{
@ -82,7 +83,7 @@ namespace Volo.Abp.Cli.ProjectBuilding
var options = args.ExtraProperties
.Where(x => !x.Key.Equals(CliConsts.Command, StringComparison.InvariantCultureIgnoreCase))
.Where(x => !x.Key.Equals("tiered", StringComparison.InvariantCultureIgnoreCase))
.Where(x => !x.Key.Equals(NewCommand.Options.DatabaseProvider.Long, StringComparison.InvariantCultureIgnoreCase) &&
.Where(x => !x.Key.Equals(NewCommand.Options.DatabaseProvider.Long, StringComparison.InvariantCultureIgnoreCase) &&
!x.Key.Equals(NewCommand.Options.DatabaseProvider.Short, StringComparison.InvariantCultureIgnoreCase))
.Where(x => !x.Key.Equals(NewCommand.Options.OutputFolder.Long, StringComparison.InvariantCultureIgnoreCase) &&
!x.Key.Equals(NewCommand.Options.OutputFolder.Short, StringComparison.InvariantCultureIgnoreCase))
@ -92,6 +93,8 @@ namespace Volo.Abp.Cli.ProjectBuilding
!x.Key.Equals(NewCommand.Options.Mobile.Short, StringComparison.InvariantCultureIgnoreCase))
.Where(x => !x.Key.Equals(NewCommand.Options.Version.Long, StringComparison.InvariantCultureIgnoreCase) &&
!x.Key.Equals(NewCommand.Options.Version.Short, StringComparison.InvariantCultureIgnoreCase))
.Where(x => !x.Key.Equals(NewCommand.Options.TemplateSource.Short, StringComparison.InvariantCultureIgnoreCase) &&
!x.Key.Equals(NewCommand.Options.TemplateSource.Long, StringComparison.InvariantCultureIgnoreCase))
.Select(x => x.Key).ToList();
await CliAnalyticsCollect.CollectAsync(new CliAnalyticsCollectInputDto

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

@ -18,7 +18,7 @@ namespace Volo.Abp.Cli.ProjectModification
Logger = NullLogger<DbContextFileBuilderConfigureAdder>.Instance;
}
public void Add(string path, string moduleConfiguration)
public bool Add(string path, string moduleConfiguration)
{
var file = File.ReadAllText(path);
@ -32,13 +32,18 @@ namespace Volo.Abp.Cli.ProjectModification
if (indexToInsert <= 0 || indexToInsert >= file.Length)
{
Logger.LogWarning($"\"OnModelCreating(ModelBuilder builder)\" method couldn't be found in {path}");
return;
return false;
}
file = file.Insert(indexToInsert, " " + stringToAdd + Environment.NewLine + " ");
}
else
{
return false;
}
File.WriteAllText(path, file);
return true;
}
protected int FindIndexToInsert(string file)

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

@ -53,7 +53,6 @@ namespace Volo.Abp.Cli.ProjectModification
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();

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

@ -0,0 +1,9 @@
using System.Collections.Generic;
namespace Volo.Abp.Cli.ProjectModification
{
public class ModuleWithMastersInfo : ModuleInfo
{
public List<ModuleWithMastersInfo> MasterModuleInfos { get; set; }
}
}

140
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NugetPackageToLocalReferenceConverter.cs

@ -0,0 +1,140 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using Volo.Abp.Cli.Utils;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Cli.ProjectModification
{
public class NugetPackageToLocalReferenceConverter : ITransientDependency
{
public async Task Convert(ModuleWithMastersInfo module, string solutionFile)
{
var nugetPackageList = GetNugetPackages(module);
var modulesFolder = Path.Combine(Path.GetDirectoryName(solutionFile), "modules");
var srcFolder = Path.Combine(Path.GetDirectoryName(solutionFile), "src");
var testFolder = Path.Combine(Path.GetDirectoryName(solutionFile), "test");
ConvertToLocalReference(modulesFolder, nugetPackageList, "..\\..\\..\\");
ConvertToLocalReference(srcFolder, nugetPackageList, "..\\..\\modules\\");
ConvertToLocalReference(testFolder, nugetPackageList, "..\\..\\modules\\", "test");
}
private void ConvertToLocalReference(string folder, List<NugetPackageInfoWithModuleName> nugetPackageList, string localPathPrefix, string sourceFile = "src")
{
var projectFiles = GetProjectFilesUnder(folder);
foreach (var projectFile in projectFiles)
{
var content = File.ReadAllText(projectFile);
var doc = new XmlDocument() { PreserveWhitespace = true };
doc.Load(StreamHelper.GenerateStreamFromString(content));
var convertedProject = ProcessReferenceNodes(folder, doc, nugetPackageList, localPathPrefix, sourceFile);
File.WriteAllText(projectFile, convertedProject);
}
}
private string ProcessReferenceNodes(string folder, XmlDocument doc, List<NugetPackageInfoWithModuleName> nugetPackageList, string localPathPrefix, string sourceFile = "src")
{
var nodes = doc.SelectNodes("/Project/ItemGroup/PackageReference[starts-with(@Include, 'Volo.Abp')]");
if (nodes == null)
{
return doc.OuterXml;
}
foreach (XmlNode oldNode in nodes)
{
var oldNodeIncludeValue = oldNode?.Attributes?["Include"]?.Value;
var moduleName = nugetPackageList.FirstOrDefault(n => n.NugetPackage.Name == oldNodeIncludeValue)?.ModuleName;
if (moduleName == null)
{
var localProject = GetProjectFilesUnder(folder).FirstOrDefault(f=> f.EndsWith($"{oldNodeIncludeValue}.csproj"));
if (localProject != null)
{
moduleName = Directory.GetParent(Directory.GetParent(Path.GetDirectoryName(localProject)).FullName).Name;
if (oldNodeIncludeValue.EndsWith(".test", StringComparison.InvariantCultureIgnoreCase) ||
oldNodeIncludeValue.EndsWith(".tests", StringComparison.InvariantCultureIgnoreCase))
{
sourceFile = "test";
}
else
{
sourceFile = "src";
}
}
else
{
continue;
}
}
var referenceProjectPath =
$"{localPathPrefix}{moduleName}\\{sourceFile}\\{oldNodeIncludeValue}\\{oldNodeIncludeValue}.csproj";
XmlNode newNode = GetNewReferenceNode(doc, referenceProjectPath);
oldNode?.ParentNode?.ReplaceChild(newNode, oldNode);
}
return doc.OuterXml;
}
protected XmlElement GetNewReferenceNode(XmlDocument doc, string newValue)
{
var newNode = doc.CreateElement("ProjectReference");
var includeAttr = doc.CreateAttribute("Include");
includeAttr.Value = newValue;
newNode.Attributes.Append(includeAttr);
return newNode;
}
public List<NugetPackageInfoWithModuleName> GetNugetPackages(ModuleWithMastersInfo module)
{
var list = new List<NugetPackageInfoWithModuleName>();
list.AddRange(module.NugetPackages.Select(n => new NugetPackageInfoWithModuleName
{
ModuleName = module.Name,
NugetPackage = n
}));
if (module.MasterModuleInfos != null)
{
foreach (var masterModule in module.MasterModuleInfos)
{
list.AddRange(GetNugetPackages(masterModule));
}
}
return list;
}
private static string[] GetProjectFilesUnder(string path)
{
return Directory.GetFiles(path,
"*.csproj",
SearchOption.AllDirectories);
}
public class NugetPackageInfoWithModuleName
{
public NugetPackageInfo NugetPackage { get; set; }
public string ModuleName { get; set; }
}
}
}

2
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ProjectNpmPackageAdder.cs

@ -20,7 +20,7 @@ namespace Volo.Abp.Cli.ProjectModification
public Task AddAsync(string directory, NpmPackageInfo npmPackage)
{
var packageJsonFilePath = Path.Combine(directory, "package.json");
if (!File.Exists(packageJsonFilePath))
if (!File.Exists(packageJsonFilePath) || File.ReadAllText(packageJsonFilePath).Contains($"\"{npmPackage.Name}\""))
{
return Task.CompletedTask;
}

5
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ProjectNugetPackageAdder.cs

@ -50,6 +50,11 @@ namespace Volo.Abp.Cli.ProjectModification
public Task AddAsync(string projectFile, NugetPackageInfo package)
{
if (File.ReadAllText(projectFile).Contains($"\"{package.Name}\""))
{
return Task.CompletedTask;
}
using (DirectoryHelper.ChangeCurrentDirectory(Path.GetDirectoryName(projectFile)))
{
Logger.LogInformation($"Installing '{package.Name}' package to the project '{Path.GetFileNameWithoutExtension(projectFile)}'...");

36
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionAbpVersionFinder.cs

@ -0,0 +1,36 @@
using System.IO;
using System.Xml;
using Volo.Abp.Cli.Utils;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Cli.ProjectModification
{
public class SolutionAbpVersionFinder : ITransientDependency
{
public string Find(string solutionFile)
{
var projectFilesUnderSrc = Directory.GetFiles(Path.GetDirectoryName(solutionFile),
"*.csproj",
SearchOption.AllDirectories);
foreach (var projectFile in projectFilesUnderSrc)
{
var content = File.ReadAllText(projectFile);
var doc = new XmlDocument() { PreserveWhitespace = true };
doc.Load(StreamHelper.GenerateStreamFromString(content));
var nodes = doc.SelectNodes("/Project/ItemGroup/PackageReference[starts-with(@Include, 'Volo.Abp')]");
var value = nodes?[0]?.Attributes?["Version"]?.Value;
if (value != null)
{
return value;
}
}
return null;
}
}
}

117
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionFileModifier.cs

@ -0,0 +1,117 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Cli.ProjectModification
{
public class SolutionFileModifier : ITransientDependency
{
public async Task AddModuleToSolutionFileAsync(ModuleWithMastersInfo module, string solutionFile)
{
await AddModule(module, solutionFile);
}
private async Task AddModule(ModuleWithMastersInfo module, string solutionFile)
{
var srcModuleFolderId = await AddNewFolderAndGetIdOrGetExistingId(solutionFile, module.Name, await AddNewFolderAndGetIdOrGetExistingId(solutionFile, "modules"));
var testModuleFolderId = await AddNewFolderAndGetIdOrGetExistingId(solutionFile, module.Name + ".Tests", await AddNewFolderAndGetIdOrGetExistingId(solutionFile, "test"));
var file = File.ReadAllText(solutionFile);
var lines = file.Split(Environment.NewLine).ToList();
var projectsUnderModule = Directory.GetFiles(
Path.Combine(Path.GetDirectoryName(solutionFile), "modules", module.Name),
"*.csproj",
SearchOption.AllDirectories);
var projectsUnderTest = Directory.GetFiles(
Path.Combine(Path.GetDirectoryName(solutionFile), "modules", module.Name, "test"),
"*.csproj",
SearchOption.AllDirectories);
foreach (var projectPath in projectsUnderModule)
{
var parentFolderId = projectsUnderTest.Contains(projectPath) ? testModuleFolderId : srcModuleFolderId;
var projectId = Path.GetFileName(projectPath).Replace(".csproj","");
var projectParentFolderInModule = projectsUnderTest.Contains(projectPath) ? "test" : "src";
if (lines.Any(l => l.Contains($"\"{projectId}\"")))
{
continue;
}
var projectGuid = Guid.NewGuid().ToString();
var newProjectLine = "Project(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"" + projectId + "\"," +
" \"modules\\" + module.Name + "\\"+ projectParentFolderInModule + "\\" + projectId + "\\" + projectId + ".csproj\", \"{" + projectGuid + "}\""
+ Environment.NewLine + "EndProject";
lines.InsertAfter(l => l.Trim().Equals("EndProject"), newProjectLine);
var newPostSolutionLine =
" {" + projectGuid + "}.Debug|Any CPU.ActiveCfg = Debug|Any CPU" + Environment.NewLine +
" {" + projectGuid + "}.Debug|Any CPU.Build.0 = Debug|Any CPU" + Environment.NewLine +
" {" + projectGuid + "}.Release|Any CPU.ActiveCfg = Release|Any CPU" + Environment.NewLine +
" {" + projectGuid + "}.Release|Any CPU.Build.0 = Release|Any CPU";
lines.InsertAfter(l=>l.Contains("GlobalSection") && l.Contains("ProjectConfigurationPlatforms"), newPostSolutionLine);
var newPreSolutionLine =
" {"+ projectGuid + "} = {"+ parentFolderId + "}";
lines.InsertAfter(l=>l.Contains("GlobalSection") && l.Contains("NestedProjects"), newPreSolutionLine);
}
File.WriteAllText(solutionFile, string.Join(Environment.NewLine, lines));
if (module.MasterModuleInfos != null)
{
foreach (var masterModule in module.MasterModuleInfos)
{
await AddModule(masterModule, solutionFile);
}
}
}
private async Task<string> AddNewFolderAndGetIdOrGetExistingId(string solutionFile, string folderName, string parentFolderId = null)
{
var file = File.ReadAllText(solutionFile);
var lines = file.Split(Environment.NewLine).ToList();
string folderId;
var folderLineIndex = lines.FindIndex(l =>
l.Contains("2150E333-8FDC-42A3-9474-1A3956D46DE8") && l.Contains("\""+ folderName + "\""));
if (folderLineIndex < 0)
{
folderId = Guid.NewGuid().ToString();
var newFolderLine = "Project(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \""+ folderName + "\", \""+ folderName + "\", \"{" + folderId + "}\""
+ Environment.NewLine + "EndProject";
lines.InsertAfter(l => l.Trim().Equals("EndProject"), newFolderLine);
if (parentFolderId != null)
{
var newPreSolutionLine =
" {" + folderId + "} = {" + parentFolderId + "}";
lines.InsertAfter(l => l.Contains("GlobalSection") && l.Contains("NestedProjects"), newPreSolutionLine);
}
}
else
{
folderId = lines[folderLineIndex].Replace("\"", " ").Replace("{", " ").Replace("}", " ").TrimEnd()
.Split(" ").Last();
}
File.WriteAllText(solutionFile, string.Join(Environment.NewLine, lines));
return folderId;
}
}
}

68
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs

@ -7,6 +7,7 @@ using System.IO;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using Volo.Abp.Cli.Commands.Services;
using Volo.Abp.Cli.Http;
using Volo.Abp.Cli.ProjectBuilding;
using Volo.Abp.DependencyInjection;
@ -26,6 +27,9 @@ namespace Volo.Abp.Cli.ProjectModification
protected ProjectNpmPackageAdder ProjectNpmPackageAdder { get; }
protected NpmGlobalPackagesChecker NpmGlobalPackagesChecker { get; }
protected IRemoteServiceExceptionHandler RemoteServiceExceptionHandler { get; }
public SourceCodeDownloadService SourceCodeDownloadService { get; }
public SolutionFileModifier SolutionFileModifier { get; }
public NugetPackageToLocalReferenceConverter NugetPackageToLocalReferenceConverter { get; }
public SolutionModuleAdder(
IJsonSerializer jsonSerializer,
@ -35,7 +39,10 @@ namespace Volo.Abp.Cli.ProjectModification
DerivedClassFinder derivedClassFinder,
ProjectNpmPackageAdder projectNpmPackageAdder,
NpmGlobalPackagesChecker npmGlobalPackagesChecker,
IRemoteServiceExceptionHandler remoteServiceExceptionHandler)
IRemoteServiceExceptionHandler remoteServiceExceptionHandler,
SourceCodeDownloadService sourceCodeDownloadService,
SolutionFileModifier solutionFileModifier,
NugetPackageToLocalReferenceConverter nugetPackageToLocalReferenceConverter)
{
JsonSerializer = jsonSerializer;
ProjectNugetPackageAdder = projectNugetPackageAdder;
@ -45,6 +52,9 @@ namespace Volo.Abp.Cli.ProjectModification
ProjectNpmPackageAdder = projectNpmPackageAdder;
NpmGlobalPackagesChecker = npmGlobalPackagesChecker;
RemoteServiceExceptionHandler = remoteServiceExceptionHandler;
SourceCodeDownloadService = sourceCodeDownloadService;
SolutionFileModifier = solutionFileModifier;
NugetPackageToLocalReferenceConverter = nugetPackageToLocalReferenceConverter;
Logger = NullLogger<SolutionModuleAdder>.Instance;
}
@ -52,7 +62,9 @@ namespace Volo.Abp.Cli.ProjectModification
[NotNull] string solutionFile,
[NotNull] string moduleName,
string startupProject,
bool skipDbMigrations = false)
string version,
bool skipDbMigrations = false,
bool withSourceCode = false)
{
Check.NotNull(solutionFile, nameof(solutionFile));
Check.NotNull(moduleName, nameof(moduleName));
@ -63,6 +75,42 @@ namespace Volo.Abp.Cli.ProjectModification
var projectFiles = ProjectFinder.GetProjectFiles(solutionFile);
await AddNugetAndNpmReferences(module, projectFiles);
if (withSourceCode)
{
var modulesFolderInSolution = Path.Combine(Path.GetDirectoryName(solutionFile), "modules");
await DownloadSourceCodesToSolutionFolder(module, modulesFolderInSolution, version);
await SolutionFileModifier.AddModuleToSolutionFileAsync(module, solutionFile);
await NugetPackageToLocalReferenceConverter.Convert(module, solutionFile);
}
ModifyDbContext(projectFiles, module, startupProject, skipDbMigrations);
}
private async Task DownloadSourceCodesToSolutionFolder(ModuleWithMastersInfo module, string modulesFolderInSolution, string version = null)
{
await SourceCodeDownloadService.DownloadAsync(
module.Name,
Path.Combine(modulesFolderInSolution, module.Name),
version,
null,
null
);
if (module.MasterModuleInfos == null)
{
return;
}
foreach (var masterModule in module.MasterModuleInfos)
{
await DownloadSourceCodesToSolutionFolder(masterModule, modulesFolderInSolution, version);
}
}
private async Task AddNugetAndNpmReferences(ModuleWithMastersInfo module, string[] projectFiles)
{
foreach (var nugetPackage in module.NugetPackages)
{
var targetProjectFile = ProjectFinder.FindNuGetTargetProjectFile(projectFiles, nugetPackage.Target);
@ -84,7 +132,8 @@ namespace Volo.Abp.Cli.ProjectModification
foreach (var targetProject in targetProjects)
{
foreach (var npmPackage in module.NpmPackages.Where(p => p.ApplicationType.HasFlag(NpmApplicationType.Mvc)))
foreach (var npmPackage in module.NpmPackages.Where(p =>
p.ApplicationType.HasFlag(NpmApplicationType.Mvc)))
{
await ProjectNpmPackageAdder.AddAsync(Path.GetDirectoryName(targetProject), npmPackage);
}
@ -95,8 +144,6 @@ namespace Volo.Abp.Cli.ProjectModification
Logger.LogDebug("Target project is not available for NPM packages.");
}
}
ModifyDbContext(projectFiles, module, startupProject, skipDbMigrations);
}
protected void ModifyDbContext(string[] projectFiles, ModuleInfo module, string startupProject, bool skipDbMigrations = false)
@ -127,20 +174,19 @@ namespace Volo.Abp.Cli.ProjectModification
return;
}
DbContextFileBuilderConfigureAdder.Add(dbContextFile, module.EfCoreConfigureMethodName);
var addedNewBuilder = DbContextFileBuilderConfigureAdder.Add(dbContextFile, module.EfCoreConfigureMethodName);
if (!skipDbMigrations)
if (addedNewBuilder && !skipDbMigrations)
{
EfCoreMigrationAdder.AddMigration(dbMigrationsProject, module.Name, startupProject);
}
}
protected virtual async Task<ModuleInfo> FindModuleInfoAsync(string moduleName)
protected virtual async Task<ModuleWithMastersInfo> FindModuleInfoAsync(string moduleName)
{
using (var client = new CliHttpClient())
{
var url = $"{CliUrls.WwwAbpIo}api/app/module/byName/?name=" + moduleName;
var url = $"{CliUrls.WwwAbpIo}api/app/module/byNameWithDetails/?name=" + moduleName;
var response = await client.GetAsync(url);
@ -155,7 +201,7 @@ namespace Volo.Abp.Cli.ProjectModification
}
var responseContent = await response.Content.ReadAsStringAsync();
return JsonSerializer.Deserialize<ModuleInfo>(responseContent);
return JsonSerializer.Deserialize<ModuleWithMastersInfo>(responseContent);
}
}
}

20
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Utils/StreamHelper.cs

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace Volo.Abp.Cli.Utils
{
public static class StreamHelper
{
public static Stream GenerateStreamFromString(string s)
{
var stream = new MemoryStream();
var writer = new StreamWriter(stream);
writer.Write(s);
writer.Flush();
stream.Position = 0;
return stream;
}
}
}

0
modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp/FodyWeavers.xml → framework/src/Volo.Abp.Http.Client.IdentityModel.Web/FodyWeavers.xml

0
modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp/FodyWeavers.xsd → framework/src/Volo.Abp.Http.Client.IdentityModel.Web/FodyWeavers.xsd

27
framework/src/Volo.Abp.Http.Client.IdentityModel.Web/Properties/launchSettings.json

@ -0,0 +1,27 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:52306/",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Volo.Abp.Http.Client.IdentityModel": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:52307/"
}
}
}

23
framework/src/Volo.Abp.Http.Client.IdentityModel.Web/Volo.Abp.Http.Client.IdentityModel.Web.csproj

@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<AssemblyName>Volo.Abp.Http.Client.IdentityModel.Web</AssemblyName>
<PackageId>Volo.Abp.Http.Client.IdentityModel.Web</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>
<ProjectReference Include="..\Volo.Abp.Http.Client.IdentityModel\Volo.Abp.Http.Client.IdentityModel.csproj" />
</ItemGroup>
</Project>

12
framework/src/Volo.Abp.Http.Client.IdentityModel.Web/Volo/Abp/Http/Client/IdentityModel/Web/AbpHttpClientIdentityModelWebModule.cs

@ -0,0 +1,12 @@
using Volo.Abp.Modularity;
namespace Volo.Abp.Http.Client.IdentityModel.Web
{
[DependsOn(
typeof(AbpHttpClientIdentityModelModule)
)]
public class AbpHttpClientIdentityModelWebModule : AbpModule
{
}
}

48
framework/src/Volo.Abp.Http.Client.IdentityModel.Web/Volo/Abp/Http/Client/IdentityModel/Web/HttpContextIdentityModelRemoteServiceHttpClientAuthenticator.cs

@ -0,0 +1,48 @@
using System.Threading.Tasks;
using IdentityModel.Client;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Http.Client.Authentication;
using Volo.Abp.IdentityModel;
namespace Volo.Abp.Http.Client.IdentityModel.Web
{
[Dependency(ReplaceServices = true)]
public class HttpContextIdentityModelRemoteServiceHttpClientAuthenticator : IdentityModelRemoteServiceHttpClientAuthenticator
{
public IHttpContextAccessor HttpContextAccessor { get; set; }
public HttpContextIdentityModelRemoteServiceHttpClientAuthenticator(
IIdentityModelAuthenticationService identityModelAuthenticationService)
: base(identityModelAuthenticationService)
{
}
public override async Task Authenticate(RemoteServiceHttpClientAuthenticateContext context)
{
if (context.RemoteService.GetUseCurrentAccessToken() != false)
{
var accessToken = await GetAccessTokenFromHttpContextOrNullAsync();
if (accessToken != null)
{
context.Request.SetBearerToken(accessToken);
return;
}
}
await base.Authenticate(context);
}
protected virtual async Task<string> GetAccessTokenFromHttpContextOrNullAsync()
{
var httpContext = HttpContextAccessor?.HttpContext;
if (httpContext == null)
{
return null;
}
return await httpContext.GetTokenAsync("access_token");
}
}
}

6
framework/src/Volo.Abp.Http.Client.IdentityModel/Volo.Abp.Http.Client.IdentityModel.csproj

@ -1,18 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Abp.Http.Client.IdentityModel</AssemblyName>
<PackageId>Volo.Abp.Http.Client.IdentityModel</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>

28
framework/src/Volo.Abp.Http.Client.IdentityModel/Volo/Abp/Http/Client/IdentityModel/IdentityModelRemoteServiceHttpClientAuthenticator.cs

@ -1,7 +1,4 @@
using System.Threading.Tasks;
using IdentityModel.Client;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Http.Client.Authentication;
using Volo.Abp.IdentityModel;
@ -11,8 +8,6 @@ namespace Volo.Abp.Http.Client.IdentityModel
[Dependency(ReplaceServices = true)]
public class IdentityModelRemoteServiceHttpClientAuthenticator : IRemoteServiceHttpClientAuthenticator, ITransientDependency
{
public IHttpContextAccessor HttpContextAccessor { get; set; }
protected IIdentityModelAuthenticationService IdentityModelAuthenticationService { get; }
public IdentityModelRemoteServiceHttpClientAuthenticator(
@ -21,33 +16,12 @@ namespace Volo.Abp.Http.Client.IdentityModel
IdentityModelAuthenticationService = identityModelAuthenticationService;
}
public async Task Authenticate(RemoteServiceHttpClientAuthenticateContext context)
public virtual async Task Authenticate(RemoteServiceHttpClientAuthenticateContext context)
{
if (context.RemoteService.GetUseCurrentAccessToken() != false)
{
var accessToken = await GetAccessTokenFromHttpContextOrNullAsync();
if (accessToken != null)
{
context.Request.SetBearerToken(accessToken);
return;
}
}
await IdentityModelAuthenticationService.TryAuthenticateAsync(
context.Client,
context.RemoteService.GetIdentityClient()
);
}
protected virtual async Task<string> GetAccessTokenFromHttpContextOrNullAsync()
{
var httpContext = HttpContextAccessor?.HttpContext;
if (httpContext == null)
{
return null;
}
return await httpContext.GetTokenAsync("access_token");
}
}
}

6
framework/src/Volo.Abp.Http.Client/Volo.Abp.Http.Client.csproj

@ -1,18 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Abp.Http.Client</AssemblyName>
<PackageId>Volo.Abp.Http.Client</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>

19
framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/ApiDescriptionFinder.cs

@ -24,7 +24,7 @@ namespace Volo.Abp.Http.Client.DynamicProxying
};
public ApiDescriptionFinder(
IApiDescriptionCache cache,
IApiDescriptionCache cache,
IDynamicProxyHttpClientFactory httpClientFactory)
{
Cache = cache;
@ -57,7 +57,7 @@ namespace Volo.Abp.Http.Client.DynamicProxying
for (int i = 0; i < methodParameters.Length; i++)
{
if (action.ParametersOnMethod[i].TypeAsString != methodParameters[i].ParameterType.GetFullNameWithAssemblyName())
if (!TypeMatches(action.ParametersOnMethod[i], methodParameters[i]))
{
found = false;
break;
@ -104,5 +104,20 @@ namespace Volo.Abp.Http.Client.DynamicProxying
return (ApplicationApiDescriptionModel)result;
}
}
protected virtual bool TypeMatches(MethodParameterApiDescriptionModel actionParameter, ParameterInfo methodParameter)
{
return NormalizeTypeName(actionParameter.TypeAsString) ==
NormalizeTypeName(methodParameter.ParameterType.GetFullNameWithAssemblyName());
}
protected virtual string NormalizeTypeName(string typeName)
{
const string placeholder = "%COREFX%";
const string netCoreLib = "System.Private.CoreLib";
const string netFxLib = "mscorlib";
return typeName.Replace(netCoreLib, placeholder).Replace(netFxLib, placeholder);
}
}
}

2
framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/AbpIdentityModelModule.cs

@ -13,6 +13,8 @@ namespace Volo.Abp.IdentityModel
{
var configuration = context.Services.GetConfiguration();
context.Services.AddHttpClient();
Configure<AbpIdentityClientOptions>(configuration);
}
}

3
framework/src/Volo.Abp.Quartz/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
framework/src/Volo.Abp.Quartz/FodyWeavers.xsd

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

25
framework/src/Volo.Abp.Quartz/Volo.Abp.Quartz.csproj

@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Abp.Quartz</AssemblyName>
<PackageId>Volo.Abp.Quartz</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Quartz" Version="3.0.7" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Core\Volo.Abp.Core.csproj" />
</ItemGroup>
</Project>

41
framework/src/Volo.Abp.Quartz/Volo/Abp/Quartz/AbpQuartzJobFactory.cs

@ -0,0 +1,41 @@
using System;
using System.Collections.Concurrent;
using Microsoft.Extensions.DependencyInjection;
using Quartz;
using Quartz.Spi;
namespace Volo.Abp.Quartz
{
/// <summary>
/// Get the job from the dependency injection
/// </summary>
public class AbpQuartzJobFactory : IJobFactory
{
private readonly IServiceProvider _serviceProvider;
private readonly ConcurrentDictionary<IJob, IServiceScope> _scopes = new ConcurrentDictionary<IJob, IServiceScope>();
public AbpQuartzJobFactory(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
var scope = _serviceProvider.CreateScope();
var job = scope.ServiceProvider.GetRequiredService(bundle.JobDetail.JobType) as IJob;
if (job == null)
{
throw new ArgumentException("Given job does not implement IJob");
}
_scopes.TryAdd(job, scope);
return job;
}
public void ReturnJob(IJob job)
{
_scopes.TryRemove(job, out var serviceScope);
serviceScope?.Dispose();
}
}
}

34
framework/src/Volo.Abp.Quartz/Volo/Abp/Quartz/AbpQuartzModule.cs

@ -0,0 +1,34 @@
using Microsoft.Extensions.DependencyInjection;
using Quartz;
using Quartz.Impl;
using Quartz.Spi;
using Volo.Abp.Modularity;
using Volo.Abp.Threading;
namespace Volo.Abp.Quartz
{
public class AbpQuartzModule : AbpModule
{
private IScheduler _scheduler;
public override void ConfigureServices(ServiceConfigurationContext context)
{
var options = context.Services.ExecutePreConfiguredActions<AbpQuartzPreOptions>();
context.Services.AddSingleton(AsyncHelper.RunSync(() => new StdSchedulerFactory(options.Properties).GetScheduler()));
context.Services.AddSingleton(typeof(IJobFactory), typeof(AbpQuartzJobFactory));
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
_scheduler = context.ServiceProvider.GetService<IScheduler>();
_scheduler.JobFactory = context.ServiceProvider.GetService<IJobFactory>();
_scheduler.Start();
}
public override void OnApplicationShutdown(ApplicationShutdownContext context)
{
//TODO: ABP may provide two methods for application shutdown: OnPreApplicationShutdown & OnApplicationShutdown
_scheduler.Shutdown();
}
}
}

14
framework/src/Volo.Abp.Quartz/Volo/Abp/Quartz/AbpQuartzPreOptions.cs

@ -0,0 +1,14 @@
using System.Collections.Specialized;
namespace Volo.Abp.Quartz
{
public class AbpQuartzPreOptions
{
public NameValueCollection Properties { get; set; }
public AbpQuartzPreOptions()
{
Properties = new NameValueCollection();
}
}
}

7
framework/src/Volo.Abp.Security/System/Security/Principal/AbpClaimsIdentityExtensions.cs

@ -17,8 +17,11 @@ namespace System.Security.Principal
{
return null;
}
return Guid.Parse(userIdOrNull.Value);
if (Guid.TryParse(userIdOrNull.Value, out Guid result))
{
return result;
}
return null;
}
public static Guid? FindUserId([NotNull] this IIdentity identity)

1
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditTestController.cs

@ -5,7 +5,6 @@ using Volo.Abp.Auditing;
namespace Volo.Abp.AspNetCore.Mvc.Auditing
{
[Route("api/audit-test")]
[Audited]
public class AuditTestController : AbpController
{
private readonly AbpAuditingOptions _options;

59
framework/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/BasicThemeDemoMenuContributor.cs

@ -17,12 +17,61 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo
private void AddMainMenuItems(MenuConfigurationContext context)
{
context.Menu.AddItem(
new ApplicationMenuItem("BasicThemeDemo.Components", "Components")
.AddItem(
new ApplicationMenuItem("BasicThemeDemo.Components.Buttons", "Buttons", url: "/Components/Buttons")
)
var menuItem = new ApplicationMenuItem("BasicThemeDemo.Components", "Components");
menuItem.AddItem(
new ApplicationMenuItem("BasicThemeDemo.Components.Alerts", "Alerts", url: "/Components/Alerts")
);
menuItem.AddItem(
new ApplicationMenuItem("BasicThemeDemo.Components.Badges", "Badges", url: "/Components/Badges")
);
menuItem.AddItem(
new ApplicationMenuItem("BasicThemeDemo.Components.Borders", "Borders", url: "/Components/Borders")
);
menuItem.AddItem(
new ApplicationMenuItem("BasicThemeDemo.Components.Breadcrumbs", "Breadcrumbs", url: "/Components/Breadcrumbs")
);
menuItem.AddItem(
new ApplicationMenuItem("BasicThemeDemo.Components.Buttons", "Buttons", url: "/Components/Buttons")
);
menuItem.AddItem(
new ApplicationMenuItem("BasicThemeDemo.Components.Cards", "Cards", url: "/Components/Cards")
);
menuItem.AddItem(
new ApplicationMenuItem("BasicThemeDemo.Components.Collapse", "Collapse", url: "/Components/Collapse")
);
//menuItem.AddItem(
// new ApplicationMenuItem("BasicThemeDemo.Components.Dropdowns", "Dropdowns", url: "/Components/Dropdowns")
//);
menuItem.AddItem(
new ApplicationMenuItem("BasicThemeDemo.Components.Grids", "Grids", url: "/Components/Grids")
);
menuItem.AddItem(
new ApplicationMenuItem("BasicThemeDemo.Components.ListGroups", "List Groups", url: "/Components/ListGroups")
);
menuItem.AddItem(
new ApplicationMenuItem("BasicThemeDemo.Components.Modals", "Modals", url: "/Components/Modals")
);
menuItem.AddItem(
new ApplicationMenuItem("BasicThemeDemo.Components.Navs", "Navs", url: "/Components/Navs")
);
menuItem.AddItem(
new ApplicationMenuItem("BasicThemeDemo.Components.Popovers", "Popovers", url: "/Components/Popovers")
);
menuItem.AddItem(
new ApplicationMenuItem("BasicThemeDemo.Components.ProgressBars", "Progress Bars", url: "/Components/ProgressBars")
);
menuItem.AddItem(
new ApplicationMenuItem("BasicThemeDemo.Components.Tables", "Tables", url: "/Components/Tables")
);
menuItem.AddItem(
new ApplicationMenuItem("BasicThemeDemo.Components.Tabs", "Tabs", url: "/Components/Tabs")
);
menuItem.AddItem(
new ApplicationMenuItem("BasicThemeDemo.Components.Tooltips", "Tooltips", url: "/Components/Tooltips")
);
context.Menu.AddItem(menuItem);
}
}
}

8
framework/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/Pages/Components/Alerts/Index.cshtml

@ -0,0 +1,8 @@
@page
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.Shared.Demos.AlertsDemo
@model Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo.Pages.Components.Alerts.IndexModel
<h2>Alerts</h2>
<p>Based on <a href="https://getbootstrap.com/docs/4.1/components/alerts/" target="_blank"> Bootstrap Alert</a>.</p>
@await Component.InvokeAsync(typeof(AlertsDemoViewComponent))

12
framework/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/Pages/Components/Alerts/Index.cshtml.cs

@ -0,0 +1,12 @@
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo.Pages.Components.Alerts
{
public class IndexModel : PageModel
{
public void OnGet()
{
}
}
}

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

Loading…
Cancel
Save