Browse Source

Merge pull request #4 from abpframework/master

pull/1162/head
Nokecy 8 years ago
committed by GitHub
parent
commit
292f2de2ff
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      .gitignore
  2. 2
      abp_io/Volo.AbpWebSite.sln
  3. 1
      abp_io/src/Volo.AbpWebSite.Web/Pages/Index.cshtml
  4. 1
      abp_io/src/Volo.AbpWebSite.Web/Volo.AbpWebSite.Web.csproj
  5. 4
      abp_io/src/Volo.AbpWebSite.Web/compilerconfig.json
  6. 3
      abp_io/src/Volo.AbpWebSite.Web/wwwroot/scss/vs.css
  7. 2
      abp_io/src/Volo.AbpWebSite.Web/wwwroot/scss/vs.min.css
  8. 10
      abp_io/src/Volo.AbpWebSite.Web/wwwroot/scss/vs.scss
  9. 2
      common.props
  10. 170
      docs/en/Apps/VoloDocs.md
  11. 4
      docs/en/AspNetCore/Auto-API-Controllers.md
  12. 6
      docs/en/AspNetCore/Bundling-Minification.md
  13. 7
      docs/en/Modules/Docs.md
  14. 26
      docs/en/Nightly-Builds.md
  15. 26
      docs/en/Samples/Microservice-Demo.md
  16. 4
      docs/en/docs-nav.json
  17. BIN
      docs/en/images/docs-create-project.jpg
  18. BIN
      docs/en/images/github-access-token-private-repo.jpg
  19. BIN
      docs/en/images/github-access-token-public-repo.jpg
  20. BIN
      docs/en/images/github-myusername.jpg
  21. BIN
      docs/en/images/microservice-sample-update-database-authserver.png
  22. BIN
      docs/en/images/microservice-sample-update-database-products.png
  23. BIN
      docs/en/images/night-build-add-nuget-package.png
  24. BIN
      docs/en/images/night-build-add-nuget-source.png
  25. BIN
      docs/en/images/volodocs-iis-add-website.png
  26. BIN
      docs/en/images/volodocs-iis-application-pool.png
  27. 46
      docs/zh-Hans/AspNetCore/Bundling-Minification.md
  28. 25
      docs/zh-Hans/Nightly-Builds.md
  29. 4
      docs/zh-Hans/docs-nav.json
  30. BIN
      docs/zh-Hans/images/night-build-add-nuget-package.png
  31. BIN
      docs/zh-Hans/images/night-build-add-nuget-source.png
  32. 2
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/MultiTenancy/MultiTenancyOptionsExtensions.cs
  33. 3
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs
  34. 8
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/pt-BR.json
  35. 5
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/zh-Hans.json
  36. 4
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/modal-manager.js
  37. 30
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/jquery/jquery-extensions.js
  38. 1
      framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/RolePermissionValueProvider.cs
  39. 2
      framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AsyncCrudAppService.cs
  40. 6
      framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs
  41. 28
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/CurrentClaimsPrincipalTenantResolveContributor.cs
  42. 24
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/CurrentUserTenantResolveContributor.cs
  43. 2
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantResolveOptions.cs
  44. 3
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json
  45. 17
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pt-BR.json
  46. 3
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/tr.json
  47. 3
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/pt-BR.json
  48. 7
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/zh-Hans.json
  49. 3
      framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/en.json
  50. 2
      framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/pt-BR.json
  51. 7
      framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/zh-Hans.json
  52. 2
      framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/pt-BR.json
  53. 7
      framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/zh-Hans.json
  54. 5
      framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/pt-BR.json
  55. 11
      framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/zh-Hans.json
  56. 11
      modules/audit-logging/test/Volo.Abp.AuditLogging.EntityFrameworkCore.Tests/Volo/Abp/AuditLogging/EntityFrameworkCore/AuditLogRepository_Tests.cs
  57. 11
      modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/AuditLogRepository_Tests.cs
  58. 232
      modules/audit-logging/test/Volo.Abp.AuditLogging.TestBase/Volo/Abp/AuditLogging/AuditLogRepository_Tests.cs
  59. 13
      modules/audit-logging/test/Volo.Abp.AuditLogging.TestBase/Volo/Abp/AuditLogging/AuditLogging_Repository_Resolve_Tests.cs
  60. 22
      modules/blogging/Volo.Blogging.sln
  61. 2
      modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Posts/PostWithDetailsDto.cs
  62. 1
      modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Posts/PostAppService.cs
  63. 2
      modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Blogs/IBlogRepository.cs
  64. 4
      modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/Post.cs
  65. 7
      modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Tagging/Tag.cs
  66. 5
      modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Blogs/EfCoreBlogRepository.cs
  67. 5
      modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Blogs/MongoBlogRepository.cs
  68. 1
      modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Tagging/MongoTagRepository.cs
  69. 391
      modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Detail.cshtml
  70. 53
      modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Index.cshtml
  71. 2
      modules/blogging/test/Volo.Blogging.Application.Tests/Volo.Blogging.Application.Tests.csproj
  72. 18
      modules/blogging/test/Volo.Blogging.Domain.Tests/Volo.Blogging.Domain.Tests.csproj
  73. 11
      modules/blogging/test/Volo.Blogging.Domain.Tests/Volo/Abp/Blogging/BloggingDomainTestBase.cs
  74. 12
      modules/blogging/test/Volo.Blogging.Domain.Tests/Volo/Abp/Blogging/BloggingDomainTestModule.cs
  75. 32
      modules/blogging/test/Volo.Blogging.Domain.Tests/Volo/Abp/Blogging/Blogs/Blog_Tests.cs
  76. 22
      modules/blogging/test/Volo.Blogging.Domain.Tests/Volo/Abp/Blogging/Comments/Comment_Tests.cs
  77. 65
      modules/blogging/test/Volo.Blogging.Domain.Tests/Volo/Abp/Blogging/Posts/Post_Tests.cs
  78. 64
      modules/blogging/test/Volo.Blogging.Domain.Tests/Volo/Abp/Blogging/Tagging/Tag_Tests.cs
  79. 71
      modules/blogging/test/Volo.Blogging.Domain.Tests/Volo/Abp/Blogging/Users/BlogUser_Test.cs
  80. 7
      modules/blogging/test/Volo.Blogging.EntityFrameworkCore.Tests/Volo/Blogging/Blogs/BlogRepository_Tests.cs
  81. 8
      modules/blogging/test/Volo.Blogging.EntityFrameworkCore.Tests/Volo/Blogging/Comments/CommentRepository_Tests.cs
  82. 6
      modules/blogging/test/Volo.Blogging.EntityFrameworkCore.Tests/Volo/Blogging/EntityFrameworkCore/BloggingEntityFrameworkCoreTestModule.cs
  83. 8
      modules/blogging/test/Volo.Blogging.EntityFrameworkCore.Tests/Volo/Blogging/Posts/PostRepository_Tests.cs
  84. 8
      modules/blogging/test/Volo.Blogging.EntityFrameworkCore.Tests/Volo/Blogging/Tagging/TagRepository_Tests.cs
  85. 19
      modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo.Blogging.MongoDB.Tests.csproj
  86. 8
      modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/Blogs/BlogRepository_Tests.cs
  87. 8
      modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/Comments/CommentRepository_Tests.cs
  88. 32
      modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/MongoDB/BloggingMongoDBTestModule.cs
  89. 8
      modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/Posts/PostRepository_Tests.cs
  90. 8
      modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/Tagging/TagRepository_Tests.cs
  91. 2
      modules/blogging/test/Volo.Blogging.TestBase/Volo/Blogging/BloggingTestData.cs
  92. 9
      modules/blogging/test/Volo.Blogging.TestBase/Volo/Blogging/BloggingTestDataBuilder.cs
  93. 54
      modules/blogging/test/Volo.Blogging.TestBase/Volo/Blogging/Comments/CommentRepository_Tests.cs
  94. 41
      modules/blogging/test/Volo.Blogging.TestBase/Volo/Blogging/Posts/PostRepository_Tests.cs
  95. 73
      modules/blogging/test/Volo.Blogging.TestBase/Volo/Blogging/Tagging/TagRepository_Tests.cs
  96. 13
      modules/blogging/test/Volo.Blogging.TestBase/Volo/Blogging/Users/BlogUserRepository_Tests.cs
  97. 6
      modules/docs/README.md
  98. 76
      modules/docs/Volo.Docs.sln
  99. 4
      modules/docs/app/Volo.DocsTestApp/Pages/Index.cshtml
  100. 16
      modules/docs/app/Volo.DocsTestApp/Pages/Index.cshtml.cs

2
.gitignore

@ -267,7 +267,7 @@ framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Logs/*.*
modules/blog/app/Volo.BlogTestApp/Logs/*.*
modules/blogging/app/Volo.BloggingTestApp/Logs/*.*
modules/blogging/app/Volo.BloggingTestApp/wwwroot/files/*.*
modules/docs/app/Volo.DocsTestApp/Logs/*.*
modules/docs/app/VoloDocs.Web/Logs/*.*
samples/BookStore/src/Acme.BookStore.Web/Logs/*.*
templates/module/app/MyCompanyName.MyProjectName.DemoApp/Logs/*.*
templates/mvc/src/MyCompanyName.MyProjectName.Web/Logs/*.*

2
abp_io/Volo.AbpWebSite.sln

@ -11,7 +11,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.AbpWebSite.Application
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.AbpWebSite.EntityFrameworkCore", "src\Volo.AbpWebSite.EntityFrameworkCore\Volo.AbpWebSite.EntityFrameworkCore.csproj", "{028C05DB-61BF-41EF-B9AD-614A43CD0A7F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Utils.SolutionTemplating", "src\Volo.Utils.SolutionTemplating\Volo.Utils.SolutionTemplating.csproj", "{742FCDDD-537C-42CC-AF16-A92C094D4B1D}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Utils.SolutionTemplating", "src\Volo.Utils.SolutionTemplating\Volo.Utils.SolutionTemplating.csproj", "{742FCDDD-537C-42CC-AF16-A92C094D4B1D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution

1
abp_io/src/Volo.AbpWebSite.Web/Pages/Index.cshtml

@ -1,5 +1,4 @@
@page
@using Volo.AbpWebSite
@model Volo.AbpWebSite.Pages.IndexModel
@{
Layout = "~/Pages/Shared/HomePageLayout.cshtml";

1
abp_io/src/Volo.AbpWebSite.Web/Volo.AbpWebSite.Web.csproj

@ -54,6 +54,7 @@
<ItemGroup>
<Folder Include="Downloads\" />
<Folder Include="wwwroot\assets\applications\" />
</ItemGroup>
</Project>

4
abp_io/src/Volo.AbpWebSite.Web/compilerconfig.json

@ -2,5 +2,9 @@
{
"outputFile": "wwwroot/scss/vs.css",
"inputFile": "wwwroot/scss/vs.scss"
},
{
"outputFile": "Pages/Applications.css",
"inputFile": "Pages/Applications.scss"
}
]

3
abp_io/src/Volo.AbpWebSite.Web/wwwroot/scss/vs.css

@ -694,3 +694,6 @@ span.code-arrow {
body {
background-size: cover; }
.applications-container .card-body p {
min-height: 7em; }

2
abp_io/src/Volo.AbpWebSite.Web/wwwroot/scss/vs.min.css

File diff suppressed because one or more lines are too long

10
abp_io/src/Volo.AbpWebSite.Web/wwwroot/scss/vs.scss

@ -19,4 +19,12 @@
body {
background-size: cover;
}
}
.applications-container {
.card-body {
p {
min-height: 7em;
}
}
}

2
common.props

@ -1,7 +1,7 @@
<Project>
<PropertyGroup>
<LangVersion>latest</LangVersion>
<Version>0.15.0</Version>
<Version>0.16.0</Version>
<NoWarn>$(NoWarn);CS1591</NoWarn>
<PackageIconUrl>https://abp.io/assets/abp_nupkg.png</PackageIconUrl>
<PackageProjectUrl>https://abp.io</PackageProjectUrl>

170
docs/en/Apps/VoloDocs.md

@ -0,0 +1,170 @@
# VoloDocs
## What is VoloDocs?
VoloDocs is a cross-platform web application that allows you to easily create beautiful documentation and build developer communities. It simplifies software documentation with the help of GitHub integration. You use the power of GitHub for versioning, hosting of your docs. You let your users to edit a document.
## Main Features
- Serves documents from your GitHub repository.
- Supports Markdown / HTML document formatting.
- Supports versioning (integrated to GitHub releases).
- Supports multiple projects.
- Allows users to edit a document on GitHub.
- Cross-platform; deployable to Windows / Linux / macOS.
## GitHub Repository
It's free & open-source. You can browse VoloDocs source-code and contribute on GitHub:
https://github.com/abpframework/abp/tree/master/modules/docs
## Download
You can download the VoloDocs release from the following link:
http://apps.abp.io/VoloDocs/VoloDocs.zip *(will be ready soon...)*
## Folder Structure
When you extract the `VoloDocs.zip` file, you will see a `Web` folder and a `Migrator` folder. `Web` folder contains the website files and `Migrator` contains the application to build your database. Before publishing your website, you need to create a new database or update your existing database to the latest. If this is the first time you install VoloDocs, `Migrator` will create a new database for you, otherwise it updates to the latest version. The only setting you need to configure, is the `ConnectionString` which is located in the `appsettings.json` file. See the next section to learn how to configure your VoloDocs application.
## Steps by Step Deployment
- ### Database Migration
To update your existing database or create your initial database, go to `Migrator` folder in your VoloDocs directory.
Open `appsettings.json` in your text editor and set your database connection string. If you don't know how to write the connection string for your database system, you can check out https://www.connectionstrings.com/.
After you set your connection string, run `Migrate.bat` for Windows platform and `VoloDocs.Migrator` for other operating systems. That's it now configure your website.
- ### Configuring Website
Go to `Web` folder in your VoloDocs directory. Open `appsettings.json` in your text editor. Set your connection string (same as in the `Migrator`'s `appsettings.json`). Set `title` of your website. This will be written on the left-upper corner of your website. That's it! Now you can publish your website.
If you want to run
- ### Publishing Website
In the previous step, you created or updated your database. Ensure that your database exists on the specified connection string.
- #### Publishing to IIS
- Move `Web` folder to your `wwwroot ` folder.
- Rename `Web` folder to `VoloDocs` (Now you have `C:\inetpub\wwwroot\VoloDocs`).![Add IIS Website](../images/volodocs-iis-add-website.png)
- The `VoloDocs` application pool is being created automatically. Open **Application Pools** and double click `VoloDocs` application pool and set
- **.NET CLR version**: `No Managed Code`
- **Managed pipeline mode**: `Integrated`
![Add IIS Website](../images/volodocs-iis-application-pool.png)
- If you get the below error, it means don't have the hosting bundle installed on the server. See [this document](https://docs.microsoft.com/aspnet/core/host-and-deploy/iis/#install-the-net-core-hosting-bundle) to learn how to install it or [download Hosting Bundle](https://www.microsoft.com/net/permalink/dotnetcore-current-windows-runtime-bundle-installer) and run on your server.
```
Handler "aspNetCore" has a bad module "AspNetCoreModuleV2" in its module list using IIS
```
- Further information about hosting VoloDocs check out [Microsoft's official document for hosting ASP.NET Core application on IIS](https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/iis).
- #### Publishing to Azure
Microsoft has a good document on how to deploy your ASP.NET Core web app to Azure App Service. We recommend you to read this document https://docs.microsoft.com/en-us/azure/app-service/app-service-web-get-started-dotnet.
- #### Running the Application From Command Line
Alternatively you can run the application from command line, navigate to `VoloDocs\Web` folder and run the below command in your command line for Windows:
```powershell
dotnet VoloDocs.Web.dll
```
- ### First Run
To start the website, navigate to your address (as configured in the previous section).
When you first open the website, you need to create a project.
#### Creating a Project
Go to the following address to create project
- `http://<yourwebsite>/Account/Login?returnUrl=/Docs/Admin/Projects`
##### Default credentials
To login the admin side, use the following credentials:
* **Username**: `admin`
* **Password**: `1q2w3E*`
##### An example project definition
Here's a sample project information that uses GitHub source.
We will configure the VoloDocs to show ABP Framework's documentation that's stored in GitHub.
Here's the link to ABP Framework GitHub docs folder:
https://github.com/abpframework/abp/tree/master/docs/en
* **Name**: `ABP Framework`
* **Short name**: `abp`
* **Format**: `markdown`
* **Default document name**: `Index`
* **Navigation document name**: `docs-nav.json` ([see the sample navigation](https://github.com/abpframework/abp/blob/master/docs/en/docs-nav.json))
* **Minimum version**: *leave empty* *(hides the previous versions)*
* **Main web site URL**: `/`
* **Latest version branch name**: leave empty ()
* **GitHub root URL**: `https://github.com/abpframework/abp/tree/{version}/docs/en/`
* **GitHub access token**: [see how to retrieve GitHub access token](#retrieving-github-access-token)
* **GitHub user agent**: [see how to learn your GitHub username](#learn-your-github-username)
![Creating a new project](../images/docs-create-project.jpg)
##### Retrieving GitHub Access Token
To create a personal access token in GitHub, you need to visit the **Settings** of the user account and under **Developer settings** you will find **Personal access tokens**. Select **Generate new token**, enter in a name as the Token description and enable the repo checkbox. Alternatively, to enter generate new token, browse to https://github.com/settings/tokens/new.
###### Generate Token for Public Repositories
To access public repositories, check `public_repo` under the `repo` section. This will enable VoloDocs to access your public GitHub repositories. Click `Generate Token` button on the bottom of the page.
![Retrieve GitHub Access Token for Public Repo](../images/github-access-token-public-repo.jpg)
###### Generate Token for Private Repositories
To access public repositories, check all items under the `repo` section. This will enable VoloDocs to access your private GitHub repositories. Click `Generate Token` button on the bottom of the page.
![Retrieve GitHub Access Token for Private Repo](../images/github-access-token-private-repo.jpg)
###### Learn Your GitHub Username
To learn your GitHub username, click on your profile picture on the top-right corner of the GitHub page. You will see your username right after the text "Signed in as ..."
![Your GitHub Username](../images/github-myusername.jpg)
After you save the project, go to root website address and you will see your documentation.
`http://<yourwebsite>/documents`

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

@ -80,7 +80,7 @@ Then the route for getting a book will be '**/api/volosoft/book-store/book/{id}*
* Removing '**Async**' postfix. If the method name is 'GetPhonesAsync' then it becomes 'GetPhones'.
* Removing **HTTP method prefix**. 'GetList', 'GetAll', 'Get', 'Put', 'Update', 'Delete', 'Remove', 'Create', 'Add', 'Insert', 'Post' and 'Patch' prefixes are removed based on the selected HTTP method. So, 'GetPhones' becomes 'Phones' since 'Get' prefix is a duplicate for a GET request.
* Converting the result to **camelCase**.
* If the resulting action name is **empty** then it's not added to the route. If it's not empty, it's added to the route (like '/phones'). For 'GetAllAsync' method name it will be empty, for 'GetPhonesAsync' method name is will be 'phones'.
* If the resulting action name is **empty** then it's not added to the route. If it's not empty, it's added to the route (like '/phones'). For 'GetAllAsync' method name it will be empty, for 'GetPhonesAsync' method name it will be 'phones'.
* Normalization can be customized by setting the `UrlActionNameNormalizer` option. It's an action delegate that is called for every method.
* If there is another parameter with 'Id' postfix, then it's also added to the route as the final route segment (like '/phoneId').
@ -135,4 +135,4 @@ public class PersonAppService : ApplicationService
}
````
Disabled `IsMetadataEnabled` which hides this service from API explorer and it will not be discoverable. However, it still can be usable for the clients know the exact API path/route.
Disabled `IsMetadataEnabled` which hides this service from API explorer and it will not be discoverable. However, it still can be usable for the clients know the exact API path/route.

6
docs/en/AspNetCore/Bundling-Minification.md

@ -194,7 +194,7 @@ services.Configure<BundlingOptions>(options =>
options
.ScriptBundles
.Configure("MyGlobalBundle", bundle => {
bundle.AddContributors(typeof(MyExtensionStyleBundleContributor));
bundle.AddContributors(typeof(MyExtensionGlobalStyleContributor));
});
});
````
@ -279,9 +279,9 @@ public class MyExtensionStyleBundleContributor : BundleContributor
Using the built-in contributors for standard packages;
* Prevents you typing **invalid the resource paths**.
* Prevents you typing **the invalid resource paths**.
* Prevents changing your contributor if the resource **path changes** (the dependant contributor will handle it).
* Prevents multiple modules adding the **duplicate the files**.
* Prevents multiple modules adding the **duplicate files**.
* Manages **dependencies recursively** (adds dependencies of dependencies, if necessary).
#### Volo.Abp.AspNetCore.Mvc.UI.Packages Package

7
docs/en/Modules/Docs.md

@ -472,4 +472,9 @@ The upper sample `JSON` file renders the below navigation menu as `HTML`.
Finally a new Docs Module is added to your project which is feeded with GitHub.
Finally a new Docs Module is added to your project which is feeded with GitHub.
## Next
Docs Module is also available as a standalone application. Check out [VoloDocs](../Apps/VoloDocs).

26
docs/en/Nightly-Builds.md

@ -0,0 +1,26 @@
# Nightly Builds
All framework & module packages are deployed to MyGet every night in weekdays. So, you can use or test the latest code without waiting the next release.
## Configure Visual Studio
> Requires Visual Studio 2017+
1. Go to `Tools > Options > NuGet Package Manager > Package Source`.
2. Click the green `+` icon.
3. Set `ABP Nightly` as *Name* and `https://www.myget.org/F/abp-nightly/api/v3/index.json` as the *Source* as shown below:
![night-build-add-nuget-source](images/night-build-add-nuget-source.png)
4. Click the `Update` button.
5. Click the `OK` button to save changes.
## Install Package
Now, you can install preview / nightly packages to your project from Nuget Browser or Package Manager Console.
![night-build-add-nuget-package](images/night-build-add-nuget-package.png)
1. In the nuget browser, select "Include prereleases".
2. Change package source to "All".
3. Search a package. You will see prereleases of the package formatted as `(VERSION)-preview(DATE)` (like *v0.16.0-preview20190401* in this sample).
4. You can click to the `Install` button to add package to your project.

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

@ -116,11 +116,29 @@ To be able to run the solution from source code, following tools should be insta
* Run `dotnet restore` from the command line inside the `samples\MicroserviceDemo` folder.
* Build the solution in Visual Studio.
#### Restore Databases
#### Create Databases
Open `MsDemo_Identity.zip` and `MsDemo_ProductManagement.zip` inside the `samples\MicroserviceDemo\databases` folder and restore to the SQL Server.
MongoDB database is created dynamically, however you need to create database schemas for SQL server databases. The solution is configured to use Entity Core Code First migrations, so you can easily create databases.
> Notice that: These databases have EF Core migrations in the solution, however they don't have seed data, especially required for IdentityServer4 configuration. So, restoring the databases is much more easier.
There are two SQL server databases in this solution.
##### MsDemo_Identity Database
* Right click to the `AuthServer.Host` project and click to the `Set as startup project`.
* Open the **Package Manager Console** (Tools -> Nuget Package Manager -> Package Manager Console)
* Select `AuthServer.Host` as the **Default project**.
* Run `Update-Database` command.
![microservice-sample-update-database-authserver](../images/microservice-sample-update-database-authserver.png)
##### MsDemo_ProductManagement
- Right click to the `ProductService.Host` project and click to the `Set as startup project`.
- Open the **Package Manager Console** (Tools -> Nuget Package Manager -> Package Manager Console)
- Select `ProductService.Host` as the **Default project**.
- Run `Update-Database` command.
![microservice-sample-update-database-products](../images/microservice-sample-update-database-products.png)
#### Run Projects
@ -136,6 +154,8 @@ Run the projects with the following order (right click to each project, set as s
* BackendAdminApp.Host
* PublicWebSite.Host
When you run projects, they will add some initial demo data to their databases.
## A Brief Overview of the Solution
The Visual Studio solution consists of multiple projects each have different roles in the system:

4
docs/en/docs-nav.json

@ -276,6 +276,10 @@
{
"text": "Testing"
},
{
"text": "Nightly Builds",
"path": "Nightly-Builds.md"
},
{
"text": "Contribution Guide",
"path": "Contribution/Index.md"

BIN
docs/en/images/docs-create-project.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

BIN
docs/en/images/github-access-token-private-repo.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 KiB

BIN
docs/en/images/github-access-token-public-repo.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 KiB

BIN
docs/en/images/github-myusername.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

BIN
docs/en/images/microservice-sample-update-database-authserver.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

BIN
docs/en/images/microservice-sample-update-database-products.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

BIN
docs/en/images/night-build-add-nuget-package.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
docs/en/images/night-build-add-nuget-source.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
docs/en/images/volodocs-iis-add-website.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
docs/en/images/volodocs-iis-application-pool.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

46
docs/zh-Hans/AspNetCore/Bundling-Minification.md

@ -196,7 +196,7 @@ services.Configure<BundlingOptions>(options =>
options
.ScriptBundles
.Configure("MyGlobalBundle", bundle => {
bundle.AddContributors(typeof(MyExtensionStyleBundleContributor));
bundle.AddContributors(typeof(MyExtensionGlobalStyleContributor));
});
});
````
@ -214,7 +214,7 @@ services.Configure<BundlingOptions>(options =>
`abp-style`和`abp-script`标签可以使用`type`属性(而不是`src`属性), 如本示例所示. 添加bundle贡献者时, 其依赖关系也会自动添加到bundle中.
#### Contributor Dependencies
#### 贡献者依赖关系
bundle贡献者可以与其他贡献者具有一个或多个依赖关系.
例如:
@ -227,9 +227,39 @@ public class MyExtensionStyleBundleContributor : BundleContributor
}
````
添加bundle贡献者时,其依赖关系将 **自动并递归** 添加. **依赖顺序** 通过阻止 **重复** 添加的依赖关系. 即使它们处于分离的束中,也会阻止重复. ABP在页面中组织所有bundle并消除重复.
添加bundle贡献者时,其依赖关系将 **自动并递归** 添加. **依赖顺序** 通过阻止 **重复** 添加的依赖关系. 即使它们处于分离的bundle中,也会阻止重复. ABP在页面中组织所有bundle并消除重复.
创建贡献者和定义依赖关系是一种跨不同模块组织包创建的方法.
创建贡献者和定义依赖关系是一种跨不同模块组织bundle创建的方法.
#### 贡献者扩展
在某些高级应用场景中, 当用到一个bundle贡献者时,你可能想做一些额外的配置. 贡献者扩展可以和被扩展的贡献者无缝衔接.
下面的示例为 prism.js 脚本库添加一些样式:
````csharp
public class MyPrismjsStyleExtension : BundleContributor
{
public override void ConfigureBundle(BundleConfigurationContext context)
{
context.Files.AddIfNotContains("/libs/prismjs/plugins/toolbar/prism-toolbar.css");
}
}
````
然后你可以配置 `BundleContributorOptions` 去扩展已存在的 `PrismjsStyleBundleContributor`.
````csharp
Configure<BundleContributorOptions>(options =>
{
options
.Extensions<PrismjsStyleBundleContributor>()
.Add<MyPrismjsStyleExtension>();
});
````
任何时候当 `PrismjsStyleBundleContributor` 被添加到bundle中时, `MyPrismjsStyleExtension` 也会被自动添加.
#### 访问 IServiceProvider
@ -239,7 +269,7 @@ public class MyExtensionStyleBundleContributor : BundleContributor
将特定的NPM包资源(js,css文件)添加到包中对于该包非常简单. 例如, 你总是为bootstrap NPM包添加`bootstrap.css`文件.
所有[标准NPM包](Client-Side-Package-Management.md)都有内置的贡献者. 例如,如果你的贡献者依赖于引导程序,你可以声明它,而不是自己添加bootstrap.css.
所有[标准NPM包](Client-Side-Package-Management.md)都有内置的贡献者. 例如,如果你的贡献者依赖于bootstrap,你可以声明它,而不是自己添加bootstrap.css.
````C#
[DependsOn(typeof(BootstrapStyleContributor))] //Define the bootstrap style dependency
@ -261,7 +291,7 @@ public class MyExtensionStyleBundleContributor : BundleContributor
> 默认情况下已在启动模板安装此软件包. 大多数情况下,你不需要手动安装它.
标准包贡献者在`Volo.Abp.AspNetCore.Mvc.UI.Packages` NuGet包中定义.
安装到你的项目中:
将它安装到你的项目中:
````
install-package Volo.Abp.AspNetCore.Mvc.UI.Packages
@ -283,9 +313,9 @@ namespace MyCompany.MyProject
}
````
#### Bundle Inheritance
#### Bundle 继承
在某些特定情况下, 可能需要从其他bundle创建一个 **新** bundle **继承**, 从bundle继承(递归)继承该bundle的所有文件/贡献者. 然后派生的bundle可以添加或修改文件/贡献者**而无需修改**原始包.
在某些特定情况下, 可能需要从其他bundle创建一个 **新** bundle **继承**, 从bundle继承(递归)会继承该bundle的所有文件/贡献者. 然后派生的bundle可以添加或修改文件/贡献者**而无需修改**原始bundle.
例如:
````c#

25
docs/zh-Hans/Nightly-Builds.md

@ -0,0 +1,25 @@
# 每日构建
所有框架和模块包都每晚都部署到MyGet. 因此你可以使用或测试最新的代码,而无需等待下一个版本.
## 在Visual Studio配置
> 需要Visual Studio 2017以上
1. 在VS中打开: `工具 > 选项 > NuGet 包管理器 > 程序包源`
2. 单击绿色的`+`图标
3. 在底部输入名称(ABP Nightly)和并粘贴URL(`https://www.myget.org/F/abp-nightly/api/v3/index.json`)到源上.
![night-build-add-nuget-source](images/night-build-add-nuget-source.png)
3. 单击`更新`按钮
4. 点击`确定`按钮保存
## 安装包
现在, 你可以从**管理NuGet包** 或 **程序包管理器控制台** 将预览/夜间程序包安装到你的项目中.
![night-build-add-nuget-package](images/night-build-add-nuget-package.png)
1. 在nuget浏览中,选择"包括预发行版".
2. 将包源更改为`全部`.
3. 搜索nuget包. 你将看到包的预发布格式为`(VERSION)-preview(DATE)` (如本示例中的**v0.16.0-preview20190401**).
4. 你可以单击`安装`按钮将包添加到项目中.

4
docs/zh-Hans/docs-nav.json

@ -278,6 +278,10 @@
{
"text": "测试"
},
{
"text": "每日构建",
"path": "Nightly-Builds.md"
},
{
"text": "贡献指南",
"path": "Contribution/Index.md"

BIN
docs/zh-Hans/images/night-build-add-nuget-package.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
docs/zh-Hans/images/night-build-add-nuget-source.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

2
framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/MultiTenancy/MultiTenancyOptionsExtensions.cs

@ -8,7 +8,7 @@ namespace Volo.Abp.MultiTenancy
public static void AddDomainTenantResolver(this TenantResolveOptions options, string domainFormat)
{
options.TenantResolvers.InsertAfter(
r => r is CurrentClaimsPrincipalTenantResolveContributor,
r => r is CurrentUserTenantResolveContributor,
new DomainTenantResolveContributor(domainFormat)
);
}

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

@ -124,8 +124,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
return GetLabelAsHtmlUsingTagHelper(context, output) + GetRequiredSymbol(context, output);
}
protected virtual string GetRequiredSymbol(TagHelperContext context, TagHelperOutput output)
{
if (!TagHelper.DisplayRequiredSymbol)

8
framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/pt-BR.json

@ -1,9 +1,11 @@
{
"culture": "pt-BR",
"texts": {
"GivenTenantIsNotAvailable": "Tenant não está disponível: {0}",
"SwitchTenant": "Trocar tenant",
"GivenTenantIsNotAvailable": "Inquilino não está disponível: {0}",
"Tenant": "Inquilino",
"Switch": "trocar",
"Name": "Nome",
"SwitchTenantHint": "Deixe o campo de nome em branco para alternar para o lado do host."
"SwitchTenantHint": "Deixe o campo de nome em branco para alternar para o lado do host.",
"NotSelected": "Não selecionado"
}
}

5
framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/zh-Hans.json

@ -4,6 +4,9 @@
"GivenTenantIsNotAvailable": "给定的租户不可用: {0}",
"SwitchTenant": "切换租户",
"Name": "名称",
"SwitchTenantHint": "将name字段留空以切换到宿主端."
"SwitchTenantHint": "将name字段留空以切换到宿主端.",
"Tenant": "租户",
"Switch": "切换",
"NotSelected": "未选中"
}
}

4
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/modal-manager.js

@ -69,6 +69,10 @@ $.validator.defaults.ignore = ''; //TODO: Would be better if we can apply only f
//TODO: data-ajaxForm comparison seems wrong!
if (_$form.attr('data-ajaxForm') === undefined || _$form.attr('data-ajaxForm') === false) {
_$form.abpAjaxForm();
}
if (_$form.attr('data-check-form-on-close') === undefined || _$form.attr('data-check-form-on-close') != 'false') {
_$form.needConfirmationOnUnsavedClose(_$modal);
}
_$form.on('abp-ajax-success',

30
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/jquery/jquery-extensions.js

@ -3,6 +3,10 @@
return;
}
var localize = function (key) {
return abp.localization.getResource('AbpUi')(key);
};
/* A simple jQuery plug-in to make a button busy. */
$.fn.buttonBusy = function (isBusy) {
return $(this).each(function () {
@ -127,4 +131,30 @@
});
};
$.fn.needConfirmationOnUnsavedClose = function ($modal) {
var $form = $(this);
var formSaved = false;
var unEditedForm = JSON.stringify($form.serializeFormToObject());
$modal.on("hide.bs.modal", function (e) {
var currentForm = JSON.stringify($form.serializeFormToObject());
var thereAreUnsavedChanges = currentForm !== unEditedForm;
if (!formSaved && thereAreUnsavedChanges) {
e.preventDefault();
abp.message.confirm(localize('AreYouSureYouWantToCancelEditingWarningMessage'),
function (result) {
if (result) {
formSaved = true;
$modal.modal('hide');
}
});
}
});
$(this).on('abp-ajax-success',function () {
formSaved = true;
});
};
})(jQuery);

1
framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/RolePermissionValueProvider.cs

@ -19,6 +19,7 @@ namespace Volo.Abp.Authorization.Permissions
public override async Task<PermissionGrantResult> CheckAsync(PermissionValueCheckContext context)
{
var roles = context.Principal?.FindAll(AbpClaimTypes.Role).Select(c => c.Value).ToArray();
if (roles == null || !roles.Any())
{
return PermissionGrantResult.Undefined;

2
framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AsyncCrudAppService.cs

@ -34,10 +34,8 @@ namespace Volo.Abp.Application.Services
public abstract class AsyncCrudAppService<TEntity, TEntityDto, TKey, TGetAllInput, TCreateInput>
: AsyncCrudAppService<TEntity, TEntityDto, TKey, TGetAllInput, TCreateInput, TCreateInput>
where TGetAllInput : IPagedAndSortedResultRequest
where TEntity : class, IEntity<TKey>
where TEntityDto : IEntityDto<TKey>
where TCreateInput : IEntityDto<TKey>
{
protected AsyncCrudAppService(IRepository<TEntity, TKey> repository)
: base(repository)

6
framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs

@ -225,7 +225,11 @@ namespace Volo.Abp.Http.Client.DynamicProxying
}
//TODO: Is that the way we want? Couldn't send the culture (not ui culture)
requestMessage.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue(CultureInfo.CurrentUICulture.Name));
var currentCulture = CultureInfo.CurrentUICulture.Name ?? CultureInfo.CurrentCulture.Name;
if (!currentCulture.IsNullOrEmpty())
{
requestMessage.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue(currentCulture));
}
}
private string GetConfiguredApiVersion()

28
framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/CurrentClaimsPrincipalTenantResolveContributor.cs

@ -1,28 +0,0 @@
using System.Linq;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Security.Claims;
namespace Volo.Abp.MultiTenancy
{
public class CurrentClaimsPrincipalTenantResolveContributor : TenantResolveContributorBase
{
public const string ContributorName = "CurrentClaims";
public override string Name => ContributorName;
public override void Resolve(ITenantResolveContext context)
{
var principal = context.ServiceProvider.GetRequiredService<ICurrentPrincipalAccessor>().Principal;
if (principal?.Identity?.IsAuthenticated != true)
{
return;
}
context.Handled = true;
context.TenantIdOrName = principal
.Claims
.FirstOrDefault(c => c.Type == AbpClaimTypes.TenantId)
?.Value;
}
}
}

24
framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/CurrentUserTenantResolveContributor.cs

@ -0,0 +1,24 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Users;
namespace Volo.Abp.MultiTenancy
{
public class CurrentUserTenantResolveContributor : TenantResolveContributorBase
{
public const string ContributorName = "CurrentUser";
public override string Name => ContributorName;
public override void Resolve(ITenantResolveContext context)
{
var currentUser = context.ServiceProvider.GetRequiredService<ICurrentUser>();
if (currentUser.IsAuthenticated != true)
{
return;
}
context.Handled = true;
context.TenantIdOrName = currentUser.TenantId?.ToString();
}
}
}

2
framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantResolveOptions.cs

@ -12,7 +12,7 @@ namespace Volo.Abp.MultiTenancy
{
TenantResolvers = new List<ITenantResolveContributor>
{
new CurrentClaimsPrincipalTenantResolveContributor()
new CurrentUserTenantResolveContributor()
};
}
}

3
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json

@ -45,6 +45,7 @@
"PagerShowMenuEntries": "Show _MENU_ entries",
"DatatableActionDropdownDefaultText": "Actions",
"ChangePassword": "Change password",
"PersonalInfo": "My profile"
"PersonalInfo": "My profile",
"AreYouSureYouWantToCancelEditingWarningMessage": "You have unsaved changes."
}
}

17
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pt-BR.json

@ -26,16 +26,25 @@
"Edit": "Editar",
"Refresh": "Refrescar",
"ProcessingWithThreeDot": "Processando...",
"LoadingWithThreeDot": "Carregando...",
"Welcome": "Bem Vindo",
"Login": "Entrar",
"Register": "cadastrar",
"Register": "Registrar-se",
"Logout": "Sair",
"Submit": "Enviar",
"Back": "Voltar",
"PagerSearch": "Pesquisar",
"PagerNext": "Próximo",
"PagerPrevious": "Anterior",
"PagerInfo": "Mostrando _START_ até _END_ de _TOTAL_ registros.",
"PagerFirst": "Primeira",
"PagerLast": "Última",
"PagerInfo": "Mostrando _START_ até _END_ de _TOTAL_ registros",
"PagerInfoEmpty": "Mostrando 0 até 0 de 0 registros",
"PagerInfoFiltered": "(filtrado de um total de _MAX_ registros)",
"NoDataAvailableInDatatable": "Nenhum dado disponível",
"PagerShowMenuEntries": "Mostrando _MENU_ registros",
"DatatableActionDropdownDefaultText": "Ações",
"ChangePassword": "Alterar senha",
"ChangePassword": "Alterar Senha",
"PersonalInfo": "Perfil"
}
}
}

3
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/tr.json

@ -45,6 +45,7 @@
"PagerShowMenuEntries": "Sayfada _MENU_ kayıt göster.",
"DatatableActionDropdownDefaultText": "İşlemler",
"ChangePassword": "Şifre değiştir",
"PersonalInfo": "Profilim"
"PersonalInfo": "Profilim",
"AreYouSureYouWantToCancelEditingWarningMessage": "Kaydedilmemiş değişiklikler var."
}
}

3
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/pt-BR.json

@ -1,6 +1,7 @@
{
"culture": "pt-BR",
"texts": {
"BirthDate": "Aniversário"
"BirthDate": "Aniversário",
"Value1": "Valor Um"
}
}

7
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/zh-Hans.json

@ -0,0 +1,7 @@
{
"culture": "zh-Hans",
"texts": {
"BirthDate": "生日",
"Value1": "Value One"
}
}

3
framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/en.json

@ -1,6 +1,7 @@
{
"culture": "en",
"texts": {
"USA": "United States of America"
"USA": "United States of America",
"Brazil": "Brasil"
}
}

2
framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/pt-BR.json

@ -4,4 +4,4 @@
"USA": "Estados Unidos da América",
"Brazil": "Brasil"
}
}
}

7
framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/zh-Hans.json

@ -0,0 +1,7 @@
{
"culture": "zh-Hans",
"texts": {
"USA": "美国",
"Brazil": "巴西"
}
}

2
framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/pt-BR.json

@ -4,4 +4,4 @@
"ThisFieldIsRequired": "Este campo é obrigatório",
"MaxLenghtErrorMessage": "Este campo pode ser no máximo de '{0}' caracteres"
}
}
}

7
framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/zh-Hans.json

@ -0,0 +1,7 @@
{
"culture": "zh-Hans",
"texts": {
"ThisFieldIsRequired": "此字段是必填字段",
"MaxLenghtErrorMessage": "该字段最多可包含'{0}'个字符"
}
}

5
framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/pt-BR.json

@ -5,6 +5,7 @@
"Car": "Carro",
"CarPlural": "Carros",
"MaxLenghtErrorMessage": "O comprimento deste campo pode ser no máximo de '{0}' caracteres",
"Universe": "Universo"
"Universe": "Universo",
"FortyTwo": "Quarenta e Dois"
}
}
}

11
framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/zh-Hans.json

@ -0,0 +1,11 @@
{
"culture": "zh-Hans",
"texts": {
"Hello <b>{0}</b>.": "你好 <b>{0}</b>.",
"Car": "汽车",
"CarPlural": "汽车",
"MaxLenghtErrorMessage": "此字段的长度最多为'{0}'个字符",
"Universe": "宇宙",
"FortyTwo": "四十二"
}
}

11
modules/audit-logging/test/Volo.Abp.AuditLogging.EntityFrameworkCore.Tests/Volo/Abp/AuditLogging/EntityFrameworkCore/AuditLogRepository_Tests.cs

@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Volo.Abp.AuditLogging.EntityFrameworkCore
{
public class AuditLogRepository_Tests : AuditLogRepository_Tests<AbpAuditLoggingEntityFrameworkCoreTestModule>
{
}
}

11
modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/AuditLogRepository_Tests.cs

@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Volo.Abp.AuditLogging.MongoDB
{
public class AuditLogRepository_Tests : AuditLogRepository_Tests<AbpAuditLoggingMongoDbTestModule>
{
}
}

232
modules/audit-logging/test/Volo.Abp.AuditLogging.TestBase/Volo/Abp/AuditLogging/AuditLogRepository_Tests.cs

@ -0,0 +1,232 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using Shouldly;
using Volo.Abp.Auditing;
using Volo.Abp.Guids;
using Volo.Abp.Modularity;
using Xunit;
namespace Volo.Abp.AuditLogging
{
public abstract class AuditLogRepository_Tests<TStartupModule> : AuditLoggingTestBase<TStartupModule>
where TStartupModule : IAbpModule
{
protected IAuditLogRepository AuditLogRepository { get; }
protected IGuidGenerator GuidGenerator { get; }
protected AuditLogRepository_Tests()
{
AuditLogRepository = GetRequiredService<IAuditLogRepository>();
GuidGenerator = GetRequiredService<IGuidGenerator>();
}
[Fact]
public async Task GetListAsync()
{
// Arrange
var userId = new Guid("4456fb0d-74cc-4807-9eee-23e551e6cb06");
var userId2 = new Guid("4456fb0d-74cc-4807-9eee-23e551e6cb06");
var ipAddress = "153.1.7.61";
var firstComment = "first Comment";
var log1 = new AuditLogInfo
{
UserId = userId,
ImpersonatorUserId = Guid.NewGuid(),
ImpersonatorTenantId = Guid.NewGuid(),
ExecutionTime = DateTime.Today,
ExecutionDuration = 42,
ClientIpAddress = ipAddress,
ClientName = "MyDesktop",
BrowserInfo = "Chrome",
Comments = new List<string> { firstComment, "Second Comment" },
UserName = "Douglas",
EntityChanges = {
new EntityChangeInfo
{
EntityId = Guid.NewGuid().ToString(),
EntityTypeFullName = "Volo.Abp.AuditLogging.TestEntity",
ChangeType = EntityChangeType.Created,
ChangeTime = DateTime.Now,
PropertyChanges = new List<EntityPropertyChangeInfo>
{
new EntityPropertyChangeInfo
{
PropertyTypeFullName = typeof(string).FullName,
PropertyName = "Name",
NewValue = "New value",
OriginalValue = null
}
}
},
new EntityChangeInfo
{
EntityId = Guid.NewGuid().ToString(),
EntityTypeFullName = "Volo.Abp.AuditLogging.TestEntity",
ChangeType = EntityChangeType.Created,
ChangeTime = DateTime.Now,
PropertyChanges = new List<EntityPropertyChangeInfo>
{
new EntityPropertyChangeInfo
{
PropertyTypeFullName = typeof(string).FullName,
PropertyName = "Name",
NewValue = "New value",
OriginalValue = null
}
}
}
}
};
var log2 = new AuditLogInfo
{
UserId = userId2,
ImpersonatorUserId = Guid.NewGuid(),
ImpersonatorTenantId = Guid.NewGuid(),
ExecutionTime = DateTime.Today,
ExecutionDuration = 42,
ClientIpAddress = ipAddress,
ClientName = "MyDesktop",
BrowserInfo = "Chrome",
Comments = new List<string> { firstComment, "Second Comment" },
HttpStatusCode = (int?)HttpStatusCode.BadGateway,
EntityChanges = {
new EntityChangeInfo
{
EntityId = Guid.NewGuid().ToString(),
EntityTypeFullName = "Volo.Abp.AuditLogging.TestEntity",
ChangeType = EntityChangeType.Created,
ChangeTime = DateTime.Now,
PropertyChanges = new List<EntityPropertyChangeInfo>
{
new EntityPropertyChangeInfo
{
PropertyTypeFullName = typeof(string).FullName,
PropertyName = "Name",
NewValue = "New value",
OriginalValue = null
}
}
}
}
};
AuditLogRepository.Insert(new AuditLog(GuidGenerator, log1));
AuditLogRepository.Insert(new AuditLog(GuidGenerator, log2));
//Assert
var logs = await AuditLogRepository.GetListAsync();
logs.ShouldNotBeNull();
logs.ShouldContain(x => x.UserId == userId);
logs.ShouldContain(x => x.UserId == userId2);
}
[Fact]
public async Task GetCountAsync()
{
// Arrange
var userId = new Guid("4456fb0d-74cc-4807-9eee-23e551e6cb06");
var userId2 = new Guid("4456fb0d-74cc-4807-9eee-23e551e6cb06");
var ipAddress = "153.1.7.61";
var firstComment = "first Comment";
var log1 = new AuditLogInfo
{
UserId = userId,
ImpersonatorUserId = Guid.NewGuid(),
ImpersonatorTenantId = Guid.NewGuid(),
ExecutionTime = DateTime.Today,
ExecutionDuration = 42,
ClientIpAddress = ipAddress,
ClientName = "MyDesktop",
BrowserInfo = "Chrome",
Comments = new List<string> { firstComment, "Second Comment" },
UserName = "Douglas",
EntityChanges = {
new EntityChangeInfo
{
EntityId = Guid.NewGuid().ToString(),
EntityTypeFullName = "Volo.Abp.AuditLogging.TestEntity",
ChangeType = EntityChangeType.Created,
ChangeTime = DateTime.Now,
PropertyChanges = new List<EntityPropertyChangeInfo>
{
new EntityPropertyChangeInfo
{
PropertyTypeFullName = typeof(string).FullName,
PropertyName = "Name",
NewValue = "New value",
OriginalValue = null
}
}
},
new EntityChangeInfo
{
EntityId = Guid.NewGuid().ToString(),
EntityTypeFullName = "Volo.Abp.AuditLogging.TestEntity",
ChangeType = EntityChangeType.Created,
ChangeTime = DateTime.Now,
PropertyChanges = new List<EntityPropertyChangeInfo>
{
new EntityPropertyChangeInfo
{
PropertyTypeFullName = typeof(string).FullName,
PropertyName = "Name",
NewValue = "New value",
OriginalValue = null
}
}
}
}
};
var log2 = new AuditLogInfo
{
UserId = userId2,
ImpersonatorUserId = Guid.NewGuid(),
ImpersonatorTenantId = Guid.NewGuid(),
ExecutionTime = DateTime.Today,
ExecutionDuration = 42,
ClientIpAddress = ipAddress,
ClientName = "MyDesktop",
BrowserInfo = "Chrome",
Comments = new List<string> { firstComment, "Second Comment" },
HttpStatusCode = (int?)HttpStatusCode.BadGateway,
EntityChanges = {
new EntityChangeInfo
{
EntityId = Guid.NewGuid().ToString(),
EntityTypeFullName = "Volo.Abp.AuditLogging.TestEntity",
ChangeType = EntityChangeType.Created,
ChangeTime = DateTime.Now,
PropertyChanges = new List<EntityPropertyChangeInfo>
{
new EntityPropertyChangeInfo
{
PropertyTypeFullName = typeof(string).FullName,
PropertyName = "Name",
NewValue = "New value",
OriginalValue = null
}
}
}
}
};
AuditLogRepository.Insert(new AuditLog(GuidGenerator, log1));
AuditLogRepository.Insert(new AuditLog(GuidGenerator, log2));
//Assert
var logs = await AuditLogRepository.GetCountAsync();
logs.ShouldBe(2);
}
}
}

13
modules/audit-logging/test/Volo.Abp.AuditLogging.TestBase/Volo/Abp/AuditLogging/AuditLogging_Repository_Resolve_Tests.cs

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Text;
using Volo.Abp.Modularity;
namespace Volo.Abp.AuditLogging
{
public class AuditLogging_Repository_Resolve_Tests<TStartupModule> : AuditLoggingTestBase<TStartupModule>
where TStartupModule : IAbpModule
{
}
}

22
modules/blogging/Volo.Blogging.sln

@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27703.2026
# Visual Studio Version 16
VisualStudioVersion = 16.0.28729.10
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Blogging.Domain.Shared", "src\Volo.Blogging.Domain.Shared\Volo.Blogging.Domain.Shared.csproj", "{F1D954AD-001A-4533-A8CC-94DDCF70B552}"
EndProject
@ -35,9 +35,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Blogging.EntityFramewo
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Blogging.Application.Tests", "test\Volo.Blogging.Application.Tests\Volo.Blogging.Application.Tests.csproj", "{C949B953-80B3-4B36-B535-1AD74A34FEAC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Blogging.MongoDB", "src\Volo.Blogging.MongoDB\Volo.Blogging.MongoDB.csproj", "{98C2D36A-F874-405D-8565-9CE59438E879}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Blogging.MongoDB", "src\Volo.Blogging.MongoDB\Volo.Blogging.MongoDB.csproj", "{98C2D36A-F874-405D-8565-9CE59438E879}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.BloggingTestApp.MongoDb", "app\Volo.BloggingTestApp.MongoDb\Volo.BloggingTestApp.MongoDb.csproj", "{4C818374-2DE8-422F-8585-975E8366DB26}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.BloggingTestApp.MongoDb", "app\Volo.BloggingTestApp.MongoDb\Volo.BloggingTestApp.MongoDb.csproj", "{4C818374-2DE8-422F-8585-975E8366DB26}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Blogging.MongoDB.Tests", "test\Volo.Blogging.MongoDB.Tests\Volo.Blogging.MongoDB.Tests.csproj", "{0A29F64C-11F1-40B6-8E6D-91E86823775E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Blogging.Domain.Tests", "test\Volo.Blogging.Domain.Tests\Volo.Blogging.Domain.Tests.csproj", "{B6D7EF20-9921-490A-AA95-47E3E174DC9B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -105,6 +109,14 @@ Global
{4C818374-2DE8-422F-8585-975E8366DB26}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4C818374-2DE8-422F-8585-975E8366DB26}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4C818374-2DE8-422F-8585-975E8366DB26}.Release|Any CPU.Build.0 = Release|Any CPU
{0A29F64C-11F1-40B6-8E6D-91E86823775E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0A29F64C-11F1-40B6-8E6D-91E86823775E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0A29F64C-11F1-40B6-8E6D-91E86823775E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0A29F64C-11F1-40B6-8E6D-91E86823775E}.Release|Any CPU.Build.0 = Release|Any CPU
{B6D7EF20-9921-490A-AA95-47E3E174DC9B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B6D7EF20-9921-490A-AA95-47E3E174DC9B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B6D7EF20-9921-490A-AA95-47E3E174DC9B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B6D7EF20-9921-490A-AA95-47E3E174DC9B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -125,6 +137,8 @@ Global
{C949B953-80B3-4B36-B535-1AD74A34FEAC} = {25B3A516-5C0D-42E3-9294-E8A9346CEE4B}
{98C2D36A-F874-405D-8565-9CE59438E879} = {42BF26EF-B8C7-42DC-9FFB-3653109B7776}
{4C818374-2DE8-422F-8585-975E8366DB26} = {EB4FB44A-FE39-4245-9DAD-D6437BCE3870}
{0A29F64C-11F1-40B6-8E6D-91E86823775E} = {25B3A516-5C0D-42E3-9294-E8A9346CEE4B}
{B6D7EF20-9921-490A-AA95-47E3E174DC9B} = {25B3A516-5C0D-42E3-9294-E8A9346CEE4B}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {F2BAE819-78D4-407A-9201-22473B2850B0}

2
modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Posts/PostWithDetailsDto.cs

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using JetBrains.Annotations;
using Volo.Abp.Application.Dtos;
using Volo.Blogging.Tagging.Dtos;
@ -21,6 +22,7 @@ namespace Volo.Blogging.Posts
public int CommentCount { get; set; }
[CanBeNull]
public BlogUserDto Writer { get; set; }
public List<TagDto> Tags { get; set; }

1
modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Posts/PostAppService.cs

@ -156,7 +156,6 @@ namespace Volo.Blogging.Posts
var post = new Post(
id: GuidGenerator.Create(),
blogId: input.BlogId,
creatorId: CurrentUser.GetId(),
title: input.Title,
coverImage: input.CoverImage,
url: input.Url

2
modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Blogs/IBlogRepository.cs

@ -7,7 +7,5 @@ namespace Volo.Blogging.Blogs
public interface IBlogRepository : IBasicRepository<Blog, Guid>
{
Task<Blog> FindByShortNameAsync(string shortName);
Task<int> GetTotalCount();
}
}

4
modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/Post.cs

@ -23,7 +23,6 @@ namespace Volo.Blogging.Posts
[CanBeNull]
public virtual string Content { get; set; }
[CanBeNull]
public virtual int ReadCount { get; protected set; }
public virtual Collection<PostTag> Tags { get; protected set; }
@ -33,10 +32,9 @@ namespace Volo.Blogging.Posts
}
public Post(Guid id, Guid blogId, Guid creatorId, [NotNull] string title, [NotNull] string coverImage, [NotNull] string url)
public Post(Guid id, Guid blogId, [NotNull] string title, [NotNull] string coverImage, [NotNull] string url)
{
Id = id;
CreatorId = creatorId;
BlogId = blogId;
Title = Check.NotNullOrWhiteSpace(title, nameof(title));
Url = Check.NotNullOrWhiteSpace(url, nameof(url));

7
modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Tagging/Tag.cs

@ -44,6 +44,13 @@ namespace Volo.Blogging.Tagging
{
return;
}
if (UsageCount - number <= 0)
{
UsageCount = 0;
return;
}
UsageCount -= number;
}

5
modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Blogs/EfCoreBlogRepository.cs

@ -19,10 +19,5 @@ namespace Volo.Blogging.Blogs
{
return await DbSet.FirstOrDefaultAsync(p => p.ShortName == shortName);
}
public async Task<int> GetTotalCount()
{
return await DbSet.CountAsync();
}
}
}

5
modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Blogs/MongoBlogRepository.cs

@ -17,10 +17,5 @@ namespace Volo.Blogging.Blogs
{
return await GetMongoQueryable().FirstOrDefaultAsync(p => p.ShortName == shortName);
}
public async Task<int> GetTotalCount()
{
return await GetMongoQueryable().CountAsync();
}
}
}

1
modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Tagging/MongoTagRepository.cs

@ -44,6 +44,7 @@ namespace Volo.Blogging.Tagging
foreach (var tag in tags)
{
tag.DecreaseUsageCount();
Update(tag);
}
}
}

391
modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Detail.cshtml

@ -46,11 +46,18 @@
<div class="article-owner">
<div class="article-infos">
<div class="user-card">
@if (Model.Post.Writer != null)
{
<a>
<img gravatar-email="@Model.Post.Writer.Email" default-image="Identicon" class="article-avatar" />
</a>
}
<a>
<img gravatar-email="@Model.Post.Writer.Email" default-image="Identicon" class="article-avatar" />
</a>
<a>
<strong> @(Model.Post.Writer == null ? "" : Model.Post.Writer.UserName)</strong>, @ConvertDatetimeToTimeAgo(Model.Post.CreationTime)
@if (Model.Post.Writer != null)
{
<strong>@(Model.Post.Writer.UserName),</strong>
}
@ConvertDatetimeToTimeAgo(Model.Post.CreationTime)
</a>
<span class="vs-seperator">|</span>
<a>
@ -64,14 +71,14 @@
{
<span class="seperator">|</span>
<a asp-page="./Edit" asp-route-postId="@Model.Post.Id" asp-route-blogShortName="@Model.BlogShortName">
<i class="fa fa-pencil"></i> @L["Edit"]
<i class="fa fa-pencil"></i> @L["Edit"]
</a>
}
@if (await Authorization.IsGrantedAsync(BloggingPermissions.Posts.Delete) || (CurrentUser.Id == Model.Post.CreatorId))
{
<span class="seperator">|</span>
<a href="#" id="DeletePostLink" data-postid="@Model.Post.Id" data-blogShortName="@Model.BlogShortName">
<i class="fa fa-trash"></i> @L["Delete"]
<i class="fa fa-trash"></i> @L["Delete"]
</a>
}
</div>
@ -95,223 +102,223 @@
</div>
<div class="row">
<div class="col-md-8 mx-auto">
@if (Model.Post.Tags.Count > 0)
{
<div class="tags">
<h5>@L["TagsInThisArticle"]</h5>
@foreach (var tag in Model.Post.Tags)
<div class="col-md-8 mx-auto">
@if (Model.Post.Tags.Count > 0)
{
<a asp-page="/Blog/Posts/Index" asp-route-blogShortName="@Model.BlogShortName" asp-route-tagName="@tag.Name" class="tag">@tag.Name</a>
<div class="tags">
<h5>@L["TagsInThisArticle"]</h5>
@foreach (var tag in Model.Post.Tags)
{
<a asp-page="/Blog/Posts/Index" asp-route-blogShortName="@Model.BlogShortName" asp-route-tagName="@tag.Name" class="tag">@tag.Name</a>
}
</div>
}
</div>
}
@if (Model.CommentsWithReplies.Count > 0)
{
<abp-row v-align="Start">
<abp-column size-sm="_12">
<p class="float-left"><i class="fa fa-comment"></i> @L["CommentWithCount", @Model.CommentCount]</p>
@if (hasCommentingPermission)
{
<a abp-button="Primary" class="btn-rounded float-right active" href="#LeaveComment">@L["LeaveComment"]</a>
}
else
{
<a abp-button="Primary" class="btn-rounded float-right active" asp-page="/Account/Login" target="_blank">@L["LeaveComment"]</a>
}
</abp-column>
</abp-row>
}
<div class="comment-area">
@foreach (var commentWithRepliesDto in Model.CommentsWithReplies)
{
<div class="media">
<img gravatar-email="@commentWithRepliesDto.Comment.Writer.Email" default-image="Identicon" class="d-flex mr-3 rounded-circle comment-avatar"/>
<div class="media-body">
<h5 class="comment-owner">
@(commentWithRepliesDto.Comment.Writer == null ? "" : commentWithRepliesDto.Comment.Writer.UserName)
<span class="float-right">@ConvertDatetimeToTimeAgo(commentWithRepliesDto.Comment.CreationTime)</span>
</h5>
<p id="@commentWithRepliesDto.Comment.Id">
@commentWithRepliesDto.Comment.Text
</p>
<div class="comment-buttons font-75 bg-light">
@if (Model.CommentsWithReplies.Count > 0)
{
<abp-row v-align="Start">
<abp-column size-sm="_12">
<p class="float-left"><i class="fa fa-comment"></i> @L["CommentWithCount", @Model.CommentCount]</p>
@if (hasCommentingPermission)
{
<a href="#" class="tag replyLink" data-relpyid="@commentWithRepliesDto.Comment.Id">
<i class="fa fa-reply" aria-hidden="true"></i> @L["Reply"]
</a>
<a abp-button="Primary" class="btn-rounded float-right active" href="#LeaveComment">@L["LeaveComment"]</a>
}
@if (await Authorization.IsGrantedAsync(BloggingPermissions.Comments.Delete))
else
{
<span class="seperator">|</span>
<a href="#" class="tag deleteLink" data-deleteid="@commentWithRepliesDto.Comment.Id">
<i class="fa fa-trash" aria-hidden="true"></i> @L["Delete"]
</a>
<a abp-button="Primary" class="btn-rounded float-right active" asp-page="/Account/Login" target="_blank">@L["LeaveComment"]</a>
}
</abp-column>
</abp-row>
}
@if (await Authorization.IsGrantedAsync(BloggingPermissions.Comments.Update) || (CurrentUser.Id == commentWithRepliesDto.Comment.CreatorId))
{
<span class="seperator">|</span>
<a href="#" class="tag updateLink" data-updateid="@commentWithRepliesDto.Comment.Id">
<i class="fa fa-pencil" aria-hidden="true"></i> @L["Edit"]
</a>
}
</div>
<div class="comment-area">
@foreach (var commentWithRepliesDto in Model.CommentsWithReplies)
{
<div class="media">
<img gravatar-email="@commentWithRepliesDto.Comment.Writer.Email" default-image="Identicon" class="d-flex mr-3 rounded-circle comment-avatar" />
<div class="media-body">
<h5 class="comment-owner">
@(commentWithRepliesDto.Comment.Writer == null ? "" : commentWithRepliesDto.Comment.Writer.UserName)
<span class="float-right">@ConvertDatetimeToTimeAgo(commentWithRepliesDto.Comment.CreationTime)</span>
</h5>
<p id="@commentWithRepliesDto.Comment.Id">
@commentWithRepliesDto.Comment.Text
</p>
<div class="comment-buttons font-75 bg-light">
@if (hasCommentingPermission)
{
<div class="comment-form mt-4 replyForm">
<div class="clearfix bg-light p-4">
<h3 class="mt-0">
@L["ReplyTo", commentWithRepliesDto.Comment.Writer == null ? "" : commentWithRepliesDto.Comment.Writer.UserName]
@if (hasCommentingPermission)
{
<a href="#" class="tag replyLink" data-relpyid="@commentWithRepliesDto.Comment.Id">
<i class="fa fa-reply" aria-hidden="true"></i> @L["Reply"]
</a>
}
</h3>
<div>
<form method="post">
<input name="postId" value="@Model.Post.Id" hidden/>
<input name="repliedCommentId" value="@commentWithRepliesDto.Comment.Id" hidden/>
@if (await Authorization.IsGrantedAsync(BloggingPermissions.Comments.Delete))
{
<span class="seperator">|</span>
<a href="#" class="tag deleteLink" data-deleteid="@commentWithRepliesDto.Comment.Id">
<i class="fa fa-trash" aria-hidden="true"></i> @L["Delete"]
</a>
}
<div class="form-group">
<textarea class="form-control no-border" name="text" id="textBoxId" rows="4"></textarea>
@if (await Authorization.IsGrantedAsync(BloggingPermissions.Comments.Update) || (CurrentUser.Id == commentWithRepliesDto.Comment.CreatorId))
{
<span class="seperator">|</span>
<a href="#" class="tag updateLink" data-updateid="@commentWithRepliesDto.Comment.Id">
<i class="fa fa-pencil" aria-hidden="true"></i> @L["Edit"]
</a>
}
</div>
@if (hasCommentingPermission)
{
<div class="comment-form mt-4 replyForm">
<div class="clearfix bg-light p-4">
<h3 class="mt-0">
@L["ReplyTo", commentWithRepliesDto.Comment.Writer == null ? "" : commentWithRepliesDto.Comment.Writer.UserName]
</h3>
<div>
<form method="post">
<input name="postId" value="@Model.Post.Id" hidden />
<input name="repliedCommentId" value="@commentWithRepliesDto.Comment.Id" hidden />
<div class="form-group">
<textarea class="form-control no-border" name="text" id="textBoxId" rows="4"></textarea>
</div>
<abp-button button-type="Primary" class="btn-rounded float-right" type="submit" text="@L["Comment"].Value" />
<abp-button button-type="Danger" class="btn-rounded float-right replyCancelButton" text="@L["Cancel"].Value" />
</form>
</div>
<abp-button button-type="Primary" class="btn-rounded float-right" type="submit" text="@L["Comment"].Value"/>
<abp-button button-type="Danger" class="btn-rounded float-right replyCancelButton" text="@L["Cancel"].Value"/>
</form>
</div>
</div>
</div>
</div>
}
@if (await Authorization.IsGrantedAsync(BloggingPermissions.Comments.Update) || (CurrentUser.Id == commentWithRepliesDto.Comment.CreatorId))
{
<div class="comment-form mt-4 editForm">
<div class="clearfix bg-light p-4">
<div>
<form class="editFormClass">
<input name="commentId" value="@commentWithRepliesDto.Comment.Id" hidden/>
<div class="form-group">
<textarea class="form-control no-border" name="text" id="textBoxId" rows="4">@commentWithRepliesDto.Comment.Text</textarea>
}
@if (await Authorization.IsGrantedAsync(BloggingPermissions.Comments.Update) || (CurrentUser.Id == commentWithRepliesDto.Comment.CreatorId))
{
<div class="comment-form mt-4 editForm">
<div class="clearfix bg-light p-4">
<div>
<form class="editFormClass">
<input name="commentId" value="@commentWithRepliesDto.Comment.Id" hidden />
<div class="form-group">
<textarea class="form-control no-border" name="text" id="textBoxId" rows="4">@commentWithRepliesDto.Comment.Text</textarea>
</div>
<abp-button button-type="Primary" class="btn-rounded float-right" type="submit" text="@L["Submit"].Value" />
<abp-button button-type="Danger" class="btn-rounded float-right editCancelButton" text="@L["Cancel"].Value" />
</form>
</div>
<abp-button button-type="Primary" class="btn-rounded float-right" type="submit" text="@L["Submit"].Value"/>
<abp-button button-type="Danger" class="btn-rounded float-right editCancelButton" text="@L["Cancel"].Value"/>
</form>
</div>
</div>
</div>
</div>
}
}
@foreach (var reply in commentWithRepliesDto.Replies)
{
<div class="media">
<img gravatar-email="@reply.Writer.Email" default-image="Identicon" class="d-flex mr-3 rounded-circle comment-avatar"/>
<div class="media-body">
<h5 class="comment-owner">
@(reply.Writer == null ? "" : reply.Writer.UserName)
<span class="float-right">@ConvertDatetimeToTimeAgo(reply.CreationTime)</span>
</h5>
<p id="@reply.Id">
@reply.Text
</p>
<div class="comment-buttons font-75 bg-light">
@foreach (var reply in commentWithRepliesDto.Replies)
{
<div class="media">
<img gravatar-email="@reply.Writer.Email" default-image="Identicon" class="d-flex mr-3 rounded-circle comment-avatar" />
<div class="media-body">
<h5 class="comment-owner">
@(reply.Writer == null ? "" : reply.Writer.UserName)
<span class="float-right">@ConvertDatetimeToTimeAgo(reply.CreationTime)</span>
</h5>
<p id="@reply.Id">
@reply.Text
</p>
<div class="comment-buttons font-75 bg-light">
@if (hasCommentingPermission)
{
<a href="#" class="tag replyLink" data-relpyid="@commentWithRepliesDto.Comment.Id">
<i class="fa fa-reply" aria-hidden="true"></i> @L["Reply"]
</a>
}
@if (await Authorization.IsGrantedAsync(BloggingPermissions.Comments.Delete) || (CurrentUser.Id == commentWithRepliesDto.Comment.CreatorId))
{
<span class="seperator">|</span>
<a href="#" class="tag deleteLink" data-deleteid="@reply.Id">
<i class="fa fa-trash" aria-hidden="true"></i> @L["Delete"]
</a>
}
@if (hasCommentingPermission)
{
<a href="#" class="tag replyLink" data-relpyid="@commentWithRepliesDto.Comment.Id">
<i class="fa fa-reply" aria-hidden="true"></i> @L["Reply"]
</a>
}
@if (await Authorization.IsGrantedAsync(BloggingPermissions.Comments.Delete) || (CurrentUser.Id == commentWithRepliesDto.Comment.CreatorId))
{
<span class="seperator">|</span>
<a href="#" class="tag deleteLink" data-deleteid="@reply.Id">
<i class="fa fa-trash" aria-hidden="true"></i> @L["Delete"]
</a>
}
@if (await Authorization.IsGrantedAsync(BloggingPermissions.Comments.Update) || (CurrentUser.Id == commentWithRepliesDto.Comment.CreatorId))
{
<span class="seperator">|</span>
<a href="#" class="tag updateLink" data-updateid="@reply.Id">
<i class="fa fa-pencil" aria-hidden="true"></i> @L["Edit"]
</a>
}
</div>
@if (await Authorization.IsGrantedAsync(BloggingPermissions.Comments.Update) || (CurrentUser.Id == commentWithRepliesDto.Comment.CreatorId))
{
<span class="seperator">|</span>
<a href="#" class="tag updateLink" data-updateid="@reply.Id">
<i class="fa fa-pencil" aria-hidden="true"></i> @L["Edit"]
</a>
}
</div>
@if (hasCommentingPermission)
{
<div class="comment-form mt-4 replyForm">
<div class="clearfix bg-light p-4">
<h3 class="mt-0">
@L["ReplyTo", commentWithRepliesDto.Comment.Writer == null ? "" : commentWithRepliesDto.Comment.Writer.UserName]
</h3>
<div>
<form method="post">
<input name="postId" value="@Model.Post.Id" hidden/>
<input name="repliedCommentId" value="@commentWithRepliesDto.Comment.Id" hidden/>
<div class="form-group">
<textarea class="form-control no-border" name="text" id="textBoxId" rows="4"></textarea>
@if (hasCommentingPermission)
{
<div class="comment-form mt-4 replyForm">
<div class="clearfix bg-light p-4">
<h3 class="mt-0">
@L["ReplyTo", commentWithRepliesDto.Comment.Writer == null ? "" : commentWithRepliesDto.Comment.Writer.UserName]
</h3>
<div>
<form method="post">
<input name="postId" value="@Model.Post.Id" hidden />
<input name="repliedCommentId" value="@commentWithRepliesDto.Comment.Id" hidden />
<div class="form-group">
<textarea class="form-control no-border" name="text" id="textBoxId" rows="4"></textarea>
</div>
<abp-button button-type="Primary" class="btn-rounded float-right" type="submit" text="@L["Submit"].Value" />
<abp-button button-type="Danger" class="btn-rounded float-right replyCancelButton" text="@L["Cancel"].Value" />
</form>
</div>
<abp-button button-type="Primary" class="btn-rounded float-right" type="submit" text="@L["Submit"].Value"/>
<abp-button button-type="Danger" class="btn-rounded float-right replyCancelButton" text="@L["Cancel"].Value"/>
</form>
</div>
</div>
</div>
</div>
}
@if (await Authorization.IsGrantedAsync(BloggingPermissions.Comments.Update) || (CurrentUser.Id == commentWithRepliesDto.Comment.CreatorId))
{
<div class="comment-form mt-4 editForm">
<div class="clearfix bg-light p-4">
<div>
<form class="editFormClass">
<input name="commentId" value="@reply.Id" hidden/>
<div class="form-group">
<textarea class="form-control no-border" name="text" id="textBoxId" rows="4">@reply.Text</textarea>
}
@if (await Authorization.IsGrantedAsync(BloggingPermissions.Comments.Update) || (CurrentUser.Id == commentWithRepliesDto.Comment.CreatorId))
{
<div class="comment-form mt-4 editForm">
<div class="clearfix bg-light p-4">
<div>
<form class="editFormClass">
<input name="commentId" value="@reply.Id" hidden />
<div class="form-group">
<textarea class="form-control no-border" name="text" id="textBoxId" rows="4">@reply.Text</textarea>
</div>
<abp-button button-type="Primary" class="btn-rounded float-right" type="submit" text="@L["Submit"].Value" />
<abp-button button-type="Danger" class="btn-rounded float-right editCancelButton" text="@L["Cancel"].Value" />
</form>
</div>
<abp-button button-type="Primary" class="btn-rounded float-right" type="submit" text="@L["Submit"].Value"/>
<abp-button button-type="Danger" class="btn-rounded float-right editCancelButton" text="@L["Cancel"].Value"/>
</form>
</div>
</div>
</div>
}
</div>
}
</div>
</div>
}
</div>
}
</div>
</div>
}
</div>
}
</div>
@if (hasCommentingPermission)
{
<div class="comment-form mt-4" id="LeaveComment">
<div class="vs-blog-title mb-0">
<h3>@L["LeaveComment"]</h3>
</div>
<div class="clearfix bg-light p-4">
<div>
<form method="post">
<input name="postId" value="@Model.Post.Id" hidden/>
<input name="repliedCommentId" id="repliedCommentId" hidden/>
<div class="form-group">
<textarea class="form-control no-border" name="text" id="textBoxId" rows="4"></textarea>
@if (hasCommentingPermission)
{
<div class="comment-form mt-4" id="LeaveComment">
<div class="vs-blog-title mb-0">
<h3>@L["LeaveComment"]</h3>
</div>
<div class="clearfix bg-light p-4">
<div>
<form method="post">
<input name="postId" value="@Model.Post.Id" hidden />
<input name="repliedCommentId" id="repliedCommentId" hidden />
<div class="form-group">
<textarea class="form-control no-border" name="text" id="textBoxId" rows="4"></textarea>
</div>
<abp-button button-type="Primary" class="btn-rounded float-right" type="submit" text="@L["Submit"].Value" />
</form>
</div>
<abp-button button-type="Primary" class="btn-rounded float-right" type="submit" text="@L["Submit"].Value"/>
</form>
</div>
</div>
</div>
}
else
{
<a abp-button="Primary" class="btn-rounded float-right active mt-3" asp-page="/Account/Login" target="_blank">@L["LeaveComment"]</a>
}
</div>
}
else
{
<a abp-button="Primary" class="btn-rounded float-right active mt-3" asp-page="/Account/Login" target="_blank">@L["LeaveComment"]</a>
}
</div>
</div>
</div>

53
modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Index.cshtml

@ -81,26 +81,29 @@
<a asp-page="./Detail" asp-route-postUrl="@post.Url" asp-route-blogShortName="@Model.BlogShortName" class="btn btn-primary btn-rounded">@L["ContinueReading"]</a>
</div>
<div class="article-owner">
<div class="article-infos">
<div class="user-card">
<a>
<img gravatar-email="@post.Writer.Email" default-image="Identicon" class="article-avatar" />
</a>
<a>
<strong>@post.Writer.UserName</strong>, @ConvertDatetimeToTimeAgo(post.CreationTime)
</a>
<span class="vs-seperator">|</span>
<a>
<i class="fa fa-eye"></i> @L["WiewsWithCount", post.ReadCount]
</a>
<span class="vs-seperator">|</span>
<a>
<i class="fa fa-comment"></i> @L["CommentWithCount", post.CommentCount]
</a>
@if (post.Writer != null)
{
<div class="article-owner">
<div class="article-infos">
<div class="user-card">
<a>
<img gravatar-email="@post.Writer.Email" default-image="Identicon" class="article-avatar" />
</a>
<a>
<strong>@post.Writer.UserName</strong>, @ConvertDatetimeToTimeAgo(post.CreationTime)
</a>
<span class="vs-seperator">|</span>
<a>
<i class="fa fa-eye"></i> @L["WiewsWithCount", post.ReadCount]
</a>
<span class="vs-seperator">|</span>
<a>
<i class="fa fa-comment"></i> @L["CommentWithCount", post.CommentCount]
</a>
</div>
</div>
</div>
</div>
}
</div>
}
@ -137,7 +140,12 @@
<div class="article-infos">
<div class="user-card">
<a asp-page="./Detail" asp-route-postUrl="@post.Url" asp-route-blogShortName="@Model.BlogShortName">
<strong>@post.Writer.UserName</strong>, @ConvertDatetimeToTimeAgo(post.CreationTime)
@if (post.Writer != null)
{
<strong>@(post.Writer.UserName),</strong>
}
@ConvertDatetimeToTimeAgo(post.CreationTime)
</a>
</div>
</div>
@ -196,7 +204,12 @@
<img gravatar-email="@post.Writer.Email" default-image="Identicon" class="article-avatar" />
</a>
<a>
<strong>@post.Writer.UserName</strong>, @ConvertDatetimeToTimeAgo(post.CreationTime)
@if (post.Writer != null)
{
<strong>@(post.Writer.UserName),</strong>
}
@ConvertDatetimeToTimeAgo(post.CreationTime)
</a>
<span class="vs-seperator">|</span>
<a>

2
modules/blogging/test/Volo.Blogging.Application.Tests/Volo.Blogging.Application.Tests.csproj

@ -13,7 +13,7 @@
<ItemGroup>
<ProjectReference Include="..\..\src\Volo.Blogging.Application\Volo.Blogging.Application.csproj" />
<ProjectReference Include="..\Volo.Blogging.EntityFrameworkCore.Tests\Volo.Blogging.EntityFrameworkCore.Tests.csproj" />
<ProjectReference Include="..\Volo.Blogging.Domain.Tests\Volo.Blogging.Domain.Tests.csproj" />
</ItemGroup>
</Project>

18
modules/blogging/test/Volo.Blogging.Domain.Tests/Volo.Blogging.Domain.Tests.csproj

@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Blogging.EntityFrameworkCore.Tests\Volo.Blogging.EntityFrameworkCore.Tests.csproj" />
<ProjectReference Include="..\Volo.Blogging.TestBase\Volo.Blogging.TestBase.csproj" />
</ItemGroup>
</Project>

11
modules/blogging/test/Volo.Blogging.Domain.Tests/Volo/Abp/Blogging/BloggingDomainTestBase.cs

@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Volo.Blogging
{
public abstract class BloggingDomainTestBase : BloggingTestBase<BloggingTestBaseModule>
{
}
}

12
modules/blogging/test/Volo.Blogging.Domain.Tests/Volo/Abp/Blogging/BloggingDomainTestModule.cs

@ -0,0 +1,12 @@
using Volo.Abp.Modularity;
namespace Volo.Blogging
{
[DependsOn(
typeof(BloggingEntityFrameworkCoreTestModule),
typeof(BloggingTestBaseModule)
)]
public class BloggingDomainTestModule : AbpModule
{
}
}

32
modules/blogging/test/Volo.Blogging.Domain.Tests/Volo/Abp/Blogging/Blogs/Blog_Tests.cs

@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Text;
using Shouldly;
using Volo.Blogging.Blogs;
using Xunit;
namespace Volo.Blogging
{
public class Blog_Tests
{
[Theory]
[InlineData("aaa")]
[InlineData("bbb")]
public void SetName(string name)
{
var blog = new Blog(Guid.NewGuid(), "test blog", "test");
blog.SetName(name);
blog.Name.ShouldBe(name);
}
[Theory]
[InlineData("aaa")]
[InlineData("bbb")]
public void SetShortName(string name)
{
var blog = new Blog(Guid.NewGuid(), "test blog", "test");
blog.SetShortName(name);
blog.ShortName.ShouldBe(name);
}
}
}

22
modules/blogging/test/Volo.Blogging.Domain.Tests/Volo/Abp/Blogging/Comments/Comment_Tests.cs

@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Text;
using Shouldly;
using Volo.Blogging.Comments;
using Xunit;
namespace Volo.Blogging
{
public class Comment_Tests
{
[Theory]
[InlineData("aaa")]
[InlineData("bbb")]
public void SetText(string text)
{
var comment = new Comment(Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid(), "good");
comment.SetText(text);
comment.Text.ShouldBe(text);
}
}
}

65
modules/blogging/test/Volo.Blogging.Domain.Tests/Volo/Abp/Blogging/Posts/Post_Tests.cs

@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using System.Text;
using Shouldly;
using Volo.Blogging.Comments;
using Volo.Blogging.Posts;
using Xunit;
namespace Volo.Blogging
{
public class Post_Tests
{
[Fact]
public void IncreaseReadCount()
{
var post = new Post(Guid.NewGuid(), Guid.NewGuid(), "abp", "⊙o⊙", "abp.io");
post.IncreaseReadCount();
post.ReadCount.ShouldBe(1);
}
[Theory]
[InlineData("aaa")]
[InlineData("bbb")]
public void SetTitle(string title)
{
var post = new Post(Guid.NewGuid(), Guid.NewGuid(), "abp", "⊙o⊙", "abp.io");
post.SetTitle(title);
post.Title.ShouldBe(title);
}
[Theory]
[InlineData("aaa")]
[InlineData("bbb")]
public void SetUrl(string url)
{
var post = new Post(Guid.NewGuid(), Guid.NewGuid(), "abp", "⊙o⊙", "abp.io");
post.SetUrl(url);
post.Url.ShouldBe(url);
}
[Fact]
public void AddTag()
{
var post = new Post(Guid.NewGuid(), Guid.NewGuid(), "abp", "⊙o⊙", "abp.io");
var tagId = Guid.NewGuid();
post.AddTag(tagId);
post.Tags.ShouldContain(x => x.TagId == tagId);
}
[Fact]
public void RemoveTag()
{
var post = new Post(Guid.NewGuid(), Guid.NewGuid(), "abp", "⊙o⊙", "abp.io");
var tagId = Guid.NewGuid();
post.AddTag(tagId);
post.Tags.ShouldContain(x => x.TagId == tagId);
post.RemoveTag(tagId);
post.Tags.ShouldNotContain(x => x.TagId == tagId);
}
}
}

64
modules/blogging/test/Volo.Blogging.Domain.Tests/Volo/Abp/Blogging/Tagging/Tag_Tests.cs

@ -0,0 +1,64 @@
using System;
using System.Collections.Generic;
using System.Text;
using Shouldly;
using Volo.Blogging.Tagging;
using Xunit;
namespace Volo.Blogging
{
public class Tag_Tests
{
[Theory]
[InlineData("aaa")]
[InlineData("bbb")]
public void SetName(string name)
{
var tag = new Tag(Guid.NewGuid(), "abp", 0, "abp tag");
tag.SetName(name);
tag.Name.ShouldBe(name);
}
[Theory]
[InlineData(1)]
[InlineData(2)]
[InlineData(3)]
public void IncreaseUsageCount(int number)
{
var tag = new Tag(Guid.NewGuid(), "abp", 0, "abp tag");
tag.IncreaseUsageCount(number);
tag.UsageCount.ShouldBe(number);
}
[Theory]
[InlineData(1)]
[InlineData(2)]
[InlineData(3)]
public void DecreaseUsageCount(int number)
{
var tag = new Tag(Guid.NewGuid(), "abp", 10, "abp tag");
tag.DecreaseUsageCount(number);
tag.UsageCount.ShouldBe(10 - number);
}
[Fact]
public void DecreaseUsageCount_Should_Greater_ThanOrEqual_Zero()
{
var tag = new Tag(Guid.NewGuid(), "abp", 10, "abp tag");
tag.DecreaseUsageCount(100);
tag.UsageCount.ShouldBe(0);
}
[Theory]
[InlineData("aaa")]
[InlineData("bbb")]
public void SetDescription(string description)
{
var tag = new Tag(Guid.NewGuid(), "abp", 0, "abp tag");
tag.SetDescription(description);
tag.Description.ShouldBe(description);
}
}
}

71
modules/blogging/test/Volo.Blogging.Domain.Tests/Volo/Abp/Blogging/Users/BlogUser_Test.cs

@ -0,0 +1,71 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Text;
using Shouldly;
using Volo.Abp.Users;
using Volo.Blogging.Users;
using Xunit;
namespace Volo.Blogging
{
public class BlogUser_Test
{
[Fact]
public void Update()
{
var userId = Guid.NewGuid();
var tenantId = Guid.NewGuid();
var blogUser = new BlogUser(new UserData(userId, "bob lee", "boblee@volosoft.com", "lee", "bob", true,
"123456", true, tenantId));
var userData = new UserData(userId, "lee bob", "leebob@volosoft.com", "bob", "lee", false,
"654321", false, tenantId);
blogUser.Update(userData);
blogUser.Equals(new BlogUser(userData)).ShouldBeTrue();
}
[Fact]
public void Update_User_Id_Must_Equals()
{
var userId = Guid.NewGuid();
var tenantId = Guid.NewGuid();
var blogUser = new BlogUser(new UserData(userId, "bob lee", "boblee@volosoft.com", "lee", "bob", true,
"123456", true, tenantId));
var userData = new UserData(Guid.NewGuid(), "lee bob", "leebob@volosoft.com", "bob", "lee", false,
"654321", false, tenantId);
Assert.Throws<ArgumentException>(() => blogUser.Update(userData));
}
[Fact]
public void Update_Tenant_Id_Must_Equals()
{
var userId = Guid.NewGuid();
var tenantId = Guid.NewGuid();
var blogUser = new BlogUser(new UserData(userId, "bob lee", "boblee@volosoft.com", "lee", "bob", true,
"123456", true, tenantId));
var userData = new UserData(userId, "lee bob", "leebob@volosoft.com", "bob", "lee", false,
"654321", false, Guid.NewGuid());
Assert.Throws<ArgumentException>(() => blogUser.Update(userData));
}
[Fact]
public void BlogUserEquals()
{
var userId = Guid.NewGuid();
var tenantId = Guid.NewGuid();
var blogUser = new BlogUser(new UserData(userId, "bob lee", "john@volosoft.com", "lee", "bob", true,
"123456", true, tenantId));
var blogUser2= new BlogUser(new UserData(userId, "bob lee", "john@volosoft.com", "lee", "bob", true,
"123456", true, tenantId));
blogUser.Equals(blogUser2).ShouldBeTrue();
}
}
}

7
modules/blogging/test/Volo.Blogging.EntityFrameworkCore.Tests/Volo/Blogging/Blogs/BlogRepository_Tests.cs

@ -1,9 +1,8 @@
using Volo.Blogging.EntityFrameworkCore;
using Volo.Blogging.Blogs;
namespace Volo.Blogging.Blogs
namespace Volo.Blogging
{
public class BlogRepository_Tests : BlogRepository_Tests<BloggingEntityFrameworkCoreTestModule>
{
}
}
}

8
modules/blogging/test/Volo.Blogging.EntityFrameworkCore.Tests/Volo/Blogging/Comments/CommentRepository_Tests.cs

@ -0,0 +1,8 @@
using Volo.Blogging.Comments;
namespace Volo.Blogging
{
public class CommentRepository_Tests : CommentRepository_Tests<BloggingEntityFrameworkCoreTestModule>
{
}
}

6
modules/blogging/test/Volo.Blogging.EntityFrameworkCore.Tests/Volo/Blogging/EntityFrameworkCore/BloggingEntityFrameworkCoreTestModule.cs

@ -2,12 +2,12 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.Modularity;
using Volo.Blogging.EntityFrameworkCore;
namespace Volo.Blogging.EntityFrameworkCore
namespace Volo.Blogging
{
[DependsOn(
typeof(BloggingEntityFrameworkCoreModule),
@ -49,4 +49,4 @@ namespace Volo.Blogging.EntityFrameworkCore
_sqliteConnection.Dispose();
}
}
}
}

8
modules/blogging/test/Volo.Blogging.EntityFrameworkCore.Tests/Volo/Blogging/Posts/PostRepository_Tests.cs

@ -0,0 +1,8 @@
using Volo.Blogging.Posts;
namespace Volo.Blogging
{
public class PostRepository_Tests : PostRepository_Tests<BloggingEntityFrameworkCoreTestModule>
{
}
}

8
modules/blogging/test/Volo.Blogging.EntityFrameworkCore.Tests/Volo/Blogging/Tagging/TagRepository_Tests.cs

@ -0,0 +1,8 @@
using Volo.Blogging.Tagging;
namespace Volo.Blogging
{
public class TagRepository_Tests : TagRepository_Tests<BloggingEntityFrameworkCoreTestModule>
{
}
}

19
modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo.Blogging.MongoDB.Tests.csproj

@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
<PackageReference Include="Mongo2Go" Version="2.2.8" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Volo.Blogging.MongoDB\Volo.Blogging.MongoDB.csproj" />
<ProjectReference Include="..\Volo.Blogging.TestBase\Volo.Blogging.TestBase.csproj" />
</ItemGroup>
</Project>

8
modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/Blogs/BlogRepository_Tests.cs

@ -0,0 +1,8 @@
using Volo.Blogging.Blogs;
namespace Volo.Blogging
{
public class BlogRepository_Tests : BlogRepository_Tests<BloggingMongoDBTestModule>
{
}
}

8
modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/Comments/CommentRepository_Tests.cs

@ -0,0 +1,8 @@
using Volo.Blogging.Comments;
namespace Volo.Blogging
{
public class CommentRepository_Tests : CommentRepository_Tests<BloggingMongoDBTestModule>
{
}
}

32
modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/MongoDB/BloggingMongoDBTestModule.cs

@ -0,0 +1,32 @@
using Mongo2Go;
using Volo.Abp;
using Volo.Abp.Data;
using Volo.Abp.Modularity;
using Volo.Blogging.MongoDB;
namespace Volo.Blogging
{
[DependsOn(
typeof(BloggingTestBaseModule),
typeof(BloggingMongoDbModule)
)]
public class BloggingMongoDBTestModule : AbpModule
{
private MongoDbRunner _mongoDbRunner;
public override void ConfigureServices(ServiceConfigurationContext context)
{
_mongoDbRunner = MongoDbRunner.Start();
Configure<DbConnectionOptions>(options =>
{
options.ConnectionStrings.Default = _mongoDbRunner.ConnectionString;
});
}
public override void OnApplicationShutdown(ApplicationShutdownContext context)
{
_mongoDbRunner.Dispose();
}
}
}

8
modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/Posts/PostRepository_Tests.cs

@ -0,0 +1,8 @@
using Volo.Blogging.Posts;
namespace Volo.Blogging
{
public class PostRepository_Tests : PostRepository_Tests<BloggingMongoDBTestModule>
{
}
}

8
modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/Tagging/TagRepository_Tests.cs

@ -0,0 +1,8 @@
using Volo.Blogging.Tagging;
namespace Volo.Blogging
{
public class TagRepository_Tests : TagRepository_Tests<BloggingMongoDBTestModule>
{
}
}

2
modules/blogging/test/Volo.Blogging.TestBase/Volo/Blogging/BloggingTestData.cs

@ -9,6 +9,8 @@ namespace Volo.Blogging
public Guid Blog1Post1Id { get; } = Guid.NewGuid();
public Guid Blog1Post2Id { get; } = Guid.NewGuid();
public Guid Blog1Post1Comment1Id { get; } = Guid.NewGuid();
public Guid Blog1Post1Comment2Id { get; } = Guid.NewGuid();
public string Tag1Name { get; } = "Tag1Name";
public string Tag2Name { get; } = "Tag2Name";
}
}

9
modules/blogging/test/Volo.Blogging.TestBase/Volo/Blogging/BloggingTestDataBuilder.cs

@ -39,10 +39,13 @@ namespace Volo.Blogging
public async Task BuildAsync()
{
await _blogRepository.InsertAsync(new Blog(_testData.Blog1Id, "The First Blog", "blog-1"));
await _postRepository.InsertAsync(new Post(_testData.Blog1Post1Id, _testData.Blog1Id, Guid.Empty, "title", "coverImage", "url"));
await _postRepository.InsertAsync(new Post(_testData.Blog1Post2Id, _testData.Blog1Id, Guid.Empty, "title", "coverImage", "url"));
await _postRepository.InsertAsync(new Post(_testData.Blog1Post1Id, _testData.Blog1Id, "title", "coverImage", "url"));
await _postRepository.InsertAsync(new Post(_testData.Blog1Post2Id, _testData.Blog1Id, "title2", "coverImage2", "url2"));
await _commentRepository.InsertAsync(new Comment(_testData.Blog1Post1Comment1Id,_testData.Blog1Post1Id,null,"text"));
await _tagRepository.InsertAsync(new Tag(_testData.Blog1Id, _testData.Tag1Name));
await _commentRepository.InsertAsync(new Comment(_testData.Blog1Post1Comment2Id, _testData.Blog1Post1Id, _testData.Blog1Post1Comment1Id, "text"));
await _tagRepository.InsertAsync(new Tag(_testData.Blog1Id, _testData.Tag1Name, 10));
await _tagRepository.InsertAsync(new Tag(_testData.Blog1Id, _testData.Tag2Name));
}
}
}

54
modules/blogging/test/Volo.Blogging.TestBase/Volo/Blogging/Comments/CommentRepository_Tests.cs

@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Shouldly;
using Volo.Abp.Modularity;
using Xunit;
namespace Volo.Blogging.Comments
{
public abstract class CommentRepository_Tests<TStartupModule> : BloggingTestBase<TStartupModule>
where TStartupModule : IAbpModule
{
protected ICommentRepository CommentRepository { get; }
protected BloggingTestData BloggingTestData { get; }
protected CommentRepository_Tests()
{
CommentRepository = GetRequiredService<ICommentRepository>();
BloggingTestData = GetRequiredService<BloggingTestData>();
}
[Fact]
public async Task GetListOfPostAsync()
{
var comments = await CommentRepository.GetListOfPostAsync(BloggingTestData.Blog1Post1Id);
comments.ShouldNotBeNull();
comments.Count.ShouldBe(2);
comments.ShouldAllBe(x => x.PostId == BloggingTestData.Blog1Post1Id);
}
[Fact]
public async Task GetCommentCountOfPostAsync()
{
var count = await CommentRepository.GetCommentCountOfPostAsync(BloggingTestData.Blog1Post1Id);
count.ShouldBe(2);
}
[Fact]
public async Task GetRepliesOfComment()
{
var comment = await CommentRepository.GetRepliesOfComment(BloggingTestData.Blog1Post1Comment1Id);
comment.ShouldNotBeNull();
comment.ShouldContain(x => x.Id == BloggingTestData.Blog1Post1Comment2Id);
}
[Fact]
public async Task DeleteOfPost()
{
await CommentRepository.DeleteOfPost(BloggingTestData.Blog1Post1Id);
(await CommentRepository.GetListAsync()).ShouldBeEmpty();
}
}
}

41
modules/blogging/test/Volo.Blogging.TestBase/Volo/Blogging/Posts/PostRepository_Tests.cs

@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Shouldly;
using Volo.Abp.Modularity;
using Xunit;
namespace Volo.Blogging.Posts
{
public abstract class PostRepository_Tests<TStartupModule> : BloggingTestBase<TStartupModule>
where TStartupModule : IAbpModule
{
protected IPostRepository PostRepository { get; }
protected BloggingTestData BloggingTestData { get; }
protected PostRepository_Tests()
{
PostRepository = GetRequiredService<IPostRepository>();
BloggingTestData = GetRequiredService<BloggingTestData>();
}
[Fact]
public async Task GetListOfPostAsync()
{
var posts = await PostRepository.GetPostsByBlogId(BloggingTestData.Blog1Id);
posts.ShouldNotBeNull();
posts.Count.ShouldBe(2);
posts.ShouldContain(x => x.Id == BloggingTestData.Blog1Post1Id);
posts.ShouldContain(x => x.Id == BloggingTestData.Blog1Post2Id);
}
[Fact]
public async Task GetPostByUrl()
{
var post = await PostRepository.GetPostByUrl(BloggingTestData.Blog1Id, "url");
post.ShouldNotBeNull();
post.Url.ShouldBe("url");
}
}
}

73
modules/blogging/test/Volo.Blogging.TestBase/Volo/Blogging/Tagging/TagRepository_Tests.cs

@ -0,0 +1,73 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Shouldly;
using Volo.Abp.Modularity;
using Xunit;
namespace Volo.Blogging.Tagging
{
public abstract class TagRepository_Tests<TStartupModule> : BloggingTestBase<TStartupModule>
where TStartupModule : IAbpModule
{
protected ITagRepository TagRepository { get; }
protected BloggingTestData BloggingTestData { get; }
protected TagRepository_Tests()
{
TagRepository = GetRequiredService<ITagRepository>();
BloggingTestData = GetRequiredService<BloggingTestData>();
}
[Fact]
public async Task GetListAsync()
{
var tags = await TagRepository.GetListAsync(BloggingTestData.Blog1Id);
tags.ShouldNotBeNull();
tags.Count.ShouldBe(2);
}
[Fact]
public async Task GetByNameAsync()
{
var tag = await TagRepository.GetByNameAsync(BloggingTestData.Blog1Id, BloggingTestData.Tag1Name);
tag.ShouldNotBeNull();
tag.Name.ShouldBe(BloggingTestData.Tag1Name);
}
[Fact]
public async Task FindByNameAsync()
{
var tag = await TagRepository.FindByNameAsync(BloggingTestData.Blog1Id, BloggingTestData.Tag1Name);
tag.ShouldNotBeNull();
tag.Name.ShouldBe(BloggingTestData.Tag1Name);
}
[Fact]
public async Task GetListAsync2()
{
var tagIds = (await TagRepository.GetListAsync()).Select(x => x.Id).ToList();
var tags = await TagRepository.GetListAsync(tagIds);
tags.ShouldNotBeNull();
tags.Count.ShouldBe(tagIds.Count);
}
[Fact]
public async Task DecreaseUsageCountOfTags()
{
var tag = await TagRepository.FindByNameAsync(BloggingTestData.Blog1Id, BloggingTestData.Tag1Name);
var usageCount = tag.UsageCount;
TagRepository.DecreaseUsageCountOfTags(new List<Guid>()
{
tag.Id
});
await TagRepository.FindByNameAsync(BloggingTestData.Blog1Id, BloggingTestData.Tag1Name);
(await TagRepository.FindByNameAsync(BloggingTestData.Blog1Id, BloggingTestData.Tag1Name)).UsageCount
.ShouldBe(usageCount - 1);
}
}
}

13
modules/blogging/test/Volo.Blogging.TestBase/Volo/Blogging/Users/BlogUserRepository_Tests.cs

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Text;
using Volo.Abp.Modularity;
namespace Volo.Blogging.Users
{
public abstract class BlogUserRepository_Tests<TStartupModule> : BloggingTestBase<TStartupModule>
where TStartupModule : IAbpModule
{
}
}

6
modules/docs/README.md

@ -1,4 +1,4 @@
# docs module
# Docs Module
This module is used to create technical documentation web sites. [abp.io](https://abp.io) web site uses this module for its documentation.
### Screenshot
@ -7,7 +7,7 @@ This module is used to create technical documentation web sites. [abp.io](https:
### Main Features
* Can read documents from a Github repository.
* Retrieves documents from a Github repository.
* Supports Markdown document formatting.
* Supports versioning (integrated to Github releases).
* Support multiple projects.
* Supports multiple projects.

76
modules/docs/Volo.Docs.sln

@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27703.1
# Visual Studio Version 16
VisualStudioVersion = 16.0.28729.10
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{42416152-5BAB-4706-93A6-57A19E71FE14}"
EndProject
@ -23,10 +23,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Docs.Web", "src\Volo.D
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "app", "app", "{555508AD-F593-43E3-9354-9FA51512F181}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.DocsTestApp", "app\Volo.DocsTestApp\Volo.DocsTestApp.csproj", "{30BC20A3-85CE-4907-8FD0-54153C3F190C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.DocsTestApp.EntityFrameworkCore", "app\Volo.DocsTestApp.EntityFrameworkCore\Volo.DocsTestApp.EntityFrameworkCore.csproj", "{A5F88BCB-6B22-4E2D-AE89-AEF1E3DC727A}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "domain", "domain", "{A982A58E-1E92-4764-9F56-39E7AABB8556}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "admin-app", "admin-app", "{BCA19441-17E9-43E6-AED1-15344D18F967}"
@ -43,6 +39,24 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Docs.Admin.HttpApi.Cli
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Docs.Admin.Web", "src\Volo.Docs.Admin.Web\Volo.Docs.Admin.Web.csproj", "{116A6145-9D66-4867-B3EF-A464FAC47946}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{59D430A9-AC61-4457-8338-5DA0705ABB5D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Docs.Application.Tests", "test\Volo.Docs.Application.Tests\Volo.Docs.Application.Tests.csproj", "{1BE0A197-55D0-40FF-A182-DBCF2E38D0C3}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Docs.Domain.Tests", "test\Volo.Docs.Domain.Tests\Volo.Docs.Domain.Tests.csproj", "{213F44A8-F9C1-4F04-9159-37E232FF18F2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Docs.EntityFrameworkCore.Tests", "test\Volo.Docs.EntityFrameworkCore.Tests\Volo.Docs.EntityFrameworkCore.Tests.csproj", "{89F895EA-C4A0-4D91-9181-016F78459776}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Docs.TestBase", "test\Volo.Docs.TestBase\Volo.Docs.TestBase.csproj", "{C8BF652A-6DDF-4E5C-8CBA-BA5AFC50BFE2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Docs.Admin.Application.Tests", "test\Volo.Docs.Admin.Application.Tests\Volo.Docs.Admin.Application.Tests.csproj", "{E9CF69BC-EEA6-4621-BE0E-64EE37C89807}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VoloDocs.EntityFrameworkCore", "app\VoloDocs.EntityFrameworkCore\VoloDocs.EntityFrameworkCore.csproj", "{1B459653-8DAC-41CD-A08E-28D6E74265D3}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VoloDocs.Web", "app\VoloDocs.Web\VoloDocs.Web.csproj", "{057EA924-4524-4452-840C-5E3D509F2ED3}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VoloDocs.Migrator", "app\VoloDocs.Migrator\VoloDocs.Migrator.csproj", "{8A5E5001-C017-44A8-ADDA-DC66C102556E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -81,14 +95,6 @@ Global
{871FB966-C89F-4AF5-BB1D-172625AA571C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{871FB966-C89F-4AF5-BB1D-172625AA571C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{871FB966-C89F-4AF5-BB1D-172625AA571C}.Release|Any CPU.Build.0 = Release|Any CPU
{30BC20A3-85CE-4907-8FD0-54153C3F190C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{30BC20A3-85CE-4907-8FD0-54153C3F190C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{30BC20A3-85CE-4907-8FD0-54153C3F190C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{30BC20A3-85CE-4907-8FD0-54153C3F190C}.Release|Any CPU.Build.0 = Release|Any CPU
{A5F88BCB-6B22-4E2D-AE89-AEF1E3DC727A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A5F88BCB-6B22-4E2D-AE89-AEF1E3DC727A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A5F88BCB-6B22-4E2D-AE89-AEF1E3DC727A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A5F88BCB-6B22-4E2D-AE89-AEF1E3DC727A}.Release|Any CPU.Build.0 = Release|Any CPU
{37D483C8-400B-4127-A6D0-2EE4E80CB696}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{37D483C8-400B-4127-A6D0-2EE4E80CB696}.Debug|Any CPU.Build.0 = Debug|Any CPU
{37D483C8-400B-4127-A6D0-2EE4E80CB696}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -109,6 +115,38 @@ Global
{116A6145-9D66-4867-B3EF-A464FAC47946}.Debug|Any CPU.Build.0 = Debug|Any CPU
{116A6145-9D66-4867-B3EF-A464FAC47946}.Release|Any CPU.ActiveCfg = Release|Any CPU
{116A6145-9D66-4867-B3EF-A464FAC47946}.Release|Any CPU.Build.0 = Release|Any CPU
{1BE0A197-55D0-40FF-A182-DBCF2E38D0C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1BE0A197-55D0-40FF-A182-DBCF2E38D0C3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1BE0A197-55D0-40FF-A182-DBCF2E38D0C3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1BE0A197-55D0-40FF-A182-DBCF2E38D0C3}.Release|Any CPU.Build.0 = Release|Any CPU
{213F44A8-F9C1-4F04-9159-37E232FF18F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{213F44A8-F9C1-4F04-9159-37E232FF18F2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{213F44A8-F9C1-4F04-9159-37E232FF18F2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{213F44A8-F9C1-4F04-9159-37E232FF18F2}.Release|Any CPU.Build.0 = Release|Any CPU
{89F895EA-C4A0-4D91-9181-016F78459776}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{89F895EA-C4A0-4D91-9181-016F78459776}.Debug|Any CPU.Build.0 = Debug|Any CPU
{89F895EA-C4A0-4D91-9181-016F78459776}.Release|Any CPU.ActiveCfg = Release|Any CPU
{89F895EA-C4A0-4D91-9181-016F78459776}.Release|Any CPU.Build.0 = Release|Any CPU
{C8BF652A-6DDF-4E5C-8CBA-BA5AFC50BFE2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C8BF652A-6DDF-4E5C-8CBA-BA5AFC50BFE2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C8BF652A-6DDF-4E5C-8CBA-BA5AFC50BFE2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C8BF652A-6DDF-4E5C-8CBA-BA5AFC50BFE2}.Release|Any CPU.Build.0 = Release|Any CPU
{E9CF69BC-EEA6-4621-BE0E-64EE37C89807}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E9CF69BC-EEA6-4621-BE0E-64EE37C89807}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E9CF69BC-EEA6-4621-BE0E-64EE37C89807}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E9CF69BC-EEA6-4621-BE0E-64EE37C89807}.Release|Any CPU.Build.0 = Release|Any CPU
{1B459653-8DAC-41CD-A08E-28D6E74265D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1B459653-8DAC-41CD-A08E-28D6E74265D3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1B459653-8DAC-41CD-A08E-28D6E74265D3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1B459653-8DAC-41CD-A08E-28D6E74265D3}.Release|Any CPU.Build.0 = Release|Any CPU
{057EA924-4524-4452-840C-5E3D509F2ED3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{057EA924-4524-4452-840C-5E3D509F2ED3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{057EA924-4524-4452-840C-5E3D509F2ED3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{057EA924-4524-4452-840C-5E3D509F2ED3}.Release|Any CPU.Build.0 = Release|Any CPU
{8A5E5001-C017-44A8-ADDA-DC66C102556E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8A5E5001-C017-44A8-ADDA-DC66C102556E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8A5E5001-C017-44A8-ADDA-DC66C102556E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8A5E5001-C017-44A8-ADDA-DC66C102556E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -122,8 +160,6 @@ Global
{30808C64-F590-47F7-AF8A-256F6B6E186B} = {8B0CDFC9-E313-4323-9390-59CFFAAC60B5}
{BF3FDDFF-BED8-422C-82E9-07F181A2D47F} = {8B0CDFC9-E313-4323-9390-59CFFAAC60B5}
{871FB966-C89F-4AF5-BB1D-172625AA571C} = {8B0CDFC9-E313-4323-9390-59CFFAAC60B5}
{30BC20A3-85CE-4907-8FD0-54153C3F190C} = {555508AD-F593-43E3-9354-9FA51512F181}
{A5F88BCB-6B22-4E2D-AE89-AEF1E3DC727A} = {555508AD-F593-43E3-9354-9FA51512F181}
{A982A58E-1E92-4764-9F56-39E7AABB8556} = {42416152-5BAB-4706-93A6-57A19E71FE14}
{BCA19441-17E9-43E6-AED1-15344D18F967} = {42416152-5BAB-4706-93A6-57A19E71FE14}
{8B0CDFC9-E313-4323-9390-59CFFAAC60B5} = {42416152-5BAB-4706-93A6-57A19E71FE14}
@ -132,6 +168,14 @@ Global
{262F38DB-62AF-427F-96E2-C6385C5AB695} = {BCA19441-17E9-43E6-AED1-15344D18F967}
{81EE378A-0DE1-47BA-86D9-08EF6317BB95} = {BCA19441-17E9-43E6-AED1-15344D18F967}
{116A6145-9D66-4867-B3EF-A464FAC47946} = {BCA19441-17E9-43E6-AED1-15344D18F967}
{1BE0A197-55D0-40FF-A182-DBCF2E38D0C3} = {59D430A9-AC61-4457-8338-5DA0705ABB5D}
{213F44A8-F9C1-4F04-9159-37E232FF18F2} = {59D430A9-AC61-4457-8338-5DA0705ABB5D}
{89F895EA-C4A0-4D91-9181-016F78459776} = {59D430A9-AC61-4457-8338-5DA0705ABB5D}
{C8BF652A-6DDF-4E5C-8CBA-BA5AFC50BFE2} = {59D430A9-AC61-4457-8338-5DA0705ABB5D}
{E9CF69BC-EEA6-4621-BE0E-64EE37C89807} = {59D430A9-AC61-4457-8338-5DA0705ABB5D}
{1B459653-8DAC-41CD-A08E-28D6E74265D3} = {555508AD-F593-43E3-9354-9FA51512F181}
{057EA924-4524-4452-840C-5E3D509F2ED3} = {555508AD-F593-43E3-9354-9FA51512F181}
{8A5E5001-C017-44A8-ADDA-DC66C102556E} = {555508AD-F593-43E3-9354-9FA51512F181}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {13691265-2547-4FFF-B757-E8FACB05679D}

4
modules/docs/app/Volo.DocsTestApp/Pages/Index.cshtml

@ -1,4 +0,0 @@
@page
@model Volo.DocsTestApp.Pages.IndexModel
<h3>Welcome to the Docs Demo!</h3>
<a href="/documents/">Go to documents...</a>

16
modules/docs/app/Volo.DocsTestApp/Pages/Index.cshtml.cs

@ -1,16 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace Volo.DocsTestApp.Pages
{
public class IndexModel : PageModel
{
public void OnGet()
{
}
}
}

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

Loading…
Cancel
Save