diff --git a/.gitignore b/.gitignore index 742c5b4584..1b1e3d8201 100644 --- a/.gitignore +++ b/.gitignore @@ -23,7 +23,7 @@ bld/ [Ll]og/ # Visual Studio 2015 cache/options directory -.vs/ +**/.vs/ # Uncomment if you have tasks that create the project's static files in wwwroot #wwwroot/ @@ -268,7 +268,6 @@ modules/blog/app/Volo.BlogTestApp/Logs/*.* modules/blogging/app/Volo.BloggingTestApp/Logs/*.* modules/blogging/app/Volo.BloggingTestApp/wwwroot/files/*.* 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/*.* diff --git a/README.md b/README.md index f6304ad5b3..ee043bdb62 100644 --- a/README.md +++ b/README.md @@ -8,36 +8,25 @@ See the official [web site (abp.io)](https://abp.io/) for more information. ### Status -This project is in **very early preview** stage and it's not suggested to use it in a real project. +This project is in **preview** stage and it's not suggested to use it in production yet. ### Documentation See the documentation. -### How to Build - -- Run the `build-all.ps1`. It will build all the solutions in this repository. - ### Development #### Pre Requirements -- Visual Studio 2017 15.9.0+ +- Visual Studio 2019 16.1.0+ #### Framework -Framework solution is located under the `framework` folder. It has no external dependency. Just open `Volo.Abp.sln` by Visual Studio and start the development. +Framework solution is located under the `framework` folder. It has no external dependency. #### Modules/Templates -[Modules](modules/) and [Templates](templates/) have their own solutions and have **local references** to the framework. Unfortunately, Visual Studio has some problems with local references to projects those are out of the solution. As a workaround, you should follow the steps below in order to start developing a module/template: - -- Disable "*Automatically check for missing packages during build in Visual Studio*" in the Visual Studio options. - -![disable-package-restore-visual-studio](docs/en/images/disable-package-restore-visual-studio.png) - -- When you open a solution, first run `dotnet restore` in the root folder of the solution. -- When you change a dependency of a project (or any of the dependencies of your projects change their dependencies), run `dotnet restore` again. +[Modules](modules/) and [Templates](templates/) have their own solutions and have **local references** to the framework and each other. ### Contribution diff --git a/docs/cs/Index.md b/docs/cs/Index.md new file mode 100644 index 0000000000..3a86344660 --- /dev/null +++ b/docs/cs/Index.md @@ -0,0 +1,30 @@ +# ABP dokumentace + +ABP je **open source aplikační framework** se zaměřením na vývoj webových aplikací založených na ASP.NET Core, zároveň ho však lze využít i k vývoji jiných typů aplikací. + +K procházení dokumentace využijte navigační nabídky vlevo. + +## Stav projektu + +ABP je **novou generací** open source frameworku [ASP.NET Boilerplate](https://aspnetboilerplate.com/). V současné době je v ranné fázi a není připraven k ostrému nasazení. Na dokumentaci se stále pracuje a ještě zdaleka není dokončena. + +Pro aplikace na krátkodobé a ostré nasazení je doporučeno použít [ASP.NET Boilerplate](https://aspnetboilerplate.com/) framework, který je bohatý na funkce, vyspělý, aktivně udržovaný a aktuální. + +## Začínáme + +Nejsnazší cestou jak začít nový projekt s ABP je užití startovací šablony: + +* [ASP.NET Core MVC Šablona](Getting-Started-AspNetCore-MVC-Template.md) + +Pokud chcete začít od nuly (s prázdným projektem) tak manuálně nainstalujte ABP Framework s pomocí následujících tutoriálů: + +* [Konzolová Aplikace](Getting-Started-Console-Application.md) +* [ASP.NET Core Web Aplikace](Getting-Started-AspNetCore-Application.md) + +## Zdrojový kód + +ABP je hostovaný na GitHub. Zobrazit [zdrojový kód](https://github.com/abpframework/abp). + +## Chcete přispět? + +ABP je komunitně řízený open source projekt. Podívejte se na [průvodce pro přispěvatele](Contribution/Index.md) pokud chcete být součástí tohoto projektu. diff --git a/docs/cs/docs-nav.json b/docs/cs/docs-nav.json new file mode 100644 index 0000000000..4b976b4812 --- /dev/null +++ b/docs/cs/docs-nav.json @@ -0,0 +1,292 @@ +{ + "items": [ + { + "text": "Začínáme", + "items": [ + { + "text": "Ze startovacích šablon", + "items": [ + { + "text": "ASP.NET Core MVC", + "path": "Getting-Started-AspNetCore-MVC-Template.md" + } + ] + }, + { + "text": "Z prázdných projektů", + "items": [ + { + "text": "S ASP.NET Core Web aplikací", + "path": "Getting-Started-AspNetCore-Application.md" + }, + { + "text": "S konzolovou aplikací", + "path": "Getting-Started-Console-Application.md" + } + ] + } + ] + }, + { + "text": "Tutoriály", + "items": [ + { + "text": "Vývoj aplikace", + "items": [ + { + "text": "S ASP.NET Core MVC", + "path": "Tutorials/AspNetCore-Mvc/Part-I.md" + } + ] + } + ] + }, + { + "text": "CLI", + "path": "CLI.md" + }, + { + "text": "Základy", + "items": [ + { + "text": "Vkládání závislostí", + "path": "Dependency-Injection.md", + "items": [ + { + "text": "AutoFac integrace", + "path": "Autofac-Integration.md" + } + ] + }, + { + "text": "Virtuální systém souborů", + "path": "Virtual-File-System.md" + }, + { + "text": "Lokalizace", + "path": "Localization.md" + }, + { + "text": "Zpracování výjimek", + "path": "Exception-Handling.md" + }, + { + "text": "Validace" + }, + { + "text": "Autorizace" + }, + { + "text": "Ukládání do mezipaměti" + }, + { + "text": "Audit" + }, + { + "text": "Správa nastavení" + } + ] + }, + { + "text": "Události", + "items": [ + { + "text": "Event bus (místní)" + }, + { + "text": "Distribuovaný event bus", + "items": [ + { + "text": "RabbitMQ integrace" + } + ] + } + ] + }, + { + "text": "Služby", + "items": [ + { + "text": "Serializace objektu" + }, + { + "text": "Serializace JSON" + }, + { + "text": "Emailování" + }, + { + "text": "GUIDy" + }, + { + "text": "Vláknování" + }, + { + "text": "Časování" + } + ] + }, + { + "text": "Multitenance", + "path": "Multi-Tenancy.md" + }, + { + "text": "Vývoj modulů", + "items": [ + { + "text": "Základy", + "path": "Module-Development-Basics.md" + }, + { + "text": "Zásuvné moduly" + }, + { + "text": "Nejlepší praktiky", + "path": "Best-Practices/Index.md" + } + ] + }, + { + "text": "Domain driven design", + "path": "Domain-Driven-Design.md", + "items": [ + { + "text": "Doménová vrstva", + "items": [ + { + "text": "Entity & agregované kořeny", + "path": "Entities.md" + }, + { + "text": "Hodnotové objekty" + }, + { + "text": "Repozitáře", + "path": "Repositories.md" + }, + { + "text": "Doménové služby" + }, + { + "text": "Specifikace" + } + ] + }, + { + "text": "Aplikační vrstva", + "items": [ + { + "text": "Aplikační služby", + "path": "Application-Services.md" + }, + { + "text": "Objekty přenosu dat" + }, + { + "text": "Jednotka práce" + } + ] + } + ] + }, + { + "text": "ASP.NET Core", + "items": [ + { + "text": "API", + "items": [ + { + "text": "Automatické API řadiče", + "path": "AspNetCore/Auto-API-Controllers.md" + }, + { + "text": "Dynamičtí C# API klienti", + "path": "AspNetCore/Dynamic-CSharp-API-Clients.md" + } + ] + }, + { + "text": "Uživatelské rozhraní", + "items": [ + { + "text": "Správa klientských balíčků", + "path": "AspNetCore/Client-Side-Package-Management.md" + }, + { + "text": "Svazování & minifikace", + "path": "AspNetCore/Bundling-Minification.md" + }, + { + "text": "Tag pomocníci", + "path": "Tag-Helpers.md" + }, + { + "text": "Motivy", + "path": "AspNetCore/Theming.md" + } + ] + } + ] + }, + { + "text": "Přístup k datům", + "items": [ + { + "text": "Entity Framework Core integrace", + "path": "Entity-Framework-Core.md" + }, + { + "text": "MongoDB integrace", + "path": "MongoDB.md" + } + ] + }, + { + "text": "Pozadí", + "items": [ + { + "text": "Úkony na pozadí", + "path": "Background-Jobs.md", + "items": [ + { + "text": "Hangfire integrace", + "path": "Background-Jobs-Hangfire.md" + }, + { + "text": "RabbitMQ integrace", + "path": "Background-Jobs-RabbitMq.md" + } + ] + } + ] + }, + { + "text": "Vzorky", + "items": [ + { + "text": "Mikroslužby demo", + "path": "Samples/Microservice-Demo.md" + } + ] + }, + { + "text": "Moduly aplikace", + "path": "Modules/Index.md" + }, + { + "text": "Architektura mikroslužby", + "path": "Microservice-Architecture.md" + }, + { + "text": "Testování" + }, + { + "text": "Noční sestavení", + "path": "Nightly-Builds.md" + }, + { + "text": "Průvodce pro přispěvatele", + "path": "Contribution/Index.md" + } + ] +} \ No newline at end of file diff --git a/docs/docs-langs.json b/docs/docs-langs.json new file mode 100644 index 0000000000..012c7e6ef0 --- /dev/null +++ b/docs/docs-langs.json @@ -0,0 +1,19 @@ +{ + "Languages":[ + { + "DisplayName" : "Čeština", + "Code" : "cs", + "IsDefault": false + }, + { + "DisplayName" : "English", + "Code" : "en", + "IsDefault": true + }, + { + "DisplayName" : "简体中文", + "Code" : "zh-Hans", + "IsDefault": false + } + ] +} \ No newline at end of file diff --git a/docs/en/AspNetCore/Auto-API-Controllers.md b/docs/en/AspNetCore/Auto-API-Controllers.md index b81afbcac4..77819c48c9 100644 --- a/docs/en/AspNetCore/Auto-API-Controllers.md +++ b/docs/en/AspNetCore/Auto-API-Controllers.md @@ -2,7 +2,7 @@ Once you create an [application service](../Application-Services.md), you generally want to create an API controller to expose this service as an HTTP (REST) API endpoint. A typical API controller does nothing but redirects method calls to the application service and configures the REST API using attributes like [HttpGet], [HttpPost], [Route]... etc. -ABP can **automagically** configures your application services as MVC API Controllers by convention. Most of time you don't care about its detailed configuration, but it's possible fully customize it. +ABP can **automagically** configure your application services as API Controllers by convention. Most of time you don't care about its detailed configuration, but it's possible to fully customize it. ## Configuration @@ -16,7 +16,9 @@ public class BookStoreWebModule : AbpModule { Configure(options => { - options.ConventionalControllers.Create(typeof(BookStoreApplicationModule).Assembly); + options + .ConventionalControllers + .Create(typeof(BookStoreApplicationModule).Assembly); }); } } diff --git a/docs/en/AspNetCore/Tag-Helpers.md b/docs/en/AspNetCore/Tag-Helpers.md deleted file mode 100644 index 4949a3ec63..0000000000 --- a/docs/en/AspNetCore/Tag-Helpers.md +++ /dev/null @@ -1,3 +0,0 @@ -# Tag Helpers - -TODO \ No newline at end of file diff --git a/docs/en/AspNetCore/Tag-Helpers/Dynamic-Forms.md b/docs/en/AspNetCore/Tag-Helpers/Dynamic-Forms.md new file mode 100644 index 0000000000..6d700f030d --- /dev/null +++ b/docs/en/AspNetCore/Tag-Helpers/Dynamic-Forms.md @@ -0,0 +1,3 @@ +## Dynamic Forms + +This is not documented yet. You can see a [demo](http://bootstrap-taghelpers.abp.io/Components/DynamicForms) for now. \ No newline at end of file diff --git a/docs/en/Tag-Helpers.md b/docs/en/AspNetCore/Tag-Helpers/Index.md similarity index 100% rename from docs/en/Tag-Helpers.md rename to docs/en/AspNetCore/Tag-Helpers/Index.md diff --git a/docs/en/Aspect-Oriented-Programming.md b/docs/en/Aspect-Oriented-Programming.md new file mode 100644 index 0000000000..76a23daa8f --- /dev/null +++ b/docs/en/Aspect-Oriented-Programming.md @@ -0,0 +1,3 @@ +## Dynamic Proxying / Interceptors + +TODO \ No newline at end of file diff --git a/docs/en/CLI.md b/docs/en/CLI.md new file mode 100644 index 0000000000..d210560910 --- /dev/null +++ b/docs/en/CLI.md @@ -0,0 +1,137 @@ +# ABP CLI + +ABP CLI (Command Line Interface) is a command line tool to perform some common operations for ABP based solutions. + +## Installation + +ABP CLI is a [dotnet global tool](https://docs.microsoft.com/en-us/dotnet/core/tools/global-tools). Install it using a command line window: + +````bash +dotnet tool install -g Volo.Abp.Cli +```` + +To update an existing installation: + +````bash +dotnet tool update -g Volo.Abp.Cli +```` + +## Commands + +### new + +Generates a new solution based on the ABP [startup templates](Startup-Templates/Index.md). + +Basic usage: + +````bash +abp new [options] +```` + +Example: + +````bash +abp new Acme.BookStore +```` + +* Acme.BookStore is the solution name here. +* Common convention is to name a solution is like *YourCompany.YourProject*. However, you can use different naming like *YourProject* (single level namespacing) or *YourCompany.YourProduct.YourModule* (three levels namespacing). + +#### Options + +* `--template` or `-t`: Specifies the template name. Default template name is `mvc`. Available templates: + * `mvc` (default): ASP.NET Core [MVC application template](Startup-Templates/Mvc.md). Additional options: + * `--database-provider` or `-d`: Specifies the database provider. Default provider is `ef`. Available providers: + * `ef`: Entity Framework Core. + * `mongodb`: MongoDB. + * `--tiered`: Creates a tiered solution where Web and Http API layers are physically separated. If not specified, it creates a layered solution which is less complex and suitable for most scenarios. + * `mvc-module`: ASP.NET Core [MVC module template](Startup-Templates/Mvc-Module.md). Additional options: + * `--no-ui`: Specifies to not include the UI. This makes possible to create service-only modules (a.k.a. microservices - without UI). +* `--output-folder` or `-o`: Specifies the output folder. Default value is the current directory. + +### add-package + +Adds a new ABP package to a project by, + +* Adding related nuget package as a dependency to the project. +* Adding `[DependsOn(...)]` attribute to the module class in the project (see the [module development document](Module-Development-Basics.md)). + +> Notice that the added module may require additional configuration which is generally indicated in the documentation of the related package. + +Basic usage: + +````bash +abp add-package [options] +```` + +Example: + +```` +abp add-package Volo.Abp.MongoDB +```` + +* This example adds the Volo.Abp.MongoDB package to the project. + +#### Options + +* `--project` or `-p`: Specifies the project (.csproj) file path. If not specified, CLI tries to find a .csproj file in the current directory. + +### add-module + +Adds a multi-package module to a solution by finding all packages of the module, finding related projects in the solution and adding each package to the corresponding project in the solution. + +> A business module generally consists of several packages (because of layering, different database providr options or other reasons). Using `add-module` command dramatically simplifies adding a module to a solution. However, each module may require some additional configurations which is generally indicated in the documentation of the related module. + +Basic usage: + +````bash +abp add-module [options] +```` + +Example: + +```bash +abp add-module Volo.Blogging +``` + +* This example add the Volo.Blogging module to the solution. + +#### Options + +* `--solution` or `-s`: Specifies the solution (.sln) file path. If not specified, CLI tries to find a .sln file in the current directory. +* `--skip-db-migrations`: For EF Core database provider, it automatically adds a new code first migration (`Add-Migration`) and updates the database (`Update-Database`) if necessary. Specify this option to skip this operation. + +### update + +Updating all ABP related packages can be tedious since there are many packages of the framework and modules. This command automatically updates all ABP related packages in a solution or project to the latest versions. + +Usage: + +````bash +abp update [options] +```` + +* If you run in a directory with a .sln file, it updates all ABP related packages of the all projects of the solution to the latest versions. +* If you run in a directory with a .csproj file, it updates all ABP related packages of the project to the latest versions. + +#### Options + +* `--include-previews` or `-p`: Includes preview, beta and rc packages while checking the latest versions. + +### help + +Writes basic usage information of the CLI. + +Usage: + +````bash +abp help [command-name] +```` + +Examples: + +````bash +abp help # Shows a general help. +abp help new # Shows help about the "new" command. +```` + diff --git a/docs/en/Caching.md b/docs/en/Caching.md new file mode 100644 index 0000000000..f7d9c52407 --- /dev/null +++ b/docs/en/Caching.md @@ -0,0 +1,3 @@ +# Caching + +TODO \ No newline at end of file diff --git a/docs/en/Contribution/Localization-Text-Files.md b/docs/en/Contribution/Localization-Text-Files.md index ed773a1d73..3932800575 100644 --- a/docs/en/Contribution/Localization-Text-Files.md +++ b/docs/en/Contribution/Localization-Text-Files.md @@ -2,19 +2,39 @@ Here, a list of localization text files for anyone wants to contribute to localization of the texts coming from the framework. We will keep this list up to date: -* https://github.com/abpframework/abp/tree/master/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json * https://github.com/abpframework/abp/tree/master/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/en.json * https://github.com/abpframework/abp/tree/master/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpValidation/en.json +* https://github.com/abpframework/abp/tree/master/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/en.json +* https://github.com/abpframework/abp/tree/master/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json +* https://github.com/abpframework/abp/tree/master/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/en.json +* https://github.com/abpframework/abp/tree/master/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/Localization/en.json +* https://github.com/abpframework/abp/tree/master/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/en.json +* https://github.com/abpframework/abp/tree/master/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/en.json +* https://github.com/abpframework/abp/tree/master/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/en.json +* https://github.com/abpframework/abp/tree/master/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/SourceExt/en.json * https://github.com/abpframework/abp/tree/master/modules/account/src/Volo.Abp.Account.Web/Localization/Resources/AbpAccount/Web/en.json -* https://github.com/abpframework/abp/tree/master/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en.json -* https://github.com/abpframework/abp/tree/master/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/en.json * https://github.com/abpframework/abp/tree/master/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Localization/Resources/Blogging/ApplicationContracts/en.json -* https://github.com/abpframework/abp/tree/master/modules/identity/src/Volo.Abp.Identity.Web/Localization/Resources/AbpIdentity/en.json -* https://github.com/abpframework/abp/tree/master/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Localization/Domain/en.json +* https://github.com/abpframework/abp/tree/master/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/en.json +* https://github.com/abpframework/abp/tree/master/modules/docs/app/VoloDocs.Web/Localization/Resources/VoloDocs/Web/en.json +* https://github.com/abpframework/abp/tree/master/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/en.json +* https://github.com/abpframework/abp/tree/master/modules/docs/src/Volo.Docs.Admin.Web/Localization/Resources/Docs/Web/en.json +* https://github.com/abpframework/abp/tree/master/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en.json +* https://github.com/abpframework/abp/tree/master/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/Localization/ApplicationContracts/en.json +* https://github.com/abpframework/abp/tree/master/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/Localization/Domain/en.json +* https://github.com/abpframework/abp/tree/master/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Localization/Resources/FeatureManagement/en.json * https://github.com/abpframework/abp/tree/master/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/Localization/ApplicationContracts/en.json +* https://github.com/abpframework/abp/tree/master/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Localization/Domain/en.json +* https://github.com/abpframework/abp/tree/master/modules/identity/src/Volo.Abp.Identity.Web/Localization/Resources/AbpIdentity/en.json * https://github.com/abpframework/abp/tree/master/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Localization/Resources/AbpPermissionManagement/en.json -* https://github.com/abpframework/abp/tree/master/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Localization/Resources/AbpTenantManagement/Web/en.json +* https://github.com/abpframework/abp/tree/master/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Localization/Resources/AbpSettingManagement/en.json * https://github.com/abpframework/abp/tree/master/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/Localization/ApplicationContracts/en.json -* https://github.com/abpframework/abp/tree/master/templates/mvc/src/MyCompanyName.MyProjectName.Domain/Localization/MyProjectName/en.json -* https://github.com/abpframework/abp/tree/master/templates/module/src/MyCompanyName.MyProjectName.Domain/MyCompanyName/MyProjectName/Localization/Domain/en.json -* https://github.com/abpframework/abp/tree/master/templates/module/src/MyCompanyName.MyProjectName.Web/Localization/Resources/MyProjectName/en.json \ No newline at end of file +* https://github.com/abpframework/abp/tree/master/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Localization/Resources/AbpTenantManagement/Web/en.json +* https://github.com/abpframework/abp/tree/master/samples/BookStore/src/Acme.BookStore.Domain.Shared/Localization/BookStore/en.json +* https://github.com/abpframework/abp/tree/master/samples/DashboardDemo/src/DashboardDemo.Domain/Localization/DashboardDemo/en.json +* https://github.com/abpframework/abp/tree/master/samples/MicroserviceDemo/modules/product/src/ProductManagement.Application.Contracts/ProductManagement/Localization/ApplicationContracts/en.json +* https://github.com/abpframework/abp/tree/master/samples/MicroserviceDemo/modules/product/src/ProductManagement.Domain/ProductManagement/Localization/Domain/en.json +* https://github.com/abpframework/abp/tree/master/samples/MicroserviceDemo/modules/product/src/ProductManagement.Web/Localization/Resources/ProductManagement/en.json +* https://github.com/abpframework/abp/tree/master/templates/mvc-module/src/MyCompanyName.MyProjectName.Application.Contracts/Localization/MyProjectName/ApplicationContracts/en.json +* https://github.com/abpframework/abp/tree/master/templates/mvc-module/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/DomainShared/en.json +* https://github.com/abpframework/abp/tree/master/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Localization/MyProjectName/Web/en.json +* https://github.com/abpframework/abp/tree/master/templates/mvc/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/en.json diff --git a/docs/en/CorrelationId.md b/docs/en/CorrelationId.md new file mode 100644 index 0000000000..99bcd448f4 --- /dev/null +++ b/docs/en/CorrelationId.md @@ -0,0 +1,3 @@ +# Correlation ID + +TODO \ No newline at end of file diff --git a/docs/en/Data-Filtering.md b/docs/en/Data-Filtering.md new file mode 100644 index 0000000000..284f74918a --- /dev/null +++ b/docs/en/Data-Filtering.md @@ -0,0 +1,3 @@ +# Data Filtering + +TODO \ No newline at end of file diff --git a/docs/en/Data-Seeding.md b/docs/en/Data-Seeding.md new file mode 100644 index 0000000000..0b424e7e0d --- /dev/null +++ b/docs/en/Data-Seeding.md @@ -0,0 +1,3 @@ +# Data Seeding + +TODO \ No newline at end of file diff --git a/docs/en/Distributed-Event-Bus.md b/docs/en/Distributed-Event-Bus.md new file mode 100644 index 0000000000..03beb814d2 --- /dev/null +++ b/docs/en/Distributed-Event-Bus.md @@ -0,0 +1,3 @@ +# Distributed Event Bus + +TODO \ No newline at end of file diff --git a/docs/en/Extension-Methods-And-Helpers.md b/docs/en/Extension-Methods-And-Helpers.md new file mode 100644 index 0000000000..8dac0a56ee --- /dev/null +++ b/docs/en/Extension-Methods-And-Helpers.md @@ -0,0 +1,3 @@ +# Extension Methods & Helpers + +TODO \ No newline at end of file diff --git a/docs/en/Getting-Started-AspNetCore-MVC-Template.md b/docs/en/Getting-Started-AspNetCore-MVC-Template.md index cb24eb543f..1e643b18cf 100644 --- a/docs/en/Getting-Started-AspNetCore-MVC-Template.md +++ b/docs/en/Getting-Started-AspNetCore-MVC-Template.md @@ -1,40 +1,45 @@ -## ASP.NET Core MVC Template +## Getting Started With the ASP.NET Core MVC Template This tutorials explains how to create a new ASP.NET Core MVC web application using the startup template, configure and run it. -### Creating a new project +### Creating a New Project -Go to [the template creation page](https://abp.io/Templates), enter a project name and create your project as shown below: +This tutorial uses **ABP CLI** to create a new project. See the [Get Started](https://abp.io/get-started) page for other options. -![bookstore-create--template](images/bookstore-create-template.png) +Install the ABP CLI using a command line window, if you've not installed before: -When you click the *create* button, a new Visual Studio solution is created and downloaded with the name you have provided. +````bash +dotnet tool install -g Volo.Abp.Cli +```` -#### Pre Requirements +Use `abp new` command in an empty folder to create your project: -The downloaded project requires; +```` +abp new Acme.BookStore +```` -* [Visual Studio 2017 (v15.7.0+)](https://visualstudio.microsoft.com/tr/downloads/) -* [.NET Core 2.1.1+](https://www.microsoft.com/net/download/dotnet-core/) +> You can use different level of namespaces; e.g. BookStore, Acme.BookStore or Acme.Retail.BookStore. -### The Solution Structure +`new` command creates a **layered MVC application** with **Entity Framework Core** as the database provider. However, it has additional options. See the [CLI documentation](CLI.md) for all available options. -Extract the zip file downloaded and open in **Visual Studio 2017 (15.9.0+)**: +#### Pre Requirements -![bookstore-visual-studio-solution](images/bookstore-visual-studio-solution-v2.png) +The created solution requires; -The solution has a layered structure (based on Domain Driven Design) where; +* [Visual Studio 2017 (v15.9.0+)](https://visualstudio.microsoft.com/tr/downloads/) +* [.NET Core 2.2+](https://www.microsoft.com/net/download/dotnet-core/) -* ``.Domain`` is the domain layer. -* ``.Application`` is the application layer. -* ``.Web`` is the presentation layer. -* ``.EntityFrameworkCore`` is the EF Core integration package. +### The Solution Structure + +Open the solution in **Visual Studio**: + +![bookstore-visual-studio-solution](images/bookstore-visual-studio-solution-v3.png) -EF Core database migrations are separated to a project named `.EntityFrameworkCore.DbMigrations`. +The solution has a layered structure (based on [Domain Driven Design](Domain-Driven-Design.md)) and contains unit & integration test projects properly configured to work with **EF Core** & **SQLite in-memory** database. -The solution also contains unit & integration test projects properly configured to work with **EF Core** & **SQLite in-memory** database. +> See [MVC application template document](Startup-Templates/Mvc.md) to understand the solution structure in details. -### Creating the Database +### Database Connection String Check the **connection string** in the `appsettings.json` file under the `.Web` project: @@ -46,9 +51,29 @@ Check the **connection string** in the `appsettings.json` file under the `.Web` } ```` -The solution is configured to use **Entity Framework Core** with **MS SQL Server**. EF Core supports [various](https://docs.microsoft.com/en-us/ef/core/providers/) database providers, so you can use another DBMS if you want. +The solution is configured to use **Entity Framework Core** with **MS SQL Server**. EF Core supports [various](https://docs.microsoft.com/en-us/ef/core/providers/) database providers, so you can use another DBMS if you want. Change the connection string if you need. + +### Create Database & Apply Database Migrations + +You have two options to create the database. -Right click to the `.Web` project and select **Set as StartUp Project**: +#### Using the DbMigrator Application + +The solution contains a console application (named `Acme.BookStore.DbMigrator` in this sample) that can create database, apply migrations and seed initial data. It is useful on development as well as on production environment. + +> `.DbMigrator` project has its own `appsettings.json`. So, if you have changed the connection string above, you should also change this one. + +Right click to the `.DbMigrator` project and select **Set as StartUp Project**: + +![set-as-startup-project](images/set-as-startup-project.png) + +Hit F5 (or Ctrl+F5) to run the application. It will have an output like shown below: + +![set-as-startup-project](images/db-migrator-app.png) + +#### Using EF Core Update-Database Command + +Ef Core has `Update-Database` command which creates database if necessary and applies pending migrations. Right click to the `.Web` project and select **Set as StartUp Project**: ![set-as-startup-project](images/set-as-startup-project.png) @@ -58,17 +83,19 @@ Open the **Package Manager Console**, select `.EntityFrameworkCore.DbMigrations` This will create a new database based on the configured connection string. +> Using the `.Migrator` tool is the suggested way, because it also seeds the initial data to be able to properly run the web application. + ### Running the Application -You can now run the application which will open the **home** page: +Ensure that the `.Web` project is the startup project. Run the application which will open the **home** page in your browser: ![bookstore-homepage](images/bookstore-homepage.png) Click the **Login** button, enter `admin` as the username and `1q2w3E*` as the password to login to the application. -The startup template includes the **identity management** module. Once you login, the Identity management menu will be available where you can manage **roles**, **users** and their **permissions**. +The startup template includes the **identity management** and **tenant management** modules. Once you login, the Administration menu will be available where you can manage **tenants**, **roles**, **users** and their **permissions**. User management page is shown below: -![bookstore-user-management](images/bookstore-user-management.png) +![bookstore-user-management](images/bookstore-user-management-v2.png) ### What's Next? diff --git a/docs/en/Index.md b/docs/en/Index.md index b1bccab0ea..d911bf66e2 100644 --- a/docs/en/Index.md +++ b/docs/en/Index.md @@ -6,7 +6,7 @@ Explore the left navigation menu to deep dive in the documentation. ## Project Status -ABP is the **next generation** of the open source [ASP.NET Boilerplate](https://aspnetboilerplate.com/) framework. It's currently in early preview stage and not ready to use in production. The documentation is still in progress and it is incomplete yet. +ABP is the **next generation** of the open source [ASP.NET Boilerplate](https://aspnetboilerplate.com/) framework. It's currently in early preview stage and not ready to use in production. The documentation is still in progress and it is far from complete. For short-term and production level applications, it's suggested to use [ASP.NET Boilerplate](https://aspnetboilerplate.com/) framework which has rich feature set, mature, actively maintained and up-to-date. diff --git a/docs/en/Integration-Tests.md b/docs/en/Integration-Tests.md new file mode 100644 index 0000000000..f9f6830956 --- /dev/null +++ b/docs/en/Integration-Tests.md @@ -0,0 +1,3 @@ +# Integration Tests + +TODO! \ No newline at end of file diff --git a/docs/en/JavaScript/Dynamic-JavaScript-API-Clients.md b/docs/en/JavaScript/Dynamic-JavaScript-API-Clients.md new file mode 100644 index 0000000000..539d3ac15a --- /dev/null +++ b/docs/en/JavaScript/Dynamic-JavaScript-API-Clients.md @@ -0,0 +1,3 @@ +## Dynamic JavaScript API Clients + +TODO \ No newline at end of file diff --git a/docs/en/Local-Event-Bus.md b/docs/en/Local-Event-Bus.md new file mode 100644 index 0000000000..859ec8d28e --- /dev/null +++ b/docs/en/Local-Event-Bus.md @@ -0,0 +1,3 @@ +# Local Event Bus + +TODO \ No newline at end of file diff --git a/docs/en/SMS-Sending.md b/docs/en/SMS-Sending.md new file mode 100644 index 0000000000..75069aacbe --- /dev/null +++ b/docs/en/SMS-Sending.md @@ -0,0 +1,3 @@ +# Emailing + +TODO! \ No newline at end of file diff --git a/docs/en/Settings.md b/docs/en/Settings.md new file mode 100644 index 0000000000..767955a9d2 --- /dev/null +++ b/docs/en/Settings.md @@ -0,0 +1,3 @@ +# Settings + +TODO! \ No newline at end of file diff --git a/docs/en/Specifications.md b/docs/en/Specifications.md new file mode 100644 index 0000000000..ea4f140e95 --- /dev/null +++ b/docs/en/Specifications.md @@ -0,0 +1,3 @@ +# Specifications + +TODO! \ No newline at end of file diff --git a/docs/en/Startup-Templates/Index.md b/docs/en/Startup-Templates/Index.md new file mode 100644 index 0000000000..cb7e020663 --- /dev/null +++ b/docs/en/Startup-Templates/Index.md @@ -0,0 +1,11 @@ +# Startup Templates + +While you can start with an empty project and add needed packages manually, startup templates makes easy and comfortable to start a new solution with the ABP framework. + +Click to the name from the list below to see the documentation of the related startup template: + +* [**mvc**](Mvc.md): ASP.NET Core MVC application template. +* [**mvc-module**](Mvc-Module.md): ASP.NET Core MVC module/service template. + + + diff --git a/docs/en/Startup-Templates/Mvc-Module.md b/docs/en/Startup-Templates/Mvc-Module.md new file mode 100644 index 0000000000..96c91b4c4b --- /dev/null +++ b/docs/en/Startup-Templates/Mvc-Module.md @@ -0,0 +1,160 @@ +# MVC Module Startup Template + +This template can be used to create a **reusable [application module](../Modules/Index.md)** based on the [module development best practices & conventions](../Best-Practices/Index.md). It is also suitable for creating **microservices** (with or without UI). + +## How to Start With? + +You can use the [ABP CLI](../CLI.md) to create a new project using this startup template. Alternatively, you can directly create & download from the [Get Started](https://abp.io/get-started) page. CLI approach is used here. + +First, install the ABP CLI if you haven't installed before: + +```bash +dotnet tool install -g Volo.Abp.Cli +``` + +Then use the `abp new` command in an empty folder to create a new solution: + +```bash +abp new Acme.IssueManagement -t mvc-module +``` + +- `Acme.IssueManagement` is the solution name, like *YourCompany.YourProduct*. You can use single level, two-levels or three-levels naming. + +### Without User Interface + +The template comes with a UI by default. You can use `--no-ui` option to not include the UI layer. + +````bash +abp new Acme.IssueManagement -t mvc-module --no-ui +```` + +## Solution Structure + +Based on the options you've specified, you will get a slightly different solution structure. If you don't specify any option, you will have a solution like shown below: + +![issuemanagement-module-solution](../images/issuemanagement-module-solution.png) + +Projects are organized as `src`, `test` and `host` folders: + +* `src` folder contains the actual module which is layered based on [DDD](../Domain-Driven-Design.md) principles. +* `test` folder contains unit & integration tests. +* `host` folder contains applications with different configurations to demonstrate how to host the module in an application. These are not a part of the module, but useful on development. + +The diagram below shows the layers & project dependencies of the module: + +![layered-project-dependencies-module](../images/layered-project-dependencies-module.png) + +Each section below will explain the related project & its dependencies. + +### .Domain.Shared Project + +This project contains constants, enums and other objects these are actually a part of the domain layer, but needed to be used by all layers/projects in the solution. + +An `IssueType` enum and an `IssueConts` class (which may have some constant fields for the `Issue` entity, like `MaxTitleLength`) are good candidates for this project. + +- This project has no dependency to other projects in the solution. All other projects depend on this directly or indirectly. + +### .Domain Project + +This is the domain layer of the solution. It mainly contains [entities, aggregate roots](../Entities.md), [domain services](../Domain-Services.md), [value types](../Value-Types.md), [repository interfaces](../Repositories.md) and other domain objects. + +An `Issue` entity, an `IssueManager` domain service and an `IIssueRepository` interface are good candidates for this project. + +- Depends on the `.Domain.Shared` because it uses constants, enums and other objects defined in that project. + +### .Application.Contracts Project + +This project mainly contains [application service](../Application-Services.md) **interfaces** and [Data Transfer Objects](../Data-Transfer-Objects.md) (DTO) of the application layer. It does exists to separate interface & implementation of the application layer. In this way, the interface project can be shared to the clients as a contract package. + +An `IIssueAppService` interface and an `IssueCreationDto` class are good candidates for this project. + +- Depends on the `.Domain.Shared` because it may use constants, enums and other shared objects of this project in the application service interfaces and DTOs. + +### .Application Project + +This project contains the [application service](../Application-Services.md) **implementations** of the interfaces defined in the `.Application.Contracts` project. + +An `IssueAppService` class is a good candidate for this project. + +- Depends on the `.Application.Contracts` project to be able to implement the interfaces and use the DTOs. +- Depends on the `.Domain` project to be able to use domain objects (entities, repository interfaces... etc.) to perform the application logic. + +### .EntityFrameworkCore Project + +This is the integration project for EF Core. It defines the `DbContext` and implements repository interfaces defined in the `.Domain` project. + +- Depends on the `.Domain` project to be able to reference to entities and repository interfaces. + +> You can delete this project if you don't want to support EF Core for your module. + +### .MongoDB Project + +This is the integration project for MongoDB. + +- Depends on the `.Domain` project to be able to reference to entities and repository interfaces. + +> You can delete this project if you don't want to support MongoDB for your module. + +### Test Projects + +The solution has multiple test projects, one for each layer: + +- `.Domain.Tests` is used to test the domain layer. +- `.Application.Tests` is used to test the application layer. +- `.EntityFrameworkCore.Tests` is used to test EF Core configuration and custom repositories. +- `.MongoDB.Tests` is used to test EF Core configuration and custom repositories. +- `.TestBase` is a base (shared) project for all tests. + +In addition, `.HttpApi.Client.ConsoleTestApp` is a console application (not an automated test project) which demonstrate the usage of HTTP APIs from a Dotnet application. + +Test projects are prepared for integration testing; + +- It is fully integrated to ABP framework and all services in your application. +- It uses SQLite in-memory database for EF Core. For MongoDB, it uses the [Mongo2Go](https://github.com/Mongo2Go/Mongo2Go) library. +- Authorization is disabled, so any application service can be easily used in tests. + +You can still create unit tests for your classes which will be harder to write (because you will need to prepare mock/fake objects), but faster to run (because it only tests a single class and skips all initialization process). + +> Domain & Application tests are using EF Core. If you remove EF Core integration or you want to use MongoDB for testing these layers, you should manually change project references & module dependencies. + +### Host Projects + +The solution has a few host applications to run your module on development. Host applications are used to run your module in a fully configured application. It is useful on development. Host applications includes some other modules in addition to the module being developed: + +* + +Host applications support two types of scenarios. + +#### Single (Unified) Application Scenario + +If your module has a UI, then `.Web.Unified` application is used to host the UI and API on a single point. It has its own `appsettings.json` file (that includes the database connection string) and EF Core database migrations. + +For the `.Web.Unified` application, there is a single database, named `YourProjectName_Unified` (like *IssueManagement_Unified* for this sample). + +> If you've selected the `--no-ui` option, this project will not be in your solution. + +##### How to Run? + +Set it as the startup project, run `Update-Database` command for the EF Core from Package Manager Console and run your application. Default username is `admin` and password is `1q2w3E*`. + +#### Separated Deployment & Databases Scenario + +In this scenario, there are three applications; + +* `.IdentityServer` application is an authentication server used by other applications. It has its own `appsettings.json` that contains database connection and other configurations. +* `.HttpApi.Host` hosts the HTTP API of the module. It has its own `appsettings.json` that contains database connections and other configurations. +* `.Web.Host` host the UI of the module. This project contains an `appsettings.json` file, but it does not have a connection string because it never connects to the database. Instead, it mainly contains endpoint of the remote API server and the authentication server. + +The diagram below shows the relation of the applications: + +![tiered-solution-applications](../images/tiered-solution-applications.png) + +`.Web.Host` project uses OpenId Connect Authentication to get identity and access tokens for the current user from the `.IdentityServer`. Then uses the access token to call the `.HttpApi.Host`. HTTP API server uses bearer token authentication to obtain claims from the access token to authorize the current user. + +##### How to Run? + +You should run the application with the given order: + +- First, run the `.IdentityServer` since other applications depends on it. +- Then run the `.HttpApi.Host` since it is used by the `.Web.Host` application. +- Finally, you can run the `.Web.Host` project and login to the application using `admin` as the username and `1q2w3E*` as the password. \ No newline at end of file diff --git a/docs/en/Startup-Templates/Mvc.md b/docs/en/Startup-Templates/Mvc.md new file mode 100644 index 0000000000..cdaa689db2 --- /dev/null +++ b/docs/en/Startup-Templates/Mvc.md @@ -0,0 +1,260 @@ +# MVC Application Startup Template + +## Introduction + +This template provides a layered (or tiered, based on the preference) application structure based on the [Domain Driven Design](../Domain-Driven-Design.md) (DDD) practices. + +This document explains the solution structure and projects in details. + +* See [Getting Started With the ASP.NET Core MVC Template](../Getting-Started-AspNetCore-MVC-Template.md) to create a new solution and run it for this template. +* See the [ASP.NET Core MVC Tutorial](../Tutorials/AspNetCore-Mvc/Part-I.md) to learn how to develop applications using this template. + +## How to Start With? + +You can use the [ABP CLI](../CLI.md) to create a new project using this startup template. Alternatively, you can directly create & download from the [Get Started](https://abp.io/get-started) page. CLI approach is used here. + +First, install the ABP CLI if you haven't installed before: + +````bash +dotnet tool install -g Volo.Abp.Cli +```` + +Then use the `abp new` command in an empty folder to create a new solution: + +````bash +abp new Acme.BookStore -t mvc +```` + +* `Acme.BookStore` is the solution name, like *YourCompany.YourProduct*. You can use single level, two-levels or three-levels naming. +* This example specified the template name (`-t` or `--template` option). However, `mvc` is already the default template if you don't specify it. + +### Specify the Database Provider + +This template supports the following database providers: + +- `ef`: Entity Framework Core (default) +- `mongodb`: MongoDB + +Use `-d` (or `--database-provider`) option to specify the database provider: + +````bash +abp new Acme.BookStore -d mongodb +```` + +### Create a Tiered Solution + +`--tiered` option is used to create a tiered solution where Web and Http API layers are physically separated. If not specified, it creates a layered solution which is less complex and suitable for most scenarios. + +````bash +abp new Acme.BookStore --tiered +```` + +See the "Tiered Structure" section below for the tiered approach. + +## Solution Structure + +Based on the options you've specified, you will get a slightly different solution structure. + +### Default Structure + +If you don't specify any option, you will have a solution like shown below: + +![bookstore-visual-studio-solution-v3](../images/bookstore-visual-studio-solution-v3.png) + +Projects are organized in `src` and `test` folders. `src` folder contains the actual application which is layered based on [DDD](../Domain-Driven-Design.md) principles as mentioned before. + +The diagram below shows the layers & project dependencies of the application: + +![layered-project-dependencies](../images/layered-project-dependencies.png) + +Each section below will explain the related project & its dependencies. + +#### .Domain.Shared Project + +This project contains constants, enums and other objects these are actually a part of the domain layer, but needed to be used by all layers/projects in the solution. + +A `BookType` enum and a `BookConts` class (which may have some constant fields for the `Book` entity, like `MaxNameLength`) are good candidates for this project. + +* This project has no dependency to other projects in the solution. All other projects depend on this directly or indirectly. + +#### .Domain Project + +This is the domain layer of the solution. It mainly contains [entities, aggregate roots](../Entities.md), [domain services](../Domain-Services.md), [value types](../Value-Types.md), [repository interfaces](../Repositories.md) and other domain objects. + +A `Book` entity, a `BookManager` domain service and an `IBookRepository` interface are good candidates for this project. + +* Depends on the `.Domain.Shared` because it uses constants, enums and other objects defined in that project. + +#### .Application.Contracts Project + +This project mainly contains [application service](../Application-Services.md) **interfaces** and [Data Transfer Objects](../Data-Transfer-Objects.md) (DTO) of the application layer. It does exists to separate interface & implementation of the application layer. In this way, the interface project can be shared to the clients as a contract package. + +An `IBookAppService` interface and a `BookCreationDto` class are good candidates for this project. + +* Depends on the `.Domain.Shared` because it may use constants, enums and other shared objects of this project in the application service interfaces and DTOs. + +#### .Application Project + +This project contains the [application service](../Application-Services.md) **implementations** of the interfaces defined in the `.Application.Contracts` project. + +A `BookAppService` class is a good candidate for this project. + +* Depends on the `.Application.Contracts` project to be able to implement the interfaces and use the DTOs. +* Depends on the `.Domain` project to be able to use domain objects (entities, repository interfaces... etc.) to perform the application logic. + +#### .EntityFrameworkCore Project + +This is the integration project for the EF Core. It defines the `DbContext` and implements repository interfaces defined in the `.Domain` project. + +* Depends on the `.Domain` project to be able to reference to entities and repository interfaces. + +> This project is available only if you are using EF Core as the database provider. If you select another database provider, its name will be different. + +#### .EntityFrameworkCore.DbMigrations Project + +Contains EF Core database migrations for the solution. It has a separated `DbContext` to dedicated to manage migrations. + +ABP is a modular framework and with an ideal design, each module has its own `DbContext` class. This is where the migration `DbContext` comes into play and unifies all `DbContext` configurations into a single model to maintain a single database schema. For more advanced scenarios, you can have multiple databases (each contains a single or a few module tables) and multiple migration `DbContext`s (each maintains a different database schema). + +Notice that the migration `DbContext` is only used for database migrations and *not used on runtime*. + +* Depends on the `.EntityFrameworkCore` project since it re-uses the configuration defined for the `DbContext` of the application. + +> This project is available only if you are using EF Core as the database provider. + +#### .DbMigrator Project + +This is a console application which simplifies to execute database migrations on development and production environments. When you run this application, it; + +* Creates the database if necessary. +* Applies the pending database migrations. +* Seeds initial data if needed. + +> This project has its own `appsettings.json` file. So, if you want to change the database connection string, remember to change this file too. + +Especially, seeding initial data is important at this point. ABP has a modular data seed infrastructure. See [its documentation](../Data-Seeding.md) for more about the data seeding. + +While creating database & applying migrations seems only necessary for relational databases, this projects comes even if you choose a NoSQL database provider (like MongoDB). In that case, it still seeds initial data which is necessary for the application. + +* Depends on the `.EntityFrameworkCore.DbMigrations` project (for EF Core) since it needs to access to the migrations. +* Depends on the `.Application.Contracts` project to be able to access permission definitions, because initial data seeder grants all permissions for the admin role by default. + +#### .HttpApi Project + +This project is used to define your API Controllers. + +Most of time you don't need to manually define API Controllers since ABP's [Auto API Controllers](../AspNetCore/Auto-API-Controllers.md) feature creates them automagically based on your application layer. However, in case of you need to write API controllers, this is the best place to do it. + +* Depends on the `.Application.Contracts` project to be able to inject the application service interfaces. + +#### .HttpApi.Client Project + +This is a project that defines C# client proxies to use the HTTP APIs of the solution. You can share this library to 3rd-party clients, so they can easily consume your HTTP APIs in their Dotnet applications (For other type of applications, they can still use your APIs, either manually or using a tool in their own platform) + +Most of time you don't need to manually create C# client proxies, thanks to ABP's [Dynamic C# API Clients](../AspNetCore/Dynamic-CSharp-API-Clients.md) feature. + +`.HttpApi.Client.ConsoleTestApp` project is a console application created to demonstrate the usage of the client proxies. + +* Depends on the `.Application.Contracts` project to be able to share the same application service interfaces and DTOs with the remote service. + +> You can delete this project & dependencies if you don't need to create C# client proxies for your APIs. + +#### .Web Project + +This project contains the User Interface (UI) of the application. It contains razor pages, JavaScript files, style files, images and so on... + +This project contains the main `appsettings.json` file that contains the connection string and other configuration of the application. + +* Depends on the `.HttpApi` since UI layer needs to use APIs and application service interfaces of the solution. + +> If you check the source code of the `.Web.csproj` file, you will see the references to the `.Application` and the `.EntityFrameworkCore.DbMigrations` projects. +> +> These references are actually not needed while coding your UI layer, because UI layer normally doesn't depend on the EF Core or the Application layer's implementation. This startup templates are ready for the tiered deployment, where API layer is hosted in a separate server than the UI layer. +> +> However, if you don't choose the `--tiered` option, these references will be in the .Web project to be able to host the Web, API and application layers in a single application endpoint. +> +> This gives you to ability to use domain entities & repositories in your presentation layer. However, this is considered as a bad practice according to the DDD. + +#### Test Projects + +The solution has multiple test projects, one for each layer: + +* `.Domain.Tests` is used to test the domain layer. +* `.Application.Tests` is used to test the application layer. +* `.EntityFrameworkCore.Tests` is used to test EF Core configuration and custom repositories. +* `.Web.Tests` is used to test the UI. +* `.TestBase` is a base (shared) project for all tests. + +In addition, `.HttpApi.Client.ConsoleTestApp` is a console application (not an automated test project) which demonstrate the usage of HTTP APIs from a Dotnet application. + +Test projects are prepared for integration testing; + +* It is fully integrated to ABP framework and all services in your application. +* It uses SQLite in-memory database for EF Core. For MongoDB, it uses the [Mongo2Go](https://github.com/Mongo2Go/Mongo2Go) library. +* Authorization is disabled, so any application service can be easily used in tests. + +You can still create unit tests for your classes which will be harder to write (because you will need to prepare mock/fake objects), but faster to run (because it only tests a single class and skips all initialization process). + +#### How to Run? + +Set `.Web` as the startup project and run the application. Default username is `admin` and password is `1q2w3E*`. + +See [Getting Started With the ASP.NET Core MVC Template](../Getting-Started-AspNetCore-MVC-Template.md) for more information. + +### Tiered Structure + +If you specify the `--tiered` option as described above, the solution created will be a tiered solution. The purpose of the tiered structure is to be able to **deploy Web application and HTTP API to different servers**: + +![bookstore-visual-studio-solution-v3](../images/tiered-solution-servers.png) + +* Browser runs your UI by executing HTML, CSS & JavaScript. +* Web servers hosts static UI files (CSS, JavaScript, image... etc.) & dynamic components (e.g. Razor pages). It performs HTTP requests to the API server to execute the business logic of the application. +* API Server hosts the HTTP APIs which then use application & domain layers of the application to perform the business logic. +* Finally, database server hosts your database. + +So, the resulting solution allows a 4-tiered deployment, by comparing to 3-tiered deployment of the default structure explained before. + +> Unless you actually need to such a 4-tiered deployment, its suggested to go with the default structure which is simpler to develop, deploy and maintain. + +The solution structure is shown below: + +![bookstore-visual-studio-solution-v3](../images/bookstore-visual-studio-solution-tiered.png) + +As different from the default structure, two new projects come into play: `.IdentityServer` & `.HttpApi.Host`. + +#### .IdentityServer Project + +This project is used as an authentication server for other projects. `.Web` project uses OpenId Connect Authentication to get identity and access tokens for the current user from the IdentityServer. Then uses the access token to call the HTTP API server. HTTP API server uses bearer token authentication to obtain claims from the access token to authorize the current user. + +![tiered-solution-applications](../images/tiered-solution-applications.png) + +ABP uses the open source [IdentityServer4](https://identityserver.io/) framework for the authentication between applications. See [IdentityServer4 documentation](http://docs.identityserver.io) for details about the IdentityServer4 and OpenID Connect protocol. + +It has its own `appsettings.json` that contains database connection and other configurations. + +#### .HttpApi.Host Project + +This project is an application that hosts the API of the solution. It has its own `appsettings.json` that contains database connection and other configurations. + +#### .Web Project + +Just like the default structure, this project contains the User Interface (UI) of the application. It contains razor pages, JavaScript files, style files, images and so on... + +This project contains an `appsettings.json` file, but this time it does not have a connection string because it never connects to the database. Instead, it mainly contains endpoint of the remote API server and the authentication server. + +#### Pre-requirements + +* [Redis](https://redis.io/): The applications use Redis as as distributed cache. So, you need to have Redis installed & running. + +#### How to Run? + +You should run the application with the given order: + +* First, run the `.IdentityServer` since other applications depends on it. +* Then run the `.HttpApi.Host` since it is used by the `.Web` application. +* Finally, you can run the `.Web` project and login to the application (using `admin` as the username and `1q2w3E*` as the password). + +## What's Next? + +- See [Getting Started With the ASP.NET Core MVC Template](../Getting-Started-AspNetCore-MVC-Template.md) to create a new solution and run it for this template. +- See the [ASP.NET Core MVC Tutorial](../Tutorials/AspNetCore-Mvc/Part-I.md) to learn how to develop applications using this template. \ No newline at end of file diff --git a/docs/en/Testing.md b/docs/en/Testing.md new file mode 100644 index 0000000000..5dafef3daf --- /dev/null +++ b/docs/en/Testing.md @@ -0,0 +1,3 @@ +# Testing + +TODO! \ No newline at end of file diff --git a/docs/en/Tutorials/AspNetCore-Mvc/Part-I.md b/docs/en/Tutorials/AspNetCore-Mvc/Part-I.md index ecc302c34d..288f7fe075 100644 --- a/docs/en/Tutorials/AspNetCore-Mvc/Part-I.md +++ b/docs/en/Tutorials/AspNetCore-Mvc/Part-I.md @@ -2,43 +2,45 @@ ### About this Tutorial -In this tutorial series, you will build an application that is used to manage a list of books & their authors. **Entity Framework Core** (EF Core) will be used as the ORM provider (as it comes pre-configured with the [startup template](https://abp.io/Templates)). +In this tutorial series, you will build an application that is used to manage a list of books & their authors. **Entity Framework Core** (EF Core) will be used as the ORM provider as it is the default database provider. -This is the first part of the tutorial series. See all parts: +This is the first part of the ASP.NET Core MVC tutorial series. See all parts: - **Part I: Create the project and a book list page (this tutorial)** - [Part II: Create, Update and Delete books](Part-II.md) - [Part III: Integration Tests](Part-III.md) -You can download the **source code** of the application [from here](https://github.com/volosoft/abp/tree/master/samples/BookStore). +You can access to the **source code** of the application from [the GitHub repository](https://github.com/volosoft/abp/tree/master/samples/BookStore). ### Creating the Project -Go to the [startup template page](https://abp.io/Templates) and download a new project named `Acme.BookStore`, create the database and run the application by following the [template document](../../Getting-Started-AspNetCore-MVC-Template.md). +Create a new project named `Acme.BookStore`, create the database and run the application by following the [Getting Started document](../../Getting-Started-AspNetCore-MVC-Template.md). ### Solution Structure -This is the how the layered solution structure looks after it's created from the startup template: +This is how the layered solution structure looks after it's created: -![bookstore-visual-studio-solution](images/bookstore-visual-studio-solution-v2.png) +![bookstore-visual-studio-solution](images/bookstore-visual-studio-solution-v3.png) + +> You can see [MVC application template document](../../Startup-Templates/Mvc.md) to understand the solution structure in details. However, you will understand the basics with this tutorial. ### Create the Book Entity -Define [entities](../../Entities.md) in the **domain layer** (`Acme.BookStore.Domain` project) of the solution. The main entity of the application is the `Book`: +Domain layer in the startup template is separated into two projects: + +- `Acme.BookStore.Domain` contains your [entities](../../Entities.md), [domain services](../../Domain-Services.md) and other core domain objects. +- `Acme.BookStore.Domain.Shared` contains constants, enums or other domain related objects those can be shared with clients. + +Define [entities](../../Entities.md) in the **domain layer** (`Acme.BookStore.Domain` project) of the solution. The main entity of the application is the `Book`. Create a class, named `Book`, in the `Acme.BookStore.Domain` project as shown below: ````C# using System; -using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; using Volo.Abp.Domain.Entities.Auditing; namespace Acme.BookStore { - [Table("Books")] public class Book : AuditedAggregateRoot { - [Required] - [StringLength(128)] public string Name { get; set; } public BookType Type { get; set; } @@ -50,22 +52,22 @@ namespace Acme.BookStore } ```` -* ABP has two fundamental base classes for entities: `AggregateRoot` and `Entity`. **Aggregate Root** is one of the **Domain Driven Design (DDD)** concepts. See [entity document](../../Entities.md) for more details and best practices. +* ABP has two fundamental base classes for entities: `AggregateRoot` and `Entity`. **Aggregate Root** is one of the **Domain Driven Design (DDD)** concepts. See [entity document](../../Entities.md) for details and best practices. * `Book` entity inherits `AuditedAggregateRoot` which adds some auditing properties (`CreationTime`, `CreatorId`, `LastModificationTime`... etc.) on top of the `AggregateRoot` class. * `Guid` is the **primary key type** of the `Book` entity. * Used **data annotation attributes** in this code for EF Core mappings. Alternatively you could use EF Core's [fluent mapping API](https://docs.microsoft.com/en-us/ef/core/modeling) instead. #### BookType Enum -The `BookType` enum used above is defined as below: +Define the `BookType` enum in the `Acme.BookStore.Domain.Shared` project: ````C# namespace Acme.BookStore { - public enum BookType : byte + public enum BookType { Undefined, - Advanture, + Adventure, Biography, Dystopia, Fantastic, @@ -91,14 +93,15 @@ EF Core requires you to relate entities with your DbContext. The easiest way to #### Configure Your Book Entity -Open BookStoreDbContextModelCreatingExtensions.cs file from the `Acme.BookStore.EntityFrameworkCore` project, add following code to the end of ConfigureBookStore method to configure Book entity: +Open `BookStoreDbContextModelCreatingExtensions.cs` file in the `Acme.BookStore.EntityFrameworkCore` project and add following code to the end of the `ConfigureBookStore` method to configure the Book entity: ````C# - builder.Entity(b => - { - b.ToTable(BookStoreConsts.DbTablePrefix + "Books", BookStoreConsts.DbSchema); - b.ConfigureExtraProperties(); - }); +builder.Entity(b => +{ + b.ToTable(BookStoreConsts.DbTablePrefix + "Books", BookStoreConsts.DbSchema); + b.ConfigureAuditedAggregateRoot(); //auto configure for the base class props + b.Property(x => x.Name).IsRequired().HasMaxLength(128); +}); ```` #### Add New Migration & Update the Database @@ -115,26 +118,27 @@ PM> Update-Database #### Add Sample Data -`Update-Database` command created the `Books` table in the database. Open your database and enter a few sample rows, so you can show them on the page: +`Update-Database` command created the `AppBooks` table in the database. Open your database and enter a few sample rows, so you can show them on the page: ![bookstore-books-table](images/bookstore-books-table.png) ### Create the Application Service -The next step is to create an [application service](../../Application-Services.md) to manage (create, list, update, delete...) the books. +The next step is to create an [application service](../../Application-Services.md) to manage (create, list, update, delete...) the books. Application layer in the startup template is separated into two projects: + +* `Acme.BookStore.Application.Contracts` mainly contains your DTOs and application service interfaces. +* `Acme.BookStore.Application` contains the implementations of your application services. #### BookDto -Create a DTO class named `BookDto` into the `Acme.BookStore.Application` project: +Create a DTO class named `BookDto` into the `Acme.BookStore.Application.Contracts` project: ````C# using System; using Volo.Abp.Application.Dtos; -using Volo.Abp.AutoMapper; namespace Acme.BookStore { - [AutoMapFrom(typeof(Book))] public class BookDto : AuditedEntityDto { public string Name { get; set; } @@ -151,20 +155,34 @@ namespace Acme.BookStore * **DTO** classes are used to **transfer data** between the *presentation layer* and the *application layer*. See the [Data Transfer Objects document](../../Data-Transfer-Objects.md) for more details. * `BookDto` is used to transfer book data to the presentation layer in order to show the book information on the UI. * `BookDto` is derived from the `AuditedEntityDto` which has audit properties just like the `Book` class defined above. -* `[AutoMapFrom(typeof(Book))]` is used to create AutoMapper mapping from the `Book` class to the `BookDto` class. In this way, you get automatic conversion of `Book` objects to `BookDto` objects (instead of manually copy all properties). + +It will be needed to convert `Book` entities to `BookDto` objects while returning books to the presentation layer. [AutoMapper](https://automapper.org) library can automate this conversion when you define the proper mapping. Startup template comes with AutoMapper configured, so you can just define the mapping in the `BookStoreApplicationAutoMapperProfile` class in the `Acme.BookStore.Application` project: + +````csharp +using AutoMapper; + +namespace Acme.BookStore +{ + public class BookStoreApplicationAutoMapperProfile : Profile + { + public BookStoreApplicationAutoMapperProfile() + { + CreateMap(); + } + } +} +```` #### CreateUpdateBookDto -Create a DTO class named `CreateUpdateBookDto` into the `Acme.BookStore.Application` project: +Create a DTO class named `CreateUpdateBookDto` into the `Acme.BookStore.Application.Contracts` project: ````c# using System; using System.ComponentModel.DataAnnotations; -using Volo.Abp.AutoMapper; namespace Acme.BookStore { - [AutoMapTo(typeof(Book))] public class CreateUpdateBookDto { [Required] @@ -184,11 +202,17 @@ namespace Acme.BookStore ```` * This DTO class is used to get book information from the user interface while creating or updating a book. -* It defines data annotation attributes (like `[Required]`) to define validations for the properties. DTOs are automatically validated by ABP. +* It defines data annotation attributes (like `[Required]`) to define validations for the properties. DTOs are [automatically validated](../../Validation.md) by the ABP framework. + +Like done for the `BookDto` above, create a mapping from the `CreateUpdateBookDto` object to the `Book` entity: + +````csharp +CreateMap(); +```` #### IBookAppService -Define an interface named `IBookAppService` for the book application service: +Define an interface named `IBookAppService` in the `Acme.BookStore.Application.Contracts` project: ````C# using System; @@ -210,13 +234,13 @@ namespace Acme.BookStore } ```` -* Defining interfaces for application services is not required by the framework. However, it's suggested as best practice. -* `IAsyncCrudAppService` defines common **CRUD** methods: `GetAsync`, `GetListAsync`, `CreateAsync`, `UpdateAsync` and `DeleteAsync`. It's not required to extend it. Instead, you could inherit from the empty `IApplicationService` interface and define your own methods. -* There are some variations of the `IAsyncCrudAppService` where you can use a single DTO or separated DTOs for each method. +* Defining interfaces for application services is not required by the framework. However, it's suggested as a best practice. +* `IAsyncCrudAppService` defines common **CRUD** methods: `GetAsync`, `GetListAsync`, `CreateAsync`, `UpdateAsync` and `DeleteAsync`. It's not required to extend it. Instead, you could inherit from the empty `IApplicationService` interface and define your own methods manually. +* There are some variations of the `IAsyncCrudAppService` where you can use separated DTOs for each method. #### BookAppService -Implement the `IBookAppService` as named `BookAppService`: +Implement the `IBookAppService` as named `BookAppService` in the `Acme.BookStore.Application` project: ````C# using System; @@ -241,23 +265,23 @@ namespace Acme.BookStore ```` * `BookAppService` is derived from `AsyncCrudAppService<...>` which implements all the CRUD methods defined above. -* `BookAppService` injects `IRepository` which is the default repository created for the `Book` entity. ABP automatically creates repositories for each aggregate root (or entity). See the [repository document](../../Repositories.md). -* `BookAppService` uses `IObjectMapper` to convert `Book` objects to `BookDto` objects and `CreateUpdateBookDto` objects to `Book` objects. The Startup template uses the [AutoMapper](http://automapper.org/) library as object mapping provider. You defined mappings using the `AutoMapFrom` and the `AutoMapTo` attributes above. See the [AutoMapper integration document](../../AutoMapper-Integration.md) for details. +* `BookAppService` injects `IRepository` which is the default repository for the `Book` entity. ABP automatically creates default repositories for each aggregate root (or entity). See the [repository document](../../Repositories.md). +* `BookAppService` uses `IObjectMapper` to convert `Book` objects to `BookDto` objects and `CreateUpdateBookDto` objects to `Book` objects. The Startup template uses the [AutoMapper](http://automapper.org/) library as the object mapping provider. You defined the mappings before, so it will work as expected. ### Auto API Controllers -You normally create **Controllers** to expose application services as **HTTP API** endpoints. Thus allowing browser or 3rd-party clients to call them via AJAX. - -ABP can [**automagically**](../../AspNetCore/Auto-API-Controllers.md) configures your application services as MVC API Controllers by convention. +You normally create **Controllers** to expose application services as **HTTP API** endpoints. Thus allowing browser or 3rd-party clients to call them via AJAX. ABP can [**automagically**](../../AspNetCore/Auto-API-Controllers.md) configures your application services as MVC API Controllers by convention. #### Swagger UI -The startup template is configured to run the [swagger UI](https://swagger.io/tools/swagger-ui/) using the [Swashbuckle.AspNetCore](https://github.com/domaindrivendev/Swashbuckle.AspNetCore) library. Run the application and enter `http://localhost:53929/swagger/` as URL on your browser. +The startup template is configured to run the [swagger UI](https://swagger.io/tools/swagger-ui/) using the [Swashbuckle.AspNetCore](https://github.com/domaindrivendev/Swashbuckle.AspNetCore) library. Run the application and enter `https://localhost:XXXX/swagger/` (replace XXXX by your own port) as URL on your browser. You will see some built-in service endpoints as well as the `Book` service and its REST-style endpoints: ![bookstore-swagger](images/bookstore-swagger.png) +Swagger has a nice UI to test APIs. You can try to execute the `[GET] /api/app/book` API to get a list of books. + ### Dynamic JavaScript Proxies It's common to call HTTP API endpoints via AJAX from the **JavaScript** side. You can use `$.ajax` or another tool to call the endpoints. However, ABP offers a better way. @@ -266,7 +290,7 @@ ABP **dynamically** creates JavaScript **proxies** for all API endpoints. So, yo #### Testing in the Browser Developer Console -You can easily test the JavaScript proxy using your favorite browser's **Developer Console** now. Run the application again, open your browser's **developer tools** (shortcut: F12), switch to the **Console** tab, type the following code and press enter: +You can easily test the JavaScript proxies using your favorite browser's **Developer Console** now. Run the application, open your browser's **developer tools** (shortcut: F12), switch to the **Console** tab, type the following code and press enter: ````js acme.bookStore.book.getList({}).done(function (result) { console.log(result); }); @@ -275,7 +299,7 @@ acme.bookStore.book.getList({}).done(function (result) { console.log(result); }) * `acme.bookStore` is the namespace of the `BookAppService` converted to [camelCase](https://en.wikipedia.org/wiki/Camel_case). * `book` is the conventional name for the `BookAppService` (removed AppService postfix and converted to camelCase). * `getList` is the conventional name for the `GetListAsync` method defined in the `AsyncCrudAppService` base class (removed Async postfix and converted to camelCase). -* `{}` argument is used to send an empty object to the `GetListAsync` method which normally expects an object of type `PagedAndSortedResultRequestDto` which is used to send paging and sorting options to the server. +* `{}` argument is used to send an empty object to the `GetListAsync` method which normally expects an object of type `PagedAndSortedResultRequestDto` that is used to send paging and sorting options to the server (all properties are optional, so you can send an empty object). * `getList` function returns a `promise`. So, you can pass a callback to the `done` (or `then`) function to get the result from the server. Running this code produces the following output: @@ -298,7 +322,7 @@ You should see a message in the console something like that: successfully created the book with id: f3f03580-c1aa-d6a9-072d-39e75c69f5c7 ```` -Check the `books` table in the database to see the new book row. You can try `get`, `update` and `delete` functions too. +Check the `Books` table in the database to see the new book row. You can try `get`, `update` and `delete` functions yourself. ### Create the Books Page @@ -306,20 +330,21 @@ It's time to create something visible and usable! Instead of classic MVC, we wil Create a new `Books` folder under the `Pages` folder of the `Acme.BookStore.Web` project and add a new Razor Page named `Index.cshtml`: -![bookstore-add-index-page](images/bookstore-add-index-page.png) +![bookstore-add-index-page](images/bookstore-add-index-page-v2.png) Open the `Index.cshtml` and change the content as shown below: ````html @page -@using Acme.BookStore.Pages.Books -@inherits Acme.BookStore.Pages.BookStorePageBase +@using Acme.BookStore.Web.Pages.Books +@inherits Acme.BookStore.Web.Pages.BookStorePageBase @model IndexModel

Books

```` -* Change the default inhertitance of the Razor View Page Model so it **inherits** from the `BookStorePageBase` class (instead of `PageModel`). The `BookStorePageBase` class which comes with the startup template and provides some shared properties/methods used by all pages. +* This code changes the default inheritance of the Razor View Page Model so it **inherits** from the `BookStorePageBase` class (instead of `PageModel`). The `BookStorePageBase` class which comes with the startup template and provides some shared properties/methods used by all pages. +* Ensure that the `IndexModel` (*Index.cshtml.cs)* has the `Acme.BookStore.Pages.Books` namespace, or update it in the `Index.cshtml`. #### Add Books Page to the Main Menu @@ -334,17 +359,16 @@ context.Menu.AddItem( #### Localizing the Menu Items -Localization texts are located under the `Localization/BookStore` folder of the `Acme.BookStore.Domain` project: +Localization texts are located under the `Localization/BookStore` folder of the `Acme.BookStore.Domain.Shared` project: -![bookstore-localization-files](images/bookstore-localization-files.png) +![bookstore-localization-files](images/bookstore-localization-files-v2.png) -Open the `en.json` file and add localization texts for `Menu:BookStore` and `Menu:Books` keys: +Open the `en.json` file and add localization texts for `Menu:BookStore` and `Menu:Books` keys to the end of the file: ````json { "culture": "en", "texts": { - //... "Menu:BookStore": "Book Store", "Menu:Books": "Books" } @@ -352,9 +376,9 @@ Open the `en.json` file and add localization texts for `Menu:BookStore` and `Men ```` * ABP's localization system is built on [ASP.NET Core's standard localization](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/localization) system and extends it in many ways. See the [localization document](../../Localization.md) for details. -* Localization key names are arbitrary, you can set any name. We prefer to add `Menu` namespace for menu items to distinguish from other texts. If a text is not defined in the localization file, it **fallbacks** to the localization key (ASP.NET Core's standard behavior). +* Localization key names are arbitrary. You can set any name. We prefer to add `Menu:` prefix for menu items to distinguish from other texts. If a text is not defined in the localization file, it **fallbacks** to the localization key (ASP.NET Core's standard behavior). -Run the application and see the menu items are added to the top bar: +Run the application and see the new menu item has been added to the top bar: ![bookstore-menu-items](images/bookstore-menu-items.png) @@ -362,17 +386,16 @@ When you click to the Books menu item, you are redirected to the new Books page. #### Book List -We will use the [Datatables.net](https://datatables.net/) JQuery plugin to show list of tables on the page. Datatables can completely work via AJAX, so it is fast and provides a good user experience. Datatables plugin is configured in the startup template, so you can directly use it in any page without including any style or script file to your page. +We will use the [Datatables.net](https://datatables.net/) JQuery plugin to show list of tables on the page. Datatables can completely work via AJAX, it is fast and provides a good user experience. Datatables plugin is configured in the startup template, so you can directly use it in any page without including any style or script file to your page. -##### Index.cshtml Changes +##### Index.cshtml Change the `Pages/Books/Index.cshtml` as following: ````html @page -@using Acme.BookStore.Pages.Books -@inherits Acme.BookStore.Pages.BookStorePageBase -@model IndexModel +@inherits Acme.BookStore.Web.Pages.BookStorePageBase +@model Acme.BookStore.Web.Pages.Books.IndexModel @section scripts { @@ -405,7 +428,7 @@ Change the `Pages/Books/Index.cshtml` as following: Create `index.js` JavaScript file under the `Pages/Books/` folder: -![bookstore-index-js-file](images/bookstore-index-js-file.png) +![bookstore-index-js-file](images/bookstore-index-js-file-v2.png) `index.js` content is shown below: diff --git a/docs/en/Tutorials/AspNetCore-Mvc/Part-II.md b/docs/en/Tutorials/AspNetCore-Mvc/Part-II.md index eeb14db8bb..180133d713 100644 --- a/docs/en/Tutorials/AspNetCore-Mvc/Part-II.md +++ b/docs/en/Tutorials/AspNetCore-Mvc/Part-II.md @@ -2,13 +2,13 @@ ### About this Tutorial -This is the second part of the tutorial series. See all parts: +This is the second part of the ASP.NET Core MVC tutorial series. See all parts: * [Part I: Create the project and a book list page](Part-I.md) * **Part II: Create, Update and Delete books (this tutorial)** * [Part III: Integration Tests](Part-III.md) -You can download the **source code** of the application [from here](https://github.com/volosoft/abp/tree/master/samples/BookStore). +You can access to the **source code** of the application from [the GitHub repository](https://github.com/volosoft/abp/tree/master/samples/BookStore). ### Creating a New Book @@ -20,7 +20,7 @@ In this section, you will learn how to create a new modal dialog form to create Create a new razor page, named `CreateModal.cshtml` under the `Pages/Books` folder of the `Acme.BookStore.Web` project: -![bookstore-add-create-dialog](images/bookstore-add-create-dialog.png) +![bookstore-add-create-dialog](images/bookstore-add-create-dialog-v2.png) ##### CreateModal.cshtml.cs @@ -30,7 +30,7 @@ Open the `CreateModal.cshtml.cs` file (`CreateModalModel` class) and replace wit using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; -namespace Acme.BookStore.Pages.Books +namespace Acme.BookStore.Web.Pages.Books { public class CreateModalModel : BookStorePageModelBase { @@ -63,9 +63,9 @@ Open the `CreateModal.cshtml` file and paste the code below: ````html @page -@inherits Acme.BookStore.Pages.BookStorePageBase +@inherits Acme.BookStore.Web.Pages.BookStorePageBase @using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal -@model Acme.BookStore.Pages.Books.CreateModalModel +@model Acme.BookStore.Web.Pages.Books.CreateModalModel @{ Layout = null; } @@ -83,7 +83,7 @@ Open the `CreateModal.cshtml` file and paste the code below: * This modal uses `abp-dynamic-form` tag helper to automatically create the form from the `CreateBookViewModel` class. * `abp-model` attribute indicates the model object, the `Book` property in this case. * `data-ajaxForm` attribute makes the form submitting via AJAX, instead of a classic page post. - * `abp-form-content` tag helper is a placeholder to render the form controls (this is optional and needed only if you added some other content in the `abp-dynamic-form` tag, just like in this view). + * `abp-form-content` tag helper is a placeholder to render the form controls (this is optional and needed only if you added some other content in the `abp-dynamic-form` tag, just like in this page). #### Add the "New book" Button @@ -138,12 +138,12 @@ Create a new razor page, named `EditModal.cshtml` under the `Pages/Books` folder Open the `EditModal.cshtml.cs` file (`EditModalModel` class) and replace with the following code: -````C# +````csharp using System; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; -namespace Acme.BookStore.Pages.Books +namespace Acme.BookStore.Web.Pages.Books { public class EditModalModel : BookStorePageModelBase { @@ -153,7 +153,7 @@ namespace Acme.BookStore.Pages.Books [BindProperty] public CreateUpdateBookDto Book { get; set; } - + private readonly IBookAppService _bookAppService; public EditModalModel(IBookAppService bookAppService) @@ -180,38 +180,26 @@ namespace Acme.BookStore.Pages.Books * Mapped `BookDto` (received from the `BookAppService.GetAsync`) to `CreateUpdateBookDto` in the `GetAsync` method. * The `OnPostAsync` simply uses `BookAppService.UpdateAsync` to update the entity. -#### CreateUpdateBookDto +#### BookDto to CreateUpdateBookDto Mapping -In order to perform `BookDto` to `CreateUpdateBookDto` object mapping, change the `CreateUpdateBookDto` class as shown below: +In order to perform `BookDto` to `CreateUpdateBookDto` object mapping, open the `BookStoreWebAutoMapperProfile.cs` in the `Acme.BookStore.Web` project and change it as shown below: -````C# -using System; -using System.ComponentModel.DataAnnotations; -using Volo.Abp.AutoMapper; +````csharp +using AutoMapper; -namespace Acme.BookStore +namespace Acme.BookStore.Web { - [AutoMapTo(typeof(Book))] - [AutoMapFrom(typeof(BookDto))] - public class CreateUpdateBookDto + public class BookStoreWebAutoMapperProfile : Profile { - [Required] - [StringLength(128)] - public string Name { get; set; } - - [Required] - public BookType Type { get; set; } = BookType.Undefined; - - [Required] - public DateTime PublishDate { get; set; } - - [Required] - public float Price { get; set; } + public BookStoreWebAutoMapperProfile() + { + CreateMap(); + } } } ```` -* Just added the `[AutoMapFrom(typeof(BookDto))]` attribute to create the mapping. +* Just added `CreateMap();` as the mapping definition. #### EditModal.cshtml @@ -219,8 +207,8 @@ Replace `EditModal.cshtml` content with the following content: ````html @page -@inherits Acme.BookStore.Pages.BookStorePageBase -@using Acme.BookStore.Pages.Books +@inherits Acme.BookStore.Web.Pages.BookStorePageBase +@using Acme.BookStore.Web.Pages.Books @using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal @model EditModalModel @{ @@ -231,7 +219,7 @@ Replace `EditModal.cshtml` content with the following content: - + @@ -240,7 +228,7 @@ Replace `EditModal.cshtml` content with the following content: This page is very similar to the `CreateModal.cshtml` except; -* It includes an `abp-input` for the `Id` property to store id of the editing book. +* It includes an `abp-input` for the `Id` property to store id of the editing book (which is a hidden input). * It uses `Books/EditModal` as the post URL and *Update* text as the modal header. #### Add "Actions" Dropdown to the Table @@ -420,6 +408,12 @@ $(function () { }); ```` +Open the `en.json` in the `Acme.BookStore.Domain.Shared` project and add the following line: + +````json +"BookDeletionConfirmationMessage": "Are you sure to delete the book {0}?" +```` + Run the application and try to delete a book. ### Next Part diff --git a/docs/en/Tutorials/AspNetCore-Mvc/Part-III.md b/docs/en/Tutorials/AspNetCore-Mvc/Part-III.md index b70521dad0..7b97fcf483 100644 --- a/docs/en/Tutorials/AspNetCore-Mvc/Part-III.md +++ b/docs/en/Tutorials/AspNetCore-Mvc/Part-III.md @@ -2,22 +2,21 @@ ### About this Tutorial -This is the third part of the tutorial series. See all parts: +This is the third part of the ASP.NET Core MVC tutorial series. See all parts: - [Part I: Create the project and a book list page](Part-I.md) - [Part II: Create, Update and Delete books](Part-II.md) - **Part III: Integration Tests (this tutorial)** -You can download the **source code** of the application [from here](https://github.com/volosoft/abp/tree/master/samples/BookStore). +You can access to the **source code** of the application from [the GitHub repository](https://github.com/volosoft/abp/tree/master/samples/BookStore). ### Test Projects in the Solution -There are two test projects in the solution: +There are multiple test projects in the solution: -* `Acme.BookStore.Application.Tests` is for unit & integration tests. You can write tests for application service methods. It uses **EF Core SQLite in-memory** database. -* `Acme.BookStore.Web.Tests` is for full stack integration tests including the web layer. So, you can write tests for UI pages too. +![bookstore-test-projects-v2](images/bookstore-test-projects-v2.png) -Test projects use the following libraries for testing: +Each project is used to test the related application project. Test projects use the following libraries for testing: * [xunit](https://xunit.github.io/) as the main test framework. * [Shoudly](http://shouldly.readthedocs.io/en/latest/) as an assertion library. @@ -25,79 +24,40 @@ Test projects use the following libraries for testing: ### Adding Test Data -Startup template contains the `BookStoreTestDataBuilder` class in the `Acme.BookStore.Application.Tests` project that creates some data to run tests on. It's shown below: +Startup template contains the `BookStoreTestDataSeedContributor` class in the `Acme.BookStore.TestBase` project that creates some data to run tests on. -````C# -using System.Threading.Tasks; -using Volo.Abp.DependencyInjection; -using Volo.Abp.Identity; -using Volo.Abp.Threading; - -namespace Acme.BookStore -{ - public class BookStoreTestDataBuilder : ITransientDependency - { - private readonly IIdentityDataSeeder _identityDataSeeder; - - public BookStoreTestDataBuilder(IIdentityDataSeeder identityDataSeeder) - { - _identityDataSeeder = identityDataSeeder; - } - - public void Build() - { - AsyncHelper.RunSync(BuildInternalAsync); - } - - public async Task BuildInternalAsync() - { - await _identityDataSeeder.SeedAsync("1q2w3E*"); - } - } -} -```` - -* It simply uses `IIdentityDataSeeder` which is implemented by the identity module and creates an admin role and admin user. You can use them in your tests. -* You can add new test data in the `BuildInternalAsync` method. - -Change the `BookStoreTestDataBuilder` class as show below: +Change the `BookStoreTestDataSeedContributor` class as show below: ````C# using System; using System.Threading.Tasks; +using Volo.Abp.Data; using Volo.Abp.DependencyInjection; using Volo.Abp.Domain.Repositories; -using Volo.Abp.Identity; -using Volo.Abp.Threading; +using Volo.Abp.Guids; namespace Acme.BookStore { - public class BookStoreTestDataBuilder : ITransientDependency + public class BookStoreTestDataSeedContributor + : IDataSeedContributor, ITransientDependency { - private readonly IIdentityDataSeeder _identityDataSeeder; private readonly IRepository _bookRepository; + private readonly IGuidGenerator _guidGenerator; - public BookStoreTestDataBuilder( - IIdentityDataSeeder identityDataSeeder, - IRepository bookRepository) + public BookStoreTestDataSeedContributor( + IRepository bookRepository, + IGuidGenerator guidGenerator) { - _identityDataSeeder = identityDataSeeder; _bookRepository = bookRepository; + _guidGenerator = guidGenerator; } - public void Build() - { - AsyncHelper.RunSync(BuildInternalAsync); - } - - public async Task BuildInternalAsync() + public async Task SeedAsync(DataSeedContext context) { - await _identityDataSeeder.SeedAsync("1q2w3E*"); - await _bookRepository.InsertAsync( new Book { - Id = Guid.NewGuid(), + Id = _guidGenerator.Create(), Name = "Test book 1", Type = BookType.Fantastic, PublishDate = new DateTime(2015, 05, 24), @@ -108,7 +68,7 @@ namespace Acme.BookStore await _bookRepository.InsertAsync( new Book { - Id = Guid.NewGuid(), + Id = _guidGenerator.Create(), Name = "Test book 2", Type = BookType.Science, PublishDate = new DateTime(2014, 02, 11), @@ -120,7 +80,8 @@ namespace Acme.BookStore } ```` -* Injected `IRepository` and used it in the `BuildInternalAsync` to create two book entities. +* Injected `IRepository` and used it in the `SeedAsync` to create two book entities as the test data. +* Used `IGuidGenerator` service to create GUIDs. While `Guid.NewGuid()` would perfectly work for testing, `IGuidGenerator` has additional features especially important while using real databases (see the [Guid generation document](../../Guid-Generation.md) for more). ### Testing the BookAppService @@ -210,6 +171,8 @@ public async Task Should_Not_Create_A_Book_Without_Name() * Since the `Name` is empty, ABP throws an `AbpValidationException`. -### Testing Web Pages +Open the **Test Explorer Window** (use Test -> Windows -> Test Explorer menu if it is not visible) and **Run All** tests: + +![bookstore-appservice-tests](images/bookstore-appservice-tests.png) -TODO \ No newline at end of file +Congratulations, green icons show that tests have been successfully passed! \ No newline at end of file diff --git a/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-add-create-dialog-v2.png b/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-add-create-dialog-v2.png new file mode 100644 index 0000000000..fcadfd7a82 Binary files /dev/null and b/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-add-create-dialog-v2.png differ diff --git a/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-add-create-dialog.png b/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-add-create-dialog.png deleted file mode 100644 index 44398e6b4c..0000000000 Binary files a/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-add-create-dialog.png and /dev/null differ diff --git a/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-add-index-page-v2.png b/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-add-index-page-v2.png new file mode 100644 index 0000000000..2606bbab32 Binary files /dev/null and b/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-add-index-page-v2.png differ diff --git a/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-add-index-page.png b/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-add-index-page.png deleted file mode 100644 index 2452ca546e..0000000000 Binary files a/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-add-index-page.png and /dev/null differ diff --git a/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-appservice-tests.png b/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-appservice-tests.png new file mode 100644 index 0000000000..942d2832a6 Binary files /dev/null and b/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-appservice-tests.png differ diff --git a/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-index-js-file-v2.png b/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-index-js-file-v2.png new file mode 100644 index 0000000000..1ba9a48600 Binary files /dev/null and b/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-index-js-file-v2.png differ diff --git a/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-index-js-file.png b/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-index-js-file.png deleted file mode 100644 index e36c5dfff7..0000000000 Binary files a/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-index-js-file.png and /dev/null differ diff --git a/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-localization-files-v2.png b/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-localization-files-v2.png new file mode 100644 index 0000000000..79314dd2dc Binary files /dev/null and b/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-localization-files-v2.png differ diff --git a/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-localization-files.png b/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-localization-files.png deleted file mode 100644 index ca1da1c7ec..0000000000 Binary files a/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-localization-files.png and /dev/null differ diff --git a/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-test-projects-v2.png b/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-test-projects-v2.png new file mode 100644 index 0000000000..8701164d75 Binary files /dev/null and b/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-test-projects-v2.png differ diff --git a/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-test-projects.png b/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-test-projects.png deleted file mode 100644 index f9511d7b11..0000000000 Binary files a/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-test-projects.png and /dev/null differ diff --git a/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-visual-studio-solution-v2.png b/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-visual-studio-solution-v2.png deleted file mode 100644 index 48b5881e96..0000000000 Binary files a/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-visual-studio-solution-v2.png and /dev/null differ diff --git a/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-visual-studio-solution-v3.png b/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-visual-studio-solution-v3.png new file mode 100644 index 0000000000..307e3516a5 Binary files /dev/null and b/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-visual-studio-solution-v3.png differ diff --git a/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-visual-studio-solution.png b/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-visual-studio-solution.png deleted file mode 100644 index b47636cd68..0000000000 Binary files a/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-visual-studio-solution.png and /dev/null differ diff --git a/docs/en/Value-Objects.md b/docs/en/Value-Objects.md new file mode 100644 index 0000000000..0c6c8d4424 --- /dev/null +++ b/docs/en/Value-Objects.md @@ -0,0 +1,3 @@ +## Value Objects + +TODO \ No newline at end of file diff --git a/docs/en/docs-nav.json b/docs/en/docs-nav.json index 396b92afd3..27ebb86a2c 100644 --- a/docs/en/docs-nav.json +++ b/docs/en/docs-nav.json @@ -41,6 +41,10 @@ } ] }, + { + "text": "CLI", + "path": "CLI.md" + }, { "text": "Fundamentals", "items": [ @@ -214,7 +218,7 @@ }, { "text": "Tag Helpers", - "path": "Tag-Helpers.md" + "path": "AspNetCore/Tag-Helpers/Index.md" }, { "text": "Theming", diff --git a/docs/en/images/bookstore-user-management-v2.png b/docs/en/images/bookstore-user-management-v2.png new file mode 100644 index 0000000000..dd95740754 Binary files /dev/null and b/docs/en/images/bookstore-user-management-v2.png differ diff --git a/docs/en/images/bookstore-user-management.png b/docs/en/images/bookstore-user-management.png deleted file mode 100644 index bc3c176557..0000000000 Binary files a/docs/en/images/bookstore-user-management.png and /dev/null differ diff --git a/docs/en/images/bookstore-visual-studio-solution-tiered.png b/docs/en/images/bookstore-visual-studio-solution-tiered.png new file mode 100644 index 0000000000..19662bf731 Binary files /dev/null and b/docs/en/images/bookstore-visual-studio-solution-tiered.png differ diff --git a/docs/en/images/bookstore-visual-studio-solution-v2.png b/docs/en/images/bookstore-visual-studio-solution-v2.png deleted file mode 100644 index 48b5881e96..0000000000 Binary files a/docs/en/images/bookstore-visual-studio-solution-v2.png and /dev/null differ diff --git a/docs/en/images/bookstore-visual-studio-solution-v3.png b/docs/en/images/bookstore-visual-studio-solution-v3.png new file mode 100644 index 0000000000..307e3516a5 Binary files /dev/null and b/docs/en/images/bookstore-visual-studio-solution-v3.png differ diff --git a/docs/en/images/bookstore-visual-studio-solution.png b/docs/en/images/bookstore-visual-studio-solution.png deleted file mode 100644 index b47636cd68..0000000000 Binary files a/docs/en/images/bookstore-visual-studio-solution.png and /dev/null differ diff --git a/docs/en/images/db-migrator-app.png b/docs/en/images/db-migrator-app.png new file mode 100644 index 0000000000..ace6abb226 Binary files /dev/null and b/docs/en/images/db-migrator-app.png differ diff --git a/docs/en/images/disable-package-restore-visual-studio.png b/docs/en/images/disable-package-restore-visual-studio.png deleted file mode 100644 index 5d2343dc3f..0000000000 Binary files a/docs/en/images/disable-package-restore-visual-studio.png and /dev/null differ diff --git a/docs/en/images/issuemanagement-module-solution.png b/docs/en/images/issuemanagement-module-solution.png new file mode 100644 index 0000000000..181924dd90 Binary files /dev/null and b/docs/en/images/issuemanagement-module-solution.png differ diff --git a/docs/en/images/layered-project-dependencies-module.png b/docs/en/images/layered-project-dependencies-module.png new file mode 100644 index 0000000000..7592f49878 Binary files /dev/null and b/docs/en/images/layered-project-dependencies-module.png differ diff --git a/docs/en/images/layered-project-dependencies.png b/docs/en/images/layered-project-dependencies.png new file mode 100644 index 0000000000..c5fd1b3504 Binary files /dev/null and b/docs/en/images/layered-project-dependencies.png differ diff --git a/docs/en/images/tiered-solution-applications.png b/docs/en/images/tiered-solution-applications.png new file mode 100644 index 0000000000..fb6ede7ac5 Binary files /dev/null and b/docs/en/images/tiered-solution-applications.png differ diff --git a/docs/en/images/tiered-solution-servers.png b/docs/en/images/tiered-solution-servers.png new file mode 100644 index 0000000000..3c999b4b45 Binary files /dev/null and b/docs/en/images/tiered-solution-servers.png differ diff --git a/docs/zh-Hans/AspNetCore/Auto-API-Controllers.md b/docs/zh-Hans/AspNetCore/Auto-API-Controllers.md index afe8ea700b..93ac124913 100644 --- a/docs/zh-Hans/AspNetCore/Auto-API-Controllers.md +++ b/docs/zh-Hans/AspNetCore/Auto-API-Controllers.md @@ -2,7 +2,7 @@ 创建[应用程序服务](Application-Services.md)后, 通常需要创建API控制器以将此服务公开为HTTP(REST)API端点. 典型的API控制器除了将方法调用重定向到应用程序服务并使用[HttpGet],[HttpPost],[Route]等属性配置REST API之外什么都不做. -ABP可以按照惯例 **自动** 将你的应用程序服务配置为MVC API控制器. 大多数时候你不关心它的详细配置,但它可以完全被自定义. +ABP可以按照惯例 **自动** 将你的应用程序服务配置为API控制器. 大多数时候你不关心它的详细配置,但它可以完全被自定义. ## 配置 @@ -16,7 +16,9 @@ public class BookStoreWebModule : AbpModule { Configure(options => { - options.ConventionalControllers.Create(typeof(BookStoreApplicationModule).Assembly); + options + .ConventionalControllers + .Create(typeof(BookStoreApplicationModule).Assembly); }); } } diff --git a/docs/zh-Hans/CLI.md b/docs/zh-Hans/CLI.md new file mode 100644 index 0000000000..57799724bd --- /dev/null +++ b/docs/zh-Hans/CLI.md @@ -0,0 +1,136 @@ +# ABP CLI + +ABP CLI (命令行接口) 是一个命令行工具,用来执行基于ABP解决方案的一些常见操作. + +## Installation + +ABP CLI 是一个 [dotnet global tool](https://docs.microsoft.com/en-us/dotnet/core/tools/global-tools). 使用命令行窗口安装: + +````bash +dotnet tool install -g Volo.Abp.Cli +```` + +更新最新版本: + +````bash +dotnet tool update -g Volo.Abp.Cli +```` + +## Commands + +### new + +生成基于ABP[启动模板](Startup-Templates/Index.md)的新解决方案. + +基本用法: + +````bash +abp new <解决方案名称> [options] +```` + +示例: + +````bash +abp new Acme.BookStore +```` + +* Acme.BookStore是解决方案的名称. +* 常见的命名方式类似于 *YourCompany.YourProject*. 不过你可以使用自己喜欢的方式,如 *YourProject* (单级命名空间) 或 *YourCompany.YourProduct.YourModule* (三级命名空间). + +#### Options + +* `--template` 或 `-t`: 指定模板. 默认的模板是 `mvc`.可用的模板有: + * `mvc` (默认): ASP.NET Core [MVC应用程序模板](Startup-Templates/Mvc.md). 其他选项: + * `--database-provider` 或 `-d`: 指定数据库提供程序. 默认提供程序是 `ef`. 可用的提供程序有: + * `ef`: Entity Framework Core. + * `mongodb`: MongoDB. + * `--tiered`: 创建分层解决方案,Web和Http Api层在物理上是分开的. 如果未指定会创建一个分层的解决方案, 此解决方案没有那么复杂,适合大多数场景. + * `mvc-module`: ASP.NET Core [MVC模块模板](Startup-Templates/Mvc-Module.md). 其他选项: + * `--no-ui`: 不包含UI. 仅创建服务模块 (也称为微服务 - 没有UI). +* `--output-folder` 或 `-o`: 指定输出文件夹,默认是当前目录. + +### add-package + +添加新的ABP包到项目中 + +* 添加nuget包做为项目的依赖项目. +* 添加 `[DependsOn(...)]` attribute到项目的模块类 (请参阅 [模块开发文档](Module-Development-Basics.md)). + +> 需要注意的是添加的模块可能需要额外的配置,通常会在包的文档中指出. + +基本用法: + +````bash +abp add-package <包名> [options] +```` + +示例: + +```` +abp add-package Volo.Abp.MongoDB +```` + +* 示例中将Volo.Abp.MongoDB包添加到项目中. + +#### Options + +* `--project` 或 `-p`: 指定项目 (.csproj) 路径. 如果未指定,Cli会尝试在当前目录查找.csproj文件. + +### add-module + +通过查找模块的所有包,查找解决方案中的相关项目,并将每个包添加到解决方案中的相应项目,从而将多包模块添加到解决方案中. + +> 由于分层,不同的数据库提供程序选项或其他原因,业务模块通常由多个包组成. 使用`add-module`命令可以大大简化向模块添加模块的过程. 但是每个模块可能需要一些其他配置,这些配置通常在相关模块的文档中指出. + +基本用法: + +````bash +abp add-module <模块名称> [options] +```` + +示例: + +```bash +abp add-module Volo.Blogging +``` + +* 示例中将Volo.Blogging模块添加到解决方案中. + +#### Options + +* `--solution` 或 `-s`: 指定解决方案 (.sln) 路径. 如果未指定,CLI会尝试在当前目录中寻找.sln文件. +* `--skip-db-migrations`: 对于EF Core 数据库提供程序,它会自动添加新代码的第一次迁移 (`Add-Migration`) 并且在需要时更新数据库 (`Update-Database`). 指定此选项可跳过此操作. + +### update + +更新所有ABP相关的包可能会很繁琐,框架和模块都有很多包. 此命令自动将解决方案或项目中所有ABP相关的包更新到最新版本. + +用法: + +````bash +abp update [options] +```` + +* 如果你的文件夹中有.sln文件,运行命令会将解决方案中所有项目ABP相关的包更新到最新版本. +* 如果你的文件夹中有.csproj文件,运行命令会将项目中所有ABP相关的包更新到最新版本. + +#### Options + +* `--include-previews` 或 `-p`: 将预览版, 测试版本 和 rc 包 同时更新到最新版本. + +### help + +CLI的基本用法信息. + +用法: + +````bash +abp help [命令名] +```` + +示例: + +````bash +abp help # 显示常规帮助. +abp help new # 显示有关 "New" 命令的帮助. +```` \ No newline at end of file diff --git a/docs/zh-Hans/Contribution/Localization-Text-Files.md b/docs/zh-Hans/Contribution/Localization-Text-Files.md index ad4bca1075..36bae2890a 100644 --- a/docs/zh-Hans/Contribution/Localization-Text-Files.md +++ b/docs/zh-Hans/Contribution/Localization-Text-Files.md @@ -2,19 +2,39 @@ 这是一个来自框架的本地化文本文件列表, 任何人都可以做出贡献. 我们会将此列表保持最新: -* https://github.com/abpframework/abp/tree/master/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json * https://github.com/abpframework/abp/tree/master/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/en.json * https://github.com/abpframework/abp/tree/master/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpValidation/en.json +* https://github.com/abpframework/abp/tree/master/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/en.json +* https://github.com/abpframework/abp/tree/master/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json +* https://github.com/abpframework/abp/tree/master/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/en.json +* https://github.com/abpframework/abp/tree/master/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/Localization/en.json +* https://github.com/abpframework/abp/tree/master/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/en.json +* https://github.com/abpframework/abp/tree/master/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/en.json +* https://github.com/abpframework/abp/tree/master/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/en.json +* https://github.com/abpframework/abp/tree/master/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/SourceExt/en.json * https://github.com/abpframework/abp/tree/master/modules/account/src/Volo.Abp.Account.Web/Localization/Resources/AbpAccount/Web/en.json -* https://github.com/abpframework/abp/tree/master/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en.json -* https://github.com/abpframework/abp/tree/master/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/en.json * https://github.com/abpframework/abp/tree/master/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Localization/Resources/Blogging/ApplicationContracts/en.json -* https://github.com/abpframework/abp/tree/master/modules/identity/src/Volo.Abp.Identity.Web/Localization/Resources/AbpIdentity/en.json -* https://github.com/abpframework/abp/tree/master/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Localization/Domain/en.json +* https://github.com/abpframework/abp/tree/master/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/en.json +* https://github.com/abpframework/abp/tree/master/modules/docs/app/VoloDocs.Web/Localization/Resources/VoloDocs/Web/en.json +* https://github.com/abpframework/abp/tree/master/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/en.json +* https://github.com/abpframework/abp/tree/master/modules/docs/src/Volo.Docs.Admin.Web/Localization/Resources/Docs/Web/en.json +* https://github.com/abpframework/abp/tree/master/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en.json +* https://github.com/abpframework/abp/tree/master/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/Localization/ApplicationContracts/en.json +* https://github.com/abpframework/abp/tree/master/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/Localization/Domain/en.json +* https://github.com/abpframework/abp/tree/master/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Localization/Resources/FeatureManagement/en.json * https://github.com/abpframework/abp/tree/master/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/Localization/ApplicationContracts/en.json +* https://github.com/abpframework/abp/tree/master/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Localization/Domain/en.json +* https://github.com/abpframework/abp/tree/master/modules/identity/src/Volo.Abp.Identity.Web/Localization/Resources/AbpIdentity/en.json * https://github.com/abpframework/abp/tree/master/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Localization/Resources/AbpPermissionManagement/en.json -* https://github.com/abpframework/abp/tree/master/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Localization/Resources/AbpTenantManagement/Web/en.json +* https://github.com/abpframework/abp/tree/master/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Localization/Resources/AbpSettingManagement/en.json * https://github.com/abpframework/abp/tree/master/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/Localization/ApplicationContracts/en.json -* https://github.com/abpframework/abp/tree/master/templates/mvc/src/MyCompanyName.MyProjectName.Domain/Localization/MyProjectName/en.json -* https://github.com/abpframework/abp/tree/master/templates/module/src/MyCompanyName.MyProjectName.Domain/MyCompanyName/MyProjectName/Localization/Domain/en.json -* https://github.com/abpframework/abp/tree/master/templates/module/src/MyCompanyName.MyProjectName.Web/Localization/Resources/MyProjectName/en.json \ No newline at end of file +* https://github.com/abpframework/abp/tree/master/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Localization/Resources/AbpTenantManagement/Web/en.json +* https://github.com/abpframework/abp/tree/master/samples/BookStore/src/Acme.BookStore.Domain.Shared/Localization/BookStore/en.json +* https://github.com/abpframework/abp/tree/master/samples/DashboardDemo/src/DashboardDemo.Domain/Localization/DashboardDemo/en.json +* https://github.com/abpframework/abp/tree/master/samples/MicroserviceDemo/modules/product/src/ProductManagement.Application.Contracts/ProductManagement/Localization/ApplicationContracts/en.json +* https://github.com/abpframework/abp/tree/master/samples/MicroserviceDemo/modules/product/src/ProductManagement.Domain/ProductManagement/Localization/Domain/en.json +* https://github.com/abpframework/abp/tree/master/samples/MicroserviceDemo/modules/product/src/ProductManagement.Web/Localization/Resources/ProductManagement/en.json +* https://github.com/abpframework/abp/tree/master/templates/mvc-module/src/MyCompanyName.MyProjectName.Application.Contracts/Localization/MyProjectName/ApplicationContracts/en.json +* https://github.com/abpframework/abp/tree/master/templates/mvc-module/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/DomainShared/en.json +* https://github.com/abpframework/abp/tree/master/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Localization/MyProjectName/Web/en.json +* https://github.com/abpframework/abp/tree/master/templates/mvc/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/en.json diff --git a/docs/zh-Hans/Data-Seeding.md b/docs/zh-Hans/Data-Seeding.md new file mode 100644 index 0000000000..0b424e7e0d --- /dev/null +++ b/docs/zh-Hans/Data-Seeding.md @@ -0,0 +1,3 @@ +# Data Seeding + +TODO \ No newline at end of file diff --git a/docs/zh-Hans/Dynamic-JavaScript-API-Clients.md b/docs/zh-Hans/Dynamic-JavaScript-API-Clients.md new file mode 100644 index 0000000000..b7ca9a6965 --- /dev/null +++ b/docs/zh-Hans/Dynamic-JavaScript-API-Clients.md @@ -0,0 +1,3 @@ +## Dynamic JavaScript API Clients + + TODO \ No newline at end of file diff --git a/docs/zh-Hans/Getting-Started-AspNetCore-MVC-Template.md b/docs/zh-Hans/Getting-Started-AspNetCore-MVC-Template.md index e8ce4fa71a..497ba5f7f1 100644 --- a/docs/zh-Hans/Getting-Started-AspNetCore-MVC-Template.md +++ b/docs/zh-Hans/Getting-Started-AspNetCore-MVC-Template.md @@ -1,38 +1,43 @@ -## ASP.NET Core MVC 模板 +## ASP.NET Core MVC 模板入门 ### 创建新项目 -访问[模板创建页面](https://abp.io/Templates), 输入项目名称并创建项目, 如下所示: +本教程使用 **ABP CLI** 创建一个新项目. 更多选项, 请参阅[入门](https://cn.abp.io/get-started)页面. -![bookstore-create--template](images/bookstore-create-template.png) +如果你之前未安装,请使用命令行安装ABP CLI: -单击 *create* 按钮时,将使用你提供的名称创建一个新的Visual Studio解决方案并开始下载. +````bash +dotnet tool install -g Volo.Abp.Cli +```` + +在空文件夹中使用 `abp new` 命令来创建项目: + +```` +abp new Acme.BookStore +```` + +> 你可以使用不同级别的命名空间; 例如BookStore, Acme.BookStore或Acme.Retail.BookStore. + +`new` 命令创建**分层MVC应用程序**, **Entity Framework Core**作为数据库提供程序. 但是,它还有其他选择. 有关所有可用选项,请参见[CLI文档](CLI.md) #### 预先要求 -下载的项目需要: +创建项目的要求: * [Visual Studio 2017 (v15.9.0+)](https://visualstudio.microsoft.com/tr/downloads/) -* [.NET Core 2.1.1+](https://www.microsoft.com/net/download/dotnet-core/) +* [.NET Core 2.2+](https://www.microsoft.com/net/download/dotnet-core/) ### 解决方案结构 -下载后解压文件并在 **Visual Studio 2017(15.7.0 +)** 中打开: - -![bookstore-visual-studio-solution](images/bookstore-visual-studio-solution-v2.png) - -该解决方案具有分层结构(基于域驱动设计), 其中: +在**Visual Studio**中打开解决方案: -* ``.Domain`` 为领域层. -* ``.Application`` 为应用层. -* ``.Web`` 为是表示层. -* ``.EntityFrameworkCore`` 是EF Core集成. +![bookstore-visual-studio-solution](images/bookstore-visual-studio-solution-v3.png) -EF Core 数据库迁移被分离到名为`.EntityFrameworkCore.DbMigrations`项目中. +该解决方案具有分层结构(基于[Domain Driven Design](Domain-Driven-Design.md)), 并包含配置好的的单元&集成测试项目,可与**EF Core**和**SQLite**数据库内存一起使用. -解决方案还包含配置好的的单元&集成测试项目, 以便与 **EF Core** 和 **SQLite内存中** 数据库配合使用. +> 请参阅[MVC应用程序模板文档](Startup-Templates/Mvc.md)以详细了解解决方案结构. -### 创建数据库 +### 数据库连接字符串 查看`.Web`项目下`appsettings.json`文件中的 **连接字符串**: @@ -44,9 +49,29 @@ EF Core 数据库迁移被分离到名为`.EntityFrameworkCore.DbMigrations`项 } ```` -解决方案使用 **Entity Framework Core** 和 **MS SQL Server**. EF Core支持[各种](https://docs.microsoft.com/en-us/ef/core/providers/)数据库提供程序,因此你可以根据实际需要使用其他DBMS. +解决方案使用 **Entity Framework Core** 和 **MS SQL Server**. EF Core支持[各种](https://docs.microsoft.com/en-us/ef/core/providers/)数据库提供程序,因此你可以根据实际需要使用其他DBMS. 如果需要,请更改连接字符串. + +### 创建数据库并应用数据库迁移 + +你有两个选项来创建数据库. -右键单击`.Web`项目并**设置启动项目** +#### 使用DbMigrator应用程序 + +该解决方案包含一个控制台应用程序(在此示例中名为`Acme.BookStore.DbMigrator`),可以创建数据库,应用迁移和初始化数据. 它对开发和生产环境都很有用. + +> `.DbMigrator`项目有自己的`appsettings.json`. 因此,如果你更改了上面的连接字符串,则还应更改此字符串. + +右键单击`.DbMigrator`项目并选择 **设置为启动项目**: + +![set-as-startup-project](images/set-as-startup-project.png) + +按F5(或Ctrl + F5)运行应用程序. 它将具有如下所示的输出: + +![set-as-startup-project](images/db-migrator-app.png) + +#### 使用EF Core Update-Database命令 + +Ef Core具有`Update-Database`命令, 可根据需要创建数据库并应用挂起的迁移. 右键单击`.Web`项目并选择**设置为启动项目**: ![set-as-startup-project](images/set-as-startup-project.png) @@ -56,6 +81,8 @@ EF Core 数据库迁移被分离到名为`.EntityFrameworkCore.DbMigrations`项 这将基于配置的连接字符串创建新数据库. +> 使用`.Migrator`工具是建议的方法, 因为它还能初始化初始数据能够正确运行Web应用程序. + ### 运行应用程序 你现在可以运行应用程序,它将会打开**home**页面: @@ -64,9 +91,9 @@ EF Core 数据库迁移被分离到名为`.EntityFrameworkCore.DbMigrations`项 单击 **登录** 按钮, 输入用户名`admin`, 密码`1q2w3E*`, 登录应用程序. -启动模板包括 **身份管理(identity management)** 模块. 登录后将提供身份管理菜单,你可以在其中管理**角色**,**用户**及其**权限**. +启动模板包括**身份管理**和**租户管理**模块. 登录后,将显示"管理"菜单, 你可以在其中管理**租户**,**角色**,**用户**和**权限**. 用户管理页面如下所示: -![bookstore-user-management](images/bookstore-user-management.png) +![bookstore-user-management](images/bookstore-user-management-v2.png) ### 下一步是什么? diff --git a/docs/zh-Hans/Getting-Started-Console-Application.md b/docs/zh-Hans/Getting-Started-Console-Application.md index 6c38d86601..346836c8e3 100644 --- a/docs/zh-Hans/Getting-Started-Console-Application.md +++ b/docs/zh-Hans/Getting-Started-Console-Application.md @@ -1,4 +1,4 @@ -## 使用Console Application +## 在控制台应用中使用ABP 本教程将介绍如何从头开始以最小的依赖关系启动ABP. 你通常希望以 **[启动模板](https://abp.io/Templates)** 开头. diff --git a/docs/zh-Hans/Index.md b/docs/zh-Hans/Index.md index e14bd67fa5..fbe003b8e7 100644 --- a/docs/zh-Hans/Index.md +++ b/docs/zh-Hans/Index.md @@ -1,68 +1,32 @@ # ABP 文档 -> 翻译来自[cnAbp](https://github.com/cnabp)组织,中文网会持续跟进翻译,目前Abp vNext的英文文档还未完成,大家对整体框架没有深入的理解,翻译难免存在一些问题.敬请见谅.😀 +> 中文文档翻译来自[cnAbp](https://github.com/cnabp)组织,Abp中文网会持续跟进翻译,目前Abp vNext的英文文档还未完成,大家对整体框架没有深入的理解,翻译难免存在一些问题.敬请见谅.😀 -## 目录 +ABP是一个**开源应用程序框架**,专注于基于ASP.NET Core的Web应用程序开发,但也支持开发其他类型的应用程序. -* 入门 - * 从启动模板开始 - * [ASP.NET Core MVC 模板](Getting-Started-AspNetCore-MVC-Template.md) - * 从空项目开始 - * [使用Console Application](Getting-Started-Console-Application.md) - * [使用 ASP.NET Core Web Application](Getting-Started-AspNetCore-Application.md) -* 教程 - * 应用开发 - * [使用 ASP.NET Core MVC](Tutorials/AspNetCore-Mvc/Part-I.md) -* 基础知识 - * [依赖注入](Dependency-Injection.md) - * AutoFac 集成 - * [虚拟文件系统](Virtual-File-System.md) - * [本地化](Localization.md) - * [异常处理](Exception-Handling.md) - * 验证 - * 授权 - * 缓存 - * 审计 - * 设置管理 - * 对象映射 - * AutoMapper 集成 -* 事件 - * 本地 Event Bus - * 分布式 Event Bus - * RabbitMQ 集成 -* 服务 - * 对象序列化 - * JSON序列化 - * 邮件 - * GUIDs - * 线程 - * 定时 -* [多租户](Multi-Tenancy.md) -* 模块开发 - * [基础](Module-Development-Basics.md) - * 模块插件 - * [最佳实践](Best-Practices/Index.md) -* 领域驱动设计 - * 领域层 - * [实体&聚合根](Entities.md) - * 值对象 - * [仓储](Repositories.md) - * 领域服务 - * 规约 - * 应用服务层 - * 应用服务 - * 数据传输对象(DTO) - * 工作单元 -* ASP.NET Core MVC - * API 版本控制 - * 用户界面 - * [客户端包管理](AspNetCore/Client-Side-Package-Management.md) - * [捆绑&压缩](AspNetCore/Bundling-Minification.md) - * [Tag Helpers](Tag-Helpers.md) - * [主题](AspNetCore/Theming.md) -* 后台服务 - * [后台作业](Background-Jobs.md) -* 数据访问 - * [Entity Framework Core 集成](Entity-Framework-Core.md) - * [MongoDB 集成](MongoDB.md) -* 测试 +浏览左侧导航菜单以深入了解文档. + +## 项目状态 + +ABP是开源[ASP.NET Boilerplate](https://aspnetboilerplate.com/)框架的**下一代框架**, 它目前处于早期预览阶段,尚未准备好在生产中使用. 文档仍在进行中,远未完成. + +对于短期和生产级应用程序, 建议使用[ASP.NET Boilerplate](https://aspnetboilerplate.com/)框架,该框架具有丰富的功能集,成熟,积极维护和最新. + +## 入门 + +使用ABP开发新项目的最简单方法是使用启动模板: + +* [ASP.NET Core MVC 模板](Getting-Started-AspNetCore-MVC-Template.md) + +如果您想从头开始(使用空项目),请手动安装ABP框架并使用以下教程: + +* [控制台应用程序](Getting-Started-Console-Application.md) +* [ASP.NET Core Web 应用程序](Getting-Started-AspNetCore-Application.md) + +## 源码 + +ABP托管在GitHub上, 参见[源代码](https://github.com/abpframework/abp). + +## 贡献代码 + +ABP是一个社区驱动的开源项目.如果你想成为该项目的一部分,请参阅[贡献指南](Contribution/Index.md). diff --git a/docs/zh-Hans/Startup-Templates/Index.md b/docs/zh-Hans/Startup-Templates/Index.md new file mode 100644 index 0000000000..c4c75bbedb --- /dev/null +++ b/docs/zh-Hans/Startup-Templates/Index.md @@ -0,0 +1,8 @@ +# 启动模板 + +虽然你可以从一个空项目开始并手动添加所需的包,但启动模板可以非常轻松,舒适地使用ABP框架启动新的解决方案. + +单击下面列表中的名称以查看相关启动模板的文档: + +* [**mvc**](Mvc.md): ASP.NET Core MVC应用程序模板. +* [**mvc-module**](Mvc-Module.md): ASP.NET Core MVC模块/服务模板. \ No newline at end of file diff --git a/docs/zh-Hans/Startup-Templates/Mvc-Module.md b/docs/zh-Hans/Startup-Templates/Mvc-Module.md new file mode 100644 index 0000000000..9f19f83278 --- /dev/null +++ b/docs/zh-Hans/Startup-Templates/Mvc-Module.md @@ -0,0 +1,6 @@ +# MVC Module 启动模板 + +TODO + + + diff --git a/docs/zh-Hans/Startup-Templates/Mvc.md b/docs/zh-Hans/Startup-Templates/Mvc.md new file mode 100644 index 0000000000..48bdcd30a2 --- /dev/null +++ b/docs/zh-Hans/Startup-Templates/Mvc.md @@ -0,0 +1,259 @@ +# MVC应用程序启动模板 + +## 介绍 + +MVC应用程序启动模板是基于[领域驱动设计](../Domain-Driven-Design.md)(DDD)分层(或根据偏好分层)的应用程序结构. + +在这篇文档中详细介绍了解决方案结构和项目 + +* 参阅[ASP.NET Core MVC 模板入门](../Getting-Started-AspNetCore-MVC-Template.md)创建此模板的新解决方案并运行它. +* 参阅[ASP.NET Core MVC 教程](../Tutorials/AspNetCore-Mvc/Part-I.md)学习使用此模板开发应用程序. + +## 如何开始 + +你要以使用[ABP CLI](../CLI.md)创建基于此启动模板的新项目,或者你也可以在[入门](https://abp.io/get-started)页面创建并下载项目. 在这里我们使用CLI创建新项目. + +如果未安装ABP CLI,第一步是安装ABP CLI + +````bash +dotnet tool install -g Volo.Abp.Cli +```` + +然后使用 `abp new` 命令在空文件夹中创建新解决方案: + +````bash +abp new Acme.BookStore -t mvc +```` + +* `Acme.BookStore` 是解决方案的名称, 如*YourCompany.YourProduct*. 你可以使用单级或多级名称. +* 示例中指定了启动模板 (`-t` 或 `--template` 选项). 不过 `mvc` 是默认模板,即使未指定也会创建 `MVC` 的模板项目. + +### 指定数据库提供程序 + +`MVC`模板支持以下数据库提供程序: + +- `ef`: Entity Framework Core (默认) +- `mongodb`: MongoDB + +使用 `-d` (或 `--database-provider`) 选项指定数据库提供程序: + +````bash +abp new Acme.BookStore -d mongodb +```` + +### 创建分层解决方案 + +使用 `--tiered` 选项创建分层解决方案, Web与WebApi层在物理上是分开的. 如果未指定,CLI会创建一个分层的解决方案,这个解决方案没有那么复杂,适合大多数场景. + +````bash +abp new Acme.BookStore --tiered +```` + +有关分层的方法,请参阅下面的"分层结构"部分. + +## 解决方案结构 + +根据命令的选项,会创建略有不同的解决方案结构. + +### 默认结构 + +如果未指定选项,你会得到如下所示的解决方案: + +![bookstore-visual-studio-solution-v3](../images/bookstore-visual-studio-solution-v3.png) + +项目组织在`src`和`test`文件夹中. `src`文件夹包含实际应用程序,该应用程序基于前面提到的[DDD](../Domain-Driven-Design.md)原则进行分层. 下图展示了解决方案的层和项目的依赖关系: + +![layered-project-dependencies](../images/layered-project-dependencies.png) + +下面介绍解决方案中的项目及依赖关系. + +#### .Domain.Shared 项目 + +项目包含常量,枚举和其他对象,这些对象实际上是领域层的一部分,但是解决方案中所有的层/项目中都会使用到. + +例如 `BookType` 枚举和 `BookConts` 类 (可能是 `Book` 实体用到的常数字段,像`MaxNameLength`)都适合放在这个项目中. + +* 该项目不依赖解决方案中的其他项目. 其他项目直接或间接依赖该项目 + +#### .Domain 项目 + +解决方案的领域层. 它主要包含 [实体, 集合根](../Entities.md), [领域服务](../Domain-Services.md), [值类型](../Value-Types.md), [仓储接口](../Repositories.md) 和解决方案的其他领域对象. + +例如 `Book` 实体和 `IBookRepository` 接口都适合放在这个项目中. + +* 它依赖 `.Domain.Shared` 项目,因为项目中会用到它的一些常量,枚举和定义其他对象. + +#### .Application.Contracts 项目 + +项目主要包含 [应用服务](../Application-Services.md) **interfaces** 和应用层的 [数据传输对象](../Data-Transfer-Objects.md) (DTO). 它用于分离应用层的接口和实现. 这种方式可以将接口项目做为约定包共享给客户端. + +* 它依赖 `.Domain.Shared` 因为它可能会在应用接口和DTO中使用常量,枚举和其他的共享对象. + +#### .Application 项目 + +项目包含 `.Application.Contracts` 项目的 [应用服务](../Application-Services.md) 接口**实现**. + +* 它依赖 `.Application.Contracts` 项目, 因为它需要实现接口与使用DTO. +* 它依赖 `.Domain` 项目,因为它需要使用领域对象(实体,仓储接口等)执行应用程序逻辑. + +#### .EntityFrameworkCore 项目 + +这是集成EF Core的项目. 它定义了 `DbContext` 并实现 `.Domain` 项目中定义的仓储接口. + +* 它依赖 `.Domain` 项目,因为它需要引用实体和仓储接口. + +> 只有在你使用了EF Core做为数据库提供程序时,此项目才会可用. 如果选择的是其他数据库提供程序那么项目的名称会改变 + +#### .EntityFrameworkCore.DbMigrations 项目 + +包含解决方案的EF Core数据库迁移. 它有独立的 `DbContext` 来专门管理迁移. + +ABP是一个模块化的框架,理想的设计是让每个模块都有自己的 `DbContext` 类. 这时用于迁移的 `DbContext` 就会发挥作用. 它将所有的 `DbContext` 配置统一到单个模型中以维护单个数据库的模式. 对于更高级的场景,可以程序可以拥有多个数据库(每个数据库有一个或多个模块表)和多个迁移`DbContext`(每个都维护不同的数据库模式) + +需要注意,迁移 `DbContext` 仅用于数据库迁移,而不在*运行时*使用. + +* 它依赖 `.EntityFrameworkCore` 项目,因为它重用了应用程序的 `DbContext` 配置 . + +> 只有在你使用了EF Core做为数据库提供程序时,此项目才会可用. + +#### .DbMigrator 项目 + +这是一个控制台应用唾弃,它简化了在开发和生产环境执行数据库迁移的操作.当你使用它时; + +* 必要时创建数据库(没有数据库时). +* 应用未迁移的数据库迁移. +* 初始化种子数据(当你需要时). + +> 这个项目有自己的 `appsettings.json` 文件. 所以如果要更改数据库连接字符串,请记得也要更改此文件. + +初始化种子数据很很要,ABP具有模块化的种子数据基础设施. 种子数据的更多信息,请参阅[文档](../Data-Seeding.md). + +虽然创建数据库和应用迁移似乎只对关系数据库有用,但即使您选择NoSQL数据库提供程序(如MongoDB),也会生成此项目. 这时,它会为应用程序提供必要的初始数据. + +* 它依赖 `.EntityFrameworkCore.DbMigrations` 项目 (针对EF Core),因为它需要访问迁移文件. +* 它依赖 `.Application.Contracts` 项目,因为它需要访问权限定义在初始化种子数据时为管理员用户赋予所有权限. + +#### .HttpApi 项目 + +用于定义API控制器. + +大多数情况下,你不需要手动定义API控制器,因为ABP的[动态API](../AspNetCore/Auto-API-Controllers.md)功能会根据你的应用层自动创建API控制器. 但是,如果你需要编写API控制器,那么它是最合适的地方. + +* 它依赖 `.Application.Contracts` 项目,因为它需要注入应用服务接口. + +#### .HttpApi.Client 项目 + +定义C#客户端代理使用解决方案的HTTP API项目. 可以将上编辑共享给第三方客户端,使其轻松的在DotNet应用程序中使用你的HTTP API(其他类型的应用程序可以手动或使用其平台的工具来使用你的API). + +ABP有[动态 C# API 客户端](../AspNetCore/Dynamic-CSharp-API-Clients.md)功能,所以大多数情况下你不需要手动的创建C#客户端代理. + +`.HttpApi.Client.ConsoleTestApp` 项目是一个用于演示客户端代理用法的控制台应用程序. + +* 它依赖 `.Application.Contracts` 项目,因为它需要使用应用服务接口和DTO. + +> 如果你不需要为API创建动态C#客户端代理,可以删除此项目和依赖项 + +#### .Web 项目 + +包含应用程序的用户界面(UI). 包括Razor页面,javascript文件,样式文件,图片等... + +包含应用程序主要的 `appsettings.json` 配置文件,用于配置数据库连接字符串和应用程序的其他配置 + +* 依赖 `.HttpApi` 项目,因为UI层需要使用解决方案的API和应用服务接口. + +> 如果查看 `.Web.csproj` 源码, 你会看到对 `.Application` 和 `.EntityFrameworkCore.DbMigrations` 项目的引用. +> +> 在编写UI层时实际上不需要这些引用. 因为UI层通常不依赖于EF Core或应用层的实现. 这个启动模板已经为分层部署做好了准备,API层托管在不同与UI层的服务器中. +> +> 但是如果你不选择 `--tiered` 选项, .Web项目会有这些引用,以便能够将Web,Api和应用层托管在单个应用程序站点. +> +> 你可以在表示层中使用领域实体和仓储,但是根据DDD的理论,这被认为是一种不好的做法. + +#### 测试项目 + +解决方案有多个测试项目,每一层都会有一个: + +* `.Domain.Tests` 用于测试领域层. +* `.Application.Tests` 用于测试应用层. +* `.EntityFrameworkCore.Tests` 用于测试EF Core配置与自定义仓储. +* `.Web.Tests` 用于测试UI. +* `.TestBase` 所有测试项目的基础(共享)项目. + +此外, `.HttpApi.Client.ConsoleTestApp` 是一个控制台应用程序(不是自动化测试项目),它用于演示DotNet应用程序中HTTP API的用法. + +测试项目已为集成测试做好准备: + +* 它完成集成到ABP框架和应用程序的所有服务. +* 如果数据库提供程序是EF Core,测试项目会使用SQLite内存数据库,如果是MongoDB,它使用[Mongo2Go](https://github.com/Mongo2Go/Mongo2Go)库. +* 授权被禁用,任何的应用服务都可以在测试中轻松调用. + +你依然可以编写单元测试,只不过它很难写(因为你需要准备mock/fake对象),但它的运行速度更快(因为只测试单个类并跳过所有初始化过程). + +#### 如何运行? + +设置`.Web`为启动项目. 默认用户名 `admin`, 密码 `1q2w3E*`. + +更多信息请参阅[ASP.NET Core MVC 模板入门](../Getting-Started-AspNetCore-MVC-Template.md). + +### 分层结构 + +如果你按上面的描述指定了 `--tiered` 选项,会创建分层解决方案. 分层结构的目的是**将Web应用程序和HTTP API部署到不同的服务器**: + +![bookstore-visual-studio-solution-v3](../images/tiered-solution-servers.png) + +* 浏览器渲染HTML,执行CSS和JavaScript来运行UI. +* Web服务器托管静态文件(CSS,JavaScript,图片...等)和动态组件(如Razor页面),它通过HTTP请求到API服务器执行应用程序的业务逻辑. +* API服务器托管HTTP API,使用应用程序的应用层和领域层执行业务逻辑. +* 最后数据库服务器托管数据库. + +与之前默认结构的三层部署比较,分层解决方案允许四层部署. + +> 除非你真的需要四层部署,一般建议采用默认结构,它更易于开发,部署和维护. + +解决方案结构如下所示: + +![bookstore-visual-studio-solution-v3](../images/bookstore-visual-studio-solution-tiered.png) + +与默认结构不同,我们得到了两个新项目: `.IdentityServer` 和 `.HttpApi.Host`. + +#### .IdentityServer 项目 + +用于其他项目的身份验证服务器. `.Web`项目使用OpenId Connect身份验证获取当前用户的身份和访问令牌. 然后使用访问令牌调用HTTP API服务器. HTTP API服务器使用bearer token从访问令牌获取声明授权当前用户. + +![bookstore-visual-studio-solution-v3](../images/tiered-solution-applications.png) + +ABP使用开源的[IdentityServer4](https://identityserver.io/)框架做应用程序间的身份验证. 有关IdentityServer4和OpenId Connect协议的详细信息请参阅[IdentityServer4文档](http://docs.identityserver.io). + +它有自己的`appsettings.json`文件(数据库连接字符串等其他配置). + +#### .HttpApi.Host 项目 + +该项目是一个承载解决方案API的应用程序. + +它有自己的`appsettings.json`文件(数据库连接字符串等其他配置). + +#### .Web 项目 + +与默认结构一样,包含应用程序的用户界面(UI). 包括Razor页面,javascript文件,样式文件,图片等... + +项目包含`appsetting.json`文件,但没有连接字符串配置, 它不需要连接到数据库. 文件中主要包含远程API服务器端点和身份验证服务器 + +#### 前置条件 + +* [Redis](https://redis.io/): 应用程序使用Redis做分布式缓存,你需要安装并运行Redis. + +#### 如何运行? + +你应该按照以下顺序运行应用: + +* 首先运行`.IdentityServer`,因为其他应用程序依赖它做身份验证. +* 然后运行`.HttpApi.Server`,因为`.Web`应用程序需要访问HTTI API. +* 最后运行`.Web`并登录到应用程序(用户名: `admin` 密码: `1q2w3E*`). + +### 其他数据库提供程序 + +TODO + +#### MongoDB + +TODO \ No newline at end of file diff --git a/docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-I.md b/docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-I.md index d3e8af3523..c0f453d878 100644 --- a/docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-I.md +++ b/docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-I.md @@ -2,7 +2,7 @@ ### 关于本教程 -本教程中,你会创建一个用于管理书籍和书籍作者的程序.会用到 **Entity Framework Core** (EF Core)作为ORM([启动模板](https://abp.io/Templates)中预配置的ORM). +在本系列教程中, 你将构建一个用于管理书籍及其作者列表的应用程序. **Entity Framework Core**(EF Core)将用作ORM提供者,因为它是默认数据库提供者. 这是本教程所有章节中的第一章,下面是所有的章节: @@ -10,35 +10,37 @@ - [Part II: 创建,编辑,删除书籍](Part-II.md) - [Part III: 集成测试](Part-III.md) -你可以从[这里](https://github.com/volosoft/abp/tree/master/samples/BookStore)下载本程序的源码. +你可以从[GitHub存储库](https://github.com/volosoft/abp/tree/master/samples/BookStore)访问应用程序的**源代码**. ### 创建项目 -打开[启动模板页](https://abp.io/Templates)并下载一个新的项目叫做`Acme.BookStore`.根据[模板文档](../../Getting-Started-AspNetCore-MVC-Template.md)创建数据库并运行这个程序. +创建一个名为`Acme.BookStore`的新项目, 创建数据库并按照[入门文档](../../Getting-Started-AspNetCore-MVC-Template.md)运行应用程序. ### 解决方案的结构 下面的图片展示了从启动模板创建的项目是如何分层的. -![bookstore-visual-studio-solution](images/bookstore-visual-studio-solution-v2.png) +![bookstore-visual-studio-solution](images/bookstore-visual-studio-solution-v3.png) + +> 你可以查看[MVC应用程序模板文档](../../Startup-Templates/Mvc.md)以详细了解解决方案结构.但是,你将通过本教程了解基础知识. ### 创建Book实体 -在 **领域层** 定义[实体](../../Entities.md)(`Acme.BookStore.Domain` 项目中).这个项目最主要的实体就是`Book`: +启动模板中的域层分为两个项目: + + - `Acme.BookStore.Domain`包含你的[实体](../../Entities.md), [领域服务](../../Domain-Services.md)和其他核心域对象. + - `Acme.BookStore.Domain.Shared`包含可与客户共享的常量,枚举或其他域相关对象. + +在解决方案的**领域层**(`Acme.BookStore.Domain`项目)中定义[实体](../../Entities.md). 该应用程序的主要实体是`Book`. 在`Acme.BookStore.Domain`项目中创建一个名为`Book`的类,如下所示: ````C# using System; -using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; using Volo.Abp.Domain.Entities.Auditing; namespace Acme.BookStore { - [Table("Books")] public class Book : AuditedAggregateRoot { - [Required] - [StringLength(128)] public string Name { get; set; } public BookType Type { get; set; } @@ -50,8 +52,8 @@ namespace Acme.BookStore } ```` -* ABP有两个基本的实体基类: `AggregateRoot` 和 `Entity`.**Aggregate Root**是 **领域驱动设计(DDD)** 的概念之一.更多信息和最佳实践请查看[实体文档](../../Entities.md). -* `Book`实体继承了`AuditedAggregateRoot`,`AuditedAggregateRoot`类在`AggregateRoot`类的基础上添加了一些审计属性(`CreationTime`, `CreatorId`, `LastModificationTime`... 等.). +* ABP为实体提供了两个基本的基类: `AggregateRoot`和`Entity`. **Aggregate Root**是**域驱动设计(DDD)** 概念之一. 有关详细信息和最佳做法,请参阅[实体文档](../../Entities.md). +* `Book`实体继承了`AuditedAggregateRoot`,`AuditedAggregateRoot`类在`AggregateRoot`类的基础上添加了一些审计属性(`CreationTime`, `CreatorId`, `LastModificationTime` 等). * `Guid`是`Book`实体的主键类型. * 使用 **数据注解** 为EF Core添加映射.或者你也可以使用 EF Core 自带的[fluent mapping API](https://docs.microsoft.com/en-us/ef/core/modeling). @@ -62,10 +64,10 @@ namespace Acme.BookStore ````C# namespace Acme.BookStore { - public enum BookType : byte + public enum BookType { Undefined, - Advanture, + Adventure, Biography, Dystopia, Fantastic, @@ -91,14 +93,15 @@ public class BookStoreDbContext : AbpDbContext #### 配置你的Book实体 -从`Acme.BookStore.EntityFrameworkCore` 项目中打开 BookStoreDbContextModelCreatingExtensions.cs 文件, 在 ConfigureBookStore 方法最后添加如下代码来配置Book实体: +在`Acme.BookStore.EntityFrameworkCore`项目中打开`BookStoreDbContextModelCreatingExtensions.cs`文件,并将以下代码添加到`ConfigureBookStore`方法的末尾以配置Book实体: ````C# - builder.Entity(b => - { - b.ToTable(BookStoreConsts.DbTablePrefix + "Books", BookStoreConsts.DbSchema); - b.ConfigureExtraProperties(); - }); +builder.Entity(b => +{ + b.ToTable(BookStoreConsts.DbTablePrefix + "Books", BookStoreConsts.DbSchema); + b.ConfigureAuditedAggregateRoot(); //auto configure for the base class props + b.Property(x => x.Name).IsRequired().HasMaxLength(128); +}); ```` #### 添加新的Migration并更新数据库 @@ -115,26 +118,27 @@ PM> Update-Database #### 添加示例数据 -`Update-Database`命令会在数据库中创建`Books`表.打开这个表添加几行数据,然后就可以把这些数据展示到页面上: +`Update-Database`命令在数据库中创建了`AppBooks`表. 打开数据库并输入几个示例行,以便在页面上显示它们: ![bookstore-books-table](images/bookstore-books-table.png) ### 创建应用服务 -下一步是创建[应用服务](../../Application-Services.md)来管理(创建,列出,更新,删除...)书籍. +下一步是创建[应用服务](../../Application-Services.md)来管理(创建,列出,更新,删除)书籍. 启动模板中的应用程序层分为两个项目: + +* `Acme.BookStore.Application.Contracts`主要包含你的DTO和应用程序服务接口. +* `Acme.BookStore.Application`包含应用程序服务的实现. #### BookDto -在`Acme.BookStore.Application`项目中添加一个名为`BookDto`的DTO类: +在`Acme.BookStore.Application.Contracts`项目中创建一个名为`BookDto`的DTO类: ````C# using System; using Volo.Abp.Application.Dtos; -using Volo.Abp.AutoMapper; namespace Acme.BookStore { - [AutoMapFrom(typeof(Book))] public class BookDto : AuditedEntityDto { public string Name { get; set; } @@ -151,7 +155,23 @@ namespace Acme.BookStore * **DTO**类被用来在 **表示层** 和 **应用层** **传递数据**.查看[DTO文档](../../Data-Transfer-Objects.md)查看更多信息. * 为了在页面上展示书籍信息,`BookDto`被用来将书籍数据传递到表示层. * `BookDto`继承自 `AuditedEntityDto`.跟上面定义的`Book`类一样具有一些审计属性. -* `[AutoMapFrom(typeof(Book))]`用来创建从`Book`类到`BookDto`的AutoMapper映射.使用这种方法.你可以将`Book`对象自动转换成`BookDto`对象(而不是手动复制所有的属性). + +在将书籍返回到表示层时,需要将`Book`实体转换为`BookDto`对象. [AutoMapper](https://automapper.org)库可以在定义了正确的映射时自动执行此转换. 启动模板配置了AutoMapper,因此你只需在`Acme.BookStore.Application`项目的`BookStoreApplicationAutoMapperProfile`类中定义映射: + +````csharp +using AutoMapper; + +namespace Acme.BookStore +{ + public class BookStoreApplicationAutoMapperProfile : Profile + { + public BookStoreApplicationAutoMapperProfile() + { + CreateMap(); + } + } +} +```` #### CreateUpdateBookDto @@ -184,11 +204,17 @@ namespace Acme.BookStore ```` * 这个DTO类被用于在创建或更新书籍的时候从用户界面获取图书信息. -* 类中的属性定义了数据注解(如`[Required]`)用来定义有效性验证.ABP会自动校验DTO的数据有效性. +* 它定义了数据注释属性(如`[Required]`)来定义属性的验证. DTO由ABP框架[自动验证](../../Validation.md). + +就像上面的`BookDto`一样,创建一个从`CreateUpdateBookDto`对象到`Book`实体的映射: + +````csharp +CreateMap(); +```` #### IBookAppService -为应用服务定义一个名为 `IBookAppService` 的接口: +在`Acme.BookStore.Application.Contracts`项目中定义一个名为`IBookAppService`的接口: ````C# using System; @@ -210,15 +236,14 @@ namespace Acme.BookStore } ```` -* 为应用服务定义接口不是必须的,不过,这是推荐的最佳实践. -* `IAsyncCrudAppService`中定义了基础的 **CRUD**方法:`GetAsync`, `GetListAsync`, `CreateAsync`, `UpdateAsync` 和 `DeleteAsync`.不需要扩展它.取而代之,你可以继承空的`IApplicationService`接口定义你自己的方法. -* `IAsyncCrudAppService`有一些变体,你可以为每一个方法使用单个或者多个的DTO.(译者注:意思是类似EntityDto和UpdateEntityDto可以用同一个,也可以分别单独指定 -) +* 框架定义应用程序服务的接口不是必需的. 但是,它被建议作为最佳实践. +* `IAsyncCrudAppService`定义了常见的**CRUD**方法:`GetAsync`,`GetListAsync`,`CreateAsync`,`UpdateAsync`和`DeleteAsync`. 你可以从空的`IApplicationService`接口继承并手动定义自己的方法. +* `IAsyncCrudAppService`有一些变体, 你可以在每个方法中使用单独的DTO,也可以分别单独指定. #### BookAppService -创建 `BookAppService` 并实现 `IBookAppService`接口: +在`Acme.BookStore.Application`项目中实现名为`BookAppService`的`IBookAppService`: ````C# using System; @@ -243,23 +268,23 @@ namespace Acme.BookStore ```` * `BookAppService`继承了`AsyncCrudAppService<...>`.`AsyncCrudAppService<...>`实现了上面定义的CRUD方法. -* `BookAppService`注入了`IRepository`,`IRepository`是默认为`Book`创建的仓储.ABP会自动为每一个聚合根(或实体)创建仓储.参考[仓储文档](../../Repositories.md). -* `BookAppService`使用了 `IObjectMapper` 将`Book`转换成`BookDto`,将`CreateUpdateBookDto`转换成`Book`.启动模板中使用了[AutoMapper](http://automapper.org/)作为对象映射提供程序.你可以像上面那样使用`AutoMapFrom` 和 `AutoMapTo`定义映射.查看[AutoMapper集成文档](../../AutoMapper-Integration.md)获取更多信息. +* `BookAppService`注入`IRepository `,这是`Book`实体的默认仓储. ABP自动为每个聚合根(或实体)创建默认仓储. 请参阅[仓储文档](../../Repositories.md) +* `BookAppService`使用`IObjectMapper`将`Book`对象转换为`BookDto`对象, 将`CreateUpdateBookDto`对象转换为`Book`对象. 启动模板使用[AutoMapper](http://automapper.org/)库作为对象映射提供程序. 你之前定义了映射, 因此它将按预期工作. ### 自动生成API Controllers -你通常需要创建 **Controllers** 将应用服务暴露为 **HTTP API**.这样浏览器或第三方客户端可以通过AJAX的方式访问它们. - -ABP可以通过约定[**自动**](../../AspNetCore/Auto-API-Controllers.md)将应用服务转换成MVC API Controllers. +你通常创建**Controller**以将应用程序服务公开为**HTTP API**端点. 因此允许浏览器或第三方客户端通过AJAX调用它们. ABP可以[**自动**](../../AspNetCore/Auto-API-Controllers.md)按照惯例将你的应用程序服务配置为MVC API控制器. #### Swagger UI -启动模板使用了[Swashbuckle.AspNetCore](https://github.com/domaindrivendev/Swashbuckle.AspNetCore)库配置了[swagger UI](https://swagger.io/tools/swagger-ui/).运行程序并在浏览器中输入`http://localhost:53929/swagger/`. +启动模板配置为使用[Swashbuckle.AspNetCore](https://github.com/domaindrivendev/Swashbuckle.AspNetCore)运行[swagger UI](https://swagger.io/tools/swagger-ui/). 运行应用程序并在浏览器中输入`https://localhost:XXXX/swagger/`(用您自己的端口替换XXXX)作为URL. 你会看到一些内置的接口和`Book`的接口,它们都是REST风格的: ![bookstore-swagger](images/bookstore-swagger.png) +Swagger有一个很好的UI来测试API. 你可以尝试执行`[GET] /api/app/book` API来获取书籍列表. + ### 动态JavaScript代理 在Javascript端通过AJAX的方式调用HTTP API接口是很常见的,你可以使用`$.ajax`或这其他的工具来调用接口.当然,ABP中提供了更好的方式. @@ -270,6 +295,8 @@ ABP **自动** 为所有的API接口创建了JavaScript **代理**.因此,你可 你可以使用你钟爱的浏览器的 **开发者控制台** 中轻松测试JavaScript代理.运行程序,并打开浏览器的 **开发者工具**(快捷键:F12),切换到 **Console** 标签,输入下面的代码并回车: +你现在可以使用自己喜欢的浏览器的**开发者控制台**轻松测试JavaScript代理. 运行应用程序, 打开浏览器的**开发者工具**(快捷键:F12),切换到**Console**选项卡,输入以下代码并按回车键. + ````js acme.bookStore.book.getList({}).done(function (result) { console.log(result); }); ```` @@ -277,7 +304,7 @@ acme.bookStore.book.getList({}).done(function (result) { console.log(result); }) * `acme.bookStore`是`BookAppService`的命名空间,转换成了[驼峰命名](https://en.wikipedia.org/wiki/Camel_case). * `book`是`BookAppService`转换后的名字(去除了AppService后缀并转成了驼峰命名). * `getList`是定义在`AsyncCrudAppService`基类中的`GetListAsync`方法转换后的名字(去除了Async后缀并转成了驼峰命名). -* `{}`参数用来传递一个空的对象给`GetListAsync`方法.GetListAsync期望的参数是`PagedAndSortedResultRequestDto`类型的对象,`PagedAndSortedResultRequestDto`类型中定义了分页和排序选项. +* `{}`参数用于将空对象发送到`GetListAsync`方法,该方法通常需要一个类型为`PagedAndSortedResultRequestDto`的对象,用于向服务器发送分页和排序选项(所有属性都是可选的,所以你可以发送一个空对象). * `getList`方法返回了一个`promise`.因此,你可以传递一个回调函数到`done`(或者`then`)方法中来获取服务返回的结果. 运行这段代码会产生下面的输出: @@ -300,7 +327,7 @@ acme.bookStore.book.create({ name: 'Foundation', type: 7, publishDate: '1951-05- successfully created the book with id: f3f03580-c1aa-d6a9-072d-39e75c69f5c7 ```` -检查数据库表`books`中的数据,你会发现多了一行新数据,你也可以尝试`get`, `update` 和 `delete`方法. +检查数据库中的`Books`表以查看新书. 你可以自己尝试`get`,`update`和`delete`功能. ### 创建书籍页面 @@ -309,20 +336,21 @@ successfully created the book with id: f3f03580-c1aa-d6a9-072d-39e75c69f5c7 在 `Acme.BookStore.Web`项目的`Pages`文件夹下创建一个新的文件夹叫`Books`并添加一个名为`Index.cshtml`的Razor Page. -![bookstore-add-index-page](images/bookstore-add-index-page.png) +![bookstore-add-index-page](images/bookstore-add-index-page-v2.png) 打开`Index.cshtml`并把内容修改成下面这样: ````html @page -@using Acme.BookStore.Pages.Books -@inherits Acme.BookStore.Pages.BookStorePageBase +@using Acme.BookStore.Web.Pages.Books +@inherits Acme.BookStore.Web.Pages.BookStorePageBase @model IndexModel

Books

```` -* 修改Razor View Page Model的默认继承,使页面 **继承** 自`BookStorePageBase`类(代替`PageModel`).`BookStorePageBase`类来自于启动模板,它提供了一些公开的可以被所有的页面使用的属性/方法. +* 此代码更改了Razor View Page Model的默认继承,因此它从`BookStorePageBase`类(而不是`PageModel`)继承.启动模板附带的`BookStorePageBase`类,提供所有页面使用的一些共享属性/方法. +* 确保`IndexModel`(Index.cshtml.cs)具有`Acme.BookStore.Pages.Books`命名空间,或者在`Index.cshtml`中更新它. #### 将Books页面添加到主菜单 @@ -337,17 +365,16 @@ context.Menu.AddItem( #### 本地化菜单 -本地化的文本在`Acme.BookStore.Domain`项目的`Localization/BookStore`文件夹中. +本地化文本位于`Acme.BookStore.Domain.Shared`项目的`Localization/BookStore`文件夹下: -![bookstore-localization-files](images/bookstore-localization-files.png) +![bookstore-localization-files](images/bookstore-localization-files-v2.png) -打开`en.json`文件,为`Menu:BookStore` 和 `Menu:Books`添加本地化文本: +打开`en.json`文件,将`Menu:BookStore`和`Menu:Books`键的本地化文本添加到文件末尾: ````json { "culture": "en", "texts": { - //... "Menu:BookStore": "Book Store", "Menu:Books": "Books" } @@ -355,9 +382,9 @@ context.Menu.AddItem( ```` * ABP的本地化功能建立在[ASP.NET Core's standard localization]((https://docs.microsoft.com/en-us/aspnet/core/fundamentals/localization))之上并增加了一些扩展.查看[本地化文档](../../Localization.md). -* 本地化中key的名字是随便定义的,你可以随意命名.我们喜欢为菜单添加`Menu`命名空间,以区别于其他的文本.如果文本没有在本地化文件中定义,就会 **返回** 本地的化的key(ASP.NET Core的标准做法). +* 本地化key是任意的. 你可以设置任何名称. 我们更喜欢为菜单项添加`Menu:`前缀以区别于其他文本. 如果未在本地化文件中定义文本,则它将**返回**到本地化的key(ASP.NET Core的标准行为). -运行程序就会看到菜单已经添加到了顶部: +运行该应用程序,看到新菜单项已添加到顶部栏: ![bookstore-menu-items](images/bookstore-menu-items.png) @@ -365,17 +392,16 @@ context.Menu.AddItem( #### 书籍列表 -我们会在页面上使用JQuery插件[Datatables.net](https://datatables.net/)来展示列表.Datatables可以完全通过AJAX工作,所以它很快而且有良好的用户体验.启动模板中已经配置好了Datatables插件,因此你可以在你的页面中直接使用,不需要引用样式和脚本文件. +我们将使用[Datatables.net](https://datatables.net/)JQuery插件来显示页面上的表格列表. 数据表可以完全通过AJAX工作,速度快,并提供良好的用户体验. Datatables插件在启动模板中配置,因此你可以直接在任何页面中使用它,而需要在页面中引用样式和脚本文件. -##### 修改Index.cshtml +##### Index.cshtml 将`Pages/Books/Index.cshtml`改成下面的样子: ````html @page -@using Acme.BookStore.Pages.Books -@inherits Acme.BookStore.Pages.BookStorePageBase -@model IndexModel +@inherits Acme.BookStore.Web.Pages.BookStorePageBase +@model Acme.BookStore.Web.Pages.Books.IndexModel @section scripts { @@ -408,7 +434,7 @@ context.Menu.AddItem( 在`Pages/Books/`文件夹中创建 `index.js`文件 -![bookstore-index-js-file](images/bookstore-index-js-file.png) +![bookstore-index-js-file](images/bookstore-index-js-file-v2.png) `index.js`的内容如下: @@ -430,7 +456,7 @@ $(function () { * `abp.libs.datatables.createAjax`是帮助ABP的动态JavaScript API代理跟Datatable的格式相适应的辅助方法. * `abp.libs.datatables.normalizeConfiguration`是另一个辅助方法.不是必须的, 但是它通过为缺少的选项提供常规值来简化数据表配置. * `acme.bookStore.book.getList`是获取书籍列表的方法(上面已经介绍过了) -* 查看 [Datatable's 文档](https://datatables.net/manual/) 了解更多配置项. +* 查看 [Datatable文档](https://datatables.net/manual/) 了解更多配置项. 最终的页面如下: diff --git a/docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-II.md b/docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-II.md index 9e54ac7a2f..d462851f71 100644 --- a/docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-II.md +++ b/docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-II.md @@ -2,13 +2,13 @@ ### 关于本教程 -这是本教程所有章节中的第二章.下面是所有的章节: +这是ASP.NET Core MVC教程系列的第二章. 查看其它章节 * [Part I: 创建项目和书籍列表页面](Part-I.md) * **Part II: 创建,编辑,删除书籍(本章)** * [Part III: 集成测试](Part-III.md) -你可以从 [这里](https://github.com/volosoft/abp/tree/master/samples/BookStore) 下载本程序的**源码**. +你可以从[GitHub存储库](https://github.com/volosoft/abp/tree/master/samples/BookStore)访问应用程序的**源代码**. ### 新增 Book 实体 @@ -20,7 +20,7 @@ 在 `Acme.BookStore.Web` 项目的 `Pages/Books` 目录下新建一个 `CreateModal.cshtml` Razor页面: -![bookstore-add-create-dialog](images/bookstore-add-create-dialog.png) +![bookstore-add-create-dialog](images/bookstore-add-create-dialog-v2.png) ##### CreateModal.cshtml.cs @@ -30,7 +30,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; -namespace Acme.BookStore.Pages.Books +namespace Acme.BookStore.Web.Pages.Books { public class CreateModalModel : BookStorePageModelBase { @@ -63,9 +63,9 @@ namespace Acme.BookStore.Pages.Books ````html @page -@inherits Acme.BookStore.Pages.BookStorePageBase +@inherits Acme.BookStore.Web.Pages.BookStorePageBase @using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal -@model Acme.BookStore.Pages.Books.CreateModalModel +@model Acme.BookStore.Web.Pages.Books.CreateModalModel @{ Layout = null; } @@ -138,12 +138,12 @@ $('#NewBookButton').click(function (e) { 展开 `EditModal.cshtml`,打开 `EditModal.cshtml.cs` 文件( `EditModalModel` 类) 并替换成以下代码: -````C# +````csharp using System; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; -namespace Acme.BookStore.Pages.Books +namespace Acme.BookStore.Web.Pages.Books { public class EditModalModel : BookStorePageModelBase { @@ -180,38 +180,26 @@ namespace Acme.BookStore.Pages.Books * 在 `OnGetAsync` 方法中,将 `BookAppService.GetAsync` 方法返回的 `BookDto` 映射成 `CreateUpdateBookDto` 并赋值给Book属性. * `OnPostAsync` 方法直接使用 `BookAppService.UpdateAsync` 来更新实体. -#### CreateUpdateBookDto +#### BookDto到CreateUpdateBookDto对象映射 -为了执行从 `BookDto` 到 `CreateUpdateBookDto` 的对象映射, 按如下所示修改 `CreateUpdateBookDto`类: +为了执行`BookDto`到`CreateUpdateBookDto`对象映射,请打开`Acme.BookStore.Web`项目中的`BookStoreWebAutoMapperProfile.cs`并更改它,如下所示: -````C# -using System; -using System.ComponentModel.DataAnnotations; -using Volo.Abp.AutoMapper; +````csharp +using AutoMapper; -namespace Acme.BookStore +namespace Acme.BookStore.Web { - [AutoMapTo(typeof(Book))] - [AutoMapFrom(typeof(BookDto))] - public class CreateUpdateBookDto + public class BookStoreWebAutoMapperProfile : Profile { - [Required] - [StringLength(128)] - public string Name { get; set; } - - [Required] - public BookType Type { get; set; } = BookType.Undefined; - - [Required] - public DateTime PublishDate { get; set; } - - [Required] - public float Price { get; set; } + public BookStoreWebAutoMapperProfile() + { + CreateMap(); + } } } ```` -* 仅添加 `[AutoMapFrom(typeof(BookDto))]` 特性就可以创建上述映射关系. +* 刚刚添加了`CreateMap();`作为映射定义. #### EditModal.cshtml @@ -219,8 +207,8 @@ namespace Acme.BookStore ````html @page -@inherits Acme.BookStore.Pages.BookStorePageBase -@using Acme.BookStore.Pages.Books +@inherits Acme.BookStore.Web.Pages.BookStorePageBase +@using Acme.BookStore.Web.Pages.Books @using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal @model EditModalModel @{ @@ -231,7 +219,7 @@ namespace Acme.BookStore - + @@ -240,8 +228,8 @@ namespace Acme.BookStore 这个页面内容和 `CreateModal.cshtml` 非常相似,除了以下几点: -* 此页面包含了一个 `abp-input` 以保存所编辑book实体的 `Id` 属性值. -* 此页面指定的post地址是 `Books/EditModal` ,并用文本 *Update* 作为 modal 标题. +* 它包含`id`属性的`abp-input`, 用于存储编辑书的id(它是隐藏的Input) +* 此页面指定的post地址是`Books/EditModal`, 并用文本 *Update* 作为 modal 标题. #### 为表格添加 "操作(Actions)" 下拉菜单 @@ -420,6 +408,12 @@ $(function () { }); ```` +打开`Acme.BookStore.Domain.Shared`项目中的`en.json`并添加以下行: + +````json +"BookDeletionConfirmationMessage": "Are you sure to delete the book {0}?" +```` + 运行程序并尝试删除一个book实体. ### 下一章 diff --git a/docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-III.md b/docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-III.md index 80c28acc91..c31f750832 100644 --- a/docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-III.md +++ b/docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-III.md @@ -2,23 +2,21 @@ ### 关于本教程 -这是本教程所有章节中的第三章.下面是所有的章节: +这是ASP.NET Core MVC教程系列的第三章. 查看其它章节 - [Part I: 创建项目和书籍列表页面](Part-I.md) - [Part II: 创建,编辑,删除书籍](Part-II.md) - **Part III: 集成测试(本章)** -你可以从 [这里](https://github.com/volosoft/abp/tree/master/samples/BookStore) 下载本程序的**源码**. +你可以从[GitHub存储库](https://github.com/volosoft/abp/tree/master/samples/BookStore)访问应用程序的**源代码**. ### 解决方案中的测试项目 -本解决方案中有两个测试项目: +解决方案中有多个测试项目: +![bookstore-test-projects-v2](images/bookstore-test-projects-v2.png) -* `Acme.BookStore.Application.Tests` 项目用于单元测试和集成测试.你可以在这个项目中为Application Service方法写测试代码.这个项目使用了 **EF Core SQLite in-memory** 数据库. -* `Acme.BookStore.Web.Tests` 项目用于包含Web层的完整集成测试.所以,你也可以在这里写关于UI页面的测试. - -测试项目使用了以下库: +每个项目用于测试相关的应用程序项目.测试项目使用以下库进行测试: * [xunit](https://xunit.github.io/) 作为主测试框架. * [Shoudly](http://shouldly.readthedocs.io/en/latest/) 作为断言库. @@ -26,79 +24,39 @@ ### 添加测试用数据 -起始模板在 `Acme.BookStore.Application.Tests` 项目中包含了 `BookStoreTestDataBuilder` 类,用于创建一些测试用数据. 相关代码如下所示: - -````C# -using System.Threading.Tasks; -using Volo.Abp.DependencyInjection; -using Volo.Abp.Identity; -using Volo.Abp.Threading; - -namespace Acme.BookStore -{ - public class BookStoreTestDataBuilder : ITransientDependency - { - private readonly IIdentityDataSeeder _identityDataSeeder; - - public BookStoreTestDataBuilder(IIdentityDataSeeder identityDataSeeder) - { - _identityDataSeeder = identityDataSeeder; - } - - public void Build() - { - AsyncHelper.RunSync(BuildInternalAsync); - } - - public async Task BuildInternalAsync() - { - await _identityDataSeeder.SeedAsync("1q2w3E*"); - } - } -} -```` - -* 这里直接使用了identity模块实现的 `IIdentityDataSeeder` 接口,创建了一个admin角色和admin用户.你可以在测试代码中使用它们. -* 你可以在 `BuildInternalAsync` 方法中添加你自己的测试数据. - -按下方所示修改 `BookStoreTestDataBuilder` 类: +启动模板包含`Acme.BookStore.TestBase`项目中的`BookStoreTestDataSeedContributor`类,它创建一些数据来运行测试. +更改`BookStoreTestDataSeedContributor`类如下所示: ````C# using System; using System.Threading.Tasks; +using Volo.Abp.Data; using Volo.Abp.DependencyInjection; using Volo.Abp.Domain.Repositories; -using Volo.Abp.Identity; -using Volo.Abp.Threading; +using Volo.Abp.Guids; namespace Acme.BookStore { - public class BookStoreTestDataBuilder : ITransientDependency + public class BookStoreTestDataSeedContributor + : IDataSeedContributor, ITransientDependency { - private readonly IIdentityDataSeeder _identityDataSeeder; private readonly IRepository _bookRepository; + private readonly IGuidGenerator _guidGenerator; - public BookStoreTestDataBuilder( - IIdentityDataSeeder identityDataSeeder, - IRepository bookRepository) + public BookStoreTestDataSeedContributor( + IRepository bookRepository, + IGuidGenerator guidGenerator) { - _identityDataSeeder = identityDataSeeder; _bookRepository = bookRepository; + _guidGenerator = guidGenerator; } - public void Build() + public async Task SeedAsync(DataSeedContext context) { - AsyncHelper.RunSync(BuildInternalAsync); - } - - public async Task BuildInternalAsync() - { - await _identityDataSeeder.SeedAsync("1q2w3E*"); - await _bookRepository.InsertAsync( new Book { - Id = Guid.NewGuid(), + Id = _guidGenerator.Create(), Name = "Test book 1", Type = BookType.Fantastic, PublishDate = new DateTime(2015, 05, 24), @@ -109,7 +67,7 @@ namespace Acme.BookStore await _bookRepository.InsertAsync( new Book { - Id = Guid.NewGuid(), + Id = _guidGenerator.Create(), Name = "Test book 2", Type = BookType.Science, PublishDate = new DateTime(2014, 02, 11), @@ -121,7 +79,8 @@ namespace Acme.BookStore } ```` -* 通过构造函数注入 `IRepository`,在 `BuildInternalAsync` 方法中用它创建两个book实体. +* 注入`IRepository`并在`SeedAsync`中使用它来创建两个书实体作为测试数据. +* 使用`IGuidGenerator`服务创建GUID. 虽然`Guid.NewGuid()`非常适合测试,但`IGuidGenerator`在使用真实数据库时还有其他特别重要的功能(参见[Guid生成文档](../../Guid-Generation.md)了解更多信息). ### 测试 BookAppService @@ -211,6 +170,8 @@ public async Task Should_Not_Create_A_Book_Without_Name() * 由于 `Name` 是空值, ABP 抛出一个 `AbpValidationException` 异常. -### 测试 Web 页面 +打开**测试资源管理器**(测试 -> Windows -> 测试资源管理器)并**执行**所有测试: + +![bookstore-appservice-tests](images/bookstore-appservice-tests.png) -TODO +恭喜, 绿色图标表示测试已成功通过! diff --git a/docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-add-create-dialog-v2.png b/docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-add-create-dialog-v2.png new file mode 100644 index 0000000000..fcadfd7a82 Binary files /dev/null and b/docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-add-create-dialog-v2.png differ diff --git a/docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-add-create-dialog.png b/docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-add-create-dialog.png deleted file mode 100644 index 44398e6b4c..0000000000 Binary files a/docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-add-create-dialog.png and /dev/null differ diff --git a/docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-add-index-page-v2.png b/docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-add-index-page-v2.png new file mode 100644 index 0000000000..2606bbab32 Binary files /dev/null and b/docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-add-index-page-v2.png differ diff --git a/docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-add-index-page.png b/docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-add-index-page.png deleted file mode 100644 index 2452ca546e..0000000000 Binary files a/docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-add-index-page.png and /dev/null differ diff --git a/docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-appservice-tests.png b/docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-appservice-tests.png new file mode 100644 index 0000000000..942d2832a6 Binary files /dev/null and b/docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-appservice-tests.png differ diff --git a/docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-index-js-file-v2.png b/docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-index-js-file-v2.png new file mode 100644 index 0000000000..1ba9a48600 Binary files /dev/null and b/docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-index-js-file-v2.png differ diff --git a/docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-index-js-file.png b/docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-index-js-file.png deleted file mode 100644 index e36c5dfff7..0000000000 Binary files a/docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-index-js-file.png and /dev/null differ diff --git a/docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-localization-files-v2.png b/docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-localization-files-v2.png new file mode 100644 index 0000000000..79314dd2dc Binary files /dev/null and b/docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-localization-files-v2.png differ diff --git a/docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-localization-files.png b/docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-localization-files.png deleted file mode 100644 index ca1da1c7ec..0000000000 Binary files a/docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-localization-files.png and /dev/null differ diff --git a/docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-test-projects-v2.png b/docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-test-projects-v2.png new file mode 100644 index 0000000000..8701164d75 Binary files /dev/null and b/docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-test-projects-v2.png differ diff --git a/docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-test-projects.png b/docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-test-projects.png deleted file mode 100644 index f9511d7b11..0000000000 Binary files a/docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-test-projects.png and /dev/null differ diff --git a/docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-visual-studio-solution-v2.png b/docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-visual-studio-solution-v2.png deleted file mode 100644 index 48b5881e96..0000000000 Binary files a/docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-visual-studio-solution-v2.png and /dev/null differ diff --git a/docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-visual-studio-solution-v3.png b/docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-visual-studio-solution-v3.png new file mode 100644 index 0000000000..307e3516a5 Binary files /dev/null and b/docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-visual-studio-solution-v3.png differ diff --git a/docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-visual-studio-solution.png b/docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-visual-studio-solution.png deleted file mode 100644 index b47636cd68..0000000000 Binary files a/docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-visual-studio-solution.png and /dev/null differ diff --git a/docs/zh-Hans/Value-Objects.md b/docs/zh-Hans/Value-Objects.md new file mode 100644 index 0000000000..6735074fd4 --- /dev/null +++ b/docs/zh-Hans/Value-Objects.md @@ -0,0 +1,3 @@ +## Value Objects + + TODO \ No newline at end of file diff --git a/docs/zh-Hans/docs-nav.json b/docs/zh-Hans/docs-nav.json index 8e88cf6921..c20bd028a6 100644 --- a/docs/zh-Hans/docs-nav.json +++ b/docs/zh-Hans/docs-nav.json @@ -41,6 +41,10 @@ } ] }, + { + "text": "CLI", + "path": "CLI.md" + }, { "text": "基础知识", "items": [ diff --git a/docs/zh-Hans/images/bookstore-user-management-v2.png b/docs/zh-Hans/images/bookstore-user-management-v2.png new file mode 100644 index 0000000000..dd95740754 Binary files /dev/null and b/docs/zh-Hans/images/bookstore-user-management-v2.png differ diff --git a/docs/zh-Hans/images/bookstore-user-management.png b/docs/zh-Hans/images/bookstore-user-management.png deleted file mode 100644 index bc3c176557..0000000000 Binary files a/docs/zh-Hans/images/bookstore-user-management.png and /dev/null differ diff --git a/docs/zh-Hans/images/bookstore-visual-studio-solution-tiered.png b/docs/zh-Hans/images/bookstore-visual-studio-solution-tiered.png new file mode 100644 index 0000000000..19662bf731 Binary files /dev/null and b/docs/zh-Hans/images/bookstore-visual-studio-solution-tiered.png differ diff --git a/docs/zh-Hans/images/bookstore-visual-studio-solution-v2.png b/docs/zh-Hans/images/bookstore-visual-studio-solution-v2.png deleted file mode 100644 index 48b5881e96..0000000000 Binary files a/docs/zh-Hans/images/bookstore-visual-studio-solution-v2.png and /dev/null differ diff --git a/docs/zh-Hans/images/bookstore-visual-studio-solution-v3.png b/docs/zh-Hans/images/bookstore-visual-studio-solution-v3.png new file mode 100644 index 0000000000..307e3516a5 Binary files /dev/null and b/docs/zh-Hans/images/bookstore-visual-studio-solution-v3.png differ diff --git a/docs/zh-Hans/images/bookstore-visual-studio-solution.png b/docs/zh-Hans/images/bookstore-visual-studio-solution.png deleted file mode 100644 index b47636cd68..0000000000 Binary files a/docs/zh-Hans/images/bookstore-visual-studio-solution.png and /dev/null differ diff --git a/docs/zh-Hans/images/db-migrator-app.png b/docs/zh-Hans/images/db-migrator-app.png new file mode 100644 index 0000000000..ace6abb226 Binary files /dev/null and b/docs/zh-Hans/images/db-migrator-app.png differ diff --git a/docs/zh-Hans/images/disable-package-restore-visual-studio.png b/docs/zh-Hans/images/disable-package-restore-visual-studio.png deleted file mode 100644 index 5d2343dc3f..0000000000 Binary files a/docs/zh-Hans/images/disable-package-restore-visual-studio.png and /dev/null differ diff --git a/docs/zh-Hans/images/layered-project-dependencies.png b/docs/zh-Hans/images/layered-project-dependencies.png new file mode 100644 index 0000000000..c5fd1b3504 Binary files /dev/null and b/docs/zh-Hans/images/layered-project-dependencies.png differ diff --git a/docs/zh-Hans/images/tiered-solution-applications.png b/docs/zh-Hans/images/tiered-solution-applications.png new file mode 100644 index 0000000000..fb6ede7ac5 Binary files /dev/null and b/docs/zh-Hans/images/tiered-solution-applications.png differ diff --git a/docs/zh-Hans/images/tiered-solution-servers.png b/docs/zh-Hans/images/tiered-solution-servers.png new file mode 100644 index 0000000000..3c999b4b45 Binary files /dev/null and b/docs/zh-Hans/images/tiered-solution-servers.png differ diff --git a/framework/Volo.Abp.sln b/framework/Volo.Abp.sln index 3d0beab360..42e4b28516 100644 --- a/framework/Volo.Abp.sln +++ b/framework/Volo.Abp.sln @@ -1,6 +1,6 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.28307.168 +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.28922.388 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}" EndProject @@ -238,6 +238,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore.Mvc.UI. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore.Mvc.UI.Dashboards", "src\Volo.Abp.AspNetCore.Mvc.UI.Dashboards\Volo.Abp.AspNetCore.Mvc.UI.Dashboards.csproj", "{054D766D-5992-460E-A4D8-936D80BE2C1A}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Ldap", "src\Volo.Abp.Ldap\Volo.Abp.Ldap.csproj", "{4DADBBD2-4C63-4C90-9661-EBF6252A7D6F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Ldap.Tests", "test\Volo.Abp.Ldap.Tests\Volo.Abp.Ldap.Tests.csproj", "{38FB8F75-426E-4265-8D0E-E121837B6FCC}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -708,6 +712,14 @@ Global {054D766D-5992-460E-A4D8-936D80BE2C1A}.Debug|Any CPU.Build.0 = Debug|Any CPU {054D766D-5992-460E-A4D8-936D80BE2C1A}.Release|Any CPU.ActiveCfg = Release|Any CPU {054D766D-5992-460E-A4D8-936D80BE2C1A}.Release|Any CPU.Build.0 = Release|Any CPU + {4DADBBD2-4C63-4C90-9661-EBF6252A7D6F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4DADBBD2-4C63-4C90-9661-EBF6252A7D6F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4DADBBD2-4C63-4C90-9661-EBF6252A7D6F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4DADBBD2-4C63-4C90-9661-EBF6252A7D6F}.Release|Any CPU.Build.0 = Release|Any CPU + {38FB8F75-426E-4265-8D0E-E121837B6FCC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {38FB8F75-426E-4265-8D0E-E121837B6FCC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {38FB8F75-426E-4265-8D0E-E121837B6FCC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {38FB8F75-426E-4265-8D0E-E121837B6FCC}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -829,6 +841,8 @@ Global {F006B0B4-F25D-4511-9FB3-F17AA44BDCEA} = {447C8A77-E5F0-4538-8687-7383196D04EA} {EE1AAB08-3FBD-487F-B0B4-BEBA4B69528A} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {054D766D-5992-460E-A4D8-936D80BE2C1A} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} + {4DADBBD2-4C63-4C90-9661-EBF6252A7D6F} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} + {38FB8F75-426E-4265-8D0E-E121837B6FCC} = {447C8A77-E5F0-4538-8687-7383196D04EA} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs index 46ac3a8e90..d0b1a494ae 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs @@ -197,13 +197,12 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form selectItems.Add(new SelectListItem()); } - selectItems.AddRange(enumType.GetTypeInfo().GetMembers(BindingFlags.Public | BindingFlags.Static) - .Select((t, i) => - new SelectListItem - { - Value = ((int) Enum.Parse(enumType, t.Name)).ToString(), - Text = GetLocalizedPropertyName(localizer, enumType, t.Name) - }).ToList()); + selectItems.AddRange(enumType.GetEnumNames() + .Select(enumName => new SelectListItem + { + Value = Convert.ToUInt64(Enum.Parse(enumType, enumName)).ToString(), + Text = GetLocalizedPropertyName(localizer, enumType, enumName) + })); return selectItems; } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/cs.json b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/cs.json new file mode 100644 index 0000000000..7151dc73f3 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/cs.json @@ -0,0 +1,11 @@ +{ + "culture": "cs", + "texts": { + "GivenTenantIsNotAvailable": "Zvolený tenant není dostupný: {0}", + "Tenant": "Tenant", + "Switch": "změnit", + "Name": "Název", + "SwitchTenantHint": "Nechte pole prázdné ke změně na hostitele.", + "NotSelected": "Nevybrán" + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/pl.json b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/pl.json new file mode 100644 index 0000000000..8509b7d02b --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/pl.json @@ -0,0 +1,11 @@ +{ + "culture": "pl", + "texts": { + "GivenTenantIsNotAvailable": "Podany tenant jest niedostępny: {0}", + "Tenant": "Tenant", + "Switch": "zmień", + "Name": "Nazwa", + "SwitchTenantHint": "Pozostaw pole nazwy puste, aby przełączyć się na stronę hosta.", + "NotSelected": "Nie wybrano" + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/vi.json b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/vi.json new file mode 100644 index 0000000000..975e1b4590 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/vi.json @@ -0,0 +1,11 @@ +{ + "culture": "vi", + "texts": { + "GivenTenantIsNotAvailable": "Người thuê không có sẵn: {0}", + "Tenant": "Người thuê", + "Switch": "Chuyển đổi", + "Name": "Tên", + "SwitchTenantHint": "Để trống trường tên để chuyển sang phía máy chủ.", + "NotSelected": "Không được chọn" + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/FreezeUi/FreezeUiScriptContributor.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/FreezeUi/FreezeUiScriptContributor.cs new file mode 100644 index 0000000000..ffdd786250 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/FreezeUi/FreezeUiScriptContributor.cs @@ -0,0 +1,16 @@ +using System.Collections.Generic; +using Volo.Abp.AspNetCore.Mvc.UI.Bundling; +using Volo.Abp.AspNetCore.Mvc.UI.Packages.Core; +using Volo.Abp.Modularity; + +namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.FreezeUi +{ + [DependsOn(typeof(CoreScriptContributor))] + public class FreezeUiScriptContributor : BundleContributor + { + public override void ConfigureBundle(BundleConfigurationContext context) + { + context.Files.AddIfNotContains("/libs/freeze-ui/freeze-ui.min.css"); + } + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/FreezeUi/FreezeUiStyleContributor.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/FreezeUi/FreezeUiStyleContributor.cs new file mode 100644 index 0000000000..96f4996663 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/FreezeUi/FreezeUiStyleContributor.cs @@ -0,0 +1,16 @@ +using System.Collections.Generic; +using Volo.Abp.AspNetCore.Mvc.UI.Bundling; +using Volo.Abp.AspNetCore.Mvc.UI.Packages.Bootstrap; +using Volo.Abp.Modularity; + +namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.FreezeUi +{ + [DependsOn(typeof(BootstrapStyleContributor))] + public class FreezeUiStyleContributor : BundleContributor + { + public override void ConfigureBundle(BundleConfigurationContext context) + { + context.Files.AddIfNotContains("/libs/freeze-ui/freeze-ui.min.css"); + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalScriptContributor.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalScriptContributor.cs index 10354b37d0..8271c0e05a 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalScriptContributor.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalScriptContributor.cs @@ -3,6 +3,7 @@ using Volo.Abp.AspNetCore.Mvc.UI.Packages.Anchor; using Volo.Abp.AspNetCore.Mvc.UI.Packages.Bootstrap; using Volo.Abp.AspNetCore.Mvc.UI.Packages.Clipboard; using Volo.Abp.AspNetCore.Mvc.UI.Packages.DatatablesNetBs4; +using Volo.Abp.AspNetCore.Mvc.UI.Packages.FreezeUi; using Volo.Abp.AspNetCore.Mvc.UI.Packages.JQuery; using Volo.Abp.AspNetCore.Mvc.UI.Packages.JQueryForm; using Volo.Abp.AspNetCore.Mvc.UI.Packages.JQueryValidationUnobtrusive; @@ -27,7 +28,8 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Bundling typeof(DatatablesNetBs4ScriptContributor), typeof(SweetalertScriptContributor), typeof(ToastrScriptBundleContributor), - typeof(TimeagoScriptContributor))] + typeof(TimeagoScriptContributor), + typeof(FreezeUiScriptContributor))] public class SharedThemeGlobalScriptContributor : BundleContributor { public override void ConfigureBundle(BundleConfigurationContext context) @@ -40,7 +42,8 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Bundling "/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/modal-manager.js", "/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js", "/libs/abp/aspnetcore-mvc-ui-theme-shared/sweetalert/abp-sweetalert.js", - "/libs/abp/aspnetcore-mvc-ui-theme-shared/toastr/abp-toastr.js" + "/libs/abp/aspnetcore-mvc-ui-theme-shared/toastr/abp-toastr.js", + "/libs/abp/aspnetcore-mvc-ui-theme-shared/freeze-ui/abp-freeze-ui.js" }); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalStyleContributor.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalStyleContributor.cs index 3402b92e99..7fb8181373 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalStyleContributor.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalStyleContributor.cs @@ -2,6 +2,7 @@ using Volo.Abp.AspNetCore.Mvc.UI.Packages.Bootstrap; using Volo.Abp.AspNetCore.Mvc.UI.Packages.DatatablesNetBs4; using Volo.Abp.AspNetCore.Mvc.UI.Packages.FontAwesome; +using Volo.Abp.AspNetCore.Mvc.UI.Packages.FreezeUi; using Volo.Abp.AspNetCore.Mvc.UI.Packages.Select2; using Volo.Abp.AspNetCore.Mvc.UI.Packages.Toastr; using Volo.Abp.Modularity; @@ -13,7 +14,8 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Bundling typeof(FontAwesomeStyleContributor), typeof(ToastrStyleBundleContributor), typeof(Select2StyleContributor), - typeof(DatatablesNetBs4StyleContributor) + typeof(DatatablesNetBs4StyleContributor), + typeof(FreezeUiStyleContributor) )] public class SharedThemeGlobalStyleContributor : BundleContributor { diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/freeze-ui/abp-freeze-ui.js b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/freeze-ui/abp-freeze-ui.js new file mode 100644 index 0000000000..309765a482 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/freeze-ui/abp-freeze-ui.js @@ -0,0 +1,46 @@ +var abp = abp || {}; +(function ($) { + if (!window.FreezeUI || !$) { + return; + } + + /* MESSAGE **************************************************/ + /*Package from https://alexradulescu.github.io/freeze-ui/*/ + + abp.ui = abp.ui || {}; + + /* UI BLOCK */ + + abp.ui.block = function (elm) { + if (elm) { + window.FreezeUI({ selector: elm }); + } else { + window.FreezeUI(); + } + }; + + abp.ui.unblock = function () { + window.UnFreezeUI(); + }; + + /* UI BUSY */ + + abp.ui.setBusy = function (element, text, freezeDelay) { + var opt = { text : text ? text : ' ' }; + + if (element) { + opt.element = element; + } + + if (freezeDelay) { + opt.freezeDelay = freezeDelay; + } + + window.FreezeUI(opt); + }; + + abp.ui.clearBusy = function () { + window.UnFreezeUI(); + }; + +})(jQuery); \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/jquery/jquery-extensions.js b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/jquery/jquery-extensions.js index 3b177ea3d5..b3fa839d10 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/jquery/jquery-extensions.js +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/jquery/jquery-extensions.js @@ -63,14 +63,14 @@ }); }; - var toCamelCase = function(str) { + var toCamelCase = function (str) { var regexs = [ /(^[A-Z])/, // first char of string /((\.)[A-Z])/ // first char after a dot (.) ]; regexs.forEach( - function(regex) { + function (regex) { var infLoopAvoider = 0; while (regex.test(str)) { @@ -115,7 +115,19 @@ } data.map(function (x) { - obj[x.name] = x.value; + //TODO: improve mapping. it only supports one level deep object. + var names = x.name.split("."); + if (names.length === 1 && !obj[names[0]]) { + obj[names[0]] = x.value; + } + else if (names.length === 2) { + if (!obj[names[0]]) { + obj[names[0]] = {}; + } + if (!obj[names[0]][names[1]]) { + obj[names[0]][names[1]] = x.value; + } + } }); return obj; @@ -152,7 +164,7 @@ } }); - $(this).on('abp-ajax-success',function () { + $(this).on('abp-ajax-success', function () { formSaved = true; }); }; diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo.Abp.AspNetCore.Mvc.UI.csproj b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo.Abp.AspNetCore.Mvc.UI.csproj index 47ed3724bd..9911b60b5c 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo.Abp.AspNetCore.Mvc.UI.csproj +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo.Abp.AspNetCore.Mvc.UI.csproj @@ -11,7 +11,7 @@ - + diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpMvcJsonContractResolver.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpMvcJsonContractResolver.cs index 55174481a0..695212f563 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpMvcJsonContractResolver.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpMvcJsonContractResolver.cs @@ -12,9 +12,12 @@ namespace Volo.Abp.AspNetCore.Mvc.Json public class AbpMvcJsonContractResolver : DefaultContractResolver { private readonly Lazy _dateTimeConverter; + public AbpMvcJsonContractResolver(IServiceCollection services) { _dateTimeConverter = services.GetServiceLazy(); + + NamingStrategy = new CamelCaseNamingStrategy(); } protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) diff --git a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/AbpApplicationBuilderExtensions.cs b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/AbpApplicationBuilderExtensions.cs index 5f1c7ea4d8..25a9d38d06 100644 --- a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/AbpApplicationBuilderExtensions.cs +++ b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/AbpApplicationBuilderExtensions.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Globalization; using System.Linq; using JetBrains.Annotations; @@ -47,7 +48,7 @@ namespace Microsoft.AspNetCore.Builder .UseMiddleware(); } - public static IApplicationBuilder UseAbpRequestLocalization(this IApplicationBuilder app) + public static IApplicationBuilder UseAbpRequestLocalization(this IApplicationBuilder app, Action optionsAction = null) { IReadOnlyList languages; string defaultLanguage; @@ -61,28 +62,27 @@ namespace Microsoft.AspNetCore.Builder defaultLanguage = settingProvider.GetOrNull(LocalizationSettingNames.DefaultLanguage); } - if (!languages.Any()) - { - return app.UseRequestLocalization(); - } + var options = !languages.Any() + ? new RequestLocalizationOptions() + : new RequestLocalizationOptions + { + DefaultRequestCulture = DefaultGetRequestCulture(defaultLanguage, languages), + + SupportedCultures = languages + .Select(l => l.CultureName) + .Distinct() + .Select(c => new CultureInfo(c)) + .ToArray(), + + SupportedUICultures = languages + .Select(l => l.UiCultureName) + .Distinct() + .Select(c => new CultureInfo(c)) + .ToArray() + }; + + optionsAction?.Invoke(options); - var options = new RequestLocalizationOptions - { - DefaultRequestCulture = DefaultGetRequestCulture(defaultLanguage, languages), - - SupportedCultures = languages - .Select(l => l.CultureName) - .Distinct() - .Select(c => new CultureInfo(c)) - .ToArray(), - - SupportedUICultures = languages - .Select(l => l.UiCultureName) - .Distinct() - .Select(c => new CultureInfo(c)) - .ToArray() - }; - return app.UseRequestLocalization(options); } diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/VirtualFileSystem/AspNetCoreContentOptions.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/VirtualFileSystem/AspNetCoreContentOptions.cs index 73d189f1d3..c4265c7ced 100644 --- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/VirtualFileSystem/AspNetCoreContentOptions.cs +++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/VirtualFileSystem/AspNetCoreContentOptions.cs @@ -22,7 +22,11 @@ namespace Volo.Abp.AspNetCore.VirtualFileSystem ".css", ".png", ".jpg", - ".jpeg" + ".jpeg", + ".woff", + ".woff2", + ".tff", + ".otf" }; } } diff --git a/framework/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj b/framework/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj index 029669c348..2d003f1d48 100644 --- a/framework/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj +++ b/framework/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj @@ -18,7 +18,7 @@ - + \ No newline at end of file diff --git a/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs b/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs index 2e8c10bad0..0c31fa31ce 100644 --- a/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs +++ b/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs @@ -59,14 +59,14 @@ namespace Volo.Abp.AutoMapper //We should prevent duplicate mapping in an application, since Mapper is static. if (!_createdMappingsBefore) { + _createdMappingsBefore = true; + Mapper.Initialize(mapperConfigurationExpression => { ConfigureAll(new AbpAutoMapperConfigurationContext(mapperConfigurationExpression, scope.ServiceProvider)); }); ValidateAll(Mapper.Configuration); - - _createdMappingsBefore = true; } scope.ServiceProvider.GetRequiredService().Mapper = Mapper.Instance; diff --git a/framework/src/Volo.Abp.Cli.Core/Volo.Abp.Cli.Core.csproj b/framework/src/Volo.Abp.Cli.Core/Volo.Abp.Cli.Core.csproj index 708c296880..e181af68ac 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo.Abp.Cli.Core.csproj +++ b/framework/src/Volo.Abp.Cli.Core/Volo.Abp.Cli.Core.csproj @@ -17,7 +17,7 @@ - + diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs index c1894b2e6b..eb22185b73 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs @@ -22,6 +22,7 @@ namespace Volo.Abp.Cli { options.Commands["help"] = typeof(HelpCommand); options.Commands["new"] = typeof(NewCommand); + options.Commands["update"] = typeof(UpdateCommand); options.Commands["add-package"] = typeof(AddPackageCommand); options.Commands["add-module"] = typeof(AddModuleCommand); options.Commands["login"] = typeof(LoginCommand); diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddModuleCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddModuleCommand.cs index 7925b82aa6..a43a910340 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddModuleCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddModuleCommand.cs @@ -40,6 +40,37 @@ namespace Volo.Abp.Cli.Commands ); } + public Task GetUsageInfo() + { + var sb = new StringBuilder(); + + sb.AppendLine(""); + sb.AppendLine("'add-module' command is used to add a multi-package ABP module to a solution."); + sb.AppendLine("It should be used in a folder containing a .sln file."); + sb.AppendLine(""); + sb.AppendLine("Usage:"); + sb.AppendLine(" abp add-module [-s|--solution]"); + sb.AppendLine(""); + sb.AppendLine("Options:"); + sb.AppendLine(" -s|--solution Specify the solution file explicitly."); + sb.AppendLine(" --skip-db-migrations Specify if a new migration will be added or not."); + sb.AppendLine(""); + sb.AppendLine("Examples:"); + sb.AppendLine(" abp add-module Volo.Blogging Adds the module to the current soluton."); + sb.AppendLine(" abp add-module Volo.Blogging -s Acme.BookStore Adds the module to the given soluton."); + sb.AppendLine(" abp add-module Volo.Blogging -s Acme.BookStore --skip-db-migrations false Adds the module to the given soluton but doesn't create a database migration."); + sb.AppendLine(""); + + return Task.FromResult(sb.ToString()); + } + + public Task GetShortDescriptionAsync() + { + return Task.FromResult("Adds a multi-package module to a solution by finding all packages of the module, " + + "finding related projects in the solution and adding each package to the" + + " corresponding project in the solution."); + } + protected virtual string GetSolutionFile(CommandLineArgs commandLineArgs) { var providedSolutionFile = PathHelper.NormalizePath( @@ -80,30 +111,6 @@ namespace Volo.Abp.Cli.Commands throw new CliUsageException(sb.ToString()); } - protected virtual string GetUsageInfo() - { - var sb = new StringBuilder(); - - sb.AppendLine(""); - sb.AppendLine("'add-module' command is used to add a multi-package ABP module to a solution."); - sb.AppendLine("It should be used in a folder containing a .sln file."); - sb.AppendLine(""); - sb.AppendLine("Usage:"); - sb.AppendLine(" abp add-module [-s|--solution]"); - sb.AppendLine(""); - sb.AppendLine("Options:"); - sb.AppendLine(" -s|--solution Specify the solution file explicitly."); - sb.AppendLine(" --skip-db-migrations Specify if a new migration will be added or not."); - sb.AppendLine(""); - sb.AppendLine("Examples:"); - sb.AppendLine(" abp add-module Volo.Blogging Adds the module to the current soluton."); - sb.AppendLine(" abp add-module Volo.Blogging -s Acme.BookStore Adds the module to the given soluton."); - sb.AppendLine(" abp add-module Volo.Blogging -s Acme.BookStore --skip-db-migrations false Adds the module to the given soluton but doesn't add-migration."); - sb.AppendLine(""); - - return sb.ToString(); - } - public static class Options { public static class Solution diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddPackageCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddPackageCommand.cs index d657000b2d..24185d7c07 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddPackageCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddPackageCommand.cs @@ -36,6 +36,35 @@ namespace Volo.Abp.Cli.Commands ); } + public Task GetUsageInfo() + { + var sb = new StringBuilder(); + + sb.AppendLine(""); + sb.AppendLine("'add-package' command is used to add an ABP package to a project."); + sb.AppendLine("It should be used in a folder containing a .csproj file."); + sb.AppendLine(""); + sb.AppendLine("Usage:"); + sb.AppendLine(" abp add-package [-p|--project]"); + sb.AppendLine(""); + sb.AppendLine("Options:"); + sb.AppendLine(" -p|--project Specify the project file explicitly."); + sb.AppendLine(""); + sb.AppendLine("Examples:"); + sb.AppendLine(" abp add-package Volo.Abp.FluentValidation Adds the package to the current project."); + sb.AppendLine(" abp add-package Volo.Abp.FluentValidation -p Acme.BookStore.Application Adds the package to the given project."); + sb.AppendLine(""); + + return Task.FromResult(sb.ToString()); + } + + public Task GetShortDescriptionAsync() + { + return Task.FromResult("Adds a new ABP package to a project by adding related nuget package" + + " as a dependency to the project and adding [DependsOn(...)] attribute to" + + " the module class in the project."); + } + protected virtual string GetProjectFile(CommandLineArgs commandLineArgs) { var providedProjectFile = PathHelper.NormalizePath( @@ -76,27 +105,6 @@ namespace Volo.Abp.Cli.Commands throw new CliUsageException(sb.ToString()); } - protected virtual string GetUsageInfo() - { - var sb = new StringBuilder(); - - sb.AppendLine(""); - sb.AppendLine("'add-package' command is used to add an ABP package to a project."); - sb.AppendLine("It should be used in a folder containing a .csproj file."); - sb.AppendLine(""); - sb.AppendLine("Usage:"); - sb.AppendLine(" abp add-package [-p|--project]"); - sb.AppendLine(""); - sb.AppendLine("Options:"); - sb.AppendLine(" -p|--project Specify the project file explicitly."); - sb.AppendLine(""); - sb.AppendLine("Examples:"); - sb.AppendLine(" abp add-package Volo.Abp.FluentValidation Adds the package to the current project."); - sb.AppendLine(" abp add-package Volo.Abp.FluentValidation -p Acme.BookStore.Application Adds the package to the given project."); - sb.AppendLine(""); - - return sb.ToString(); - } public static class Options { diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/HelpCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/HelpCommand.cs index 671bf3cbab..fe574c2112 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/HelpCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/HelpCommand.cs @@ -1,6 +1,10 @@ -using System.Threading.Tasks; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; using Volo.Abp.Cli.Args; using Volo.Abp.DependencyInjection; @@ -9,21 +13,70 @@ namespace Volo.Abp.Cli.Commands public class HelpCommand : IConsoleCommand, ITransientDependency { public ILogger Logger { get; set; } + protected CliOptions CliOptions { get; } + protected IHybridServiceScopeFactory ServiceScopeFactory { get; } - public HelpCommand() + public HelpCommand(IOptions cliOptions, + IHybridServiceScopeFactory serviceScopeFactory) { + ServiceScopeFactory = serviceScopeFactory; Logger = NullLogger.Instance; + CliOptions = cliOptions.Value; } - public Task ExecuteAsync(CommandLineArgs commandLineArgs) + public async Task ExecuteAsync(CommandLineArgs commandLineArgs) { - Logger.LogInformation(""); - Logger.LogInformation("Usage:"); - Logger.LogInformation(""); - Logger.LogInformation(" abp [options]"); - Logger.LogInformation(""); + if (string.IsNullOrWhiteSpace(commandLineArgs.Target)) + { + Logger.LogInformation(await GetUsageInfo()); + return; + } - return Task.CompletedTask; + var commandType = CliOptions.Commands[commandLineArgs.Target]; + + using (var scope = ServiceScopeFactory.CreateScope()) + { + var command = (IConsoleCommand) scope.ServiceProvider.GetRequiredService(commandType); + Logger.LogInformation(await command.GetUsageInfo()); + } + } + + public async Task GetUsageInfo() + { + var sb = new StringBuilder(); + + sb.AppendLine(""); + sb.AppendLine("Usage:"); + sb.AppendLine(""); + sb.AppendLine(" abp [options]"); + sb.AppendLine(""); + sb.AppendLine("Command List:"); + + foreach (var command in CliOptions.Commands.ToArray()) + { + string shortDescription; + + using (var scope = ServiceScopeFactory.CreateScope()) + { + shortDescription = await ((IConsoleCommand)scope.ServiceProvider.GetRequiredService(command.Value)) + .GetShortDescriptionAsync(); + } + + sb.Append(" >"); + sb.Append(command.Key); + sb.Append(string.IsNullOrWhiteSpace(shortDescription) ? "":":"); + sb.Append(" "); + sb.AppendLine(shortDescription); + } + + sb.AppendLine(""); + + return sb.ToString(); + } + + public Task GetShortDescriptionAsync() + { + return Task.FromResult(""); } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/IConsoleCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/IConsoleCommand.cs index 2b1129aab2..b9fb34210b 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/IConsoleCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/IConsoleCommand.cs @@ -6,5 +6,9 @@ namespace Volo.Abp.Cli.Commands public interface IConsoleCommand { Task ExecuteAsync(CommandLineArgs commandLineArgs); + + Task GetUsageInfo(); + + Task GetShortDescriptionAsync(); } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LoginCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LoginCommand.cs index 28bc64afd5..52517b72fa 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LoginCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LoginCommand.cs @@ -1,6 +1,7 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using System; +using System.Text; using System.Threading.Tasks; using Volo.Abp.Cli.Args; using Volo.Abp.Cli.Auth; @@ -25,20 +26,14 @@ namespace Volo.Abp.Cli.Commands { if (commandLineArgs.Target.IsNullOrEmpty()) { - Logger.LogInformation(""); - Logger.LogWarning("Username is missing."); - LogHelp(); - return; + throw new CliUsageException("Username name is missing!" + Environment.NewLine + Environment.NewLine + GetUsageInfo()); } Console.Write("Password: "); var password = ConsoleHelper.ReadSecret(); if (password.IsNullOrWhiteSpace()) { - Logger.LogInformation(""); - Logger.LogWarning("Password is missing."); - LogHelp(); - return; + throw new CliUsageException("Password name is missing!" + Environment.NewLine + Environment.NewLine + GetUsageInfo()); } await AuthService.LoginAsync(commandLineArgs.Target, password); @@ -46,14 +41,23 @@ namespace Volo.Abp.Cli.Commands Logger.LogInformation($"Successfully logged in as '{commandLineArgs.Target}'"); } - private void LogHelp() + public Task GetUsageInfo() { - Logger.LogWarning(""); - Logger.LogWarning("Usage:"); - Logger.LogWarning(" abp login "); - Logger.LogWarning(""); - Logger.LogWarning("Example:"); - Logger.LogWarning(" abp login john"); + var sb = new StringBuilder(); + + sb.AppendLine(""); + sb.AppendLine("Usage:"); + sb.AppendLine(" abp login "); + sb.AppendLine(""); + sb.AppendLine("Example:"); + sb.AppendLine(" abp login john"); + + return Task.FromResult(sb.ToString()); + } + + public Task GetShortDescriptionAsync() + { + return Task.FromResult(""); } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LogoutCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LogoutCommand.cs index 342e52f529..22d30367e6 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LogoutCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LogoutCommand.cs @@ -23,5 +23,15 @@ namespace Volo.Abp.Cli.Commands { return AuthService.LogoutAsync(); } + + public Task GetUsageInfo() + { + return Task.FromResult(""); + } + + public Task GetShortDescriptionAsync() + { + return Task.FromResult(""); + } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs index 19865bdacf..44b5416e1e 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs @@ -1,4 +1,6 @@ +using System; using System.IO; +using System.Text; using System.Threading.Tasks; using Ionic.Zip; using Microsoft.Extensions.Logging; @@ -27,23 +29,7 @@ namespace Volo.Abp.Cli.Commands { if (commandLineArgs.Target == null) { - Logger.LogInformation(""); - Logger.LogWarning("Project name is missing."); - Logger.LogWarning(""); - Logger.LogWarning("Usage:"); - Logger.LogWarning(" abp new [-t|--template] [-d|--database-provider] [-o|--output-folder]"); - Logger.LogWarning(""); - Logger.LogWarning("Options:"); - Logger.LogWarning("-t|--template "); - Logger.LogWarning("-d|--database-provider "); - Logger.LogWarning("-o|--output-folder "); - Logger.LogWarning(""); - Logger.LogWarning("Examples:"); - Logger.LogWarning(" abp new Acme.BookStore"); - Logger.LogWarning(" abp new Acme.BookStore -t mvc-module"); - Logger.LogWarning(" abp new Acme.BookStore -t mvc -d mongodb"); - Logger.LogWarning(" abp new Acme.BookStore -t mvc -d mongodb -o d:\\project"); - return; + throw new CliUsageException("Project name is missing!" + Environment.NewLine + Environment.NewLine + GetUsageInfo()); } Logger.LogInformation("Creating a new project..."); @@ -85,6 +71,40 @@ namespace Volo.Abp.Cli.Commands Logger.LogInformation($"The output folder is: '{outputFolder}'"); } + public Task GetUsageInfo() + { + var sb = new StringBuilder(); + + sb.AppendLine(""); + sb.AppendLine("Usage:"); + sb.AppendLine(" abp new [-t|--template] [-d|--database-provider] [-o|--output-folder]"); + sb.AppendLine(""); + sb.AppendLine("Options:"); + sb.AppendLine("-t|--template "); + sb.AppendLine("-o|--output-folder "); + sb.AppendLine("-d|--database-provider (if supported by the template)"); + sb.AppendLine("--tiered (if supported by the template)"); + sb.AppendLine("--no-ui (if supported by the template)"); + sb.AppendLine(""); + sb.AppendLine("Some examples:"); + sb.AppendLine(" abp new Acme.BookStore"); + sb.AppendLine(" abp new Acme.BookStore --tiered"); + sb.AppendLine(" abp new Acme.BookStore -t mvc-module"); + sb.AppendLine(" abp new Acme.BookStore -t mvc-module no-ui"); + sb.AppendLine(" abp new Acme.BookStore -d mongodb"); + sb.AppendLine(" abp new Acme.BookStore -t mvc -d mongodb"); + sb.AppendLine(" abp new Acme.BookStore -t mvc -d mongodb -o d:\\project"); + sb.AppendLine(""); + sb.AppendLine("See the documentation for more info."); + + return Task.FromResult(sb.ToString()); + } + + public Task GetShortDescriptionAsync() + { + return Task.FromResult("Generates a new solution based on the ABP startup templates."); + } + protected virtual DatabaseProvider GetDatabaseProviderOrNull(CommandLineArgs commandLineArgs) { var optionValue = commandLineArgs.Options.GetOrNull(Options.DatabaseProvider.Short, Options.DatabaseProvider.Long); diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/UpdateCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/UpdateCommand.cs new file mode 100644 index 0000000000..df95839767 --- /dev/null +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/UpdateCommand.cs @@ -0,0 +1,93 @@ +using System; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Volo.Abp.Cli.Args; +using Volo.Abp.Cli.ProjectModification; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Cli.Commands +{ + public class UpdateCommand : IConsoleCommand, ITransientDependency + { + public ILogger Logger { get; set; } + + private readonly VoloPackagesVersionUpdater _packagesVersionUpdater; + + public UpdateCommand(VoloPackagesVersionUpdater packagesVersionUpdater) + { + _packagesVersionUpdater = packagesVersionUpdater; + + Logger = NullLogger.Instance; + } + + public async Task ExecuteAsync(CommandLineArgs commandLineArgs) + { + var includePreviews = commandLineArgs.Options.GetOrNull(Options.IncludePreviews.Short, Options.IncludePreviews.Long) != null; + + var solution = Directory.GetFiles(Directory.GetCurrentDirectory(), "*.sln").FirstOrDefault(); + + if (solution != null) + { + var solutionName = Path.GetFileName(solution).RemovePostFix(".sln"); + + _packagesVersionUpdater.UpdateSolution(solution, includePreviews); + + Logger.LogInformation($"Volo packages are updated in {solutionName} solution."); + return; + } + + var project = Directory.GetFiles(Directory.GetCurrentDirectory(), "*.csproj").FirstOrDefault(); + + if (project != null) + { + var projectName = Path.GetFileName(project).RemovePostFix(".csproj"); + + _packagesVersionUpdater.UpdateProject(project, includePreviews); + + Logger.LogInformation($"Volo packages are updated in {projectName} project."); + return; + } + + throw new CliUsageException("No solution or project found in this directory." + Environment.NewLine + Environment.NewLine + GetUsageInfo()); + } + + public Task GetUsageInfo() + { + var sb = new StringBuilder(); + + sb.AppendLine(""); + sb.AppendLine("Usage:"); + sb.AppendLine(" abp update [-p|--include-previews]"); + sb.AppendLine(""); + sb.AppendLine("Options:"); + sb.AppendLine("--include-previews (if supported by the template)"); + sb.AppendLine(""); + sb.AppendLine("Some examples:"); + sb.AppendLine(" abp update"); + sb.AppendLine(" abp update --include-previews"); + sb.AppendLine(""); + sb.AppendLine("See the documentation for more info."); + + return Task.FromResult(sb.ToString()); + } + + public Task GetShortDescriptionAsync() + { + return Task.FromResult("Automatically updates all ABP related packages in a" + + " solution or project to the latest versions."); + } + + public static class Options + { + public static class IncludePreviews + { + public const string Short = "p"; + public const string Long = "include-previews"; + } + } + } +} diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/RemoveProjectFromSolutionStep.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/RemoveProjectFromSolutionStep.cs index fe5057709d..325999cfc1 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/RemoveProjectFromSolutionStep.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/RemoveProjectFromSolutionStep.cs @@ -10,6 +10,8 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps private readonly string _solutionFilePath; private readonly string _projectFolderPath; + private string ProjectNameWithQuotes => $"\"{_projectName}\""; + public RemoveProjectFromSolutionStep( string projectName, string solutionFilePath = null, @@ -59,7 +61,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps { foreach (var solutionFileLine in solutionFileLines) { - if (solutionFileLine.Contains(_projectName)) + if (solutionFileLine.Contains(ProjectNameWithQuotes)) { var curlyBracketStartIndex = solutionFileLine.LastIndexOf("{", StringComparison.OrdinalIgnoreCase); var curlyBracketEndIndex = solutionFileLine.LastIndexOf("}", StringComparison.OrdinalIgnoreCase); diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateInfo.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateInfo.cs index 4041dc8d7a..3809646ecc 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateInfo.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateInfo.cs @@ -6,10 +6,14 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building { public abstract class TemplateInfo { + [NotNull] public string Name { get; } public DatabaseProvider DefaultDatabaseProvider { get; } + [CanBeNull] + public string DocumentUrl { get; set; } + protected TemplateInfo( [NotNull] string name, DatabaseProvider defaultDatabaseProvider = DatabaseProvider.NotSpecified) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/DownloadInfo.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/DownloadInfo.cs deleted file mode 100644 index e8f51f5958..0000000000 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/DownloadInfo.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; -using Volo.Abp.Cli.ProjectBuilding.Building; -using Volo.Abp.Domain.Entities.Auditing; - -namespace Volo.Abp.Cli.ProjectBuilding -{ - [Table("Downloads")] - public class DownloadInfo : CreationAuditedAggregateRoot - { - [Required] - [StringLength(128)] - public string ProjectName { get; set; } - - [Required] - [StringLength(42)] - public string TemplateName { get; set; } - - [Required] - public DatabaseProvider DatabaseProvider { get; set; } - - [Required] - [StringLength(20)] - public string Version { get; set; } - - public int CreationDuration { get; set; } - - public DownloadInfo(string projectName, string templateName, DatabaseProvider databaseProvider, string version, int creationDuration) - { - ProjectName = projectName; - TemplateName = templateName; - DatabaseProvider = databaseProvider; - Version = version; - CreationDuration = creationDuration; - } - } -} diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ProjectBuilder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ProjectBuilder.cs index 0b66ea375d..574dd32a3d 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ProjectBuilder.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ProjectBuilder.cs @@ -1,13 +1,16 @@ using System; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp.Cli.ProjectBuilding.Building; -using Volo.Abp.Cli.Utils; using Volo.Abp.DependencyInjection; namespace Volo.Abp.Cli.ProjectBuilding { public class ProjectBuilder : IProjectBuilder, ITransientDependency { + public ILogger Logger { get; set; } + protected ITemplateStore TemplateStore { get; } protected ITemplateInfoProvider TemplateInfoProvider { get; } @@ -15,6 +18,8 @@ namespace Volo.Abp.Cli.ProjectBuilding { TemplateStore = templateStore; TemplateInfoProvider = templateInfoProvider; + + Logger = NullLogger.Instance; } public async Task BuildAsync(ProjectBuildArgs args) @@ -45,6 +50,11 @@ namespace Volo.Abp.Cli.ProjectBuilding ProjectBuildPipelineBuilder.Build(context).Execute(context); + if (!templateInfo.DocumentUrl.IsNullOrEmpty()) + { + Logger.LogInformation("Check the documentation of this template: " + templateInfo.DocumentUrl); + } + return new ProjectBuildResult(context.Result.ZipContent, args.SolutionName.ProjectName); } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Mvc/MvcTemplate.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Mvc/MvcTemplate.cs index 069c5fbf03..5df8167fad 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Mvc/MvcTemplate.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Mvc/MvcTemplate.cs @@ -14,7 +14,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Templates.Mvc public MvcTemplate() : base(TemplateName, DatabaseProvider.EntityFrameworkCore) { - + DocumentUrl = "https://docs.abp.io/en/abp/latest/Startup-Templates/Mvc"; } public override IEnumerable GetCustomSteps(ProjectBuildContext context) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/MvcModule/MvcModuleTemplate.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/MvcModule/MvcModuleTemplate.cs index e3258ec8a6..e12f97a638 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/MvcModule/MvcModuleTemplate.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/MvcModule/MvcModuleTemplate.cs @@ -14,7 +14,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Templates.MvcModule public MvcModuleTemplate() : base(TemplateName) { - + DocumentUrl = "https://docs.abp.io/en/abp/latest/Startup-Templates/Mvc-Module"; } public override IEnumerable GetCustomSteps(ProjectBuildContext context) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/VoloPackagesVersionUpdater.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/VoloPackagesVersionUpdater.cs new file mode 100644 index 0000000000..8e0be8f1a1 --- /dev/null +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/VoloPackagesVersionUpdater.cs @@ -0,0 +1,87 @@ +using System; +using System.IO; +using System.Text; +using Volo.Abp.Cli.NuGet; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Cli.ProjectModification +{ + public class VoloPackagesVersionUpdater : ITransientDependency + { + private readonly NuGetService _nuGetService; + + public VoloPackagesVersionUpdater(NuGetService nuGetService) + { + _nuGetService = nuGetService; + } + + public void UpdateSolution(string solutionPath, bool includePreviews) + { + var projectPaths = ProjectFinder.GetProjectFiles(solutionPath); + + foreach (var filePath in projectPaths) + { + UpdateInternal(filePath, includePreviews); + } + } + + public void UpdateProject(string projectPath, bool includePreviews) + { + UpdateInternal(projectPath, includePreviews); + } + + protected virtual void UpdateInternal(string projectPath, bool includePreviews) + { + var fileContent = File.ReadAllText(projectPath); + + var content = new StringBuilder(); + var index = 0; + + while (index >= 0) + { + fileContent = fileContent.Substring(index); + content.Append(ReplaceAPackage(fileContent, includePreviews, out index)); + } + + File.WriteAllText(projectPath, content.ToString()); + } + + private string ReplaceAPackage(string content, bool includePreviews, out int index) + { + var packageReferenceStartText = "nclude=\"Volo."; + var returningText = new StringBuilder(); + + var indexOfPackageReference = content.IndexOf(packageReferenceStartText, StringComparison.Ordinal); + + if (indexOfPackageReference < 0) + { + index = -1; + return content; + } + + returningText.Append(content.Substring(0, indexOfPackageReference + packageReferenceStartText.Length)); + content = content.Substring(indexOfPackageReference + packageReferenceStartText.Length); + + var indexAfterQuote = content.IndexOf("\"", StringComparison.Ordinal) + 1; + + var packageId = "Volo." + content.Substring(indexAfterQuote - 1); + + returningText.Append(content.Substring(0, indexAfterQuote)); + content = content.Substring(indexAfterQuote); + + var indexAfterSecondQuote = content.IndexOf("\"", StringComparison.Ordinal) + 1; + + returningText.Append(content.Substring(0, indexAfterSecondQuote)); + content = content.Substring(indexAfterSecondQuote); + + var indexOfThirdQuote = content.IndexOf("\"", StringComparison.Ordinal); + + var version = _nuGetService.GetLatestVersionOrNullAsync(packageId, includePreviews); + returningText.Append(version); + + index = indexOfPackageReference + packageReferenceStartText.Length + indexAfterQuote + indexAfterSecondQuote + indexOfThirdQuote; + + return returningText.ToString(); + } + } +} diff --git a/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj b/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj index e5355a19c1..509a438e0f 100644 --- a/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj +++ b/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj @@ -14,7 +14,7 @@ - + diff --git a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AsyncCrudAppService.cs b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AsyncCrudAppService.cs index 151212925a..7bc76d9923 100644 --- a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AsyncCrudAppService.cs +++ b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AsyncCrudAppService.cs @@ -45,28 +45,46 @@ namespace Volo.Abp.Application.Services } public abstract class AsyncCrudAppService - : CrudAppServiceBase, - IAsyncCrudAppService + : AsyncCrudAppService + where TEntity : class, IEntity + where TEntityDto : IEntityDto + { + protected AsyncCrudAppService(IRepository repository) + : base(repository) + { + + } + + protected override TEntityDto MapToGetListOutputDto(TEntity entity) + { + return MapToGetOutputDto(entity); + } + } + + public abstract class AsyncCrudAppService + : CrudAppServiceBase, + IAsyncCrudAppService where TEntity : class, IEntity - where TEntityDto : IEntityDto + where TGetOutputDto : IEntityDto + where TGetListOutputDto : IEntityDto { public IAsyncQueryableExecuter AsyncQueryableExecuter { get; set; } protected AsyncCrudAppService(IRepository repository) - :base(repository) + : base(repository) { AsyncQueryableExecuter = DefaultAsyncQueryableExecuter.Instance; } - public virtual async Task GetAsync(TKey id) + public virtual async Task GetAsync(TKey id) { await CheckGetPolicyAsync(); var entity = await GetEntityByIdAsync(id); - return MapToEntityDto(entity); + return MapToGetOutputDto(entity); } - public virtual async Task> GetListAsync(TGetListInput input) + public virtual async Task> GetListAsync(TGetListInput input) { await CheckGetListPolicyAsync(); @@ -79,29 +97,29 @@ namespace Volo.Abp.Application.Services var entities = await AsyncQueryableExecuter.ToListAsync(query); - return new PagedResultDto( + return new PagedResultDto( totalCount, - entities.Select(MapToEntityDto).ToList() + entities.Select(MapToGetListOutputDto).ToList() ); } - public virtual async Task CreateAsync(TCreateInput input) + public virtual async Task CreateAsync(TCreateInput input) { await CheckCreatePolicyAsync(); var entity = MapToEntity(input); - - if(entity is IMultiTenant && !HasTenantIdProperty(entity)) + + if (entity is IMultiTenant && !HasTenantIdProperty(entity)) { TryToSetTenantId(entity); } - + await Repository.InsertAsync(entity, autoSave: true); - return MapToEntityDto(entity); + return MapToGetOutputDto(entity); } - public virtual async Task UpdateAsync(TKey id, TUpdateInput input) + public virtual async Task UpdateAsync(TKey id, TUpdateInput input) { await CheckUpdatePolicyAsync(); @@ -110,7 +128,7 @@ namespace Volo.Abp.Application.Services MapToEntity(input, entity); await Repository.UpdateAsync(entity, autoSave: true); - return MapToEntityDto(entity); + return MapToGetOutputDto(entity); } public virtual async Task DeleteAsync(TKey id) diff --git a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/CrudAppService.cs b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/CrudAppService.cs index 2595bc6edd..1d43ff084d 100644 --- a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/CrudAppService.cs +++ b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/CrudAppService.cs @@ -44,8 +44,7 @@ namespace Volo.Abp.Application.Services } public abstract class CrudAppService - : CrudAppServiceBase, - ICrudAppService + : CrudAppService where TEntity : class, IEntity where TEntityDto : IEntityDto { @@ -55,15 +54,34 @@ namespace Volo.Abp.Application.Services } - public virtual TEntityDto Get(TKey id) + protected override TEntityDto MapToGetListOutputDto(TEntity entity) + { + return MapToGetOutputDto(entity); + } + } + + public abstract class CrudAppService + : CrudAppServiceBase, + ICrudAppService + where TEntity : class, IEntity + where TGetOutputDto : IEntityDto + where TGetListOutputDto : IEntityDto + { + protected CrudAppService(IRepository repository) + : base(repository) + { + + } + + public virtual TGetOutputDto Get(TKey id) { CheckGetPolicy(); var entity = GetEntityById(id); - return MapToEntityDto(entity); + return MapToGetOutputDto(entity); } - public virtual PagedResultDto GetList(TGetListInput input) + public virtual PagedResultDto GetList(TGetListInput input) { CheckGetListPolicy(); @@ -76,29 +94,29 @@ namespace Volo.Abp.Application.Services var entities = query.ToList(); - return new PagedResultDto( + return new PagedResultDto( totalCount, - entities.Select(MapToEntityDto).ToList() + entities.Select(MapToGetListOutputDto).ToList() ); } - public virtual TEntityDto Create(TCreateInput input) + public virtual TGetOutputDto Create(TCreateInput input) { CheckCreatePolicy(); var entity = MapToEntity(input); - - if(entity is IMultiTenant && !HasTenantIdProperty(entity)) + + if (entity is IMultiTenant && !HasTenantIdProperty(entity)) { TryToSetTenantId(entity); } - + Repository.Insert(entity, autoSave: true); - return MapToEntityDto(entity); + return MapToGetOutputDto(entity); } - public virtual TEntityDto Update(TKey id, TUpdateInput input) + public virtual TGetOutputDto Update(TKey id, TUpdateInput input) { CheckUpdatePolicy(); @@ -106,7 +124,7 @@ namespace Volo.Abp.Application.Services MapToEntity(input, entity); Repository.Update(entity, autoSave: true); - return MapToEntityDto(entity); + return MapToGetOutputDto(entity); } public virtual void Delete(TKey id) diff --git a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/CrudAppServiceBase.cs b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/CrudAppServiceBase.cs index b678362c53..21c19a9a4a 100644 --- a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/CrudAppServiceBase.cs +++ b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/CrudAppServiceBase.cs @@ -13,10 +13,11 @@ namespace Volo.Abp.Application.Services /// This is a common base class for CrudAppService and AsyncCrudAppService classes. /// Inherit either from CrudAppService or AsyncCrudAppService, not from this class. /// - public abstract class CrudAppServiceBase : + public abstract class CrudAppServiceBase : ApplicationService where TEntity : class, IEntity - where TEntityDto : IEntityDto + where TGetOutputDto : IEntityDto + where TGetListOutputDto : IEntityDto { protected IRepository Repository { get; } @@ -100,19 +101,29 @@ namespace Volo.Abp.Application.Services } /// - /// Maps to . + /// Maps to . /// It uses by default. - /// It can be overrided for custom mapping. + /// It can be overriden for custom mapping. /// - protected virtual TEntityDto MapToEntityDto(TEntity entity) + protected virtual TGetOutputDto MapToGetOutputDto(TEntity entity) { - return ObjectMapper.Map(entity); + return ObjectMapper.Map(entity); } /// - /// Maps to to create a new entity. + /// Maps to . /// It uses by default. - /// It can be overrided for custom mapping. + /// It can be overriden for custom mapping. + /// + protected virtual TGetListOutputDto MapToGetListOutputDto(TEntity entity) + { + return ObjectMapper.Map(entity); + } + + /// + /// Maps to to create a new entity. + /// It uses by default. + /// It can be overriden for custom mapping. /// protected virtual TEntity MapToEntity(TCreateInput createInput) { @@ -140,7 +151,7 @@ namespace Volo.Abp.Application.Services /// /// Maps to to update the entity. /// It uses by default. - /// It can be overrided for custom mapping. + /// It can be overriden for custom mapping. /// protected virtual void MapToEntity(TUpdateInput updateInput, TEntity entity) { diff --git a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/IAsyncCrudAppService.cs b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/IAsyncCrudAppService.cs index 4f97c49ae0..8f07cb2412 100644 --- a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/IAsyncCrudAppService.cs +++ b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/IAsyncCrudAppService.cs @@ -25,16 +25,24 @@ namespace Volo.Abp.Application.Services } public interface IAsyncCrudAppService - : IApplicationService + : IAsyncCrudAppService where TEntityDto : IEntityDto { - Task GetAsync(TKey id); - Task> GetListAsync(TGetListInput input); + } + + public interface IAsyncCrudAppService + : IApplicationService + where TGetOutputDto : IEntityDto + where TGetListOutputDto : IEntityDto + { + Task GetAsync(TKey id); + + Task> GetListAsync(TGetListInput input); - Task CreateAsync(TCreateInput input); + Task CreateAsync(TCreateInput input); - Task UpdateAsync(TKey id, TUpdateInput input); + Task UpdateAsync(TKey id, TUpdateInput input); Task DeleteAsync(TKey id); } diff --git a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ICrudAppService.cs b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ICrudAppService.cs index 7e8b96b9f8..2f3b770849 100644 --- a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ICrudAppService.cs +++ b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ICrudAppService.cs @@ -24,16 +24,24 @@ namespace Volo.Abp.Application.Services } public interface ICrudAppService - : IApplicationService + : ICrudAppService where TEntityDto : IEntityDto { - TEntityDto Get(TKey id); - PagedResultDto GetList(TGetListInput input); + } + + public interface ICrudAppService + : IApplicationService + where TGetOutputDto : IEntityDto + where TGetListOutputDto : IEntityDto + { + TGetOutputDto Get(TKey id); + + PagedResultDto GetList(TGetListInput input); - TEntityDto Create(TCreateInput input); + TGetOutputDto Create(TCreateInput input); - TEntityDto Update(TKey id, TUpdateInput input); + TGetOutputDto Update(TKey id, TUpdateInput input); void Delete(TKey id); } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo.Abp.EntityFrameworkCore.PostgreSql.csproj b/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo.Abp.EntityFrameworkCore.PostgreSql.csproj index ccdccb5197..bc148b42c5 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo.Abp.EntityFrameworkCore.PostgreSql.csproj +++ b/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo.Abp.EntityFrameworkCore.PostgreSql.csproj @@ -18,7 +18,7 @@ - + diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/Modeling/AbpEntityTypeBuilderExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/Modeling/AbpEntityTypeBuilderExtensions.cs index fd7a3d495b..132e91c079 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/Modeling/AbpEntityTypeBuilderExtensions.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/Modeling/AbpEntityTypeBuilderExtensions.cs @@ -261,6 +261,22 @@ namespace Volo.Abp.EntityFrameworkCore.Modeling } } + public static void ConfigureCreationAuditedAggregateRoot(this EntityTypeBuilder b) + where T : class + { + b.As().TryConfigureCreationAudited(); + b.As().TryConfigureExtraProperties(); + b.As().TryConfigureConcurrencyStamp(); + } + + public static void ConfigureAuditedAggregateRoot(this EntityTypeBuilder b) + where T : class + { + b.As().TryConfigureAudited(); + b.As().TryConfigureExtraProperties(); + b.As().TryConfigureConcurrencyStamp(); + } + public static void ConfigureFullAuditedAggregateRoot(this EntityTypeBuilder b) where T : class { diff --git a/framework/src/Volo.Abp.FluentValidation/Volo.Abp.FluentValidation.csproj b/framework/src/Volo.Abp.FluentValidation/Volo.Abp.FluentValidation.csproj index fe8a6a4192..f92af19e56 100644 --- a/framework/src/Volo.Abp.FluentValidation/Volo.Abp.FluentValidation.csproj +++ b/framework/src/Volo.Abp.FluentValidation/Volo.Abp.FluentValidation.csproj @@ -14,7 +14,7 @@ - + diff --git a/framework/src/Volo.Abp.HangFire/Volo.Abp.HangFire.csproj b/framework/src/Volo.Abp.HangFire/Volo.Abp.HangFire.csproj index e4b9db1c7b..82a980f1cf 100644 --- a/framework/src/Volo.Abp.HangFire/Volo.Abp.HangFire.csproj +++ b/framework/src/Volo.Abp.HangFire/Volo.Abp.HangFire.csproj @@ -14,7 +14,7 @@ - + diff --git a/framework/src/Volo.Abp.IdentityModel/Volo.Abp.IdentityModel.csproj b/framework/src/Volo.Abp.IdentityModel/Volo.Abp.IdentityModel.csproj index fcfff3fcb5..fa2bddfcc6 100644 --- a/framework/src/Volo.Abp.IdentityModel/Volo.Abp.IdentityModel.csproj +++ b/framework/src/Volo.Abp.IdentityModel/Volo.Abp.IdentityModel.csproj @@ -14,8 +14,8 @@ - - + + \ No newline at end of file diff --git a/framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/AbpIdentityModelModule.cs b/framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/AbpIdentityModelModule.cs index cadeb794a7..b8578ca95d 100644 --- a/framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/AbpIdentityModelModule.cs +++ b/framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/AbpIdentityModelModule.cs @@ -1,8 +1,12 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity; +using Volo.Abp.Threading; namespace Volo.Abp.IdentityModel { + [DependsOn( + typeof(AbpThreadingModule) + )] public class AbpIdentityModelModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) diff --git a/framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityClientConfiguration.cs b/framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityClientConfiguration.cs index 35ca881f7f..e2e6e45e49 100644 --- a/framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityClientConfiguration.cs +++ b/framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityClientConfiguration.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using IdentityModel; namespace Volo.Abp.IdentityModel @@ -71,6 +72,16 @@ namespace Volo.Abp.IdentityModel set => this[nameof(Scope)] = value; } + /// + /// RequireHttps. + /// Default: true. + /// + public bool RequireHttps + { + get => this.GetOrDefault(nameof(RequireHttps))?.To() ?? true; + set => this[nameof(RequireHttps)] = value.ToString().ToLowerInvariant(); + } + public IdentityClientConfiguration() { @@ -83,7 +94,8 @@ namespace Volo.Abp.IdentityModel string clientSecret, string grantType = OidcConstants.GrantTypes.ClientCredentials, string userName = null, - string userPassword = null) + string userPassword = null, + bool requireHttps = true) { this[nameof(Authority)] = authority; this[nameof(Scope)] = scope; @@ -92,6 +104,7 @@ namespace Volo.Abp.IdentityModel this[nameof(GrantType)] = grantType; this[nameof(UserName)] = userName; this[nameof(UserPassword)] = userPassword; + this[nameof(RequireHttps)] = requireHttps.ToString().ToLowerInvariant(); } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityModelAuthenticationService.cs b/framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityModelAuthenticationService.cs index 4f316ec357..032bd15457 100644 --- a/framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityModelAuthenticationService.cs +++ b/framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityModelAuthenticationService.cs @@ -10,6 +10,7 @@ using System.Net.Http; using System.Net.Http.Headers; using System.Threading.Tasks; using Volo.Abp.DependencyInjection; +using Volo.Abp.Threading; namespace Volo.Abp.IdentityModel { @@ -18,10 +19,13 @@ namespace Volo.Abp.IdentityModel { public ILogger Logger { get; set; } protected IdentityClientOptions ClientOptions { get; } + protected ICancellationTokenProvider CancellationTokenProvider { get; } public IdentityModelAuthenticationService( - IOptions options) + IOptions options, + ICancellationTokenProvider cancellationTokenProvider) { + CancellationTokenProvider = cancellationTokenProvider; ClientOptions = options.Value; Logger = NullLogger.Instance; } @@ -87,31 +91,57 @@ namespace Volo.Abp.IdentityModel ClientOptions.IdentityClients.Default; } - protected virtual async Task GetDiscoveryResponse(IdentityClientConfiguration configuration) + protected virtual async Task GetDiscoveryResponse( + IdentityClientConfiguration configuration) { - return await DiscoveryClient.GetAsync(configuration.Authority); + using (var httpClient = new HttpClient()) + { + return await httpClient.GetDiscoveryDocumentAsync(new DiscoveryDocumentRequest + { + Address = configuration.Authority, + Policy = + { + RequireHttps = configuration.RequireHttps + } + }); + } } - protected virtual async Task GetTokenResponse(DiscoveryResponse discoveryResponse, IdentityClientConfiguration configuration) + protected virtual async Task GetTokenResponse( + DiscoveryResponse discoveryResponse, + IdentityClientConfiguration configuration) { - //TODO: Pass cancellation token - - var tokenClient = new TokenClient(discoveryResponse.TokenEndpoint, configuration.ClientId, configuration.ClientSecret); - - switch (configuration.GrantType) + using (var httpClient = new HttpClient()) { - case OidcConstants.GrantTypes.ClientCredentials: - return await tokenClient.RequestClientCredentialsAsync( - configuration.Scope - ); - case OidcConstants.GrantTypes.Password: - return await tokenClient.RequestResourceOwnerPasswordAsync( - configuration.UserName, - configuration.UserPassword, - configuration.Scope - ); - default: - throw new AbpException("Grant type was not implemented: " + configuration.GrantType); + switch (configuration.GrantType) + { + case OidcConstants.GrantTypes.ClientCredentials: + return await httpClient.RequestClientCredentialsTokenAsync( + new ClientCredentialsTokenRequest + { + Address = discoveryResponse.TokenEndpoint, + Scope = configuration.Scope, + ClientId = configuration.ClientId, + ClientSecret = configuration.ClientSecret + }, + CancellationTokenProvider.Token + ); + case OidcConstants.GrantTypes.Password: + return await httpClient.RequestPasswordTokenAsync( + new PasswordTokenRequest + { + Address = discoveryResponse.TokenEndpoint, + Scope = configuration.Scope, + ClientId = configuration.ClientId, + ClientSecret = configuration.ClientSecret, + UserName = configuration.UserName, + Password = configuration.UserPassword + }, + CancellationTokenProvider.Token + ); + default: + throw new AbpException("Grant type was not implemented: " + configuration.GrantType); + } } } } diff --git a/framework/src/Volo.Abp.Ldap/Volo.Abp.Ldap.csproj b/framework/src/Volo.Abp.Ldap/Volo.Abp.Ldap.csproj new file mode 100644 index 0000000000..6b1cba1094 --- /dev/null +++ b/framework/src/Volo.Abp.Ldap/Volo.Abp.Ldap.csproj @@ -0,0 +1,24 @@ + + + + + + netstandard2.0 + Volo.Abp.Ldap + Volo.Abp.Ldap + $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; + false + false + false + + + + + + + + + + + + diff --git a/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/AbpLdapModule.cs b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/AbpLdapModule.cs new file mode 100644 index 0000000000..22b9ca7a76 --- /dev/null +++ b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/AbpLdapModule.cs @@ -0,0 +1,18 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Autofac; +using Volo.Abp.Modularity; + +namespace Volo.Abp.Ldap +{ + [DependsOn( + typeof(AbpAutofacModule) + )] + public class AbpLdapModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + var configuration = context.Services.GetConfiguration(); + Configure(configuration.GetSection("LDAP")); + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Exceptions/OrganizationNotExistException.cs b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Exceptions/OrganizationNotExistException.cs new file mode 100644 index 0000000000..9d7fb220cc --- /dev/null +++ b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Exceptions/OrganizationNotExistException.cs @@ -0,0 +1,11 @@ +namespace Volo.Abp.Ldap.Exceptions +{ + public class OrganizationNotExistException : BusinessException + { + public OrganizationNotExistException(string distinguishedName) + : base("LDAP:000001", $"the organization distinguished named {distinguishedName} does not exist.") + { + + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/ILdapManager.cs b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/ILdapManager.cs new file mode 100644 index 0000000000..f14e88b409 --- /dev/null +++ b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/ILdapManager.cs @@ -0,0 +1,72 @@ +using System.Collections.Generic; +using Volo.Abp.Ldap.Modeling; + +namespace Volo.Abp.Ldap +{ + public interface ILdapManager + { + /// + /// query the specified organizations. + /// + /// filter: (&(name=xxx)(objectClass=organizationalUnit)) when name is not null + /// filter: (&(name=*)(objectClass=organizationalUnit)) when name is null + /// + /// + /// + /// + IList GetOrganizations(string name = null); + + /// + /// query the specified organization. + /// + /// filter: (&(distinguishedName=xxx)(objectClass=organizationalUnit)) when organizationName is not null + /// + /// + /// + /// + LdapOrganization GetOrganization(string distinguishedName); + + void AddSubOrganization(string organizationName, LdapOrganization parentOrganization); + void AddSubOrganization(string organizationName, string parentDistinguishedName); + + /// + /// query the specified users. + /// + /// filter: (&(name=xxx)(objectCategory=person)(objectClass=user)) when name is not null + /// filter: (&(name=*)(objectCategory=person)(objectClass=user)) when name is null + /// + /// filter: (&(displayName=xxx)(objectCategory=person)(objectClass=user)) when displayName is not null + /// filter: (&(displayName=*)(objectCategory=person)(objectClass=user)) when displayName is null + /// + /// filter: (&(cn=xxx)(objectCategory=person)(objectClass=user)) when commonName is not null + /// filter: (&(cn=*)(objectCategory=person)(objectClass=user)) when commonName is null + /// + /// + /// + /// + /// + /// + IList GetUsers(string name = null, string displayName = null, string commonName = null); + + /// + /// query the specified User. + /// + /// filter: (&(distinguishedName=xxx)(objectCategory=person)(objectClass=user)) when distinguishedName is not null + /// + /// + /// + /// + LdapUser GetUser(string distinguishedName); + + void AddUserToOrganization(string userName, string password, LdapOrganization parentOrganization); + void AddUserToOrganization(string userName, string password, string parentDistinguishedName); + + /// + /// Authenticate + /// + /// E.g administrator@yourdomain.com.cn + /// + /// + bool Authenticate(string userDomainName, string password); + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/LdapCredentials.cs b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/LdapCredentials.cs new file mode 100644 index 0000000000..a2d2eefd74 --- /dev/null +++ b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/LdapCredentials.cs @@ -0,0 +1,9 @@ +namespace Volo.Abp.Ldap +{ + public class LdapCredentials + { + public string DomainUserName { get; set; } + + public string Password { get; set; } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/LdapHelps.cs b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/LdapHelps.cs new file mode 100644 index 0000000000..49a60a964f --- /dev/null +++ b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/LdapHelps.cs @@ -0,0 +1,34 @@ +using System.Collections.Generic; + +namespace Volo.Abp.Ldap +{ + public static class LdapHelps + { + public static string BuildCondition(string name, string value) + { + return string.IsNullOrWhiteSpace(value) ? "" : $"({name}={value})"; + } + + public static string BuildFilter(Dictionary conditions) + { + if (null == conditions ) + { + conditions = new Dictionary(); + } + + if (conditions.Keys.Count == 0) + { + conditions.Add("objectClass", "*"); // add default condition + } + + var subFilter = string.Empty; + foreach (var keyValuePair in conditions) + { + subFilter += BuildCondition(keyValuePair.Key, keyValuePair.Value); + } + + return $"(&{subFilter})"; + } + + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/LdapManager.cs b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/LdapManager.cs new file mode 100644 index 0000000000..615b22d70e --- /dev/null +++ b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/LdapManager.cs @@ -0,0 +1,332 @@ +using System; +using Microsoft.Extensions.Options; +using Novell.Directory.Ldap; +using System.Collections.Generic; +using System.Text; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Ldap.Exceptions; +using Volo.Abp.Ldap.Modeling; + +namespace Volo.Abp.Ldap +{ + public class LdapManager : ILdapManager, ITransientDependency + { + private readonly string _searchBase; + private readonly LdapOptions _ldapOptions; + + private readonly string[] _attributes = + { + "objectCategory", "objectClass", "cn", "name", "distinguishedName", + "ou", + "sAMAccountName", "userPrincipalName", "telephoneNumber", "mail" + }; + + public LdapManager(IOptions ldapSettingsOptions) + { + _ldapOptions = ldapSettingsOptions.Value; + _searchBase = _ldapOptions.SearchBase; + } + + #region Organization + /// + /// query the specified organizations. + /// + /// filter: (&(name=xxx)(objectClass=organizationalUnit)) when name is not null + /// filter: (&(objectClass=organizationalUnit)) when name is null + /// + /// + /// + /// + public IList GetOrganizations(string name = null) + { + var conditions = new Dictionary + { + {"name", name}, + {"objectClass", "organizationalUnit"}, + }; + return Query(_searchBase, conditions); + } + + /// + /// query the specified organization. + /// + /// filter: (&(distinguishedName=xxx)(objectClass=organizationalUnit)) when organizationName is not null + /// + /// + /// + /// + public LdapOrganization GetOrganization(string distinguishedName) + { + distinguishedName = Check.NotNullOrWhiteSpace(distinguishedName, nameof(distinguishedName)); + var conditions = new Dictionary + { + {"distinguishedName", distinguishedName}, + {"objectClass", "organizationalUnit"}, + }; + return QueryOne(_searchBase, conditions); + } + + public void AddSubOrganization(string organizationName, LdapOrganization parentOrganization) + { + organizationName = Check.NotNullOrWhiteSpace(organizationName, nameof(organizationName)); + var dn = $"OU={organizationName},{parentOrganization.DistinguishedName}"; + + var attributeSet = new LdapAttributeSet + { + new LdapAttribute("objectCategory", $"CN=Organizational-Unit,CN=Schema,CN=Configuration,{_ldapOptions.DomainDistinguishedName}"), + new LdapAttribute("objectClass", new[] {"top", "organizationalUnit"}), + new LdapAttribute("name", organizationName), + }; + + var newEntry = new LdapEntry(dn, attributeSet); + + using (var ldapConnection = GetConnection()) + { + ldapConnection.Add(newEntry); + } + } + + public void AddSubOrganization(string organizationName, string parentDistinguishedName) + { + organizationName = Check.NotNullOrWhiteSpace(organizationName, nameof(organizationName)); + parentDistinguishedName = + Check.NotNullOrWhiteSpace(parentDistinguishedName, nameof(parentDistinguishedName)); + + var parentOrganization = GetOrganization(parentDistinguishedName); + if (null == parentOrganization) + { + throw new OrganizationNotExistException(parentDistinguishedName); + } + + AddSubOrganization(organizationName, parentOrganization); + } + + #endregion + + #region User + /// + /// query the specified users. + /// + /// filter: (&(name=xxx)(objectCategory=person)(objectClass=user)) when name is not null + /// filter: (&(objectCategory=person)(objectClass=user)) when name is null + /// + /// filter: (&(displayName=xxx)(objectCategory=person)(objectClass=user)) when displayName is not null + /// filter: (&(objectCategory=person)(objectClass=user)) when displayName is null + /// + /// filter: (&(cn=xxx)(objectCategory=person)(objectClass=user)) when commonName is not null + /// filter: (&(objectCategory=person)(objectClass=user)) when commonName is null + /// + /// + /// + /// + /// + /// + public IList GetUsers(string name = null, string displayName = null, string commonName = null) + { + var conditions = new Dictionary + { + {"objectCategory", "person"}, + {"objectClass", "user"}, + {"name", name}, + {"displayName", displayName}, + {"cn", commonName}, + }; + return Query(_searchBase, conditions); + } + + /// + /// query the specified User. + /// + /// filter: (&(distinguishedName=xxx)(objectCategory=person)(objectClass=user)) when distinguishedName is not null + /// + /// + /// + /// + public LdapUser GetUser(string distinguishedName) + { + distinguishedName = Check.NotNullOrWhiteSpace(distinguishedName, nameof(distinguishedName)); + var conditions = new Dictionary + { + {"objectCategory", "person"}, + {"objectClass", "user"}, + {"distinguishedName", distinguishedName}, + }; + return QueryOne(_searchBase, conditions); + } + + public void AddUserToOrganization(string userName, string password, LdapOrganization parentOrganization) + { + var dn = $"CN={userName},{parentOrganization.DistinguishedName}"; + var mail = $"{userName}@{_ldapOptions.DomainName}"; + sbyte[] encodedBytes = SupportClass.ToSByteArray(Encoding.Unicode.GetBytes($"\"{password}\"")); + + var attributeSet = new LdapAttributeSet + { + new LdapAttribute("instanceType", "4"), + new LdapAttribute("objectCategory", $"CN=Person,CN=Schema,CN=Configuration,{_ldapOptions.DomainDistinguishedName}"), + new LdapAttribute("objectClass", new[] {"top", "person", "organizationalPerson", "user"}), + new LdapAttribute("name", userName), + new LdapAttribute("cn", userName), + new LdapAttribute("sAMAccountName", userName), + new LdapAttribute("userPrincipalName", userName), + new LdapAttribute("sn", userName), + new LdapAttribute("displayName", userName), + new LdapAttribute("unicodePwd", encodedBytes), + new LdapAttribute("userAccountControl", "512"), + new LdapAttribute("mail", mail), + }; + var newEntry = new LdapEntry(dn, attributeSet); + + using (var ldapConnection = GetConnection()) + { + ldapConnection.Add(newEntry); + } + } + + public void AddUserToOrganization(string userName, string password, string parentDistinguishedName) + { + var dn = $"CN={userName},{parentDistinguishedName}"; + var mail = $"{userName}@{_ldapOptions.DomainName}"; + sbyte[] encodedBytes = SupportClass.ToSByteArray(Encoding.Unicode.GetBytes($"\"{password}\"")); + + var attributeSet = new LdapAttributeSet + { + new LdapAttribute("instanceType", "4"), + new LdapAttribute("objectCategory", $"CN=Person,CN=Schema,CN=Configuration,{_ldapOptions.DomainDistinguishedName}"), + new LdapAttribute("objectClass", new[] {"top", "person", "organizationalPerson", "user"}), + new LdapAttribute("name", userName), + new LdapAttribute("cn", userName), + new LdapAttribute("sAMAccountName", userName), + new LdapAttribute("userPrincipalName", userName), + new LdapAttribute("sn", userName), + new LdapAttribute("displayName", userName), + new LdapAttribute("unicodePwd", encodedBytes), + new LdapAttribute("userAccountControl", "512"), + new LdapAttribute("mail", mail), + }; + var newEntry = new LdapEntry(dn, attributeSet); + + using (var ldapConnection = GetConnection()) + { + ldapConnection.Add(newEntry); + } + } + + #endregion + + #region Authenticate + + /// + /// Authenticate + /// + /// E.g administrator@yourdomain.com.cn + /// + /// + public bool Authenticate(string userDomainName, string password) + { + try + { + using (GetConnection(userDomainName, password)) + { + return true; + } + } + catch (Exception ) + { + return false; + } + } + + #endregion + + private ILdapConnection GetConnection(string bindUserName = null, string bindUserPassword = null) + { + // bindUserName/bindUserPassword only be used when authenticate + bindUserName = bindUserName ?? _ldapOptions.Credentials.DomainUserName; + bindUserPassword = bindUserPassword ?? _ldapOptions.Credentials.Password; + + var ldapConnection = new LdapConnection() { SecureSocketLayer = _ldapOptions.UseSsl }; + if (_ldapOptions.UseSsl) + { + ldapConnection.UserDefinedServerCertValidationDelegate += (sender, certificate, chain, sslPolicyErrors) => true; + } + ldapConnection.Connect(_ldapOptions.ServerHost, _ldapOptions.ServerPort); + + if (_ldapOptions.UseSsl) + { + ldapConnection.Bind(LdapConnection.Ldap_V3, bindUserName, bindUserPassword); + } + else + { + ldapConnection.Bind(bindUserName, bindUserPassword); + } + return ldapConnection; + } + + private IList Query(string searchBase, Dictionary conditions) where T : class, ILdapEntry + { + var filter = LdapHelps.BuildFilter(conditions); + + var result = new List(); + + using (var ldapConnection = GetConnection()) + { + var search = ldapConnection.Search(searchBase, LdapConnection.SCOPE_SUB, filter, + _attributes, false, null, null); + + LdapMessage message; + while ((message = search.getResponse()) != null) + { + if (!(message is LdapSearchResult searchResultMessage)) + { + continue; + } + var entry = searchResultMessage.Entry; + if (typeof(T) == typeof(LdapOrganization)) + { + result.Add(new LdapOrganization(entry.getAttributeSet()) as T); + } + + if (typeof(T) == typeof(LdapUser)) + { + result.Add(new LdapUser(entry.getAttributeSet()) as T); + } + } + } + return result; + } + + private T QueryOne(string searchBase, Dictionary conditions) where T : class, ILdapEntry + { + var filter = LdapHelps.BuildFilter(conditions); + + using (var ldapConnection = GetConnection()) + { + var search = ldapConnection.Search(searchBase, LdapConnection.SCOPE_SUB, filter, + _attributes, false, null, null); + + LdapMessage message; + while ((message = search.getResponse()) != null) + { + if (!(message is LdapSearchResult searchResultMessage)) + { + continue; + } + var entry = searchResultMessage.Entry; + if (typeof(T) == typeof(LdapOrganization)) + { + return new LdapOrganization(entry.getAttributeSet()) as T; + } + + if (typeof(T) == typeof(LdapUser)) + { + return new LdapUser(entry.getAttributeSet()) as T; + } + return null; + } + } + return null; + } + + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/LdapOptions.cs b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/LdapOptions.cs new file mode 100644 index 0000000000..7e4aacfa0e --- /dev/null +++ b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/LdapOptions.cs @@ -0,0 +1,24 @@ +namespace Volo.Abp.Ldap +{ + public class LdapOptions + { + public string ServerHost { get; set; } + + public int ServerPort { get; set; } + + public bool UseSsl { get; set; } + + public string SearchBase { get; set; } + + public string DomainName { get; set; } + + public string DomainDistinguishedName { get; set; } + + public LdapCredentials Credentials { get; set; } + + public LdapOptions() + { + Credentials = new LdapCredentials(); + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Modeling/ILdapEntry.cs b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Modeling/ILdapEntry.cs new file mode 100644 index 0000000000..f15775fc06 --- /dev/null +++ b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Modeling/ILdapEntry.cs @@ -0,0 +1,11 @@ +namespace Volo.Abp.Ldap.Modeling +{ + public interface ILdapEntry + { + string ObjectCategory { get; set; } + string[] ObjectClass { get; set; } + string Name { get; set; } + string DistinguishedName { get; set; } + string CommonName { get; set; } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Modeling/ILdapOrganization.cs b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Modeling/ILdapOrganization.cs new file mode 100644 index 0000000000..07c11000e8 --- /dev/null +++ b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Modeling/ILdapOrganization.cs @@ -0,0 +1,7 @@ +namespace Volo.Abp.Ldap.Modeling +{ + public interface ILdapOrganization : ILdapEntry + { + string OrganizationUnit { get; set; } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Modeling/ILdapUser.cs b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Modeling/ILdapUser.cs new file mode 100644 index 0000000000..8ef68f6607 --- /dev/null +++ b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Modeling/ILdapUser.cs @@ -0,0 +1,11 @@ +namespace Volo.Abp.Ldap.Modeling +{ + public interface ILdapUser : ILdapEntry + { + string SamAccountName { get; set; } + string UserPrincipalName { get; set; } + string DisplayName { get; set; } + string Email { get; set; } + string Phone { get; set; } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Modeling/LdapEntryBase.cs b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Modeling/LdapEntryBase.cs new file mode 100644 index 0000000000..6658a983d0 --- /dev/null +++ b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Modeling/LdapEntryBase.cs @@ -0,0 +1,24 @@ +using Novell.Directory.Ldap; + +namespace Volo.Abp.Ldap.Modeling +{ + public abstract class LdapEntryBase : ILdapEntry + { + public string ObjectCategory { get; set; } + public string[] ObjectClass { get; set; } + public string Name { get; set; } + public string CommonName { get; set; } + public string DistinguishedName { get; set; } + + protected LdapEntryBase() { } + + protected LdapEntryBase(LdapAttributeSet attributeSet) + { + ObjectCategory = attributeSet.getAttribute("objectCategory")?.StringValue; + ObjectClass = attributeSet.getAttribute("objectClass")?.StringValueArray; + Name = attributeSet.getAttribute("name")?.StringValue; + CommonName = attributeSet.getAttribute("cn")?.StringValue; + DistinguishedName = attributeSet.getAttribute("distinguishedName")?.StringValue; + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Modeling/LdapOrganization.cs b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Modeling/LdapOrganization.cs new file mode 100644 index 0000000000..e401a2514d --- /dev/null +++ b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Modeling/LdapOrganization.cs @@ -0,0 +1,17 @@ +using Novell.Directory.Ldap; + +namespace Volo.Abp.Ldap.Modeling +{ + public class LdapOrganization : LdapEntryBase, ILdapOrganization + { + public string OrganizationUnit { get; set; } + + public LdapOrganization() { } + + public LdapOrganization(LdapAttributeSet attributeSet) + : base(attributeSet) + { + OrganizationUnit = attributeSet.getAttribute("ou")?.StringValue; + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Modeling/LdapUser.cs b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Modeling/LdapUser.cs new file mode 100644 index 0000000000..d9f554d512 --- /dev/null +++ b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Modeling/LdapUser.cs @@ -0,0 +1,25 @@ +using Novell.Directory.Ldap; + +namespace Volo.Abp.Ldap.Modeling +{ + public class LdapUser : LdapEntryBase, ILdapUser + { + public string SamAccountName { get; set; } + public string UserPrincipalName { get; set; } + public string DisplayName { get; set; } + public string Email { get; set; } + public string Phone { get; set; } + + public LdapUser() { } + + public LdapUser( LdapAttributeSet attributeSet) + : base(attributeSet) + { + SamAccountName = attributeSet.getAttribute("sAMAccountName")?.StringValue; + UserPrincipalName = attributeSet.getAttribute("userPrincipalName")?.StringValue; + DisplayName = attributeSet.getAttribute("displayName")?.StringValue; + Email = attributeSet.getAttribute("mail")?.StringValue; + Phone = attributeSet.getAttribute("telephoneNumber")?.StringValue; + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Ldap/readme.md b/framework/src/Volo.Abp.Ldap/readme.md new file mode 100644 index 0000000000..dd9b84087d --- /dev/null +++ b/framework/src/Volo.Abp.Ldap/readme.md @@ -0,0 +1,171 @@ +# Volo.Abp.Ldap + +# Only Authenticate(not read/write AD) + +## Configure + +add section in `appsettings.json` + +### use SSL + +```json +"LDAP": { + "ServerHost": "192.168.101.54", + "ServerPort": 636, + "UseSsl": true +} +``` + +### not use SSL + +```json +"LDAP": { + "ServerHost": "192.168.101.54", + "ServerPort": 389, + "UseSsl": false +} +``` + +## Authenticate + + Injecting `ILdapManager` into a class. For example: + +```csharp +public class TaxAppService : ApplicationService +{ + private readonly ILdapManager _ldapManager; + + public TaxAppService(ILdapManager ldapManager) + { + _ldapManager = ldapManager; + } + + public void Authenticate(string userName, string password) + { + var result = _ldapManager.Authenticate(userName, password); + } +} +``` + +- `userName` must be full domain name. E.g abc@abc.com + +# Read/Write AD + +## Configure + +### use SSL + +```json +"LDAP": { + "ServerHost": "192.168.101.54", + "ServerPort": 636, + "UseSsl": true, + "Credentials": { + "DomainUserName": "administrator@yourdomain.com.cn", + "Password": "yH.20190528" + }, + "SearchBase": "DC=yourdomain,DC=com,DC=cn", + "DomainName": "yourdomain.com.cn", + "DomainDistinguishedName": "DC=yourdomain,DC=com,DC=cn" +} +``` + +### not use SSL + +```json +"LDAP": { + "ServerHost": "192.168.101.54", + "ServerPort": 389, + "UseSsl": false, + "Credentials": { + "DomainUserName": "administrator@yourdomain.com.cn", + "Password": "yH.20190528" + }, + "SearchBase": "DC=yourdomain,DC=com,DC=cn", + "DomainName": "yourdomain.com.cn", + "DomainDistinguishedName": "DC=yourdomain,DC=com,DC=cn" +} +``` + +- `Credentials:DomainUserName` a administrator of AD. + +- `Credentials:Password` the password for the administrator. +- `SearchBase`: where search from AD. +- `DomainName`: name of you domain. no need `www`. +- `DomainDistinguishedName`: distinguished name of root domain. + +## Query Organizations + +```cs +// query all organizations +// filter: (&(objectClass=organizationalUnit)) +_ldapManager.GetOrganizations(); + +// query organizations by name +// filter: (&(name=abc)(objectClass=organizationalUnit)) +_ldapManager.GetOrganizations("abc"); + +``` + +## Query Organization + +```csharp +// query organization by distinguished name +// filter: (&(distinguishedName=abc)(objectClass=organizationalUnit)) +_ldapManager.GetOrganization("abc"); + +``` + +## Add Organization + +```csharp +// use LdapOrganization +_ldapManager.AddSubOrganization("nameA", parentOrganization); + +// or use OrganizationDistinguishedName +_ldapManager.AddSubOrganization("nameA", "OU=Domain Controllers,DC=yourdomain,DC=com,DC=cn"); +``` + +## Query Users + +```cs +// query all users +// filter: (&(objectCategory=person)(objectClass=user)) +_ldapManager.GetUsers(); + +// query organizations by name +// filter: (&(name=abc)(objectCategory=person)(objectClass=user)) +_ldapManager.GetUsers(name : "abc"); + +// query organizations by displayName +// filter: (&(displayName=abc)(objectCategory=person)(objectClass=user)) +_ldapManager.GetUsers(displayName : "abc"); + +// query organization by commonName +// filter: (&(cn=abc)(objectCategory=person)(objectClass=user)) +_ldapManager.GetUsers(commonName : "abc"); + +``` + +## Query User + +```csharp +// query a user by distinguished name +// filter: (&(distinguishedName=abc)(objectCategory=person)(objectClass=user)) +_ldapManager.GetUser("abc"); + +``` + +## Add User + +```csharp +// use LdapOrganization +_ldapManager.AddUserToOrganization("nameA", "passwordA", parentOrganization); + +// or use OrganizationDistinguishedName +_ldapManager.AddUserToOrganization("nameA", "passwordA", "OU=Domain Controllers,DC=yourdomain,DC=com,DC=cn"); +``` + +# More + +See [unit test](../../test/Volo.Abp.Ldap.Tests) \ No newline at end of file diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpValidation/cs.json b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpValidation/cs.json new file mode 100644 index 0000000000..d38574303a --- /dev/null +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpValidation/cs.json @@ -0,0 +1,20 @@ +{ + "culture": "cs", + "texts": { + "'{0}' and '{1}' do not match.": "'{0}' a '{1}' se neshodují", + "The {0} field is not a valid credit card number.": "V poli {0} není platné číslo kreditní karty.", + "{0} is not valid.": "{0} není platný.", + "The {0} field is not a valid e-mail address.": "V poli {0} není platný email.", + "The {0} field only accepts files with the following extensions: {1}": "Pole {0} přijímá soubory pouze s následujícími koncovkami: {1}", + "The field {0} must be a string or array type with a maximum length of '{1}'.": "Vy poli {0} musí být řežezec nebo řada o maximální délce '{1}'.", + "The field {0} must be a string or array type with a minimum length of '{1}'.": "V poli {0} musí být řežezec nebo řada o minimální délce '{1}'.", + "The {0} field is not a valid phone number.": "V poli {0} není platné telefonní číslo.", + "The field {0} must be between {1} and {2}.": "Pole {0} musí být mezi {1} a {2}.", + "The field {0} must match the regular expression '{1}'.": "Pole {0} musí odpovídat regulérnímu výrazu '{1}'.", + "The {0} field is required.": "Pole {0} je povinné.", + "The field {0} must be a string with a maximum length of {1}.": "Pole {0} musí být řetězec o maximální délce {1}.", + "The field {0} must be a string with a minimum length of {2} and a maximum length of {1}.": "Pole {0} musí být řetězec o minimální délce {2} a maximální délce {1} znaků.", + "The {0} field is not a valid fully-qualified http, https, or ftp URL.": "Pole {0} není platná plně kvalifikovaná adresa http, https, nebo ftp URL.", + "The field {0} is invalid.": "Pole {0} je neplatné." + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpValidation/pl.json b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpValidation/pl.json new file mode 100644 index 0000000000..eef572eb13 --- /dev/null +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpValidation/pl.json @@ -0,0 +1,20 @@ +{ + "culture": "pl", + "texts": { + "'{0}' and '{1}' do not match.": "'{0}' i '{1}' nie są takie same.", + "The {0} field is not a valid credit card number.": "Pole {0} nie jest poprawnym numerem karty kredytowej.", + "{0} is not valid.": "{0} jest niepoprawne.", + "The {0} field is not a valid e-mail address.": "Pole {0} nie jest poprawnym adresem e-mail.", + "The {0} field only accepts files with the following extensions: {1}": "Polr {0} przyjmuje pliki tylko z następującymi rozszerzeniami: {1}", + "The field {0} must be a string or array type with a maximum length of '{1}'.": "Pole {0} musi być łańcuchem znaków lub talicą o maksymalnej długości '{1}'.", + "The field {0} must be a string or array type with a minimum length of '{1}'.": "Pole {0} musi być łańcuchem znaków lub talicą o minimalnej długości '{1}'.", + "The {0} field is not a valid phone number.": "Pole {0} nie jest poprawnym numerem telefonu.", + "The field {0} must be between {1} and {2}.": "Pole {0} musi być pomiędzy {1} i {2}.", + "The field {0} must match the regular expression '{1}'.": "Pole {0} musi pasować do wyrażenia regularnego '{1}'.", + "The {0} field is required.": "Pole {0} jest wymagane.", + "The field {0} must be a string with a maximum length of {1}.": "Pole {0} musi być łańcuchem znaków o maksymalnej długości {1}.", + "The field {0} must be a string with a minimum length of {2} and a maximum length of {1}.": "Pole {0} musi być łańcuchem znaków o minimalnej długości {2} i maksymalnej długości {1}.", + "The {0} field is not a valid fully-qualified http, https, or ftp URL.": "Pole {0} nie jest prawidłowym, w pełni kwalifikowanym adresem URL http, https lub ftp.", + "The field {0} is invalid.": "Pole {0} jest niepoprawne." + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpValidation/vi.json b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpValidation/vi.json new file mode 100644 index 0000000000..2d9c0c55f5 --- /dev/null +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpValidation/vi.json @@ -0,0 +1,19 @@ +{ + "culture": "vi", + "texts": { + "'{0}' and '{1}' do not match.": "'{0}' và '{1}' không khớp.", + "The {0} field is not a valid credit card number.": "Trường {0} không phải là một số thẻ tín dụng hợp lệ.", + "{0} is not valid.": "{0} không hợp lệ.", + "The {0} field is not a valid e-mail address.": "Trường {0} không phải là một địa chỉ email hợp lệ.", + "The {0} field only accepts files with the following extensions: {1}": "Trường {0} chỉ chấp nhận các tập tin có phần mở rộng như sau: {1}", + "The field {0} must be a string or array type with a maximum length of '{1}'.": "Trường {0} phải là một chuỗi hoặc một mảng với độ dài tối đa là '{1}'.", + "The {0} field is not a valid phone number.": "Trường {0} không phải là một số điện thoại hợp lệ", + "The field {0} must be between {1} and {2}.": "Trường {0} phải ở giữa {1} and {2}.", + "The field {0} must match the regular expression '{1}'.": "Trường {0} phải khớp với biểu thức chính quy '{1}'.", + "The {0} field is required.": "Trường {0} là bắt buộc.", + "The field {0} must be a string with a maximum length of {1}.": "Trường {0} phải là một chuỗi với độ dài tối đa là {1}.", + "The field {0} must be a string with a minimum length of {2} and a maximum length of {1}.": "Trường {0} phải là một chuỗi với độ dài tối thiểu {2} và tối đa là {1}.", + "The {0} field is not a valid fully-qualified http, https, or ftp URL.": "Trường {0} không phải là một http, https, hoặc ftp URL đủ điều kiện hợp lệ.", + "The field {0} is invalid.": "Trường {0} không có hiệu lực" + } +} diff --git a/framework/src/Volo.Abp.MongoDB/Volo.Abp.MongoDB.csproj b/framework/src/Volo.Abp.MongoDB/Volo.Abp.MongoDB.csproj index 9492e6fbf3..0610e45bfd 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo.Abp.MongoDB.csproj +++ b/framework/src/Volo.Abp.MongoDB/Volo.Abp.MongoDB.csproj @@ -14,7 +14,7 @@ - + diff --git a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/cs.json b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/cs.json new file mode 100644 index 0000000000..b2c46465c0 --- /dev/null +++ b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/cs.json @@ -0,0 +1,6 @@ +{ + "culture": "cs", + "texts": { + "Menu:Administration": "Administrace" + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/pl.json b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/pl.json new file mode 100644 index 0000000000..557d01eb31 --- /dev/null +++ b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/pl.json @@ -0,0 +1,6 @@ +{ + "culture": "pl", + "texts": { + "Menu:Administration": "Administracja" + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/pt-BR.json b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/pt-BR.json new file mode 100644 index 0000000000..d8eacbc96d --- /dev/null +++ b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/pt-BR.json @@ -0,0 +1,6 @@ +{ + "culture": "pt-BR", + "texts": { + "Menu:Administration": "Administração" + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/vi.json b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/vi.json new file mode 100644 index 0000000000..c5bf1c5ccd --- /dev/null +++ b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/vi.json @@ -0,0 +1,6 @@ +{ + "culture": "vi", + "texts": { + "Menu:Administration": "Quản trị" + } +} diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/cs.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/cs.json new file mode 100644 index 0000000000..b67fc568b3 --- /dev/null +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/cs.json @@ -0,0 +1,51 @@ +{ + "culture": "cs", + "texts": { + "InternalServerErrorMessage": "Během požadavku se vyskytla vnitřní chyba!", + "ValidationErrorMessage": "Neplatný požadavek!", + "ValidationNarrativeErrorMessageTitle": "Během ověřování byly zjištěny následující chyby.", + "DefaultErrorMessage": "Vyskytla se chyba!", + "DefaultErrorMessageDetail": "Server neposkytl detaily k chybě.", + "DefaultErrorMessage401": "Nejste přihlášeni!", + "DefaultErrorMessage401Detail": "K vykonání této operace se musíte nejprve přihlásit.", + "DefaultErrorMessage403": "Nemáte oprávnění!", + "DefaultErrorMessage403Detail": "Není vám dovoleno vykonat tuto operaci!", + "DefaultErrorMessage404": "Prostředek nenalezen!", + "DefaultErrorMessage404Detail": "Vyžádaný prostředek nebyl na serveru nalezen!", + "EntityNotFoundErrorMessage": "Neexistující entita {0} s id = {1}!", + "Error": "Chyba", + "AreYouSure": "Jste si jisti?", + "Cancel": "Zrušit", + "Yes": "Ano", + "No": "Ne", + "Close": "Zavřít", + "Save": "Uložit", + "SavingWithThreeDot": "Ukládám...", + "Actions": "Akce", + "Delete": "Smazat", + "Edit": "Upravit", + "Refresh": "Obnovit", + "ProcessingWithThreeDot": "Zpracovávám...", + "LoadingWithThreeDot": "Nahrávám...", + "Welcome": "Vítejte", + "Login": "Přihlášení", + "Register": "Registrovat", + "Logout": "Odhlásit", + "Submit": "Odeslat", + "Back": "Zpět", + "PagerSearch": "Vyhledat", + "PagerNext": "Další", + "PagerPrevious": "Předchozí", + "PagerFirst": "První", + "PagerLast": "Poslední", + "PagerInfo": "Zobrazeno od _START_ do _END_ z celkem _TOTAL_ záznamů", + "PagerInfoEmpty": "Zobrazeno od 0 do 0 z celkem 0 záznamů", + "PagerInfoFiltered": "(filtrováno ze všech _MAX_ záznamů)", + "NoDataAvailableInDatatable": "V tabulce nejsou žádná data", + "PagerShowMenuEntries": "Zobrazit _MENU_ záznamů", + "DatatableActionDropdownDefaultText": "Akce", + "ChangePassword": "Změnit heslo", + "PersonalInfo": "Můj profil", + "AreYouSureYouWantToCancelEditingWarningMessage": "Máte neuložené změny." + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pl.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pl.json new file mode 100644 index 0000000000..5f369760a1 --- /dev/null +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pl.json @@ -0,0 +1,51 @@ +{ + "culture": "pl", + "texts": { + "InternalServerErrorMessage": "Błąd wewnętrzny serwera podczas przetwarzania żądania!", + "ValidationErrorMessage": "Twoje żądanie jest niepoprawnie!", + "ValidationNarrativeErrorMessageTitle": "Wykryto następujące błędy podczas walidacji.", + "DefaultErrorMessage": "Wystąpił błąd!", + "DefaultErrorMessageDetail": "Treść błędu nie została wysłana z serwera.", + "DefaultErrorMessage401": "Nie jesteś zalogowany!", + "DefaultErrorMessage401Detail": "Musisz się zalogować, aby wykonać tą operację.", + "DefaultErrorMessage403": "Nie jesteś zautentykowany!", + "DefaultErrorMessage403Detail": "Nie masz uprawnień do wykonania tej operacji!", + "DefaultErrorMessage404": "Nie znaleziono zasobu!", + "DefaultErrorMessage404Detail": "Nie znaleziono zasobu z żądania na serwerze!", + "EntityNotFoundErrorMessage": "Nie istnieje encja {0} z id = {1}!", + "Error": "Błąd", + "AreYouSure": "Czy jesteś pewien?", + "Cancel": "Anuluj", + "Yes": "Tak", + "No": "Nie", + "Close": "Zamknij", + "Save": "Zapisz", + "SavingWithThreeDot": "Zapisywanie...", + "Actions": "Akcje", + "Delete": "Usuń", + "Edit": "Edytuj", + "Refresh": "Odśwież", + "ProcessingWithThreeDot": "Procesowanie...", + "LoadingWithThreeDot": "Ładowanie...", + "Welcome": "Witaj", + "Login": "Zaloguj", + "Register": "Zarejestruj", + "Logout": "Wyloguj", + "Submit": "Wyślij", + "Back": "Cofnij", + "PagerSearch": "Szukaj", + "PagerNext": "Następna", + "PagerPrevious": "Poprzednia", + "PagerFirst": "Pierwsza", + "PagerLast": "Ostatnia", + "PagerInfo": "Pokaż od _START_ do _END_ z _TOTAL_ rekordów", + "PagerInfoEmpty": "Pokaż od 0 do 0 z 0 rekordów", + "PagerInfoFiltered": "(filtruj od _MAX_ wszystkich rekordów)", + "NoDataAvailableInDatatable": "Nie znaleziono danych w tabeli", + "PagerShowMenuEntries": "Pokaż _MENU_ rekordów", + "DatatableActionDropdownDefaultText": "Akcje", + "ChangePassword": "Zmień hasło", + "PersonalInfo": "Mój profil", + "AreYouSureYouWantToCancelEditingWarningMessage": "Masz niezapisane zmiany." + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/vi.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/vi.json new file mode 100644 index 0000000000..21a466ccda --- /dev/null +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/vi.json @@ -0,0 +1,51 @@ +{ + "culture": "vi", + "texts": { + "InternalServerErrorMessage": "Có một lỗi nội bộ xảy ra trong quá trình thực hiện yêu cầu của bạn!", + "ValidationErrorMessage": "Yêu cầu của bạn không hợp lệ!", + "ValidationNarrativeErrorMessageTitle": "Các lỗi sau đây đã được phát hiện trong quá trình xác nhận", + "DefaultErrorMessage": "Một lỗi đã xảy ra", + "DefaultErrorMessageDetail": "Chi tiết lỗi không được gửi bởi máy chủ", + "DefaultErrorMessage401": "Bạn chưa được xác thực", + "DefaultErrorMessage401Detail": "Bạn cần đăng nhập để thực hiện thao tác này.", + "DefaultErrorMessage403": "Bạn không được phép!", + "DefaultErrorMessage403Detail": "Bạn không được phép thực hiện thao tác này!", + "DefaultErrorMessage404": "Tài nguyên không tìm thấy!", + "DefaultErrorMessage404Detail": "Tài nguyên được yêu cầu không được tìm thấy trên máy chủ!", + "EntityNotFoundErrorMessage": "Không có thực thể nào {0} với id = {1}!", + "Error": "Lỗi", + "AreYouSure": "Bạn có chắc không ?", + "Cancel": "Hủy bỏ", + "Yes": "Đồng ý", + "No": "Không", + "Close": "Đóng", + "Save": "Lưu", + "SavingWithThreeDot": "Đang lưu...", + "Actions": "Hành động", + "Delete": "Xóa", + "Edit": "Sửa", + "Refresh": "Làm mới", + "ProcessingWithThreeDot": "Đang xử lý...", + "LoadingWithThreeDot": "Đang tải...", + "Welcome": "Chào mừng bạn", + "Login": "Đăng nhập", + "Register": "Đăng ký", + "Logout": "Đăng xuất", + "Submit": "Gửi", + "Back": "Quay lại", + "PagerSearch": "Tìm kiếm", + "PagerNext": "Trang kế", + "PagerPrevious": "Trang trước", + "PagerFirst": "Trang đầu", + "PagerLast": "Trang cuối", + "PagerInfo": "Hiển thị từ _START_ đến _END_ trong _TOTAL_ mục", + "PagerInfoEmpty": "Hiển thị từ 0 đến 0 trong 0 mục", + "PagerInfoFiltered": "(được lọc từ tổng số _MAX_ mục)", + "NoDataAvailableInDatatable": "Không có dữ liệu trong bảng", + "PagerShowMenuEntries": "Hiển thị _MENU_ mục", + "DatatableActionDropdownDefaultText": "Hành động", + "ChangePassword": "Đổi mật khẩu", + "PersonalInfo": "Hồ sơ của tôi", + "AreYouSureYouWantToCancelEditingWarningMessage": "Bạn có những thay đổi chưa được lưu" + } +} diff --git a/framework/test/AbpTestBase/AbpTestBase.csproj b/framework/test/AbpTestBase/AbpTestBase.csproj index 4a25e99676..3aeaf7bd7d 100644 --- a/framework/test/AbpTestBase/AbpTestBase.csproj +++ b/framework/test/AbpTestBase/AbpTestBase.csproj @@ -15,8 +15,8 @@ - - + + diff --git a/framework/test/Volo.Abp.AspNetCore.Authentication.OAuth.Tests/Volo.Abp.AspNetCore.Authentication.OAuth.Tests.csproj b/framework/test/Volo.Abp.AspNetCore.Authentication.OAuth.Tests/Volo.Abp.AspNetCore.Authentication.OAuth.Tests.csproj index 806e426f82..b76e89b5d6 100644 --- a/framework/test/Volo.Abp.AspNetCore.Authentication.OAuth.Tests/Volo.Abp.AspNetCore.Authentication.OAuth.Tests.csproj +++ b/framework/test/Volo.Abp.AspNetCore.Authentication.OAuth.Tests/Volo.Abp.AspNetCore.Authentication.OAuth.Tests.csproj @@ -15,7 +15,7 @@ - + diff --git a/framework/test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo.Abp.AspNetCore.MultiTenancy.Tests.csproj b/framework/test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo.Abp.AspNetCore.MultiTenancy.Tests.csproj index b0d3baaad9..4142fa7f39 100644 --- a/framework/test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo.Abp.AspNetCore.MultiTenancy.Tests.csproj +++ b/framework/test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo.Abp.AspNetCore.MultiTenancy.Tests.csproj @@ -14,7 +14,7 @@ - + diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo.Abp.AspNetCore.Mvc.Tests.csproj b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo.Abp.AspNetCore.Mvc.Tests.csproj index bd0a8c1ca0..ea9514a9cb 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo.Abp.AspNetCore.Mvc.Tests.csproj +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo.Abp.AspNetCore.Mvc.Tests.csproj @@ -21,7 +21,7 @@ - + diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/cs.json b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/cs.json new file mode 100644 index 0000000000..65c0603c50 --- /dev/null +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/cs.json @@ -0,0 +1,7 @@ +{ + "culture": "cs", + "texts": { + "BirthDate": "Narozeniny", + "Value1": "Hodnota jedna" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/pl.json b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/pl.json new file mode 100644 index 0000000000..c794c9c123 --- /dev/null +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/pl.json @@ -0,0 +1,7 @@ +{ + "culture": "pl", + "texts": { + "BirthDate": "Data urodzenia", + "Value1": "Wartość jeden" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/vi.json b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/vi.json new file mode 100644 index 0000000000..046b7893f3 --- /dev/null +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/vi.json @@ -0,0 +1,7 @@ +{ + "culture": "vi", + "texts": { + "BirthDate": "Ngày sinh", + "Value1": "Giá trị thứ nhất" + } +} diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests.csproj b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests.csproj index a25b7d7d8f..93b64b0632 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests.csproj +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests.csproj @@ -20,7 +20,7 @@ - + diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Tests/Volo.Abp.AspNetCore.Mvc.UI.Tests.csproj b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Tests/Volo.Abp.AspNetCore.Mvc.UI.Tests.csproj index 74c0285f34..2404de7777 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Tests/Volo.Abp.AspNetCore.Mvc.UI.Tests.csproj +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Tests/Volo.Abp.AspNetCore.Mvc.UI.Tests.csproj @@ -17,7 +17,7 @@ - + diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Versioning.Tests/Volo.Abp.AspNetCore.Mvc.Versioning.Tests.csproj b/framework/test/Volo.Abp.AspNetCore.Mvc.Versioning.Tests/Volo.Abp.AspNetCore.Mvc.Versioning.Tests.csproj index d32284ed87..2d0ddd9412 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.Versioning.Tests/Volo.Abp.AspNetCore.Mvc.Versioning.Tests.csproj +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Versioning.Tests/Volo.Abp.AspNetCore.Mvc.Versioning.Tests.csproj @@ -17,7 +17,7 @@ - + diff --git a/framework/test/Volo.Abp.AspNetCore.Tests/Volo.Abp.AspNetCore.Tests.csproj b/framework/test/Volo.Abp.AspNetCore.Tests/Volo.Abp.AspNetCore.Tests.csproj index 9c7544a2f6..e1d676335a 100644 --- a/framework/test/Volo.Abp.AspNetCore.Tests/Volo.Abp.AspNetCore.Tests.csproj +++ b/framework/test/Volo.Abp.AspNetCore.Tests/Volo.Abp.AspNetCore.Tests.csproj @@ -14,7 +14,7 @@ - + diff --git a/framework/test/Volo.Abp.Auditing.Tests/Volo.Abp.Auditing.Tests.csproj b/framework/test/Volo.Abp.Auditing.Tests/Volo.Abp.Auditing.Tests.csproj index cb099c5168..4034493fc7 100644 --- a/framework/test/Volo.Abp.Auditing.Tests/Volo.Abp.Auditing.Tests.csproj +++ b/framework/test/Volo.Abp.Auditing.Tests/Volo.Abp.Auditing.Tests.csproj @@ -16,7 +16,7 @@ - + diff --git a/framework/test/Volo.Abp.Authorization.Tests/Volo.Abp.Authorization.Tests.csproj b/framework/test/Volo.Abp.Authorization.Tests/Volo.Abp.Authorization.Tests.csproj index 88925bb67d..40c4907756 100644 --- a/framework/test/Volo.Abp.Authorization.Tests/Volo.Abp.Authorization.Tests.csproj +++ b/framework/test/Volo.Abp.Authorization.Tests/Volo.Abp.Authorization.Tests.csproj @@ -16,7 +16,7 @@ - + diff --git a/framework/test/Volo.Abp.AutoMapper.Tests/Volo.Abp.AutoMapper.Tests.csproj b/framework/test/Volo.Abp.AutoMapper.Tests/Volo.Abp.AutoMapper.Tests.csproj index 9eb89d4af9..e2f7ed2cfd 100644 --- a/framework/test/Volo.Abp.AutoMapper.Tests/Volo.Abp.AutoMapper.Tests.csproj +++ b/framework/test/Volo.Abp.AutoMapper.Tests/Volo.Abp.AutoMapper.Tests.csproj @@ -14,7 +14,7 @@ - + \ No newline at end of file diff --git a/framework/test/Volo.Abp.Autofac.Tests/Volo.Abp.Autofac.Tests.csproj b/framework/test/Volo.Abp.Autofac.Tests/Volo.Abp.Autofac.Tests.csproj index c92d40f8be..6c1a23c66f 100644 --- a/framework/test/Volo.Abp.Autofac.Tests/Volo.Abp.Autofac.Tests.csproj +++ b/framework/test/Volo.Abp.Autofac.Tests/Volo.Abp.Autofac.Tests.csproj @@ -15,7 +15,7 @@ - + \ No newline at end of file diff --git a/framework/test/Volo.Abp.BackgroundJobs.Tests/Volo.Abp.BackgroundJobs.Tests.csproj b/framework/test/Volo.Abp.BackgroundJobs.Tests/Volo.Abp.BackgroundJobs.Tests.csproj index 7fa0474264..fea03fb2cf 100644 --- a/framework/test/Volo.Abp.BackgroundJobs.Tests/Volo.Abp.BackgroundJobs.Tests.csproj +++ b/framework/test/Volo.Abp.BackgroundJobs.Tests/Volo.Abp.BackgroundJobs.Tests.csproj @@ -16,7 +16,7 @@ - + \ No newline at end of file diff --git a/framework/test/Volo.Abp.Caching.Tests/Volo.Abp.Caching.Tests.csproj b/framework/test/Volo.Abp.Caching.Tests/Volo.Abp.Caching.Tests.csproj index 2b4696092c..3fd378b759 100644 --- a/framework/test/Volo.Abp.Caching.Tests/Volo.Abp.Caching.Tests.csproj +++ b/framework/test/Volo.Abp.Caching.Tests/Volo.Abp.Caching.Tests.csproj @@ -15,7 +15,7 @@ - + diff --git a/framework/test/Volo.Abp.Castle.Core.Tests/Volo.Abp.Castle.Core.Tests.csproj b/framework/test/Volo.Abp.Castle.Core.Tests/Volo.Abp.Castle.Core.Tests.csproj index c5a45236c2..35b9edf31f 100644 --- a/framework/test/Volo.Abp.Castle.Core.Tests/Volo.Abp.Castle.Core.Tests.csproj +++ b/framework/test/Volo.Abp.Castle.Core.Tests/Volo.Abp.Castle.Core.Tests.csproj @@ -14,7 +14,7 @@ - + \ No newline at end of file diff --git a/framework/test/Volo.Abp.Cli.Core.Tests/Volo.Abp.Cli.Core.Tests.csproj b/framework/test/Volo.Abp.Cli.Core.Tests/Volo.Abp.Cli.Core.Tests.csproj index bb2664cdc1..0fae5b99d4 100644 --- a/framework/test/Volo.Abp.Cli.Core.Tests/Volo.Abp.Cli.Core.Tests.csproj +++ b/framework/test/Volo.Abp.Cli.Core.Tests/Volo.Abp.Cli.Core.Tests.csproj @@ -9,7 +9,7 @@ - + diff --git a/framework/test/Volo.Abp.Core.Tests/Volo.Abp.Core.Tests.csproj b/framework/test/Volo.Abp.Core.Tests/Volo.Abp.Core.Tests.csproj index bd58cb0d71..119ef18d83 100644 --- a/framework/test/Volo.Abp.Core.Tests/Volo.Abp.Core.Tests.csproj +++ b/framework/test/Volo.Abp.Core.Tests/Volo.Abp.Core.Tests.csproj @@ -14,7 +14,7 @@ - + diff --git a/framework/test/Volo.Abp.Data.Tests/Volo.Abp.Data.Tests.csproj b/framework/test/Volo.Abp.Data.Tests/Volo.Abp.Data.Tests.csproj index 13c9cb2ef3..7862e4e0ef 100644 --- a/framework/test/Volo.Abp.Data.Tests/Volo.Abp.Data.Tests.csproj +++ b/framework/test/Volo.Abp.Data.Tests/Volo.Abp.Data.Tests.csproj @@ -14,7 +14,7 @@ - + diff --git a/framework/test/Volo.Abp.Ddd.Tests/Volo.Abp.Ddd.Tests.csproj b/framework/test/Volo.Abp.Ddd.Tests/Volo.Abp.Ddd.Tests.csproj index ad4141f96f..802d8a53b0 100644 --- a/framework/test/Volo.Abp.Ddd.Tests/Volo.Abp.Ddd.Tests.csproj +++ b/framework/test/Volo.Abp.Ddd.Tests/Volo.Abp.Ddd.Tests.csproj @@ -15,7 +15,7 @@ - + diff --git a/framework/test/Volo.Abp.Emailing.Tests/Volo.Abp.Emailing.Tests.csproj b/framework/test/Volo.Abp.Emailing.Tests/Volo.Abp.Emailing.Tests.csproj index ca155ab951..d8b058f05a 100644 --- a/framework/test/Volo.Abp.Emailing.Tests/Volo.Abp.Emailing.Tests.csproj +++ b/framework/test/Volo.Abp.Emailing.Tests/Volo.Abp.Emailing.Tests.csproj @@ -21,7 +21,7 @@ - + diff --git a/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/Localization/cs.json b/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/Localization/cs.json new file mode 100644 index 0000000000..b03a2b3fb1 --- /dev/null +++ b/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/Localization/cs.json @@ -0,0 +1,6 @@ +{ + "culture": "cs", + "texts": { + "hello": "hello" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/Localization/pl.json b/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/Localization/pl.json new file mode 100644 index 0000000000..6dd6654aa1 --- /dev/null +++ b/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/Localization/pl.json @@ -0,0 +1,6 @@ +{ + "culture": "pl", + "texts": { + "hello": "witaj" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/Localization/pt-BR.json b/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/Localization/pt-BR.json new file mode 100644 index 0000000000..0e33dee138 --- /dev/null +++ b/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/Localization/pt-BR.json @@ -0,0 +1,6 @@ +{ + "culture": "pt-BR", + "texts": { + "hello": "Olá" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/Localization/vi.json b/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/Localization/vi.json new file mode 100644 index 0000000000..8261599d78 --- /dev/null +++ b/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/Localization/vi.json @@ -0,0 +1,6 @@ +{ + "culture": "vi", + "texts": { + "hello": "xin chào" + } +} diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo.Abp.EntityFrameworkCore.Tests.csproj b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo.Abp.EntityFrameworkCore.Tests.csproj index 3f32baa6aa..87cf70501a 100644 --- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo.Abp.EntityFrameworkCore.Tests.csproj +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo.Abp.EntityFrameworkCore.Tests.csproj @@ -21,7 +21,7 @@ - + \ No newline at end of file diff --git a/framework/test/Volo.Abp.EventBus.Tests/Volo.Abp.EventBus.Tests.csproj b/framework/test/Volo.Abp.EventBus.Tests/Volo.Abp.EventBus.Tests.csproj index e810d5ef76..ac8c0ef36f 100644 --- a/framework/test/Volo.Abp.EventBus.Tests/Volo.Abp.EventBus.Tests.csproj +++ b/framework/test/Volo.Abp.EventBus.Tests/Volo.Abp.EventBus.Tests.csproj @@ -17,7 +17,7 @@ - + diff --git a/framework/test/Volo.Abp.Features.Tests/Volo.Abp.Features.Tests.csproj b/framework/test/Volo.Abp.Features.Tests/Volo.Abp.Features.Tests.csproj index ece1f124d5..02c7475eb0 100644 --- a/framework/test/Volo.Abp.Features.Tests/Volo.Abp.Features.Tests.csproj +++ b/framework/test/Volo.Abp.Features.Tests/Volo.Abp.Features.Tests.csproj @@ -16,7 +16,7 @@ - + diff --git a/framework/test/Volo.Abp.FluentValidation.Tests/Volo.Abp.FluentValidation.Tests.csproj b/framework/test/Volo.Abp.FluentValidation.Tests/Volo.Abp.FluentValidation.Tests.csproj index b0bc864896..999d06d67c 100644 --- a/framework/test/Volo.Abp.FluentValidation.Tests/Volo.Abp.FluentValidation.Tests.csproj +++ b/framework/test/Volo.Abp.FluentValidation.Tests/Volo.Abp.FluentValidation.Tests.csproj @@ -15,7 +15,7 @@ - + diff --git a/framework/test/Volo.Abp.Http.Client.Tests/Volo.Abp.Http.Client.Tests.csproj b/framework/test/Volo.Abp.Http.Client.Tests/Volo.Abp.Http.Client.Tests.csproj index 4997863830..aff0575607 100644 --- a/framework/test/Volo.Abp.Http.Client.Tests/Volo.Abp.Http.Client.Tests.csproj +++ b/framework/test/Volo.Abp.Http.Client.Tests/Volo.Abp.Http.Client.Tests.csproj @@ -15,7 +15,7 @@ - + \ No newline at end of file diff --git a/framework/test/Volo.Abp.Ldap.Tests/Volo.Abp.Ldap.Tests.csproj b/framework/test/Volo.Abp.Ldap.Tests/Volo.Abp.Ldap.Tests.csproj new file mode 100644 index 0000000000..c221b309c4 --- /dev/null +++ b/framework/test/Volo.Abp.Ldap.Tests/Volo.Abp.Ldap.Tests.csproj @@ -0,0 +1,18 @@ + + + + netcoreapp2.2 + latest + false + + + + + + + + + + + + diff --git a/framework/test/Volo.Abp.Ldap.Tests/Volo/Abp/Ldap/Authenticate_Tests.cs b/framework/test/Volo.Abp.Ldap.Tests/Volo/Abp/Ldap/Authenticate_Tests.cs new file mode 100644 index 0000000000..35f631b8d2 --- /dev/null +++ b/framework/test/Volo.Abp.Ldap.Tests/Volo/Abp/Ldap/Authenticate_Tests.cs @@ -0,0 +1,70 @@ +using System; +using Shouldly; +using Volo.Abp.Modularity; +using Xunit; + +namespace Volo.Abp.Ldap +{ + + public class Authenticate_Tests : AbpIntegratedTest + { + protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) + { + options.UseAutofac(); + } + + private readonly ILdapManager _ldapManager; + private readonly LdapTestData _testData; + + public Authenticate_Tests() + { + // ReSharper disable once VirtualMemberCallInConstructor + _testData = GetRequiredService(); + _ldapManager = GetRequiredService(); + } + + [Fact(Skip = "need environment AD ")] + public void Authenticate() + { + var result = _ldapManager.Authenticate(_testData.AdministratorDomainName, _testData.AdministratorPassword); + + result.ShouldBeTrue(); + } + + [Fact(Skip = "need environment AD ")] + public void Authenticate_With_Wrong_Password() + { + var result = _ldapManager.Authenticate("NonExistentNameA", "PasswordA"); + + result.ShouldBeFalse(); + } + + [DependsOn(typeof(AbpLdapModule))] + public class TestModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + // not use ssl + // "LDAP": { + // "ServerHost": "192.168.101.54", + // "ServerPort": 389, + // "UseSSL": false + // } + + // use ssl + // "LDAP": { + // "ServerHost": "192.168.101.54", + // "ServerPort": 636, + // "UseSSL": true + // } + Configure(settings => + { + settings.ServerHost = "192.168.101.54"; + settings.ServerPort = 636; + settings.UseSsl = true; + }); + } + } + } + +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Ldap.Tests/Volo/Abp/Ldap/LdapHelps_Tests.cs b/framework/test/Volo.Abp.Ldap.Tests/Volo/Abp/Ldap/LdapHelps_Tests.cs new file mode 100644 index 0000000000..06d6834992 --- /dev/null +++ b/framework/test/Volo.Abp.Ldap.Tests/Volo/Abp/Ldap/LdapHelps_Tests.cs @@ -0,0 +1,84 @@ +using System.Collections.Generic; +using Shouldly; +using Xunit; + +namespace Volo.Abp.Ldap +{ + public class LdapHelps_Tests + { + + [Fact] + public void BuildCondition_With_Value() + { + // act + var res = LdapHelps.BuildCondition("objectClass", "testNameA"); + + // assert + res.ShouldBe("(objectClass=testNameA)"); + } + + [Fact] + public void BuildCondition_With_Null_Value() + { + // act + var res = LdapHelps.BuildCondition("objectClass", null); + + // assert + res.ShouldBeEmpty(); + } + + [Fact] + public void BuildCondition_With_Empty_Value() + { + // act + var res = LdapHelps.BuildCondition("objectClass", ""); + + // assert + res.ShouldBeEmpty(); + } + + [Fact] + public void BuildCondition_With_WhiteSpace_Value() + { + // act + var res = LdapHelps.BuildCondition("objectClass", " "); + + // assert + res.ShouldBeEmpty(); + } + + [Fact] + public void BuildFilter_With_Null_Condition() + { + // act + var res = LdapHelps.BuildFilter(null); + + // assert + res.ShouldBe("(&(objectClass=*))"); + } + + [Fact] + public void BuildFilter_With_Empty_Condition() + { + // act + var res = LdapHelps.BuildFilter(new Dictionary()); + + // assert + res.ShouldBe("(&(objectClass=*))"); + } + + [Fact] + public void BuildFilter_With_Condition() + { + // act + var conditions = new Dictionary + { + {"objectClass", "testClassA"}, {"objectCategory", "testCategoryA"}, {"name", null} + }; + var res = LdapHelps.BuildFilter(conditions); + + // assert + res.ShouldBe("(&(objectClass=testClassA)(objectCategory=testCategoryA))"); + } + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Ldap.Tests/Volo/Abp/Ldap/LdapManager_Tests.cs b/framework/test/Volo.Abp.Ldap.Tests/Volo/Abp/Ldap/LdapManager_Tests.cs new file mode 100644 index 0000000000..00d9287c4f --- /dev/null +++ b/framework/test/Volo.Abp.Ldap.Tests/Volo/Abp/Ldap/LdapManager_Tests.cs @@ -0,0 +1,245 @@ +using System; +using Shouldly; +using Volo.Abp.Modularity; +using Xunit; + +namespace Volo.Abp.Ldap +{ + + public class LdapManager_Tests : AbpIntegratedTest + { + protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) + { + options.UseAutofac(); + } + + private readonly ILdapManager _ldapManager; + private readonly LdapTestData _testData; + + public LdapManager_Tests() + { + // ReSharper disable once VirtualMemberCallInConstructor + _testData = GetRequiredService(); + _ldapManager = GetRequiredService(); + } + + [Fact(Skip = "need environment AD ")] + public void GetOrganizations_With_Empty_Condition() + { + var result = _ldapManager.GetOrganizations(); + + result.ShouldNotBeNull(); + result.ShouldContain(e => e.Name == _testData.DomainControllersName); + result.ShouldContain(e => e.DistinguishedName == _testData.DomainControllersDistinguishedName); + } + + [Fact(Skip = "need environment AD ")] + public void GetOrganizations_With_Name() + { + var result = _ldapManager.GetOrganizations(_testData.DomainControllersName); + + result.ShouldNotBeNull(); + result.ShouldHaveSingleItem(); + result.ShouldContain(e => e.Name == _testData.DomainControllersName); + result.ShouldContain(e => e.DistinguishedName == _testData.DomainControllersDistinguishedName); + } + + [Fact(Skip = "need environment AD ")] + public void GetOrganizations_With_Non_Existent_Name() + { + var result = _ldapManager.GetOrganizations("NonExistentNameA"); + + result.ShouldNotBeNull(); + result.ShouldBeEmpty(); + } + + [Fact(Skip = "need environment AD ")] + public void GetOrganization() + { + var result = _ldapManager.GetOrganization(_testData.DomainControllersDistinguishedName); + + result.ShouldNotBeNull(); + result.Name.ShouldBe(_testData.DomainControllersName); + } + + [Fact(Skip = "need environment AD ")] + public void GetOrganization_With_Non_Existent_DistinguishedName() + { + var result = _ldapManager.GetOrganization("NonExistentNameA"); + + result.ShouldBeNull(); + } + + [Fact(Skip = "need environment AD ")] + public void GetUsers_With_Empty_Condition() + { + var result = _ldapManager.GetUsers(); + + result.ShouldNotBeNull(); + result.ShouldContain(e => e.Name == _testData.AdministratorName); + } + + [Fact(Skip = "need environment AD ")] + public void GetUsers_With_Name() + { + var result = _ldapManager.GetUsers(name: _testData.AdministratorName); + + result.ShouldNotBeNull(); + result.ShouldContain(e => e.Name == _testData.AdministratorName); + } + + [Fact(Skip = "need environment AD ")] + public void GetUsers_With_Non_Existent_Name() + { + var result = _ldapManager.GetUsers(name: "NonExistentNameA"); + + result.ShouldNotBeNull(); + result.ShouldBeEmpty(); + } + + [Fact(Skip = "need environment AD ")] + public void GetUsers_With_CommonName() + { + var result = _ldapManager.GetUsers(commonName: _testData.AdministratorName); + + result.ShouldNotBeNull(); + result.ShouldContain(e => e.Name == _testData.AdministratorName); + } + + [Fact(Skip = "need environment AD ")] + public void GetUsers_With_Non_Existent_CommonName() + { + var result = _ldapManager.GetUsers(commonName: "NonExistentNameA"); + + result.ShouldNotBeNull(); + result.ShouldBeEmpty(); + } + + [Fact(Skip = "need environment AD ")] + public void GetUsers_With_DisplayName() + { + var result = _ldapManager.GetUsers(displayName: _testData.AdministratorName); + + result.ShouldNotBeNull(); + // the administrator in AD. not have display name by default. + result.ShouldBeEmpty(); + } + + [Fact(Skip = "need environment AD ")] + public void GetUser() + { + var result = _ldapManager.GetUser(_testData.AdministratorDistinguishedName); + + result.ShouldNotBeNull(); + result.Name.ShouldBe(_testData.AdministratorName); + } + + [Fact(Skip = "need environment AD ")] + public void GetUser_With_Non_Existent_DistinguishedName() + { + var result = _ldapManager.GetOrganization("NonExistentNameA"); + + result.ShouldBeNull(); + } + + [Fact(Skip = "need environment AD ")] + public void Authenticate() + { + var result = _ldapManager.Authenticate(_testData.AdministratorDomainName, _testData.AdministratorPassword); + + result.ShouldBeTrue(); + } + + [Fact(Skip = "need environment AD ")] + public void Authenticate_With_Wrong_Password() + { + var result = _ldapManager.Authenticate("NonExistentNameA", "PasswordA"); + + result.ShouldBeFalse(); + } + + [Fact(Skip = "need environment AD ")] + public void AddSubOrganization() + { + var parentOrganization = _ldapManager.GetOrganization(_testData.DomainControllersDistinguishedName); + var randomName = $"Test_{DateTime.Now.Ticks}"; + + _ldapManager.AddSubOrganization(randomName, parentOrganization); + + var result = _ldapManager.GetOrganizations(randomName); + result.ShouldNotBeNull(); + result.ShouldContain(e => e.Name == randomName); + } + + [Fact(Skip = "need environment AD ")] + public void AddSubOrganization_With_DistinguishedName() + { + var randomName = $"Test_{DateTime.Now.Ticks}"; + + _ldapManager.AddSubOrganization(randomName, _testData.DomainControllersDistinguishedName); + + var result = _ldapManager.GetOrganizations(randomName); + result.ShouldNotBeNull(); + result.ShouldContain(e => e.Name == randomName); + } + + [Fact(Skip = "need environment AD ")] + public void AddOrganizationUser() + { + var parentOrganization = _ldapManager.GetOrganization(_testData.DomainControllersDistinguishedName); + var randomName = $"Test_{DateTime.Now:yyMMddHHmmss}"; + _ldapManager.AddUserToOrganization(randomName, _testData.AdministratorPassword, parentOrganization); + + var result = _ldapManager.GetUsers(randomName); + result.ShouldNotBeNull(); + result.ShouldContain(e=>e.Name == randomName); + } + + [DependsOn(typeof(AbpLdapModule))] + public class TestModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + // not use ssl + // "LDAP": { + // "ServerHost": "192.168.101.54", + // "ServerPort": 389, + // "UseSSL": false, + // "Credentials": { + // "DomainUserName": "administrator@yourdomain.com.cn", + // "Password": "yH.20190528" + // }, + // "SearchBase": "CN=Users,DC=yourdomain,DC=com,DC=cn", + // "DomainName": "yourdomain.com.cn", + // "DomainDistinguishedName": "DC=yourdomain,DC=com,DC=cn" + // } + + // use ssl + // "LDAP": { + // "ServerHost": "192.168.101.54", + // "ServerPort": 636, + // "UseSSL": true, + // "Credentials": { + // "DomainUserName": "administrator@yourdomain.com.cn", + // "Password": "yH.20190528" + // }, + // "SearchBase": "CN=Users,DC=yourdomain,DC=com,DC=cn", + // "DomainName": "yourdomain.com.cn", + // "DomainDistinguishedName": "DC=yourdomain,DC=com,DC=cn" + // } + Configure(settings => + { + settings.ServerHost = "192.168.101.54"; + settings.ServerPort = 636; + settings.UseSsl = true; + settings.Credentials.DomainUserName = "administrator@yourdomain.com.cn"; + settings.Credentials.Password = "yH.20190528"; + settings.SearchBase = "DC=yourdomain,DC=com,DC=cn"; + settings.DomainName = "yourdomain.com.cn"; + settings.DomainDistinguishedName = "DC=yourdomain,DC=com,DC=cn"; + }); + } + } + } + +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Ldap.Tests/Volo/Abp/Ldap/LdapTestData.cs b/framework/test/Volo.Abp.Ldap.Tests/Volo/Abp/Ldap/LdapTestData.cs new file mode 100644 index 0000000000..8224686daa --- /dev/null +++ b/framework/test/Volo.Abp.Ldap.Tests/Volo/Abp/Ldap/LdapTestData.cs @@ -0,0 +1,27 @@ +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Ldap +{ + public class LdapTestData : ISingletonDependency + { + public string AdministratorName { get; } = "Administrator"; + public string AdministratorPassword { get; } = "yH.20190528"; + public string AdministratorDistinguishedName { get; } = "CN=Administrator,CN=Users,DC=yourdomain,DC=com,DC=cn"; + public string AdministratorDomainName { get; } = "Administrator@yourdomain.com.cn"; + + public string DomainControllersName = "Domain Controllers"; + public string DomainControllersDistinguishedName = "OU=Domain Controllers,DC=yourdomain,DC=com,DC=cn"; + + public string RootDistinguishedName { get; } = "DC=yourdomain,DC=com,DC=cn"; + + public string Organization001Name { get; } = "Test_A"; + + public string Test001Name { get; } = "test001"; + public string Test001Password { get; } = "yH.20190528"; + public string Test001Email { get; } = "test001@yourdomain.com.cn"; + + public string Test002Name { get; } = "test002"; + public string Test002Password { get; } = "yH.20190528"; + public string Test002WrongPassword { get; } = "yH.20190529"; + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo.Abp.Localization.Tests.csproj b/framework/test/Volo.Abp.Localization.Tests/Volo.Abp.Localization.Tests.csproj index 98a01e2fc7..1decc345f4 100644 --- a/framework/test/Volo.Abp.Localization.Tests/Volo.Abp.Localization.Tests.csproj +++ b/framework/test/Volo.Abp.Localization.Tests/Volo.Abp.Localization.Tests.csproj @@ -18,7 +18,7 @@ - + diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/cs.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/cs.json new file mode 100644 index 0000000000..6f249267c0 --- /dev/null +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/cs.json @@ -0,0 +1,7 @@ +{ + "culture": "cs", + "texts": { + "USA": "Spojené státy americké", + "Brazil": "Brazílie" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/en.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/en.json index ead8fc2af8..9bc0f26698 100644 --- a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/en.json +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/en.json @@ -2,6 +2,6 @@ "culture": "en", "texts": { "USA": "United States of America", - "Brazil": "Brasil" + "Brazil": "Brazil" } } \ No newline at end of file diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/pl.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/pl.json new file mode 100644 index 0000000000..5e343cf2f9 --- /dev/null +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/pl.json @@ -0,0 +1,7 @@ +{ + "culture": "pl", + "texts": { + "USA": "Stany Zjednoczone Ameryki", + "Brazil": "Brazylia" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/vi.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/vi.json new file mode 100644 index 0000000000..a429f8295b --- /dev/null +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/vi.json @@ -0,0 +1,7 @@ +{ + "culture": "vi", + "texts": { + "USA": "Nước Mỹ", + "Brazil": "Brazil" + } +} diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/cs.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/cs.json new file mode 100644 index 0000000000..9fd414c139 --- /dev/null +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/cs.json @@ -0,0 +1,7 @@ +{ + "culture": "cs", + "texts": { + "ThisFieldIsRequired": "Toto pole je povinné", + "MaxLenghtErrorMessage": "Toto pole může mít nanejvýš '{0}' znaků" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/pl.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/pl.json new file mode 100644 index 0000000000..1d0bfdf66a --- /dev/null +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/pl.json @@ -0,0 +1,7 @@ +{ + "culture": "pl", + "texts": { + "ThisFieldIsRequired": "To pole jest wymagane", + "MaxLenghtErrorMessage": "To pole może mieć maksymalnie '{0}' znaków" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/vi.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/vi.json new file mode 100644 index 0000000000..583eebab13 --- /dev/null +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/vi.json @@ -0,0 +1,7 @@ +{ + "culture": "vi", + "texts": { + "ThisFieldIsRequired": "Trường này là bắt buộc", + "MaxLenghtErrorMessage": "Trường này có thể có tối đa là '{0}' kí tự" + } +} diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/cs.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/cs.json new file mode 100644 index 0000000000..88593c2ba8 --- /dev/null +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/cs.json @@ -0,0 +1,11 @@ +{ + "culture": "cs", + "texts": { + "Hello {0}.": "Ahoj {0}.", + "Car": "Auto", + "CarPlural": "Auta", + "MaxLenghtErrorMessage": "Toto pole může mít nanejvýš '{0}' znaků", + "Universe": "Vesmír", + "FortyTwo": "Čtyřicet dva" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/pl.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/pl.json new file mode 100644 index 0000000000..d014bc7b30 --- /dev/null +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/pl.json @@ -0,0 +1,11 @@ +{ + "culture": "pl", + "texts": { + "Hello {0}.": "Witaj {0}.", + "Car": "Samochód", + "CarPlural": "Samochody", + "MaxLenghtErrorMessage": "To pole może mieć maksymalnie '{0}' znaków", + "Universe": "Wszechświat", + "FortyTwo": "Czterdzieści dwa" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/vi.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/vi.json new file mode 100644 index 0000000000..6f5bff743c --- /dev/null +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/vi.json @@ -0,0 +1,11 @@ +{ + "culture": "vi", + "texts": { + "Hello {0}.": "Xin chào {0}.", + "Car": "Car", + "CarPlural": "Cars", + "MaxLenghtErrorMessage": "Kích thước trường này có tối đa '{0}' kí tự", + "Universe": "Vũ trụ", + "FortyTwo": "Bốn mươi hai" + } +} diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/SourceExt/cs.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/SourceExt/cs.json new file mode 100644 index 0000000000..8054f6de70 --- /dev/null +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/SourceExt/cs.json @@ -0,0 +1,6 @@ +{ + "culture": "cs", + "texts": { + "SeeYou": "Měj se" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/SourceExt/pl.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/SourceExt/pl.json new file mode 100644 index 0000000000..2935790010 --- /dev/null +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/SourceExt/pl.json @@ -0,0 +1,6 @@ +{ + "culture": "pl", + "texts": { + "SeeYou": "Do zobaczenia" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/SourceExt/vi.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/SourceExt/vi.json new file mode 100644 index 0000000000..d4d350246f --- /dev/null +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/SourceExt/vi.json @@ -0,0 +1,6 @@ +{ + "culture": "vi", + "texts": { + "SeeYou": "Hẹn gặp lại" + } +} diff --git a/framework/test/Volo.Abp.MemoryDb.Tests/Volo.Abp.MemoryDb.Tests.csproj b/framework/test/Volo.Abp.MemoryDb.Tests/Volo.Abp.MemoryDb.Tests.csproj index 062cfaf730..1d83b1e54f 100644 --- a/framework/test/Volo.Abp.MemoryDb.Tests/Volo.Abp.MemoryDb.Tests.csproj +++ b/framework/test/Volo.Abp.MemoryDb.Tests/Volo.Abp.MemoryDb.Tests.csproj @@ -16,7 +16,7 @@ - + \ No newline at end of file diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo.Abp.MongoDB.Tests.csproj b/framework/test/Volo.Abp.MongoDB.Tests/Volo.Abp.MongoDB.Tests.csproj index 5ca5401bac..a99a675193 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo.Abp.MongoDB.Tests.csproj +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo.Abp.MongoDB.Tests.csproj @@ -19,8 +19,8 @@ - - + + \ No newline at end of file diff --git a/framework/test/Volo.Abp.MultiTenancy.Tests/Volo.Abp.MultiTenancy.Tests.csproj b/framework/test/Volo.Abp.MultiTenancy.Tests/Volo.Abp.MultiTenancy.Tests.csproj index 631ad1ed81..16c27a26a6 100644 --- a/framework/test/Volo.Abp.MultiTenancy.Tests/Volo.Abp.MultiTenancy.Tests.csproj +++ b/framework/test/Volo.Abp.MultiTenancy.Tests/Volo.Abp.MultiTenancy.Tests.csproj @@ -14,7 +14,7 @@ - + diff --git a/framework/test/Volo.Abp.Security.Tests/Volo.Abp.Security.Tests.csproj b/framework/test/Volo.Abp.Security.Tests/Volo.Abp.Security.Tests.csproj index 5339246c52..46b4c9e952 100644 --- a/framework/test/Volo.Abp.Security.Tests/Volo.Abp.Security.Tests.csproj +++ b/framework/test/Volo.Abp.Security.Tests/Volo.Abp.Security.Tests.csproj @@ -14,7 +14,7 @@ - + diff --git a/framework/test/Volo.Abp.Serialization.Tests/Volo.Abp.Serialization.Tests.csproj b/framework/test/Volo.Abp.Serialization.Tests/Volo.Abp.Serialization.Tests.csproj index 99db6083c2..a7325c95c0 100644 --- a/framework/test/Volo.Abp.Serialization.Tests/Volo.Abp.Serialization.Tests.csproj +++ b/framework/test/Volo.Abp.Serialization.Tests/Volo.Abp.Serialization.Tests.csproj @@ -15,7 +15,7 @@ - + diff --git a/framework/test/Volo.Abp.Settings.Tests/Volo.Abp.Settings.Tests.csproj b/framework/test/Volo.Abp.Settings.Tests/Volo.Abp.Settings.Tests.csproj index 1e9bd3f4a0..76f2d05afa 100644 --- a/framework/test/Volo.Abp.Settings.Tests/Volo.Abp.Settings.Tests.csproj +++ b/framework/test/Volo.Abp.Settings.Tests/Volo.Abp.Settings.Tests.csproj @@ -16,7 +16,7 @@ - + diff --git a/framework/test/Volo.Abp.Specifications.Tests/Volo.Abp.Specifications.Tests.csproj b/framework/test/Volo.Abp.Specifications.Tests/Volo.Abp.Specifications.Tests.csproj index 6f2cbe09f8..e3f35153f9 100644 --- a/framework/test/Volo.Abp.Specifications.Tests/Volo.Abp.Specifications.Tests.csproj +++ b/framework/test/Volo.Abp.Specifications.Tests/Volo.Abp.Specifications.Tests.csproj @@ -15,7 +15,7 @@ - + \ No newline at end of file diff --git a/framework/test/Volo.Abp.TestApp.Tests/Volo.Abp.TestApp.Tests.csproj b/framework/test/Volo.Abp.TestApp.Tests/Volo.Abp.TestApp.Tests.csproj index 3985910708..51b60b693f 100644 --- a/framework/test/Volo.Abp.TestApp.Tests/Volo.Abp.TestApp.Tests.csproj +++ b/framework/test/Volo.Abp.TestApp.Tests/Volo.Abp.TestApp.Tests.csproj @@ -13,7 +13,7 @@ - + diff --git a/framework/test/Volo.Abp.TestApp/Volo.Abp.TestApp.csproj b/framework/test/Volo.Abp.TestApp/Volo.Abp.TestApp.csproj index 4e7b58ee84..3da0bcd7ce 100644 --- a/framework/test/Volo.Abp.TestApp/Volo.Abp.TestApp.csproj +++ b/framework/test/Volo.Abp.TestApp/Volo.Abp.TestApp.csproj @@ -18,7 +18,7 @@ - + diff --git a/framework/test/Volo.Abp.UI.Navigation.Tests/Volo.Abp.UI.Navigation.Tests.csproj b/framework/test/Volo.Abp.UI.Navigation.Tests/Volo.Abp.UI.Navigation.Tests.csproj index 10318fbf90..4fa8929ed4 100644 --- a/framework/test/Volo.Abp.UI.Navigation.Tests/Volo.Abp.UI.Navigation.Tests.csproj +++ b/framework/test/Volo.Abp.UI.Navigation.Tests/Volo.Abp.UI.Navigation.Tests.csproj @@ -14,7 +14,7 @@ - + diff --git a/framework/test/Volo.Abp.Uow.Tests/Volo.Abp.Uow.Tests.csproj b/framework/test/Volo.Abp.Uow.Tests/Volo.Abp.Uow.Tests.csproj index f3dede4b21..574891cc27 100644 --- a/framework/test/Volo.Abp.Uow.Tests/Volo.Abp.Uow.Tests.csproj +++ b/framework/test/Volo.Abp.Uow.Tests/Volo.Abp.Uow.Tests.csproj @@ -15,7 +15,7 @@ - + diff --git a/framework/test/Volo.Abp.Validation.Tests/Volo.Abp.Validation.Tests.csproj b/framework/test/Volo.Abp.Validation.Tests/Volo.Abp.Validation.Tests.csproj index 60308b96ae..7fb87036e2 100644 --- a/framework/test/Volo.Abp.Validation.Tests/Volo.Abp.Validation.Tests.csproj +++ b/framework/test/Volo.Abp.Validation.Tests/Volo.Abp.Validation.Tests.csproj @@ -15,7 +15,7 @@ - + diff --git a/framework/test/Volo.Abp.VirtualFileSystem.Tests/Volo.Abp.VirtualFileSystem.Tests.csproj b/framework/test/Volo.Abp.VirtualFileSystem.Tests/Volo.Abp.VirtualFileSystem.Tests.csproj index 895b8231ce..d69c461c29 100644 --- a/framework/test/Volo.Abp.VirtualFileSystem.Tests/Volo.Abp.VirtualFileSystem.Tests.csproj +++ b/framework/test/Volo.Abp.VirtualFileSystem.Tests/Volo.Abp.VirtualFileSystem.Tests.csproj @@ -18,7 +18,7 @@ - + diff --git a/modules/account/src/Volo.Abp.Account.Web/Localization/Resources/AbpAccount/Web/cs.json b/modules/account/src/Volo.Abp.Account.Web/Localization/Resources/AbpAccount/Web/cs.json new file mode 100644 index 0000000000..f0ec8ad410 --- /dev/null +++ b/modules/account/src/Volo.Abp.Account.Web/Localization/Resources/AbpAccount/Web/cs.json @@ -0,0 +1,21 @@ +{ + "culture": "cs", + "texts": { + "UserName": "Uživatelské jméno", + "EmailAddress": "Email", + "UserNameOrEmailAddress": "Uživatelské jméno nebo email", + "Password": "Heslo", + "RememberMe": "Zapamatovat si mě", + "UseAnotherServiceToLogin": "Použít jinou službu k přihlášení", + "UserLockedOutMessage": "Tento účet byl uzamčen z důvodu neúspěšných přihlášení. Přihlaste se prosím později.", + "InvalidUserNameOrPassword": "Neplatné uživatelské jméno nebo heslo!", + "LoginIsNotAllowed": "Není vám dovoleno se přihlásit! Musíte první potvrdit email/telefonní číslo.", + "SelfRegistrationDisabledMessage": "Vlastní registrace uživatele není povolena. K vytvoření účtu kontaktujte správce.", + "Login": "Přihlásit", + "Cancel": "Zrušit", + "Register": "Registrovat", + "InvalidLoginRequest": "Neplatný požadavek k přihlášení", + "ThereAreNoLoginSchemesConfiguredForThisClient": "Pro tohoto klienta nejsou nakonfigurovány žádné přihlašovací schémata.", + "LogInUsingYourProviderAccount": "Přihlásit pomocí vašeho účtu {0}" + } +} \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Web/Localization/Resources/AbpAccount/Web/en.json b/modules/account/src/Volo.Abp.Account.Web/Localization/Resources/AbpAccount/Web/en.json index 1055309b22..892e60f89e 100644 --- a/modules/account/src/Volo.Abp.Account.Web/Localization/Resources/AbpAccount/Web/en.json +++ b/modules/account/src/Volo.Abp.Account.Web/Localization/Resources/AbpAccount/Web/en.json @@ -14,7 +14,6 @@ "Login": "Login", "Cancel": "Cancel", "Register": "Register", - "UseAnotherServiceToLogIn.": "Use another service to log in.", "InvalidLoginRequest": "Invalid login request", "ThereAreNoLoginSchemesConfiguredForThisClient": "There are no login schemes configured for this client.", "LogInUsingYourProviderAccount": "Log in using your {0} account" diff --git a/modules/account/src/Volo.Abp.Account.Web/Localization/Resources/AbpAccount/Web/pl.json b/modules/account/src/Volo.Abp.Account.Web/Localization/Resources/AbpAccount/Web/pl.json new file mode 100644 index 0000000000..b661af8050 --- /dev/null +++ b/modules/account/src/Volo.Abp.Account.Web/Localization/Resources/AbpAccount/Web/pl.json @@ -0,0 +1,21 @@ +{ + "culture": "pl", + "texts": { + "UserName": "Nazwa użytkownika", + "EmailAddress": "Adres email", + "UserNameOrEmailAddress": "Nazwa użytkownia lub adres email", + "Password": "Hasło", + "RememberMe": "Zapamiętaj mnie", + "UseAnotherServiceToLogin": "Użyj innej usługi do zalogowania się", + "UserLockedOutMessage": "Konto użytkownika zostało zablokowane po nieudanych próbach zalogowania. Odczekaj chwilę i spróbuj ponownie.", + "InvalidUserNameOrPassword": "Niepoprawna nazwa użytkownika lub hasło!", + "LoginIsNotAllowed": "Nie jesteś uprawniony do logowania! Musisz potwierdzić swój email/numer telefonu.", + "SelfRegistrationDisabledMessage": "Rejestracja użytkowników jest wyłączona dla tej aplikacji. Skontaktuj się z administratorem aplikacji w celu rejestracji nowego użytkownika.", + "Login": "Zaloguj", + "Cancel": "Anuluj", + "Register": "Zarejestruj", + "InvalidLoginRequest": "Logowanie nieudane", + "ThereAreNoLoginSchemesConfiguredForThisClient": "Nie istnieje skonfigurany schemat logowania dla użytkownika.", + "LogInUsingYourProviderAccount": "Zaloguj używając konta {0}" + } +} \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Web/Localization/Resources/AbpAccount/Web/pt-BR.json b/modules/account/src/Volo.Abp.Account.Web/Localization/Resources/AbpAccount/Web/pt-BR.json index fec54c0476..0513d99afd 100644 --- a/modules/account/src/Volo.Abp.Account.Web/Localization/Resources/AbpAccount/Web/pt-BR.json +++ b/modules/account/src/Volo.Abp.Account.Web/Localization/Resources/AbpAccount/Web/pt-BR.json @@ -14,7 +14,6 @@ "Login": "Entrar", "Cancel": "Cancelar", "Register": "Registrar-se", - "UseAnotherServiceToLogIn.": "Use outro serviço para entrar.", "InvalidLoginRequest": "Requisição de acesso inválida!", "ThereAreNoLoginSchemesConfiguredForThisClient": "Não existe um esquema de acesso para este usuário", "LogInUsingYourProviderAccount": "Acessse utilizando sua conta {0}" diff --git a/modules/account/src/Volo.Abp.Account.Web/Localization/Resources/AbpAccount/Web/tr.json b/modules/account/src/Volo.Abp.Account.Web/Localization/Resources/AbpAccount/Web/tr.json index dfc1c9486a..3b78c3a55d 100644 --- a/modules/account/src/Volo.Abp.Account.Web/Localization/Resources/AbpAccount/Web/tr.json +++ b/modules/account/src/Volo.Abp.Account.Web/Localization/Resources/AbpAccount/Web/tr.json @@ -14,7 +14,6 @@ "Login": "Giriş yap", "Cancel": "İptal", "Register": "Kayıt ol", - "UseAnotherServiceToLogIn.": "Başka bir servisle giriş yap.", "InvalidLoginRequest": "Başarısız giriş isteği", "ThereAreNoLoginSchemesConfiguredForThisClient": "Bu client için konfigüre edilmiş giriş şeması bulunamadı.", "LogInUsingYourProviderAccount": "{0} hesabınızla giriş yapın." diff --git a/modules/account/src/Volo.Abp.Account.Web/Localization/Resources/AbpAccount/Web/vi.json b/modules/account/src/Volo.Abp.Account.Web/Localization/Resources/AbpAccount/Web/vi.json new file mode 100644 index 0000000000..56d436c1cd --- /dev/null +++ b/modules/account/src/Volo.Abp.Account.Web/Localization/Resources/AbpAccount/Web/vi.json @@ -0,0 +1,21 @@ +{ + "culture": "vi", + "texts": { + "UserName": "Tên đăng nhập", + "EmailAddress": "Địa chỉ email", + "UserNameOrEmailAddress": "Tên đăng nhập hoặc địa chỉ email", + "Password": "Mật khẩu", + "RememberMe": "Ghi nhớ", + "UseAnotherServiceToLogin": "Sử dụng dịch vụ khác để đăng nhập", + "UserLockedOutMessage": "Tài khoản người dùng đã bị khóa do các nỗ lực đăng nhập không hợp lệ. Xin vui lòng chờ một lúc và thử lại.", + "InvalidUserNameOrPassword": "Sai tên tài khoản hoặc mật khẩu!", + "LoginIsNotAllowed": "Bạn không được phép đăng nhập! Bạn cần xác nhận email/số điện thoại của bạn.", + "SelfRegistrationDisabledMessage": "Tự đăng ký người dùng bị vô hiệu hóa cho ứng dụng này. Liên hệ với quản trị viên ứng dụng để đăng ký người dùng mới.", + "Login": "Đăng nhập", + "Cancel": "Hủy bỏ", + "Register": "Đăng ký", + "InvalidLoginRequest": "Yêu cầu đăng nhập không hợp lệ", + "ThereAreNoLoginSchemesConfiguredForThisClient": "Không có chương trình đăng nhập được cấu hình cho khách hàng này.", + "LogInUsingYourProviderAccount": "Đăng nhập bằng tài khoản {0} của bạn" + } +} diff --git a/modules/account/src/Volo.Abp.Account.Web/Localization/Resources/AbpAccount/Web/zh-Hans.json b/modules/account/src/Volo.Abp.Account.Web/Localization/Resources/AbpAccount/Web/zh-Hans.json index 01e0b6b57d..6aee740de6 100644 --- a/modules/account/src/Volo.Abp.Account.Web/Localization/Resources/AbpAccount/Web/zh-Hans.json +++ b/modules/account/src/Volo.Abp.Account.Web/Localization/Resources/AbpAccount/Web/zh-Hans.json @@ -14,7 +14,6 @@ "Login": "登录", "Cancel": "取消", "Register": "注册", - "UseAnotherServiceToLogIn.": "使用其他服务登录.", "InvalidLoginRequest": "登录请求无效", "ThereAreNoLoginSchemesConfiguredForThisClient": "没有为此客户端配置登录方案.", "LogInUsingYourProviderAccount": "使用你的{0}帐户登录" diff --git a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.HangFire/Volo.Abp.BackgroundJobs.DemoApp.HangFire.csproj b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.HangFire/Volo.Abp.BackgroundJobs.DemoApp.HangFire.csproj index 8134b0c512..515f5d37f6 100644 --- a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.HangFire/Volo.Abp.BackgroundJobs.DemoApp.HangFire.csproj +++ b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.HangFire/Volo.Abp.BackgroundJobs.DemoApp.HangFire.csproj @@ -6,7 +6,7 @@ - + diff --git a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.Domain.Tests/Volo.Abp.BackgroundJobs.Domain.Tests.csproj b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.Domain.Tests/Volo.Abp.BackgroundJobs.Domain.Tests.csproj index a8ff824305..66ef602232 100644 --- a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.Domain.Tests/Volo.Abp.BackgroundJobs.Domain.Tests.csproj +++ b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.Domain.Tests/Volo.Abp.BackgroundJobs.Domain.Tests.csproj @@ -12,7 +12,7 @@ - + diff --git a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests/Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests.csproj b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests/Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests.csproj index 722d94f88e..7fd7558b02 100644 --- a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests/Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests.csproj +++ b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests/Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests.csproj @@ -13,7 +13,7 @@ - + diff --git a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo.Abp.BackgroundJobs.MongoDB.Tests.csproj b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo.Abp.BackgroundJobs.MongoDB.Tests.csproj index f3fb433d10..e999356678 100644 --- a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo.Abp.BackgroundJobs.MongoDB.Tests.csproj +++ b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo.Abp.BackgroundJobs.MongoDB.Tests.csproj @@ -13,8 +13,8 @@ - - + + diff --git a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.TestBase/Volo.Abp.BackgroundJobs.TestBase.csproj b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.TestBase/Volo.Abp.BackgroundJobs.TestBase.csproj index 1f4db1af41..ce6e3b7c1b 100644 --- a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.TestBase/Volo.Abp.BackgroundJobs.TestBase.csproj +++ b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.TestBase/Volo.Abp.BackgroundJobs.TestBase.csproj @@ -14,8 +14,8 @@ - - + + diff --git a/modules/blogging/app/Volo.BloggingTestApp/BloggingTestAppModule.cs b/modules/blogging/app/Volo.BloggingTestApp/BloggingTestAppModule.cs index 84ed5d1910..1bbc4a93a3 100644 --- a/modules/blogging/app/Volo.BloggingTestApp/BloggingTestAppModule.cs +++ b/modules/blogging/app/Volo.BloggingTestApp/BloggingTestAppModule.cs @@ -98,7 +98,14 @@ namespace Volo.BloggingTestApp options.CustomSchemaIds(type => type.FullName); }); - var cultures = new List { new CultureInfo("en"), new CultureInfo("tr"),new CultureInfo("zh-Hans") }; + var cultures = new List + { + new CultureInfo("cs"), + new CultureInfo("en"), + new CultureInfo("tr"), + new CultureInfo("zh-Hans") + }; + Configure(options => { options.DefaultRequestCulture = new RequestCulture("en"); diff --git a/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Localization/Resources/Blogging/ApplicationContracts/cs.json b/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Localization/Resources/Blogging/ApplicationContracts/cs.json new file mode 100644 index 0000000000..9b781b029e --- /dev/null +++ b/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Localization/Resources/Blogging/ApplicationContracts/cs.json @@ -0,0 +1,14 @@ +{ + "culture": "cs", + "texts": { + "Permission:Blogging": "Blog", + "Permission:Blogs": "Blogy", + "Permission:Posts": "Příspěvky", + "Permission:Tags": "Tagy", + "Permission:Comments": "Komentáře", + "Permission:Management": "Správa", + "Permission:Edit": "Upravit", + "Permission:Create": "Vytvořit", + "Permission:Delete": "Smazat" + } +} \ No newline at end of file diff --git a/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Localization/Resources/Blogging/ApplicationContracts/pl.json b/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Localization/Resources/Blogging/ApplicationContracts/pl.json new file mode 100644 index 0000000000..8806854643 --- /dev/null +++ b/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Localization/Resources/Blogging/ApplicationContracts/pl.json @@ -0,0 +1,14 @@ +{ + "culture": "pl", + "texts": { + "Permission:Blogging": "Blog", + "Permission:Blogs": "Blogi", + "Permission:Posts": "Posty", + "Permission:Tags": "Tagi", + "Permission:Comments": "Komentarze", + "Permission:Management": "Zarządzanie", + "Permission:Edit": "Edytuj", + "Permission:Create": "Utwórz", + "Permission:Delete": "Usuń" + } +} \ No newline at end of file diff --git a/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Localization/Resources/Blogging/ApplicationContracts/vi.json b/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Localization/Resources/Blogging/ApplicationContracts/vi.json new file mode 100644 index 0000000000..a32ee04bb9 --- /dev/null +++ b/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Localization/Resources/Blogging/ApplicationContracts/vi.json @@ -0,0 +1,14 @@ +{ + "culture": "vi", + "texts": { + "Permission:Blogging": "Blog", + "Permission:Blogs": "Blogs", + "Permission:Posts": "Bài viết", + "Permission:Tags": "Thẻ", + "Permission:Comments": "Bình luận", + "Permission:Management": "Quản lý", + "Permission:Edit": "Sửa", + "Permission:Create": "Tạo", + "Permission:Delete": "Xóa" + } +} diff --git a/modules/blogging/src/Volo.Blogging.Web/BloggingWebModule.cs b/modules/blogging/src/Volo.Blogging.Web/BloggingWebModule.cs index 20678ddc37..550bf059f5 100644 --- a/modules/blogging/src/Volo.Blogging.Web/BloggingWebModule.cs +++ b/modules/blogging/src/Volo.Blogging.Web/BloggingWebModule.cs @@ -45,6 +45,7 @@ namespace Volo.Blogging Configure(options => { + options.Languages.Add(new LanguageInfo("cs", "cs", "Čeština")); options.Languages.Add(new LanguageInfo("en", "en", "English")); options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe")); options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); diff --git a/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/cs.json b/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/cs.json new file mode 100644 index 0000000000..5e49b65288 --- /dev/null +++ b/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/cs.json @@ -0,0 +1,47 @@ +{ + "culture": "cs", + "texts": { + "Menu:Blogs": "Blogy", + "Menu:BlogManagement": "Správa blogu", + "Title": "Nadpis", + "Delete": "Smazat", + "Reply": "Odpovědět", + "ReplyTo": "Odpověď pro {0}", + "ContinueReading": "Číst dále", + "DaysAgo": "před {0} dny", + "YearsAgo": "před {0} roky", + "MonthsAgo": "před {0} měsíci", + "WeeksAgo": "před {0} týdny", + "MinutesAgo": "před {0} minutami", + "SecondsAgo": "před {0} sekundami", + "HoursAgo": "před {0} hodinami", + "Now": "nyní", + "Content": "Obsah", + "SeeAll": "Zobrazit vše", + "PopularTags": "Populární tagy", + "WiewsWithCount": "{0} zobrazení", + "LastPosts": "Poslední příspěvky", + "LeaveComment": "Přidat komentář", + "TagsInThisArticle": "Tagy v článku", + "Posts": "Příspěvky", + "Edit": "Upravit", + "BLOG": "BLOG", + "CommentDeletionWarningMessage": "Komentáře budou smazány.", + "PostDeletionWarningMessage": "Příspěvek bude smazán.", + "BlogDeletionWarningMessage": "Blog bude smazán.", + "AreYouSure": "Jste si jistí?", + "CommentWithCount": "{0} komentářů", + "Comment": "Komentář", + "ShareOnTwitter": "Sdílet na Twitteru", + "CoverImage": "Obrázek obálky", + "CreateANewPost": "Vytvořit nový příspěvek", + "CreateANewBlog": "Vytvořit nový blog", + "WhatIsNew": "Co je nového?", + "Name": "Název", + "ShortName": "Krátký název", + "CreationTime": "Vytvořeno", + "Description": "Popis", + "Blogs": "Blogy", + "Tags": "Tagy" + } +} \ No newline at end of file diff --git a/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/pl.json b/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/pl.json new file mode 100644 index 0000000000..15e0c7eb0d --- /dev/null +++ b/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/pl.json @@ -0,0 +1,47 @@ +{ + "culture": "pl", + "texts": { + "Menu:Blogs": "Blogi", + "Menu:BlogManagement": "Zarządzanie blogiem", + "Title": "Tytuł", + "Delete": "Usuń", + "Reply": "Odpowiedz", + "ReplyTo": "Odpowiedz {0}", + "ContinueReading": "Kontynuuj czytanie", + "DaysAgo": "{0} dni temu", + "YearsAgo": "{0} lat temu", + "MonthsAgo": "{0} miesięcy temu", + "WeeksAgo": "{0} tygodni temu", + "MinutesAgo": "{0} minut temu", + "SecondsAgo": "{0} sekund temu", + "HoursAgo": "{0} godzin temu", + "Now": "teraz", + "Content": "Treść", + "SeeAll": "Zobacz wszystko", + "PopularTags": "Popularne tagi", + "WiewsWithCount": "{0} wyświetleń", + "LastPosts": "Ostatnie wpisy", + "LeaveComment": "Zostaw komentarz", + "TagsInThisArticle": "Tagi w tym artykule", + "Posts": "Wpisy", + "Edit": "Edytuj", + "BLOG": "BLOG", + "CommentDeletionWarningMessage": "Komentarz zostanie usunięty.", + "PostDeletionWarningMessage": "Wpis zostanie usunięty.", + "BlogDeletionWarningMessage": "Blog zostanie usunięty.", + "AreYouSure": "Czy jesteś pewien?", + "CommentWithCount": "{0} komentarzy", + "Comment": "Komentarz", + "ShareOnTwitter": "Udostępnij na Twitter", + "CoverImage": "Obraz okładki", + "CreateANewPost": "Utwórz nowy wpis", + "CreateANewBlog": "Utwórz nowy blog", + "WhatIsNew": "Co nowego?", + "Name": "Nazwa", + "ShortName": "Krótka nazwa", + "CreationTime": "Data utworzenia", + "Description": "Opis", + "Blogs": "Blogi", + "Tags": "Tagi" + } +} \ No newline at end of file diff --git a/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/vi.json b/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/vi.json new file mode 100644 index 0000000000..1405337271 --- /dev/null +++ b/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/vi.json @@ -0,0 +1,47 @@ +{ + "culture": "vi", + "texts": { + "Menu:Blogs": "Blogs", + "Menu:BlogManagement": "Quản lý Blog", + "Title": "Tiêu đề", + "Delete": "Xóa", + "Reply": "Trả lời", + "ReplyTo": "Trả lời {0}", + "ContinueReading": "Tiếp tục đọc", + "DaysAgo": "{0} ngày trước", + "YearsAgo": "{0} năm trước", + "MonthsAgo": "{0} tháng trước", + "WeeksAgo": "{0} tuần trước", + "MinutesAgo": "{0} phút trước", + "SecondsAgo": "{0} giây trước", + "HoursAgo": "{0} giờ trước", + "Now": "bây giờ", + "Content": "Nội dung", + "SeeAll": "Xem tất cả", + "PopularTags": "Thẻ phổ biến", + "WiewsWithCount": "{0} lượt xem", + "LastPosts": "Bài viết cuối", + "LeaveComment": "Để lại bình luận", + "TagsInThisArticle": "Từ khóa trong bài viết này", + "Posts": "Bài viết", + "Edit": "Sửa", + "BLOG": "BLOG", + "CommentDeletionWarningMessage": "Bình luận sẽ bị xóa.", + "PostDeletionWarningMessage": "Bài viết sẽ bị xóa.", + "BlogDeletionWarningMessage": "Blog sẽ bị xóa.", + "AreYouSure": "Bạn chắc chứ?", + "CommentWithCount": "{0} bình luận", + "Comment": "Bình luận", + "ShareOnTwitter": "Chia sẻ Twitter", + "CoverImage": "Ảnh bìa", + "CreateANewPost": "Tạo một bài viết mới", + "CreateANewBlog": "Tạo một Blog mới", + "WhatIsNew": "Cái gì mới?", + "Name": "Tên", + "ShortName": "Tên rút gọn", + "CreationTime": "Thời gian tạo", + "Description": "Mô tả", + "Blogs": "Blogs", + "Tags": "Thẻ" + } +} diff --git a/modules/docs/app/VoloDocs.Web/Localization/Resources/VoloDocs/Web/cs.json b/modules/docs/app/VoloDocs.Web/Localization/Resources/VoloDocs/Web/cs.json new file mode 100644 index 0000000000..2ad18ee148 --- /dev/null +++ b/modules/docs/app/VoloDocs.Web/Localization/Resources/VoloDocs/Web/cs.json @@ -0,0 +1,9 @@ +{ + "culture": "cs", + "texts": { + "WelcomeVoloDocs": "Vítejte ve VoloDocs!", + "NoProjectWarning": "Zatím zde není žádný projekt!", + "CreateYourFirstProject": "Klikněte zde k vytvoření vašeho prvního projektu", + "NoProject": "Žádný projekt!" + } +} \ No newline at end of file diff --git a/modules/docs/app/VoloDocs.Web/Localization/Resources/VoloDocs/Web/pl.json b/modules/docs/app/VoloDocs.Web/Localization/Resources/VoloDocs/Web/pl.json new file mode 100644 index 0000000000..f131f9e139 --- /dev/null +++ b/modules/docs/app/VoloDocs.Web/Localization/Resources/VoloDocs/Web/pl.json @@ -0,0 +1,9 @@ +{ + "culture": "pl", + "texts": { + "WelcomeVoloDocs": "Witaj w VoloDocs!", + "NoProjectWarning": "Nie ma jeszcze zdefiniowanego projektu!", + "CreateYourFirstProject": "Kliknij, aby rozpocząć swój pierwszy projekt", + "NoProject": "Brak projektu!" + } +} \ No newline at end of file diff --git a/modules/docs/app/VoloDocs.Web/Localization/Resources/VoloDocs/Web/pt-BR.json b/modules/docs/app/VoloDocs.Web/Localization/Resources/VoloDocs/Web/pt-BR.json new file mode 100644 index 0000000000..cdd8a651ce --- /dev/null +++ b/modules/docs/app/VoloDocs.Web/Localization/Resources/VoloDocs/Web/pt-BR.json @@ -0,0 +1,9 @@ +{ + "culture": "pt-BR", + "texts": { + "WelcomeVoloDocs": "Bem vindo ao VoloDocs!", + "NoProjectWarning": "Ainda não existe um projeto definido!", + "CreateYourFirstProject": "Clique aqui para iniciar seu primeiro projeto", + "NoProject": "Sem projeto!" + } +} \ No newline at end of file diff --git a/modules/docs/app/VoloDocs.Web/Localization/Resources/VoloDocs/Web/vi.json b/modules/docs/app/VoloDocs.Web/Localization/Resources/VoloDocs/Web/vi.json new file mode 100644 index 0000000000..46afd97fd0 --- /dev/null +++ b/modules/docs/app/VoloDocs.Web/Localization/Resources/VoloDocs/Web/vi.json @@ -0,0 +1,9 @@ +{ + "culture": "vi", + "texts": { + "WelcomeVoloDocs": "Chào mừng đến với VoloDocs!", + "NoProjectWarning": "Không có dự án nào!", + "CreateYourFirstProject": "Nhấn vào đây để bắt đầu dự án đầu tiên của bạn", + "NoProject": "Không có dự án!" + } +} diff --git a/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml b/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml index 3cc5408311..0d75012326 100644 --- a/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml +++ b/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml @@ -1,55 +1,5 @@ @page - -@using System.Linq -@using Microsoft.AspNetCore.Mvc.Localization -@using Volo.Docs -@using Volo.Docs.Localization -@using Volo.Docs.Pages.Documents - @model VoloDocs.Web.Pages.IndexModel -@inject IHtmlLocalizer L - -@section styles { - - - +@{ } -
- -

- @L["WelcomeVoloDocs"] -

- - @if (!Model.Projects.Any()) - { -
- -
- } - else if (Model.Projects.Count > 1) - { -

@L["Projects"]

-

-

-

- } - -
diff --git a/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml.cs b/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml.cs index 8b6ffd2cdf..ec66947dd7 100644 --- a/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml.cs +++ b/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml.cs @@ -1,35 +1,26 @@ -using System.Collections.Generic; -using System.Threading.Tasks; +using System; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; +using Microsoft.Extensions.Options; using Volo.Docs; -using Volo.Docs.Projects; namespace VoloDocs.Web.Pages { public class IndexModel : PageModel { - public IReadOnlyList Projects { get; set; } + private readonly DocsUrlOptions _urlOptions; - private readonly IProjectAppService _projectAppService; - - public IndexModel(IProjectAppService projectAppService) + public IndexModel(IOptions urlOptions) { - _projectAppService = projectAppService; + _urlOptions = urlOptions.Value; } - public async Task OnGet() + public IActionResult OnGet() { - Projects = (await _projectAppService.GetListAsync()).Items; - - if (Projects.Count == 1) + //TODO: Create HomeController & Index instead of Page. Otherwise, we have an empty Index.cshtml file. + if (!_urlOptions.RoutePrefix.IsNullOrWhiteSpace()) { - return RedirectToPage("./Documents/Project/Index", new - { - projectName = Projects[0].ShortName, - version = DocsAppConsts.Latest, - documentName = Projects[0].DefaultDocumentName - }); + return Redirect("." + _urlOptions.GetFormattedRoutePrefix()); } return Page(); diff --git a/modules/docs/app/VoloDocs.Web/VoloDocsWebModule.cs b/modules/docs/app/VoloDocs.Web/VoloDocsWebModule.cs index cc018ddcc1..b87f3b12f7 100644 --- a/modules/docs/app/VoloDocs.Web/VoloDocsWebModule.cs +++ b/modules/docs/app/VoloDocs.Web/VoloDocsWebModule.cs @@ -62,6 +62,11 @@ namespace VoloDocs.Web var hostingEnvironment = context.Services.GetHostingEnvironment(); var configuration = context.Services.GetConfiguration(); + Configure(options => + { + options.RoutePrefix = null; + }); + Configure(options => { options.ConnectionStrings.Default = configuration["ConnectionString"]; @@ -107,7 +112,7 @@ namespace VoloDocs.Web Configure(options => { - + options.Languages.Add(new LanguageInfo("cs", "cs", "Čeština")); options.Languages.Add(new LanguageInfo("en", "en", "English")); options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe")); options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/cs.json b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/cs.json new file mode 100644 index 0000000000..18c3c429d4 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/cs.json @@ -0,0 +1,10 @@ +{ + "culture": "cs", + "texts": { + "Permission:DocumentManagement": "Správa dokumentů", + "Permission:Projects": "Projekty", + "Permission:Edit": "Upravit", + "Permission:Delete": "Smazat", + "Permission:Create": "Vytvořit" + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/pl.json b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/pl.json new file mode 100644 index 0000000000..e03a79585d --- /dev/null +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/pl.json @@ -0,0 +1,10 @@ +{ + "culture": "pl", + "texts": { + "Permission:DocumentManagement": "Zarządzanie dokumentacją", + "Permission:Projects": "Projekty", + "Permission:Edit": "Edytuj", + "Permission:Delete": "Usuń", + "Permission:Create": "Utwórz" + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/vi.sjon b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/vi.sjon new file mode 100644 index 0000000000..0697ddf6e8 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/vi.sjon @@ -0,0 +1,10 @@ +{ + "culture": "vi", + "texts": { + "Permission:DocumentManagement": "Quản lý tài liệu", + "Permission:Projects": "Dự án", + "Permission:Edit": "Sửa", + "Permission:Delete": "Xóa", + "Permission:Create": "Tạo" + } +} diff --git a/modules/docs/src/Volo.Docs.Admin.Web/Localization/Resources/Docs/Web/cs.json b/modules/docs/src/Volo.Docs.Admin.Web/Localization/Resources/Docs/Web/cs.json new file mode 100644 index 0000000000..471fea1b38 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Admin.Web/Localization/Resources/Docs/Web/cs.json @@ -0,0 +1,27 @@ +{ + "culture": "cs", + "texts": { + "Menu:DocumentManagement": "Dokumenty", + "Menu:ProjectManagement": "Projekty", + "CreateANewProject": "Vytvořit nový projekt", + "Edit": "Upravit", + "Create": "Vytvořit", + "Projects": "Projekty", + "Name": "Název", + "ShortName": "Krátký název", + "DocumentStoreType": "Typ uložiště dokumentu", + "Format": "Formát", + "ShortNameInfoText": "Bude použíto k unikátnímu URL.", + "DisplayName:Name": "Název", + "DisplayName:ShortName": "Krátký název", + "DisplayName:Format": "Formát", + "DisplayName:DefaultDocumentName": "Název výchozího dokumentu", + "DisplayName:NavigationDocumentName": "Název navigačního dokumentu", + "DisplayName:MinimumVersion": "Nejnižší verze", + "DisplayName:MainWebsiteUrl": "URL hlavních webových stránek", + "DisplayName:LatestVersionBranchName": "Název poslední verze odvětví", + "DisplayName:GitHubRootUrl": "GitHub kořenové URL", + "DisplayName:GitHubAccessToken": "GitHub přístupový token", + "DisplayName:GitHubUserAgent": "GitHub user agent" + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Web/Localization/Resources/Docs/Web/pl.json b/modules/docs/src/Volo.Docs.Admin.Web/Localization/Resources/Docs/Web/pl.json new file mode 100644 index 0000000000..414d4a684f --- /dev/null +++ b/modules/docs/src/Volo.Docs.Admin.Web/Localization/Resources/Docs/Web/pl.json @@ -0,0 +1,27 @@ +{ + "culture": "pl", + "texts": { + "Menu:DocumentManagement": "Dokumenty", + "Menu:ProjectManagement": "Projekty", + "CreateANewProject": "Utwórz nowy projet", + "Edit": "Edytuj", + "Create": "Utwórz", + "Projects": "Projekty", + "Name": "Nazwa", + "ShortName": "Krótka nazwa", + "DocumentStoreType": "Typ zapisu dokumentu", + "Format": "Format", + "ShortNameInfoText": "Zostanie użyty do unikalnego URL.", + "DisplayName:Name": "Nazwa", + "DisplayName:ShortName": "Krótka nazwa", + "DisplayName:Format": "Format", + "DisplayName:DefaultDocumentName": "Domyślna nazwa dokumentu", + "DisplayName:NavigationDocumentName": "Nawigacyjna nazwa dokumentu", + "DisplayName:MinimumVersion": "Minimalna wersja", + "DisplayName:MainWebsiteUrl": "Adres strony głównej", + "DisplayName:LatestVersionBranchName": "Nazwa brancha ostatniej wersji", + "DisplayName:GitHubRootUrl": "Adres URL do GitHub'a", + "DisplayName:GitHubAccessToken": "GitHub access token", + "DisplayName:GitHubUserAgent": "GitHub user agent" + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Web/Localization/Resources/Docs/Web/pt-BR.json b/modules/docs/src/Volo.Docs.Admin.Web/Localization/Resources/Docs/Web/pt-BR.json index b1a723d8b4..f77d799651 100644 --- a/modules/docs/src/Volo.Docs.Admin.Web/Localization/Resources/Docs/Web/pt-BR.json +++ b/modules/docs/src/Volo.Docs.Admin.Web/Localization/Resources/Docs/Web/pt-BR.json @@ -21,6 +21,7 @@ "DisplayName:MainWebsiteUrl": "URL do site principal", "DisplayName:LatestVersionBranchName": "Nome do branch da última versão", "DisplayName:GitHubRootUrl": "URL raíz do GitHub", - "DisplayName:GitHubAccessToken": "Token de acesso do GitHub" + "DisplayName:GitHubAccessToken": "Token de acesso do GitHub", + "DisplayName:GitHubUserAgent": "Usuário agente do GitHub" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Web/Localization/Resources/Docs/Web/vi.json b/modules/docs/src/Volo.Docs.Admin.Web/Localization/Resources/Docs/Web/vi.json new file mode 100644 index 0000000000..d39b27f295 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Admin.Web/Localization/Resources/Docs/Web/vi.json @@ -0,0 +1,27 @@ +{ + "culture": "vi", + "texts": { + "Menu:DocumentManagement": "Tài liệu", + "Menu:ProjectManagement": "Dự án", + "CreateANewProject": "Tạo dự án mới", + "Edit": "Sửa", + "Create": "Tạo", + "Projects": "Dự án", + "Name": "Tên", + "ShortName": "Tên rút gọn", + "DocumentStoreType": "DocumentStoreType", + "Format": "Định dạng", + "ShortNameInfoText": "Sẽ được sử dụng cho URL duy nhất..", + "DisplayName:Name": "Tên", + "DisplayName:ShortName": "Tên rút gọn", + "DisplayName:Format": "Định dạng", + "DisplayName:DefaultDocumentName": "Tên tài liệu mặc định", + "DisplayName:NavigationDocumentName": "Tên tài liệu điều hướng", + "DisplayName:MinimumVersion": "Phiên bản tối thiểu", + "DisplayName:MainWebsiteUrl": "URL trang web chính", + "DisplayName:LatestVersionBranchName": "Tên nhánh phiên bản mới nhất", + "DisplayName:GitHubRootUrl": "URL gốc của GitHub", + "DisplayName:GitHubAccessToken": "GitHub access token", + "DisplayName:GitHubUserAgent": "GitHub user agent" + } +} diff --git a/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/ContentWithDetailsDto.cs b/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/DocumentWithDetailsDto.cs similarity index 100% rename from modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/ContentWithDetailsDto.cs rename to modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/DocumentWithDetailsDto.cs diff --git a/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/GetDefaultDocumentInput.cs b/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/GetDefaultDocumentInput.cs index 770f43b13e..3deeb83967 100644 --- a/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/GetDefaultDocumentInput.cs +++ b/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/GetDefaultDocumentInput.cs @@ -1,5 +1,6 @@ using System; using System.ComponentModel.DataAnnotations; +using Volo.Docs.Language; using Volo.Docs.Projects; namespace Volo.Docs.Documents @@ -10,5 +11,9 @@ namespace Volo.Docs.Documents [StringLength(ProjectConsts.MaxVersionNameLength)] public string Version { get; set; } + + [Required] + [StringLength(LanguageConsts.MaxLanguageCodeLength)] + public string LanguageCode { get; set; } } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/GetDocumentInput.cs b/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/GetDocumentInput.cs index 2c887fb829..412f41b82e 100644 --- a/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/GetDocumentInput.cs +++ b/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/GetDocumentInput.cs @@ -1,5 +1,6 @@ using System; using System.ComponentModel.DataAnnotations; +using Volo.Docs.Language; using Volo.Docs.Projects; namespace Volo.Docs.Documents @@ -14,5 +15,9 @@ namespace Volo.Docs.Documents [StringLength(ProjectConsts.MaxVersionNameLength)] public string Version { get; set; } + + [Required] + [StringLength(LanguageConsts.MaxLanguageCodeLength)] + public string LanguageCode { get; set; } } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/GetDocumentResourceInput.cs b/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/GetDocumentResourceInput.cs index e34dfa5512..6f759c47d8 100644 --- a/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/GetDocumentResourceInput.cs +++ b/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/GetDocumentResourceInput.cs @@ -1,5 +1,6 @@ using System; using System.ComponentModel.DataAnnotations; +using Volo.Docs.Language; using Volo.Docs.Projects; namespace Volo.Docs.Documents @@ -14,5 +15,9 @@ namespace Volo.Docs.Documents [StringLength(ProjectConsts.MaxVersionNameLength)] public string Version { get; set; } + + [Required] + [StringLength(LanguageConsts.MaxLanguageCodeLength)] + public string LanguageCode { get; set; } } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/GetNavigationDocumentInput.cs b/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/GetNavigationDocumentInput.cs index c9ea504272..6866c8c633 100644 --- a/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/GetNavigationDocumentInput.cs +++ b/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/GetNavigationDocumentInput.cs @@ -1,5 +1,6 @@ using System; using System.ComponentModel.DataAnnotations; +using Volo.Docs.Language; using Volo.Docs.Projects; namespace Volo.Docs.Documents @@ -10,5 +11,9 @@ namespace Volo.Docs.Documents [StringLength(ProjectConsts.MaxVersionNameLength)] public string Version { get; set; } + + [Required] + [StringLength(LanguageConsts.MaxLanguageCodeLength)] + public string LanguageCode { get; set; } } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Projects/IProjectAppService.cs b/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Projects/IProjectAppService.cs index 5bfc221e4d..44f4cbf3b8 100644 --- a/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Projects/IProjectAppService.cs +++ b/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Projects/IProjectAppService.cs @@ -1,6 +1,7 @@ using System.Threading.Tasks; using Volo.Abp.Application.Dtos; using Volo.Abp.Application.Services; +using Volo.Docs.Documents; namespace Volo.Docs.Projects { @@ -11,5 +12,9 @@ namespace Volo.Docs.Projects Task GetAsync(string shortName); Task> GetVersionsAsync(string shortName); + + Task GetDefaultLanguageCode(string shortName, string version); + + Task GetLanguageListAsync(string shortName, string version); } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/DocumentAppService.cs b/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/DocumentAppService.cs index 3a4474e877..cdc50f869d 100644 --- a/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/DocumentAppService.cs +++ b/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/DocumentAppService.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Linq; using System.Threading.Tasks; using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.Logging; @@ -15,17 +16,20 @@ namespace Volo.Docs.Documents private readonly IProjectRepository _projectRepository; private readonly IDocumentStoreFactory _documentStoreFactory; protected IDistributedCache DocumentCache { get; } + protected IDistributedCache LanguageCache { get; } protected IDistributedCache ResourceCache { get; } public DocumentAppService( IProjectRepository projectRepository, IDocumentStoreFactory documentStoreFactory, IDistributedCache documentCache, + IDistributedCache languageCache, IDistributedCache resourceCache) { _projectRepository = projectRepository; _documentStoreFactory = documentStoreFactory; DocumentCache = documentCache; + LanguageCache = languageCache; ResourceCache = resourceCache; } @@ -33,9 +37,10 @@ namespace Volo.Docs.Documents { var project = await _projectRepository.GetAsync(input.ProjectId); - return await GetDocumentWithDetailsDto( + return await GetDocumentWithDetailsDtoAsync( project, input.Name, + input.LanguageCode, input.Version ); } @@ -44,9 +49,10 @@ namespace Volo.Docs.Documents { var project = await _projectRepository.GetAsync(input.ProjectId); - return await GetDocumentWithDetailsDto( + return await GetDocumentWithDetailsDtoAsync( project, - project.DefaultDocumentName, + project.DefaultDocumentName + "." + project.Format, + input.LanguageCode, input.Version ); } @@ -55,9 +61,10 @@ namespace Volo.Docs.Documents { var project = await _projectRepository.GetAsync(input.ProjectId); - return await GetDocumentWithDetailsDto( + return await GetDocumentWithDetailsDtoAsync( project, project.NavigationDocumentName, + input.LanguageCode, input.Version ); } @@ -65,12 +72,13 @@ namespace Volo.Docs.Documents public async Task GetResourceAsync(GetDocumentResourceInput input) { var project = await _projectRepository.GetAsync(input.ProjectId); - var cacheKey = $"Resource@{project.ShortName}#{input.Name}#{input.Version}"; + var cacheKey = $"Resource@{project.ShortName}#{input.LanguageCode}#{input.Name}#{input.Version}"; + input.Version = string.IsNullOrWhiteSpace(input.Version) ? project.LatestVersionBranchName : input.Version; async Task GetResourceAsync() { var store = _documentStoreFactory.Create(project.DocumentStoreType); - var documentResource = await store.GetResource(project, input.Name, input.Version); + var documentResource = await store.GetResource(project, input.Name, input.LanguageCode, input.Version); return ObjectMapper.Map(documentResource); } @@ -92,18 +100,21 @@ namespace Volo.Docs.Documents ); } - protected virtual async Task GetDocumentWithDetailsDto( + protected virtual async Task GetDocumentWithDetailsDtoAsync( Project project, string documentName, + string languageCode, string version) { - var cacheKey = $"Document@{project.ShortName}#{documentName}#{version}"; + version = string.IsNullOrWhiteSpace(version) ? project.LatestVersionBranchName : version; + + var cacheKey = $"Document@{project.ShortName}#{languageCode}#{documentName}#{version}"; async Task GetDocumentAsync() { Logger.LogInformation($"Not found in the cache. Requesting {documentName} from the store..."); var store = _documentStoreFactory.Create(project.DocumentStoreType); - var document = await store.GetDocumentAsync(project, documentName, version); + var document = await store.GetDocumentAsync(project, documentName, languageCode, version); Logger.LogInformation($"Document retrieved: {documentName}"); return CreateDocumentWithDetailsDto(project, document); } diff --git a/modules/docs/src/Volo.Docs.Application/Volo/Docs/Projects/ProjectAppService.cs b/modules/docs/src/Volo.Docs.Application/Volo/Docs/Projects/ProjectAppService.cs index 02ffac9ee9..99a6c70123 100644 --- a/modules/docs/src/Volo.Docs.Application/Volo/Docs/Projects/ProjectAppService.cs +++ b/modules/docs/src/Volo.Docs.Application/Volo/Docs/Projects/ProjectAppService.cs @@ -16,17 +16,18 @@ namespace Volo.Docs.Projects private readonly IProjectRepository _projectRepository; private readonly IDistributedCache> _versionCache; private readonly IDocumentStoreFactory _documentStoreFactory; - private readonly IGuidGenerator _guidGenerator; + protected IDistributedCache LanguageCache { get; } public ProjectAppService( IProjectRepository projectRepository, IDistributedCache> versionCache, - IDocumentStoreFactory documentStoreFactory, IGuidGenerator guidGenerator) + IDocumentStoreFactory documentStoreFactory, + IDistributedCache languageCache) { _projectRepository = projectRepository; _versionCache = versionCache; _documentStoreFactory = documentStoreFactory; - _guidGenerator = guidGenerator; + LanguageCache = languageCache; } public async Task> GetListAsync() @@ -91,5 +92,37 @@ namespace Volo.Docs.Projects return versions; } + + public async Task GetLanguageListAsync(string shortName, string version) + { + return await GetLanguageListInternalAsync(shortName, version); + } + + public async Task GetDefaultLanguageCode(string shortName, string version) + { + var languageList = await GetLanguageListInternalAsync(shortName, version); + + return (languageList.Languages.FirstOrDefault(l => l.IsDefault) ?? languageList.Languages.First()).Code; + } + + private async Task GetLanguageListInternalAsync(string shortName, string version) + { + var project = await _projectRepository.GetByShortNameAsync(shortName); + var store = _documentStoreFactory.Create(project.DocumentStoreType); + + async Task GetLanguagesAsync() + { + return await store.GetLanguageListAsync(project, version); + } + + return await LanguageCache.GetOrAddAsync( + project.ShortName, + GetLanguagesAsync, + () => new DistributedCacheEntryOptions + { + AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(24) + } + ); + } } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/Language/LanguageConfig.cs b/modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/Language/LanguageConfig.cs new file mode 100644 index 0000000000..038ec00cee --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/Language/LanguageConfig.cs @@ -0,0 +1,9 @@ +using System.Collections.Generic; + +namespace Volo.Docs.Documents +{ + public class LanguageConfig + { + public List Languages { get; set; } + } +} diff --git a/modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/Language/LanguageConfigElement.cs b/modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/Language/LanguageConfigElement.cs new file mode 100644 index 0000000000..25525394ca --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/Language/LanguageConfigElement.cs @@ -0,0 +1,11 @@ +namespace Volo.Docs.Documents +{ + public class LanguageConfigElement + { + public string DisplayName { get; set; } + + public string Code { get; set; } + + public bool IsDefault { get; set; } + } +} diff --git a/modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/Language/LanguageConsts.cs b/modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/Language/LanguageConsts.cs new file mode 100644 index 0000000000..867cc2dd4e --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/Language/LanguageConsts.cs @@ -0,0 +1,8 @@ + +namespace Volo.Docs.Language +{ + public static class LanguageConsts + { + public const int MaxLanguageCodeLength = 10; + } +} diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/IDocumentStore.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/IDocumentStore.cs index 1b001303b5..3cbf2c40f2 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/IDocumentStore.cs +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/IDocumentStore.cs @@ -1,16 +1,19 @@ using System.Collections.Generic; using System.Threading.Tasks; using Volo.Abp.Domain.Services; +using Volo.Docs.GitHub.Documents; using Volo.Docs.Projects; namespace Volo.Docs.Documents { public interface IDocumentStore : IDomainService { - Task GetDocumentAsync(Project project, string documentName, string version); + Task GetDocumentAsync(Project project, string documentName, string languageCode, string version); Task> GetVersionsAsync(Project project); - Task GetResource(Project project, string resourceName, string version); + Task GetResource(Project project, string resourceName, string languageCode, string version); + + Task GetLanguageListAsync(Project project, string version); } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/FileSystem/Documents/FileSystemDocumentStore.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/FileSystem/Documents/FileSystemDocumentStore.cs index 87a74d1702..8d85046d29 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/FileSystem/Documents/FileSystemDocumentStore.cs +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/FileSystem/Documents/FileSystemDocumentStore.cs @@ -1,7 +1,9 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.IO; using System.Security; using System.Threading.Tasks; +using Newtonsoft.Json; using Volo.Abp.Domain.Services; using Volo.Abp.IO; using Volo.Docs.Documents; @@ -14,10 +16,10 @@ namespace Volo.Docs.FileSystem.Documents { public const string Type = "FileSystem"; - public async Task GetDocumentAsync(Project project, string documentName, string version) + public async Task GetDocumentAsync(Project project, string documentName, string languageCode, string version) { var projectFolder = project.GetFileSystemPath(); - var path = Path.Combine(projectFolder, documentName); + var path = Path.Combine(projectFolder, languageCode, documentName); CheckDirectorySecurity(projectFolder, path); @@ -46,10 +48,18 @@ namespace Volo.Docs.FileSystem.Documents return Task.FromResult(new List()); } - public async Task GetResource(Project project, string resourceName, string version) + public async Task GetLanguageListAsync(Project project, string version) + { + var path = Path.Combine(project.GetFileSystemPath(), "docs-langs.json"); + var configAsJson = await FileHelper.ReadAllTextAsync(path); + + return JsonConvert.DeserializeObject(configAsJson); + } + + public async Task GetResource(Project project, string resourceName, string languageCode, string version) { var projectFolder = project.GetFileSystemPath(); - var path = Path.Combine(projectFolder, resourceName); + var path = Path.Combine(projectFolder, languageCode, resourceName); if (!DirectoryHelper.IsSubDirectoryOf(projectFolder, path)) { diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/GithubDocumentStore.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/GithubDocumentStore.cs index 2d65a17c68..c2eb1bb24d 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/GithubDocumentStore.cs +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/GithubDocumentStore.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.Extensions.Logging; +using Newtonsoft.Json; using Volo.Abp.Domain.Services; using Volo.Docs.Documents; using Volo.Docs.GitHub.Projects; @@ -27,16 +28,16 @@ namespace Volo.Docs.GitHub.Documents _githubRepositoryManager = githubRepositoryManager; } - public virtual async Task GetDocumentAsync(Project project, string documentName, string version) + public virtual async Task GetDocumentAsync(Project project, string documentName, string languageCode, string version) { var token = project.GetGitHubAccessTokenOrNull(); var rootUrl = project.GetGitHubUrl(version); - var rawRootUrl = CalculateRawRootUrl(rootUrl); + var userAgent = project.GetGithubUserAgentOrNull(); + var rawRootUrl = CalculateRawRootUrlWithLanguageCode(rootUrl, languageCode); var rawDocumentUrl = rawRootUrl + documentName; var commitHistoryUrl = project.GetGitHubUrlForCommitHistory() + documentName; - var userAgent = project.GetGithubUserAgentOrNull(); var isNavigationDocument = documentName == project.NavigationDocumentName; - var editLink = rootUrl.ReplaceFirst("/tree/", "/blob/") + documentName; + var editLink = rootUrl.ReplaceFirst("/tree/", "/blob/") + languageCode + "/" + documentName; var localDirectory = ""; var fileName = documentName; @@ -90,9 +91,9 @@ namespace Volo.Docs.GitHub.Documents return versions; } - public async Task GetResource(Project project, string resourceName, string version) + public async Task GetResource(Project project, string resourceName, string languageCode, string version) { - var rawRootUrl = CalculateRawRootUrl(project.GetGitHubUrl(version)); + var rawRootUrl = CalculateRawRootUrlWithLanguageCode(project.GetGitHubUrl(version), languageCode); var content = await DownloadWebContentAsByteArrayAsync( rawRootUrl + resourceName, project.GetGitHubAccessTokenOrNull(), @@ -102,6 +103,19 @@ namespace Volo.Docs.GitHub.Documents return new DocumentResource(content); } + public async Task GetLanguageListAsync(Project project, string version) + { + var token = project.GetGitHubAccessTokenOrNull(); + var rootUrl = project.GetGitHubUrl(version); + var userAgent = project.GetGithubUserAgentOrNull(); + + var url = CalculateRawRootUrl(rootUrl) + "docs-langs.json"; + + var configAsJson = await DownloadWebContentAsStringAsync(url, token, userAgent); + + return JsonConvert.DeserializeObject(configAsJson); + } + private async Task> GetReleasesAsync(Project project) { var url = project.GetGitHubUrl(); @@ -202,6 +216,16 @@ namespace Volo.Docs.GitHub.Documents return contributors; } + private static string CalculateRawRootUrlWithLanguageCode(string rootUrl, string languageCode) + { + return (rootUrl + .Replace("github.com", "raw.githubusercontent.com") + .ReplaceFirst("/tree/", "/") + .EnsureEndsWith('/') + + languageCode + ).EnsureEndsWith('/'); + } + private static string CalculateRawRootUrl(string rootUrl) { return rootUrl diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/cs.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/cs.json new file mode 100644 index 0000000000..4c21318fdb --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/cs.json @@ -0,0 +1,19 @@ +{ + "culture": "cs", + "texts": { + "Documents": "Dokumenty", + "BackToWebsite": "Zpět na stránky", + "Contributors": "Přispěvatelé", + "ShareOn": "Sdílet na", + "Version": "Verze", + "Edit": "Upravit", + "Delete": "Smazat", + "InThisDocument": "V tomto dokumentu", + "GoToTop": "Přejít nahoru", + "Projects": "Projekt(y)", + "NoProjectWarning": "Zatím zde není žádný projekt!", + "DocumentNotFound": "Ups, vyžádaný dokument neexistuje!", + "NavigationDocumentNotFound": "Tato verze nemá navigační dokument!", + "DocumentNotFoundInSelectedLanguage": "Tento dokument není dostupný ve vybraném jazyce. Zobrazen dokument ve výchozím jazyce." + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en.json index 31d3835a3a..f399b8f151 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en.json @@ -13,6 +13,7 @@ "Projects": "Project(s)", "NoProjectWarning": "There are no projects yet!", "DocumentNotFound": "Oops, the requested document was not found!", - "NavigationDocumentNotFound": "This version does not have a navigation document!" + "NavigationDocumentNotFound": "This version does not have a navigation document!", + "DocumentNotFoundInSelectedLanguage": "Document in the language you wanted is not found. Document in the default language is shown." } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/es.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/es.json index 94a3eec1bd..700143ad76 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/es.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/es.json @@ -3,13 +3,17 @@ "texts": { "Documents": "Documentos", "BackToWebsite": "Regresar al sitio", - "Version": "Versión", + "Contributors": "Contribuidores", + "ShareOn": "Compartilhar no", + "Version": "Versão", "Edit": "Editar", + "Delete": "Excluir", "InThisDocument": "En este documento", "GoToTop": "Subir", "Projects": "Proyecto(s)", - "NoProjectWarning": "¡Aun no hay proyectos!", - "DocumentNotFound": "¡Oops, no se encontró el documento solicitado!", - "NavigationDocumentNotFound": "Esta versión no tiene un documento de navegación!" + "NoProjectWarning": "Não há projetos ainda!", + "DocumentNotFound": "Ups! O documento solicitado não foi encontrado!", + "NavigationDocumentNotFound": "Esta versão não possui um documento de navegação!", + "DocumentNotFoundInSelectedLanguage": "Documento no idioma desejado não foi encontrado. Documento no idioma padrão é mostrado." } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/pl.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/pl.json new file mode 100644 index 0000000000..5ba3dd6c10 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/pl.json @@ -0,0 +1,18 @@ +{ + "culture": "pl", + "texts": { + "Documents": "Dokumenty", + "BackToWebsite": "Powrót do strony", + "Contributors": "Współtwórcy", + "ShareOn": "Udostępnij", + "Version": "Wersja", + "Edit": "Edytuj", + "Delete": "Usuń", + "InThisDocument": "W tym dokumencie", + "GoToTop": "Idź do góry", + "Projects": "Projekt(y)", + "NoProjectWarning": "Projekt nie istnieje!", + "DocumentNotFound": "Oops, żądany dokument nie istnieje!", + "NavigationDocumentNotFound": "Ta wersja nie posiada tego dokumentu!" + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/pt-BR.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/pt-BR.json index 05a642010c..0d1157d4c3 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/pt-BR.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/pt-BR.json @@ -4,7 +4,7 @@ "Documents": "Documentos", "BackToWebsite": "Voltar para o site", "Contributors": "Contribuidores", - "ShareOn": "Compartilhar em:", + "ShareOn": "Compartilhar em", "Version": "Versão", "Edit": "Editar", "Delete": "Excluir", @@ -12,7 +12,8 @@ "GoToTop": "Ir pra o topo", "Projects": "Projeto(s)", "NoProjectWarning": "Ainda não há projetos!", - "DocumentNotFound": "Oops, o documento solicitado foi encontrado", - "NavigationDocumentNotFound": "Esta versão não possui um documento de navegação!" + "DocumentNotFound": "Oops, o documento solicitado não foi encontrado", + "NavigationDocumentNotFound": "Esta versão não possui um documento de navegação!", + "DocumentNotFoundInSelectedLanguage": "Documento no idioma desejado não foi encontrado. Documento no idioma padrão é mostrado." } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/tr.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/tr.json index da39c6cce3..3f15a43046 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/tr.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/tr.json @@ -13,6 +13,7 @@ "Projects": "Proje(ler)", "NoProjectWarning": "Hiç proje yok!", "DocumentNotFound": "Aradığınız döküman bulunamadı!", - "NavigationDocumentNotFound": "Bu döküman için menü bulunamadı!" + "NavigationDocumentNotFound": "Bu döküman için menü bulunamadı!", + "DocumentNotFoundInSelectedLanguage": "İstediğiniz dilde belge bulunamadı. Varsayılan dilde belge gösterilir." } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/vi.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/vi.json new file mode 100644 index 0000000000..6f10e6469c --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/vi.json @@ -0,0 +1,19 @@ +{ + "culture": "vi", + "texts": { + "Documents": "Tài liệu", + "BackToWebsite": "Quay lại trang web", + "Contributors": "Người đóng góp", + "ShareOn": "Chia sẻ", + "Version": "Phiên bản", + "Edit": "Sửa", + "Delete": "Xóa", + "InThisDocument": "Trong tài liệu này", + "GoToTop": "Chuyển về đầu trang", + "Projects": "Dự án", + "NoProjectWarning": "Chưa có dự án nào!", + "DocumentNotFound": "Rất tiếc, tài liệu được yêu cầu không tìm thấy!", + "NavigationDocumentNotFound": "Phiên bản này không có tài liệu điều hướng!", + "DocumentNotFoundInSelectedLanguage": "Tài liệu bằng ngôn ngữ bạn muốn không được tìm thấy. Tài liệu trong ngôn ngữ mặc định được hiển thị." + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/zh-Hans.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/zh-Hans.json index f085265abf..43eb83334c 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/zh-Hans.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/zh-Hans.json @@ -13,6 +13,7 @@ "Projects": "项目", "NoProjectWarning": "还没有项目!", "DocumentNotFound": "找不到请求的文档!", - "NavigationDocumentNotFound": "这个版本没有导航文件!" + "NavigationDocumentNotFound": "这个版本没有导航文件!", + "DocumentNotFoundInSelectedLanguage": "本文档不适用于所选语言, 将以默认语言显示文档." } -} +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.HttpApi/Volo/Docs/Projects/DocsProjectController.cs b/modules/docs/src/Volo.Docs.HttpApi/Volo/Docs/Projects/DocsProjectController.cs index e22df620f9..039f13a44e 100644 --- a/modules/docs/src/Volo.Docs.HttpApi/Volo/Docs/Projects/DocsProjectController.cs +++ b/modules/docs/src/Volo.Docs.HttpApi/Volo/Docs/Projects/DocsProjectController.cs @@ -1,9 +1,9 @@ -using System; -using System.Threading.Tasks; +using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Volo.Abp; using Volo.Abp.Application.Dtos; using Volo.Abp.AspNetCore.Mvc; +using Volo.Docs.Documents; namespace Volo.Docs.Projects { @@ -34,11 +34,25 @@ namespace Volo.Docs.Projects return ProjectAppService.GetAsync(shortName); } + [HttpGet] + [Route("{shortName}/defaultLanguage")] + public Task GetDefaultLanguageCode(string shortName,string version) + { + return ProjectAppService.GetDefaultLanguageCode(shortName, version); + } + [HttpGet] [Route("{shortName}/versions")] public virtual Task> GetVersionsAsync(string shortName) { return ProjectAppService.GetVersionsAsync(shortName); } + + [HttpGet] + [Route("{shortName}/{version}/languageList")] + public Task GetLanguageListAsync(string shortName, string version) + { + return ProjectAppService.GetLanguageListAsync(shortName, version); + } } } diff --git a/modules/docs/src/Volo.Docs.Web/Areas/Documents/TagHelpers/TreeTagHelper.cs b/modules/docs/src/Volo.Docs.Web/Areas/Documents/TagHelpers/TreeTagHelper.cs index 38e95a6e93..edc7bfb24d 100644 --- a/modules/docs/src/Volo.Docs.Web/Areas/Documents/TagHelpers/TreeTagHelper.cs +++ b/modules/docs/src/Volo.Docs.Web/Areas/Documents/TagHelpers/TreeTagHelper.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Text; using Microsoft.AspNetCore.Razor.TagHelpers; +using Microsoft.Extensions.Options; using Volo.Docs.Documents; using Volo.Docs.Utils; @@ -12,6 +13,8 @@ namespace Volo.Docs.Areas.Documents.TagHelpers [HtmlTargetElement("ul", Attributes = "root-node")] public class TreeTagHelper : TagHelper { + private readonly DocsUrlOptions _urlOptions; + private const string LiItemTemplateWithLink = @"
  • {2}{3}
  • "; private const string ListItemAnchor = @"{2}"; @@ -35,6 +38,14 @@ namespace Volo.Docs.Areas.Documents.TagHelpers [HtmlAttributeName("project-format")] public string ProjectFormat { get; set; } + [HtmlAttributeName("language")] + public string LanguageCode { get; set; } + + public TreeTagHelper(IOptions urlOptions) + { + _urlOptions = urlOptions.Value; + } + public override void Process(TagHelperContext context, TagHelperOutput output) { var content = new StringBuilder(); @@ -107,7 +118,7 @@ namespace Volo.Docs.Areas.Documents.TagHelpers } else { - listInnerItem = string.Format(ListItemAnchor, NormalizePath(node.Path, node.HasChildItems), textCss, node.Text.IsNullOrEmpty() ? "?" : node.Text); + listInnerItem = string.Format(ListItemAnchor, NormalizePath(node.Path), textCss, node.Text.IsNullOrEmpty() ? "?" : node.Text); } return string.Format(LiItemTemplateWithLink, @@ -117,7 +128,7 @@ namespace Volo.Docs.Areas.Documents.TagHelpers content); } - private string NormalizePath(string path, bool hasChildItems) + private string NormalizePath(string path) { if (UrlHelper.IsExternalLink(path)) { @@ -131,7 +142,9 @@ namespace Volo.Docs.Areas.Documents.TagHelpers return "javascript:;"; } - return "/documents/" + ProjectName + "/" + Version + "/" + pathWithoutFileExtension; + var prefix = _urlOptions.GetFormattedRoutePrefix(); + + return prefix + LanguageCode + "/" + ProjectName + "/" + Version + "/" + pathWithoutFileExtension; } private string RemoveFileExtensionFromPath(string path) diff --git a/modules/docs/src/Volo.Docs.Web/DocsUrlOptions.cs b/modules/docs/src/Volo.Docs.Web/DocsUrlOptions.cs new file mode 100644 index 0000000000..4c72a7bcbb --- /dev/null +++ b/modules/docs/src/Volo.Docs.Web/DocsUrlOptions.cs @@ -0,0 +1,22 @@ +using System; + +namespace Volo.Docs +{ + public class DocsUrlOptions + { + /// + /// Default value: "documents"; + /// + public string RoutePrefix { get; set; } = "documents"; + + public string GetFormattedRoutePrefix() + { + if (string.IsNullOrWhiteSpace(RoutePrefix)) + { + return "/"; + } + + return RoutePrefix.EnsureEndsWith('/').EnsureStartsWith('/'); + } + } +} diff --git a/modules/docs/src/Volo.Docs.Web/DocsWebModule.cs b/modules/docs/src/Volo.Docs.Web/DocsWebModule.cs index 89301265ea..e16d36f6cb 100644 --- a/modules/docs/src/Volo.Docs.Web/DocsWebModule.cs +++ b/modules/docs/src/Volo.Docs.Web/DocsWebModule.cs @@ -1,5 +1,7 @@ -using Microsoft.AspNetCore.Mvc.RazorPages; +using System; +using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; using Volo.Abp.AspNetCore.Mvc.Localization; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap; using Volo.Abp.AspNetCore.Mvc.UI.Bundling; @@ -35,12 +37,19 @@ namespace Volo.Docs options.FileSets.AddEmbedded("Volo.Docs"); }); + var configuration = context.Services.GetConfiguration(); + Configure(options => { - //TODO: Make configurable! - options.Conventions.AddPageRoute("/Documents/Project/Index", "documents/{projectName}"); + var urlOptions = context.Services + .GetRequiredServiceLazy>() + .Value; + + var routePrefix = urlOptions.Value.GetFormattedRoutePrefix(); - options.Conventions.AddPageRoute("/Documents/Project/Index", "documents/{projectName}/{version}/{*documentName}"); + options.Conventions.AddPageRoute("/Documents/Project/Index", routePrefix + "{projectName}"); + options.Conventions.AddPageRoute("/Documents/Project/Index", routePrefix + "{languageCode}/{projectName}"); + options.Conventions.AddPageRoute("/Documents/Project/Index", routePrefix + "{languageCode}/{projectName}/{version}/{*documentName}"); }); Configure(options => diff --git a/modules/docs/src/Volo.Docs.Web/HtmlConverting/IDocumentToHtmlConverter.cs b/modules/docs/src/Volo.Docs.Web/HtmlConverting/IDocumentToHtmlConverter.cs index 1ff429510b..9346fdfb99 100644 --- a/modules/docs/src/Volo.Docs.Web/HtmlConverting/IDocumentToHtmlConverter.cs +++ b/modules/docs/src/Volo.Docs.Web/HtmlConverting/IDocumentToHtmlConverter.cs @@ -5,6 +5,6 @@ namespace Volo.Docs.HtmlConverting { public interface IDocumentToHtmlConverter { - string Convert(ProjectDto project, DocumentWithDetailsDto document,string version); + string Convert(ProjectDto project, DocumentWithDetailsDto document, string version, string languageCode); } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Web/Markdown/MarkdownDocumentToHtmlConverter.cs b/modules/docs/src/Volo.Docs.Web/Markdown/MarkdownDocumentToHtmlConverter.cs index ba44924799..426a42d59d 100644 --- a/modules/docs/src/Volo.Docs.Web/Markdown/MarkdownDocumentToHtmlConverter.cs +++ b/modules/docs/src/Volo.Docs.Web/Markdown/MarkdownDocumentToHtmlConverter.cs @@ -1,5 +1,6 @@ using System; using System.Text.RegularExpressions; +using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; using Volo.Docs.Documents; using Volo.Docs.HtmlConverting; @@ -13,17 +14,21 @@ namespace Volo.Docs.Markdown public const string Type = "md"; private readonly IMarkdownConverter _markdownConverter; + private readonly DocsUrlOptions _urlOptions; - public MarkdownDocumentToHtmlConverter(IMarkdownConverter markdownConverter) + public MarkdownDocumentToHtmlConverter(IMarkdownConverter markdownConverter, + IOptions urlOptions) { _markdownConverter = markdownConverter; + _urlOptions = urlOptions.Value; } - private const string MdLinkFormat = "[{0}](/documents/{1}/{2}{3}/{4})"; + private const string MdLinkFormat = "[{0}]({1}{2}/{3}/{4}{5}/{6})"; private const string MarkdownLinkRegExp = @"\[(.*)\]\((.*\.md)\)"; private const string AnchorLinkRegExp = @"]+href=\""(.*?)\""[^>]*>(.*)?"; - public virtual string Convert(ProjectDto project, DocumentWithDetailsDto document, string version) + public virtual string Convert(ProjectDto project, DocumentWithDetailsDto document, string version, + string languageCode) { if (document.Content.IsNullOrEmpty()) { @@ -34,7 +39,8 @@ namespace Volo.Docs.Markdown document.Content, project.ShortName, version, - document.LocalDirectory + document.LocalDirectory, + languageCode ); return _markdownConverter.ConvertToHtml(content); @@ -44,7 +50,8 @@ namespace Volo.Docs.Markdown string content, string projectShortName, string version, - string documentLocalDirectory) + string documentLocalDirectory, + string languageCode) { var normalized = Regex.Replace(content, MarkdownLinkRegExp, delegate (Match match) { @@ -66,6 +73,8 @@ namespace Volo.Docs.Markdown return string.Format( MdLinkFormat, displayText, + _urlOptions.GetFormattedRoutePrefix(), + languageCode, projectShortName, version, documentLocalDirectoryNormalized, @@ -92,6 +101,8 @@ namespace Volo.Docs.Markdown return string.Format( MdLinkFormat, displayText, + _urlOptions.GetFormattedRoutePrefix(), + languageCode, projectShortName, version, documentLocalDirectoryNormalized, diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Index.cshtml b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Index.cshtml index 1c5976e760..7b13a66aba 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Index.cshtml +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Index.cshtml @@ -29,9 +29,7 @@ {
  • - + @project.Name

    diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Index.cshtml.cs b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Index.cshtml.cs index 552aa0c21d..25083571b4 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Index.cshtml.cs +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Index.cshtml.cs @@ -1,34 +1,39 @@ +using System; using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; +using Microsoft.Extensions.Options; using Volo.Docs.Projects; namespace Volo.Docs.Pages.Documents { public class IndexModel : PageModel { + public string DocumentsUrlPrefix { get; set; } + public IReadOnlyList Projects { get; set; } private readonly IProjectAppService _projectAppService; + private readonly DocsUrlOptions _urlOptions; - public IndexModel(IProjectAppService projectAppService) + public IndexModel( + IProjectAppService projectAppService, + IOptions urlOptions) { _projectAppService = projectAppService; + _urlOptions = urlOptions.Value; } - public async Task OnGet() + public async Task OnGetAsync() { + DocumentsUrlPrefix = _urlOptions.GetFormattedRoutePrefix(); + var listResult = await _projectAppService.GetListAsync(); if (listResult.Items.Count == 1) { - return RedirectToPage("./Project/Index", new - { - projectName = listResult.Items[0].ShortName, - version = DocsAppConsts.Latest, - documentName = listResult.Items[0].DefaultDocumentName - }); + return Redirect("." + DocumentsUrlPrefix + listResult.Items[0].ShortName); } Projects = listResult.Items; diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml index 9b98ebe4b4..6fd1a21797 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml @@ -107,7 +107,7 @@ } -
    +
    @@ -116,7 +116,7 @@
    -
    +
    @if (Model.Navigation == null || Model.Navigation.Content.IsNullOrEmpty()) @@ -132,6 +132,7 @@ project-name="@Model.ProjectName" project-format="@Model.Project.Format" selected-document-name="@Model.DocumentNameWithExtension" + language="@Model.LanguageCode" id="sidebar-scroll" class="nav nav-list"> } @@ -143,7 +144,6 @@ @if (Model.Document != null) {
    -
    @@ -183,6 +190,12 @@
    + @if (Model.DocumentLanguageIsDifferent) + { + + @L["DocumentNotFoundInSelectedLanguage"] + + } @Html.Raw(Model.Document.Content)
    diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs index 378903d121..94fec82c09 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs @@ -1,10 +1,14 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Rendering; +using Microsoft.Extensions.Options; +using Volo.Abp.AspNetCore.Mvc.Localization; using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; +using Volo.Abp.Localization; using Volo.Docs.Documents; using Volo.Docs.HtmlConverting; using Volo.Docs.Models; @@ -23,8 +27,17 @@ namespace Volo.Docs.Pages.Documents.Project [BindProperty(SupportsGet = true)] public string DocumentName { get; set; } + [BindProperty(SupportsGet = true)] + public string LanguageCode { get; set; } + + public string DefaultLanguageCode { get; set; } + public ProjectDto Project { get; set; } + public LanguageConfig LanguageConfig { get; set; } + + public List LanguageSelectListItems { get; set; } + public string DocumentNameWithExtension { get; private set; } public DocumentWithDetailsDto Document { get; private set; } @@ -37,27 +50,79 @@ namespace Volo.Docs.Pages.Documents.Project public VersionInfoViewModel LatestVersionInfo { get; private set; } + public string DocumentsUrlPrefix { get; set; } + + public bool DocumentLanguageIsDifferent { get; set; } + private readonly IDocumentAppService _documentAppService; private readonly IDocumentToHtmlConverterFactory _documentToHtmlConverterFactory; private readonly IProjectAppService _projectAppService; + private readonly DocsUrlOptions _options; public IndexModel( IDocumentAppService documentAppService, IDocumentToHtmlConverterFactory documentToHtmlConverterFactory, - IProjectAppService projectAppService) + IProjectAppService projectAppService, + IOptions options) { _documentAppService = documentAppService; _documentToHtmlConverterFactory = documentToHtmlConverterFactory; _projectAppService = projectAppService; + _options = options.Value; } - public async Task OnGetAsync() + public async Task OnGetAsync() { + DocumentsUrlPrefix = _options.GetFormattedRoutePrefix(); + + if (IsDocumentCultureDifferentThanCurrent()) + { + return ReloadPageWithCulture(); + } + await SetProjectAsync(); await SetProjectsAsync(); await SetVersionAsync(); + await SetLanguageList(); + + if (IsDefaultDocument()) + { + return RedirectToDefaultDocument(); + } + + if (!CheckLanguage()) + { + return RedirectToDefaultLanguage(); + } + await SetDocumentAsync(); await SetNavigationAsync(); + SetLanguageSelectListItems(); + + return Page(); + } + + private bool IsDocumentCultureDifferentThanCurrent() + { + var currentCulture = CultureInfo.CurrentCulture; + CultureInfo newCulture; + + try + { + newCulture = CultureInfo.GetCultureInfo(LanguageCode); + + return currentCulture.Name != newCulture.Name; + } + catch (CultureNotFoundException) + { + return false; + } + + } + + private bool IsDefaultDocument() + { + return DocumentName == Project.DefaultDocumentName; } private async Task SetProjectAsync() @@ -65,6 +130,51 @@ namespace Volo.Docs.Pages.Documents.Project Project = await _projectAppService.GetAsync(ProjectName); } + private async Task SetLanguageList() + { + LanguageConfig = await _projectAppService.GetLanguageListAsync(ProjectName, Version); + SetDefaultLanguageCode(); + } + + private void SetDefaultLanguageCode() + { + DefaultLanguageCode = (LanguageConfig.Languages.FirstOrDefault(l => l.IsDefault) ?? LanguageConfig.Languages.First()).Code; + } + + private bool CheckLanguage() + { + return LanguageConfig.Languages.Any(l => l.Code == LanguageCode); + } + + private IActionResult ReloadPageWithCulture() + { + var returnUrl = DocumentsUrlPrefix + LanguageCode + "/" + ProjectName + "/" + Version + "/" + + DocumentName; + + return Redirect("/Abp/Languages/Switch?culture=" + LanguageCode + "&uiCulture=" + LanguageCode + "&returnUrl=" + returnUrl); + } + + private IActionResult RedirectToDefaultLanguage() + { + return RedirectToPage(new + { + projectName = ProjectName, + version = Version, + languageCode = DefaultLanguageCode + }); + } + + private IActionResult RedirectToDefaultDocument() + { + return RedirectToPage(new + { + projectName = ProjectName, + version = Version, + documentName = "", + languageCode = DefaultLanguageCode + }); + } + private async Task SetProjectsAsync() { var projects = await _projectAppService.GetListAsync(); @@ -72,7 +182,7 @@ namespace Volo.Docs.Pages.Documents.Project ProjectSelectItems = projects.Items.Select(p => new SelectListItem { Text = p.Name, - Value = p.Id != Project.Id ? "/documents/" + p.ShortName + "/" + DocsAppConsts.Latest : null, + Value = p.Id != Project.Id ? "/documents/" + LanguageCode + "/" + p.ShortName + "/" + DocsAppConsts.Latest : null, Selected = p.Id == Project.Id }).ToList(); } @@ -133,6 +243,7 @@ namespace Volo.Docs.Pages.Documents.Project new GetNavigationDocumentInput { ProjectId = Project.Id, + LanguageCode = LanguageCode, Version = Version } ); @@ -154,7 +265,7 @@ namespace Volo.Docs.Pages.Documents.Project version = DocsAppConsts.Latest; } - var link = "/documents/" + ProjectName + "/" + version; + var link = DocumentsUrlPrefix + LanguageCode + "/" + ProjectName + "/" + version; if (documentName != null) { @@ -178,21 +289,17 @@ namespace Volo.Docs.Pages.Documents.Project private async Task SetDocumentAsync() { - if (DocumentName.IsNullOrWhiteSpace()) - { - DocumentName = Project.DefaultDocumentName; - } - DocumentNameWithExtension = DocumentName + "." + Project.Format; try { - if (DocumentNameWithExtension.IsNullOrWhiteSpace()) + if (DocumentName.IsNullOrWhiteSpace()) { Document = await _documentAppService.GetDefaultAsync( new GetDefaultDocumentInput { ProjectId = Project.Id, + LanguageCode = LanguageCode, Version = Version } ); @@ -204,6 +311,7 @@ namespace Volo.Docs.Pages.Documents.Project { ProjectId = Project.Id, Name = DocumentNameWithExtension, + LanguageCode = LanguageCode, Version = Version } ); @@ -211,17 +319,49 @@ namespace Volo.Docs.Pages.Documents.Project } catch (DocumentNotFoundException) { - //TODO: Handle it! - throw; + if (LanguageCode != DefaultLanguageCode) + { + Document = await _documentAppService.GetAsync( + new GetDocumentInput + { + ProjectId = Project.Id, + Name = DocumentNameWithExtension, + LanguageCode = DefaultLanguageCode, + Version = Version + } + ); + + DocumentLanguageIsDifferent = true; + } + else + { + throw; + } } ConvertDocumentContentToHtml(); } + private void SetLanguageSelectListItems() + { + LanguageSelectListItems = new List(); + + foreach (var language in LanguageConfig.Languages) + { + LanguageSelectListItems.Add( + new SelectListItem( + language.DisplayName, + DocumentsUrlPrefix + language.Code + "/" + Project.ShortName + "/" + Version + "/" + DocumentName, + language.Code == LanguageCode + ) + ); + } + } + private void ConvertDocumentContentToHtml() { var converter = _documentToHtmlConverterFactory.Create(Document.Format ?? Project.Format); - var content = converter.Convert(Project, Document, GetSpecificVersionOrLatest()); + var content = converter.Convert(Project, Document, GetSpecificVersionOrLatest(), LanguageCode); content = HtmlNormalizer.ReplaceImageSources( content, diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.js b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.js index 32ce1933a7..8eb2083749 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.js +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.js @@ -1,11 +1,11 @@ (function ($) { $(function () { - var initNavigationFilter = function (navigationContainerId) { var $navigation = $("#" + navigationContainerId); + var getShownDocumentLinks = function () { return $navigation.find(".mCSB_container > li a:visible").not(".tree-toggle"); }; diff --git a/modules/docs/test/Volo.Docs.Domain.Tests/Volo/Docs/GithubDocumentStore_Tests.cs b/modules/docs/test/Volo.Docs.Domain.Tests/Volo/Docs/GithubDocumentStore_Tests.cs index 1f8bfeca77..76d1f9f68f 100644 --- a/modules/docs/test/Volo.Docs.Domain.Tests/Volo/Docs/GithubDocumentStore_Tests.cs +++ b/modules/docs/test/Volo.Docs.Domain.Tests/Volo/Docs/GithubDocumentStore_Tests.cs @@ -28,7 +28,7 @@ namespace Volo.Docs var project = await _projectRepository.FindAsync(_testData.PorjectId); project.ShouldNotBeNull(); - var document = await store.GetDocumentAsync(project, "index2", "0.123.0"); + var document = await store.GetDocumentAsync(project, "index2", "en", "0.123.0"); document.ShouldNotBeNull(); document.Title.ShouldBe("index2"); @@ -60,7 +60,7 @@ namespace Volo.Docs var project = await _projectRepository.FindAsync(_testData.PorjectId); project.ShouldNotBeNull(); - var documentResource = await store.GetResource(project, "index.md", "0.123.0"); + var documentResource = await store.GetResource(project, "index.md", "en", "0.123.0"); documentResource.ShouldNotBeNull(); documentResource.Content.ShouldBe(new byte[] diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/IFeatureAppService.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/IFeatureAppService.cs index a30b2397fa..2c337f1b2a 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/IFeatureAppService.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/IFeatureAppService.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading.Tasks; +using System.Threading.Tasks; using JetBrains.Annotations; using Volo.Abp.Application.Services; diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/Localization/ApplicationContracts/cs.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/Localization/ApplicationContracts/cs.json new file mode 100644 index 0000000000..6a060a54c1 --- /dev/null +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/Localization/ApplicationContracts/cs.json @@ -0,0 +1,6 @@ +{ + "culture": "cs", + "texts": { + + } +} \ No newline at end of file diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/Localization/ApplicationContracts/pl.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/Localization/ApplicationContracts/pl.json new file mode 100644 index 0000000000..2ea227cbf3 --- /dev/null +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/Localization/ApplicationContracts/pl.json @@ -0,0 +1,6 @@ +{ + "culture": "pl", + "texts": { + + } +} \ No newline at end of file diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/Localization/ApplicationContracts/vi.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/Localization/ApplicationContracts/vi.json new file mode 100644 index 0000000000..d8eb5f3c75 --- /dev/null +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/Localization/ApplicationContracts/vi.json @@ -0,0 +1,6 @@ +{ + "culture": "vi", + "texts": { + + } +} diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/Localization/Domain/cs.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/Localization/Domain/cs.json new file mode 100644 index 0000000000..6a060a54c1 --- /dev/null +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/Localization/Domain/cs.json @@ -0,0 +1,6 @@ +{ + "culture": "cs", + "texts": { + + } +} \ No newline at end of file diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/Localization/Domain/pl.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/Localization/Domain/pl.json new file mode 100644 index 0000000000..2ea227cbf3 --- /dev/null +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/Localization/Domain/pl.json @@ -0,0 +1,6 @@ +{ + "culture": "pl", + "texts": { + + } +} \ No newline at end of file diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/Localization/Domain/vi.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/Localization/Domain/vi.json new file mode 100644 index 0000000000..d8eb5f3c75 --- /dev/null +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/Localization/Domain/vi.json @@ -0,0 +1,6 @@ +{ + "culture": "vi", + "texts": { + + } +} diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.HttpApi/Volo/Abp/FeatureManagement/FeaturesController.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.HttpApi/Volo/Abp/FeatureManagement/FeaturesController.cs new file mode 100644 index 0000000000..ea0bfd16ee --- /dev/null +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.HttpApi/Volo/Abp/FeatureManagement/FeaturesController.cs @@ -0,0 +1,28 @@ +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc; + +namespace Volo.Abp.FeatureManagement +{ + [RemoteService] + [Area("abp")] + public class FeaturesController : AbpController, IFeatureAppService + { + private readonly IFeatureAppService _featureAppService; + + public FeaturesController(IFeatureAppService featureAppService) + { + _featureAppService = featureAppService; + } + + public Task GetAsync(string providerName, string providerKey) + { + return _featureAppService.GetAsync(providerName, providerKey); + } + + public Task UpdateAsync(string providerName, string providerKey, UpdateFeaturesDto input) + { + return _featureAppService.UpdateAsync(providerName, providerKey, input); + } + } +} \ No newline at end of file diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Localization/Resources/FeatureManagement/cs.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Localization/Resources/FeatureManagement/cs.json new file mode 100644 index 0000000000..8cbecf08ab --- /dev/null +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Localization/Resources/FeatureManagement/cs.json @@ -0,0 +1,6 @@ +{ + "culture": "cs", + "texts": { + "Features": "Funkce" + } +} \ No newline at end of file diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Localization/Resources/FeatureManagement/pl.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Localization/Resources/FeatureManagement/pl.json new file mode 100644 index 0000000000..d714a0d499 --- /dev/null +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Localization/Resources/FeatureManagement/pl.json @@ -0,0 +1,6 @@ +{ + "culture": "pl", + "texts": { + "Features": "Funkcje" + } +} \ No newline at end of file diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Localization/Resources/FeatureManagement/pt-BR.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Localization/Resources/FeatureManagement/pt-BR.json index 6d746df04c..caaacd6fd4 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Localization/Resources/FeatureManagement/pt-BR.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Localization/Resources/FeatureManagement/pt-BR.json @@ -1,6 +1,6 @@ { "culture": "pt-BR", "texts": { - + "Features": "Funcionalidades" } } \ No newline at end of file diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Localization/Resources/FeatureManagement/vi.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Localization/Resources/FeatureManagement/vi.json new file mode 100644 index 0000000000..f8eda1da21 --- /dev/null +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Localization/Resources/FeatureManagement/vi.json @@ -0,0 +1,6 @@ +{ + "culture": "vi", + "texts": { + "Features": "Tính năng" + } +} diff --git a/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/Localization/ApplicationContracts/cs.json b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/Localization/ApplicationContracts/cs.json new file mode 100644 index 0000000000..8580872991 --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/Localization/ApplicationContracts/cs.json @@ -0,0 +1,14 @@ +{ + "culture": "cs", + "texts": { + "Volo.Abp.Identity:010001": "Nemůžete smazat svůj vlastní účet!", + "Permission:IdentityManagement": "Správa identit", + "Permission:RoleManagement": "Správa rolí", + "Permission:Create": "Vytvořit", + "Permission:Edit": "Upravit", + "Permission:Delete": "Smazat", + "Permission:ChangePermissions": "Změnit oprávnění", + "Permission:UserManagement": "Správa uživatelů", + "Permission:UserLookup": "Vyhledání uživatele" + } +} \ No newline at end of file diff --git a/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/Localization/ApplicationContracts/pl.json b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/Localization/ApplicationContracts/pl.json new file mode 100644 index 0000000000..4ebaa0c660 --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/Localization/ApplicationContracts/pl.json @@ -0,0 +1,14 @@ +{ + "culture": "pl", + "texts": { + "Volo.Abp.Identity:010001": "Nie możesz usunąć swojego własnego konta!", + "Permission:IdentityManagement": "Zarządzanie tożsamością", + "Permission:RoleManagement": "Zarządanie rolami", + "Permission:Create": "Utwórz", + "Permission:Edit": "Edytuj", + "Permission:Delete": "Usuń", + "Permission:ChangePermissions": "Zmień uprawnienia", + "Permission:UserManagement": "Zarządzanie użytkownikami", + "Permission:UserLookup": "Wyszukiwanie użytkownika" + } +} \ No newline at end of file diff --git a/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/Localization/ApplicationContracts/vi.json b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/Localization/ApplicationContracts/vi.json new file mode 100644 index 0000000000..e9576d3ea9 --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/Localization/ApplicationContracts/vi.json @@ -0,0 +1,14 @@ +{ + "culture": "vi", + "texts": { + "Volo.Abp.Identity:010001": "Bạn không thể xóa tài khoản của riêng bạn!", + "Permission:IdentityManagement": "Quản lý danh tính", + "Permission:RoleManagement": "Quản lý vai trò", + "Permission:Create": "Tạo", + "Permission:Edit": "Sửa", + "Permission:Delete": "Xóa", + "Permission:ChangePermissions": "Thay đổi quyền", + "Permission:UserManagement": "Quản lý người dùng", + "Permission:UserLookup": "Tra cứu người dùng" + } +} diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Localization/Domain/cs.json b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Localization/Domain/cs.json new file mode 100644 index 0000000000..f6fdea467d --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Localization/Domain/cs.json @@ -0,0 +1,33 @@ +{ + "culture": "cs", + "texts": { + "Identity.DefaultError": "Došlo k neznámé chybě.", + "Identity.ConcurrencyFailure": "Selhání optimistické souběžnosti, objekt byl změněn.", + "Identity.DuplicateEmail": "Email '{0}' již existuje.", + "Identity.DuplicateRoleName": "Role '{0}' již existuje.", + "Identity.DuplicateUserName": "Uživatelské jméno '{0}' již existuje.", + "Identity.InvalidEmail": "Email '{0}' je neplatný.", + "Identity.InvalidPasswordHasherCompatibilityMode": "Dodaný PasswordHasherCompatibilityMode je neplatný.", + "Identity.InvalidPasswordHasherIterationCount": "Počet iterací musí být kladné celé číslo.", + "Identity.InvalidRoleName": "Role '{0}' je neplatná.", + "Identity.InvalidToken": "Neplatný token.", + "Identity.InvalidUserName": "Uživatelské jméno '{0}' je neplatné, může obsahovat pouze písmena a číslice.", + "Identity.LoginAlreadyAssociated": "Uživatel s tímto přihlášením již existuje.", + "Identity.PasswordMismatch": "Chybné heslo.", + "Identity.PasswordRequiresDigit": "Hesla musí obsahovat alespoň jednu číslici ('0'-'9').", + "Identity.PasswordRequiresLower": "Hesla musí obsahovat alespoň jedno malé písmeno ('a'-'z').", + "Identity.PasswordRequiresNonAlphanumeric": "Hesla musí obsahovat alespoň jeden nealfanumerický znak.", + "Identity.PasswordRequiresUpper": "Hesla musí obsahovat alespoň jedno velké písmeno ('A'-'Z').", + "Identity.PasswordTooShort": "Hesla musí být dlouhá alespoň {0} znaků.", + "Identity.RoleNotFound": "Role {0} neexistuje.", + "Identity.UserAlreadyHasPassword": "Uživatel již má nastavené heslo.", + "Identity.UserAlreadyInRole": "Uživatel již je v roli '{0}'.", + "Identity.UserLockedOut": "Uživatel je uzamčen.", + "Identity.UserLockoutNotEnabled": "Uzamčení není umožněno pro tohoto uživatele.", + "Identity.UserNameNotFound": "Uživatel {0} neexistuje.", + "Identity.UserNotInRole": "Uživatel není v roli '{0}'.", + "Identity.PasswordConfirmationFailed": "Heslo nesouhlasí s potvrzovacím heslem.", + "Identity.StaticRoleRenamingErrorMessage": "Statické role nemohou být přejmenovány.", + "Identity.StaticRoleDeletionErrorMessage": "Statické role nemohou být smazány." + } +} \ No newline at end of file diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Localization/Domain/pl.json b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Localization/Domain/pl.json new file mode 100644 index 0000000000..7a1011ef96 --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Localization/Domain/pl.json @@ -0,0 +1,33 @@ +{ + "culture": "pl", + "texts": { + "Identity.DefaultError": "Wystąpił niespodziewany błąd.", + "Identity.ConcurrencyFailure": "Optymistyczny błąd współbierzności, obiekt został zmodyfikowany.", + "Identity.DuplicateEmail": "Email '{0}' już istnieje.", + "Identity.DuplicateRoleName": "Rola '{0}' już istnieje.", + "Identity.DuplicateUserName": "Nazwa użytkownika '{0}' już istnieje.", + "Identity.InvalidEmail": "Email '{0}' jest niepoprawny.", + "Identity.InvalidPasswordHasherCompatibilityMode": "Dostawca PasswordHasherCompatibilityMode jest niepoprawny.", + "Identity.InvalidPasswordHasherIterationCount": "Wartość iteracji musi być większa od zera.", + "Identity.InvalidRoleName": "Rola '{0}' jest niepoprawna.", + "Identity.InvalidToken": "Niepoprawny token.", + "Identity.InvalidUserName": "Nazwa użytkownika '{0}' jest niepoprawna, może zawierać tylko litery i cyfry.", + "Identity.LoginAlreadyAssociated": "Użytkownik o tym loginie już istnieje.", + "Identity.PasswordMismatch": "Niepoprawne hasło.", + "Identity.PasswordRequiresDigit": "Hasło musi zawierać przynajmniej jedną cyfrę ('0'-'9').", + "Identity.PasswordRequiresLower": "Hasło musi zawierać przynajmniej jedną małą literę ('a'-'z').", + "Identity.PasswordRequiresNonAlphanumeric": "Hasło musi zawierać przynajmniej jeden znak alfanumeryczny.", + "Identity.PasswordRequiresUpper": "Hasło musi zawierać przynajmniej jedną wielką literę ('A'-'Z').", + "Identity.PasswordTooShort": "Hasło musi zawierać przynajmnie {0} znaków.", + "Identity.RoleNotFound": "Rola {0} nie istnieje.", + "Identity.UserAlreadyHasPassword": "Użytkownik ma już ustawione hasło.", + "Identity.UserAlreadyInRole": "Użytkownik jest już przypisany do roli '{0}'.", + "Identity.UserLockedOut": "Użytkownik jest zablokowany.", + "Identity.UserLockoutNotEnabled": "Blokada nie jest włączona dla tego użytkownika.", + "Identity.UserNameNotFound": "Użytkownik {0} nie istnieje.", + "Identity.UserNotInRole": "Użytkownik nie posiada roli '{0}'.", + "Identity.PasswordConfirmationFailed": "Podane hasła różnią się od siebie.", + "Identity.StaticRoleRenamingErrorMessage": "Statyczna rola nie może mieć zmienionej nazwy.", + "Identity.StaticRoleDeletionErrorMessage": "Statyczna rola nie może zostać usunięta." + } +} \ No newline at end of file diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Localization/Domain/vi.json b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Localization/Domain/vi.json new file mode 100644 index 0000000000..7546865cfc --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Localization/Domain/vi.json @@ -0,0 +1,33 @@ +{ + "culture": "vi", + "texts": { + "Identity.DefaultError": "Một thất bại chưa biết đã xảy ra.", + "Identity.ConcurrencyFailure": "Thất bại đồng thời lạc quan, đối tượng đã được sửa đổi.", + "Identity.DuplicateEmail": "Email '{0}' đã được sử dụng.", + "Identity.DuplicateRoleName": "Tên vài trò '{0}' đã được sử dụng.", + "Identity.DuplicateUserName": "User name '{0}' đã được sử dụng.", + "Identity.InvalidEmail": "Email '{0}' Không hợp lệ.", + "Identity.InvalidPasswordHasherCompatibilityMode": "PasswordHasherCompatibilityMode được cung cấp không hợp lệ.", + "Identity.InvalidPasswordHasherIterationCount": "Số lần lặp phải là số nguyên dương.", + "Identity.InvalidRoleName": "Tên người dùng '{0}' Không hợp lệ.", + "Identity.InvalidToken": "Token không hợp lệ.", + "Identity.InvalidUserName": "Tên người dùng '{0}' không hợp lệ, chỉ có thể chứa chữ cái hoặc chữ số.", + "Identity.LoginAlreadyAssociated": "Một người dùng có thông tin đăng nhập này đã tồn tại.", + "Identity.PasswordMismatch": "Mật khẩu không đúng.", + "Identity.PasswordRequiresDigit": "Mật khẩu phải có ít nhất một chữ số ('0'-'9').", + "Identity.PasswordRequiresLower": "Mật khẩu phải có ít nhất một chữ thường ('a'-'z').", + "Identity.PasswordRequiresNonAlphanumeric": "Mật khẩu phải có ít nhất một ký tự không phải là chữ và số.", + "Identity.PasswordRequiresUpper": "Mật khẩu phải có ít nhất một chữ hoa ('A'-'Z').", + "Identity.PasswordTooShort": "Mật khẩu phải ít nhất {0} kí tự.", + "Identity.RoleNotFound": "Vai trò {0} không tồn tại.", + "Identity.UserAlreadyHasPassword": "Người dùng đã có một mật khẩu.", + "Identity.UserAlreadyInRole": "Người dùng đã có vai trò '{0}'.", + "Identity.UserLockedOut": "Người dùng bị khóa.", + "Identity.UserLockoutNotEnabled": "Khóa không được kích hoạt cho người dùng này.", + "Identity.UserNameNotFound": "Người dùng {0} không tồn tại.", + "Identity.UserNotInRole": "Người dùng không có vai trò '{0}'.", + "Identity.PasswordConfirmationFailed": "Mật khẩu không khớp với mật khẩu xác nhận.", + "Identity.StaticRoleRenamingErrorMessage": "Vai trò này là cố định không được phép đổi tên.", + "Identity.StaticRoleDeletionErrorMessage": "Vai trò này là cố định không được phép xóa." + } +} diff --git a/modules/identity/src/Volo.Abp.Identity.Web/Localization/Resources/AbpIdentity/cs.json b/modules/identity/src/Volo.Abp.Identity.Web/Localization/Resources/AbpIdentity/cs.json new file mode 100644 index 0000000000..30217206f4 --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Web/Localization/Resources/AbpIdentity/cs.json @@ -0,0 +1,39 @@ +{ + "culture": "cs", + "texts": { + "Menu:IdentityManagement": "Správa identit", + "Users": "Uživatelé", + "NewUser": "Nový uživatel", + "UserName": "Uživatelské jméno", + "EmailAddress": "Email", + "PhoneNumber": "Telefonní číslo", + "UserInformations": "Uživatelské informace", + "DisplayName:IsDefault": "Výchozí", + "DisplayName:IsStatic": "Statické", + "DisplayName:IsPublic": "Veřejné", + "Roles": "Role", + "Password": "Heslo", + "PersonalInfo": "Můj profil", + "PersonalSettings": "Osobní nastavení", + "UserDeletionConfirmationMessage": "Uživatel '{0}' bude smazán. Jste si jistí?", + "RoleDeletionConfirmationMessage": "Role '{0}' bude smazána. Jste si jistí?", + "DisplayName:RoleName": "Název role", + "DisplayName:UserName": "Uživatelské jméno", + "DisplayName:Name": "Jméno", + "DisplayName:Surname": "Příjmení", + "DisplayName:Password": "Heslo", + "DisplayName:Email": "Email", + "DisplayName:PhoneNumber": "Telefonní číslo", + "DisplayName:TwoFactorEnabled": "Dvoufázové ověřování", + "DisplayName:LockoutEnabled": "Zamčení účtu po neúspěšných pokusech", + "NewRole": "Nová role", + "RoleName": "Název role", + "CreationTime": "Vytvořeno", + "Permissions": "Oprávnění", + "DisplayName:CurrentPassword": "Stávající heslo", + "DisplayName:NewPassword": "Nové heslo", + "DisplayName:NewPasswordConfirm": "Potvrzení nového hesla", + "PasswordChangedMessage": "Vaše heslo bylo úspěšně změněno.", + "PersonalSettingsSavedMessage": "Vaše osobní nastavení bylo úspěšně uloženo." + } +} \ No newline at end of file diff --git a/modules/identity/src/Volo.Abp.Identity.Web/Localization/Resources/AbpIdentity/pl.json b/modules/identity/src/Volo.Abp.Identity.Web/Localization/Resources/AbpIdentity/pl.json new file mode 100644 index 0000000000..922e20b042 --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Web/Localization/Resources/AbpIdentity/pl.json @@ -0,0 +1,39 @@ +{ + "culture": "pl", + "texts": { + "Menu:IdentityManagement": "Zarządzanie tożsamością", + "Users": "Użytkownicy", + "NewUser": "Nowy użytkownik", + "UserName": "Nazwa użytkownika", + "EmailAddress": "Adres email", + "PhoneNumber": "Numer telefonu", + "UserInformations": "Notyfikacje użytkownika", + "DisplayName:IsDefault": "Domyślny", + "DisplayName:IsStatic": "Statyczny", + "DisplayName:IsPublic": "Publiczny", + "Roles": "Role", + "Password": "Hasło", + "PersonalInfo": "Mój profil", + "PersonalSettings": "Ustawienia personalne", + "UserDeletionConfirmationMessage": "Użytkownik '{0}' zostanie usunięty. Czy na pewno?", + "RoleDeletionConfirmationMessage": "Rola '{0}' zostanie usunięta. Czy na pewno?", + "DisplayName:RoleName": "Nazwa roli", + "DisplayName:UserName": "Nazwa użytkownika", + "DisplayName:Name": "Imię", + "DisplayName:Surname": "Nazwisko", + "DisplayName:Password": "Hasło", + "DisplayName:Email": "Adres email", + "DisplayName:PhoneNumber": "Numer telefonu", + "DisplayName:TwoFactorEnabled": "Dwustopniowa weryfikacja", + "DisplayName:LockoutEnabled": "Blokowanie konta po nieudanych próbach zalogowania", + "NewRole": "Nowa rola", + "RoleName": "Nazwa roli", + "CreationTime": "Data utworzenia", + "Permissions": "Uprawnienia", + "DisplayName:CurrentPassword": "Aktualne hasło", + "DisplayName:NewPassword": "Nowe hasło", + "DisplayName:NewPasswordConfirm": "Powtierdź nowe hasło", + "PasswordChangedMessage": "Twoje hasło zostało zmienione pomyślnie.", + "PersonalSettingsSavedMessage": "Twoje personalne ustawienia zostały zapisane pomyślnie." + } +} \ No newline at end of file diff --git a/modules/identity/src/Volo.Abp.Identity.Web/Localization/Resources/AbpIdentity/vi.json b/modules/identity/src/Volo.Abp.Identity.Web/Localization/Resources/AbpIdentity/vi.json new file mode 100644 index 0000000000..b43484b0c8 --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Web/Localization/Resources/AbpIdentity/vi.json @@ -0,0 +1,39 @@ +{ + "culture": "vi", + "texts": { + "Menu:IdentityManagement": "Quản lý danh tính", + "Users": "Người dùng", + "NewUser": "Tạo người dùng mới", + "UserName": "Tên đăng nhập", + "EmailAddress": "Địa chỉ email", + "PhoneNumber": "Số điện thoại", + "UserInformations": "Thông tin người dùng", + "DisplayName:IsDefault": "Mặc định", + "DisplayName:IsStatic": "Cố định", + "DisplayName:IsPublic": "Công khai", + "Roles": "Vai trò", + "Password": "Mật khẩu", + "PersonalInfo": "Thông tin của tôi", + "PersonalSettings": "Thiết lập cá nhân", + "UserDeletionConfirmationMessage": "Người '{0}' sẽ bị xóa. Bạn có xác nhận điều này không?", + "RoleDeletionConfirmationMessage": "vai trò '{0}' sẽ bị xóa. Bạn có xác nhận điều này không?", + "DisplayName:RoleName": "Tên vai trò", + "DisplayName:UserName": "Tên người dùng", + "DisplayName:Name": "Tên", + "DisplayName:Surname": "Họ", + "DisplayName:Password": "mật khẩu", + "DisplayName:Email": "Địa chỉ email", + "DisplayName:PhoneNumber": "Số điện thoại", + "DisplayName:TwoFactorEnabled": "Xác thực hai yếu tố", + "DisplayName:LockoutEnabled": "Khóa tài khoản sau những lần đăng nhập thất bại", + "NewRole": "Vai trò mới", + "RoleName": "Tên vai trò", + "CreationTime": "Thời gian tạo", + "Permissions": "Quyền", + "DisplayName:CurrentPassword": "Mật khẩu hiện tại", + "DisplayName:NewPassword": "Mật khẩu mới", + "DisplayName:NewPasswordConfirm": "Xác nhận mật khẩu", + "PasswordChangedMessage": "Mật khẩu của bạn đã được thay đổi thành công.", + "PersonalSettingsSavedMessage": "Thiết lập của bạn đã được lưu lại thành công." + } +} diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerDomainModule.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerDomainModule.cs index dc06ce130d..7ddc619cfa 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerDomainModule.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerDomainModule.cs @@ -3,7 +3,6 @@ using IdentityServer4.Stores; using Microsoft.Extensions.DependencyInjection; using Volo.Abp.AutoMapper; using Volo.Abp.Caching; -using Volo.Abp.Domain; using Volo.Abp.Identity; using Volo.Abp.IdentityServer.Clients; using Volo.Abp.Modularity; diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Localization/Resources/AbpPermissionManagement/cs.json b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Localization/Resources/AbpPermissionManagement/cs.json new file mode 100644 index 0000000000..4c500d06eb --- /dev/null +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Localization/Resources/AbpPermissionManagement/cs.json @@ -0,0 +1,10 @@ +{ + "culture": "cs", + "texts": { + "Permissions": "Oprávnění", + "OnlyProviderPermissons": "Pouze tento poskytovatel", + "All": "Všechna", + "SelectAllInAllTabs": "Dát veškerá oprávnění", + "SelectAllInThisTab": "Vybrat vše" + } +} \ No newline at end of file diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Localization/Resources/AbpPermissionManagement/pl.json b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Localization/Resources/AbpPermissionManagement/pl.json new file mode 100644 index 0000000000..e1043feea7 --- /dev/null +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Localization/Resources/AbpPermissionManagement/pl.json @@ -0,0 +1,10 @@ +{ + "culture": "pl", + "texts": { + "Permissions": "Uprawnienia", + "OnlyProviderPermissons": "Tylko ten dostawca", + "All": "Wszystkie", + "SelectAllInAllTabs": "Udziel wszystkich uprawnień", + "SelectAllInThisTab": "Zaznacz wszystkie" + } +} \ No newline at end of file diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Localization/Resources/AbpPermissionManagement/pt-BR.json b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Localization/Resources/AbpPermissionManagement/pt-BR.json index 93adef2871..ac1a771466 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Localization/Resources/AbpPermissionManagement/pt-BR.json +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Localization/Resources/AbpPermissionManagement/pt-BR.json @@ -3,6 +3,8 @@ "texts": { "Permissions": "Permissões", "OnlyProviderPermissons": "Apenas este provedor", - "All": "Todos" + "All": "Todos", + "SelectAllInAllTabs": "Conceder todas as permissões", + "SelectAllInThisTab": "Selecionar todos" } } \ No newline at end of file diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Localization/Resources/AbpPermissionManagement/vi.json b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Localization/Resources/AbpPermissionManagement/vi.json new file mode 100644 index 0000000000..9364bcf588 --- /dev/null +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Localization/Resources/AbpPermissionManagement/vi.json @@ -0,0 +1,10 @@ +{ + "culture": "vi", + "texts": { + "Permissions": "Quyền", + "OnlyProviderPermissons": "Chỉ nhà cung cấp này", + "All": "Tất cả", + "SelectAllInAllTabs": "Cấp tất cả các quyền", + "SelectAllInThisTab": "Chọn tất cả" + } +} diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Localization/Resources/AbpSettingManagement/cs.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Localization/Resources/AbpSettingManagement/cs.json new file mode 100644 index 0000000000..a0357eda0c --- /dev/null +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Localization/Resources/AbpSettingManagement/cs.json @@ -0,0 +1,6 @@ +{ + "culture": "cs", + "texts": { + "Settings": "Nastavení" + } +} \ No newline at end of file diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Localization/Resources/AbpSettingManagement/pl.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Localization/Resources/AbpSettingManagement/pl.json new file mode 100644 index 0000000000..4aa474d82b --- /dev/null +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Localization/Resources/AbpSettingManagement/pl.json @@ -0,0 +1,6 @@ +{ + "culture": "pl", + "texts": { + "Settings": "Ustawienia" + } +} \ No newline at end of file diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Localization/Resources/AbpSettingManagement/vi.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Localization/Resources/AbpSettingManagement/vi.json new file mode 100644 index 0000000000..9da742c377 --- /dev/null +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Localization/Resources/AbpSettingManagement/vi.json @@ -0,0 +1,6 @@ +{ + "culture": "vi", + "texts": { + "Settings": "Cài đặt" + } +} diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Navigation/SettingManagementMainMenuContributor.cs b/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Navigation/SettingManagementMainMenuContributor.cs index 4bbb0f0bfd..9d622e6a7a 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Navigation/SettingManagementMainMenuContributor.cs +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Navigation/SettingManagementMainMenuContributor.cs @@ -19,7 +19,6 @@ namespace Volo.Abp.SettingManagement.Web.Navigation return; } - var settingManagementPageOptions = context.ServiceProvider.GetRequiredService>().Value; var settingPageCreationContext = new SettingPageCreationContext(context.ServiceProvider); if ( @@ -42,7 +41,6 @@ namespace Volo.Abp.SettingManagement.Web.Navigation icon: "fa fa-cog" ) ); - } private async Task CheckAnyOfPagePermissionsGranted( diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/Localization/ApplicationContracts/cs.json b/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/Localization/ApplicationContracts/cs.json new file mode 100644 index 0000000000..415294c34a --- /dev/null +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/Localization/ApplicationContracts/cs.json @@ -0,0 +1,11 @@ +{ + "culture": "cs", + "texts": { + "Permission:TenantManagement": "Správa tenantů", + "Permission:Create": "Vytvořit", + "Permission:Edit": "Upravit", + "Permission:Delete": "Smazat", + "Permission:ManageConnectionStrings": "Spravovat connection stringy", + "Permission:ManageFeatures": "Spravovat funkce" + } +} \ No newline at end of file diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/Localization/ApplicationContracts/pl.json b/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/Localization/ApplicationContracts/pl.json new file mode 100644 index 0000000000..500b784dfd --- /dev/null +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/Localization/ApplicationContracts/pl.json @@ -0,0 +1,11 @@ +{ + "culture": "pl", + "texts": { + "Permission:TenantManagement": "Zarządzanie tenantami", + "Permission:Create": "Utwórz", + "Permission:Edit": "Edytuj", + "Permission:Delete": "Usuń", + "Permission:ManageConnectionStrings": "Zarządzaj connection string'ami", + "Permission:ManageFeatures": "Zarządzaj fukcjami" + } +} \ No newline at end of file diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/Localization/ApplicationContracts/pt-BR.json b/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/Localization/ApplicationContracts/pt-BR.json index bf461ab29e..6631be849a 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/Localization/ApplicationContracts/pt-BR.json +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/Localization/ApplicationContracts/pt-BR.json @@ -5,6 +5,7 @@ "Permission:Create": "Criar", "Permission:Edit": "Editar", "Permission:Delete": "Excluir", + "Permission:ManageConnectionStrings": "Gerenciar conexões (connection strings)", "Permission:ManageFeatures": "Gerenciar Funcionalidades" } } \ No newline at end of file diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/Localization/ApplicationContracts/vi.json b/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/Localization/ApplicationContracts/vi.json new file mode 100644 index 0000000000..3518883435 --- /dev/null +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/Localization/ApplicationContracts/vi.json @@ -0,0 +1,11 @@ +{ + "culture": "vi", + "texts": { + "Permission:TenantManagement": "Quản lý khách thuê", + "Permission:Create": "Tạo", + "Permission:Edit": "Sửa", + "Permission:Delete": "Xóa", + "Permission:ManageConnectionStrings": "Quản lý chuỗi kết nối", + "Permission:ManageFeatures": "Quản lý các tính năng" + } +} diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/AbpTenantManagementWebModule.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/AbpTenantManagementWebModule.cs index 855fa24bb3..1549664c27 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/AbpTenantManagementWebModule.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/AbpTenantManagementWebModule.cs @@ -5,6 +5,7 @@ using Volo.Abp.AspNetCore.Mvc.Localization; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap; using Volo.Abp.AutoMapper; using Volo.Abp.FeatureManagement; +using Volo.Abp.FeatureManagement.Localization; using Volo.Abp.Localization; using Volo.Abp.Localization.Resources.AbpValidation; using Volo.Abp.Modularity; @@ -47,6 +48,7 @@ namespace Volo.Abp.TenantManagement.Web .Get() .AddBaseTypes( typeof(AbpValidationResource), + typeof(AbpFeatureManagementResource), typeof(AbpUiResource) ).AddVirtualJson("/Localization/Resources/AbpTenantManagement/Web"); }); diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Localization/Resources/AbpTenantManagement/Web/cs.json b/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Localization/Resources/AbpTenantManagement/Web/cs.json new file mode 100644 index 0000000000..df819c5798 --- /dev/null +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Localization/Resources/AbpTenantManagement/Web/cs.json @@ -0,0 +1,14 @@ +{ + "culture": "cs", + "texts": { + "Menu:TenantManagement": "Správa tenantů", + "Tenants": "Tenanty", + "NewTenant": "Nový tenant", + "TenantName": "Název tenantu", + "DisplayName:TenantName": "Název tenantu", + "TenantDeletionConfirmationMessage": "Tenant '{0}' bude smazán. Jste si jistí?", + "ConnectionStrings": "Connection stringy", + "DisplayName:DefaultConnectionString": "Výchozí connection string", + "DisplayName:UseSharedDatabase": "Použít sdílenou databázi" + } +} \ No newline at end of file diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Localization/Resources/AbpTenantManagement/Web/pl.json b/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Localization/Resources/AbpTenantManagement/Web/pl.json new file mode 100644 index 0000000000..537d235293 --- /dev/null +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Localization/Resources/AbpTenantManagement/Web/pl.json @@ -0,0 +1,14 @@ +{ + "culture": "pl", + "texts": { + "Menu:TenantManagement": "Zarządzanie tenantami", + "Tenants": "Tenanty", + "NewTenant": "Nowy tenant", + "TenantName": "Nazwa tenantu", + "DisplayName:TenantName": "Nazwa tenantu", + "TenantDeletionConfirmationMessage": "Tenant '{0}' zostanie usunięty. Czy na pewno?", + "ConnectionStrings": "Connection Strings", + "DisplayName:DefaultConnectionString": "Domyślny Connection String", + "DisplayName:UseSharedDatabase": "Użyj współdzielonej bazy danych" + } +} \ No newline at end of file diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Localization/Resources/AbpTenantManagement/Web/vi.json b/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Localization/Resources/AbpTenantManagement/Web/vi.json new file mode 100644 index 0000000000..1818cbdffd --- /dev/null +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Localization/Resources/AbpTenantManagement/Web/vi.json @@ -0,0 +1,14 @@ +{ + "culture": "vi", + "texts": { + "Menu:TenantManagement": "Quản lý người thuê", + "Tenants": "Người thuê", + "NewTenant": "Người thuê mới", + "TenantName": "Tên người thuê", + "DisplayName:TenantName": "Tên người thuê", + "TenantDeletionConfirmationMessage": "Người thuê '{0}' sẽ bị xóa. Bạn có xác nhận không?", + "ConnectionStrings": "Chuỗi kết nối", + "DisplayName:DefaultConnectionString": "Chuỗi kết nối mặc định", + "DisplayName:UseSharedDatabase": "Sử dụng cơ sở dữ liệu dùng chung" + } +} diff --git a/npm/lerna.json b/npm/lerna.json index ce492f2519..8fd04e0605 100644 --- a/npm/lerna.json +++ b/npm/lerna.json @@ -1,5 +1,5 @@ { - "version": "0.5.2", + "version": "0.6.2", "packages": [ "packs/*" ], diff --git a/npm/package-lock.json b/npm/package-lock.json new file mode 100644 index 0000000000..f91c3f00be --- /dev/null +++ b/npm/package-lock.json @@ -0,0 +1,2747 @@ +{ + "requires": true, + "lockfileVersion": 1, + "dependencies": { + "@improved/node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@improved/node/-/node-1.0.0.tgz", + "integrity": "sha512-8r6WN+Qp2EsZ6G2F1y0vpJjGFVtoCQQ1aCrvBJ1ofy7SG96nG8FfeXWalxsCbh7zMrieOF45McAb50bYCLCuBQ==", + "dev": true + }, + "JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "requires": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + } + }, + "add-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/add-stream/-/add-stream-1.0.0.tgz", + "integrity": "sha1-anmQQ3ynNtXhKI25K9MmbV9csqo=", + "dev": true + }, + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "dev": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", + "dev": true + }, + "array-ify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", + "integrity": "sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4=", + "dev": true + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "byline": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/byline/-/byline-5.0.0.tgz", + "integrity": "sha1-dBxSFkaOrcRXsDQQEYrXfejB3bE=", + "dev": true + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "camelcase-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz", + "integrity": "sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=", + "dev": true, + "requires": { + "camelcase": "^4.1.0", + "map-obj": "^2.0.0", + "quick-lru": "^1.0.0" + } + }, + "capture-stack-trace": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz", + "integrity": "sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chardet": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", + "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", + "dev": true + }, + "ci-info": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", + "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==", + "dev": true + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "dev": true + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "dev": true + }, + "cmd-shim": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/cmd-shim/-/cmd-shim-2.0.2.tgz", + "integrity": "sha1-b8vamUg6j9FdfTChlspp1oii79s=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "mkdirp": "~0.5.0" + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "columnify": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/columnify/-/columnify-1.5.4.tgz", + "integrity": "sha1-Rzfd8ce2mop8NAVweC6UfuyOeLs=", + "dev": true, + "requires": { + "strip-ansi": "^3.0.0", + "wcwidth": "^1.0.0" + } + }, + "command-join": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/command-join/-/command-join-2.0.1.tgz", + "integrity": "sha512-LBA9kSxtg2SA8itaBeuitpn4pZQOhGVP1dyU1cnXLYrBpF3sikaPhjWPqyqVh7oGpneI05RtJs9a0fftIEgXcA==", + "dev": true, + "requires": { + "@improved/node": "^1.0.0" + } + }, + "commander": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", + "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", + "dev": true, + "optional": true + }, + "compare-func": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-1.3.2.tgz", + "integrity": "sha1-md0LpFfh+bxyKxLAjsM+6rMfpkg=", + "dev": true, + "requires": { + "array-ify": "^1.0.0", + "dot-prop": "^3.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "dev": true + }, + "conventional-changelog": { + "version": "1.1.24", + "resolved": "https://registry.npmjs.org/conventional-changelog/-/conventional-changelog-1.1.24.tgz", + "integrity": "sha512-2WcSUst4Y3Z4hHvoMTWXMJr/DmgVdLiMOVY1Kak2LfFz+GIz2KDp5naqbFesYbfXPmaZ5p491dO0FWZIJoJw1Q==", + "dev": true, + "requires": { + "conventional-changelog-angular": "^1.6.6", + "conventional-changelog-atom": "^0.2.8", + "conventional-changelog-codemirror": "^0.3.8", + "conventional-changelog-core": "^2.0.11", + "conventional-changelog-ember": "^0.3.12", + "conventional-changelog-eslint": "^1.0.9", + "conventional-changelog-express": "^0.3.6", + "conventional-changelog-jquery": "^0.1.0", + "conventional-changelog-jscs": "^0.1.0", + "conventional-changelog-jshint": "^0.3.8", + "conventional-changelog-preset-loader": "^1.1.8" + } + }, + "conventional-changelog-angular": { + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-1.6.6.tgz", + "integrity": "sha512-suQnFSqCxRwyBxY68pYTsFkG0taIdinHLNEAX5ivtw8bCRnIgnpvcHmlR/yjUyZIrNPYAoXlY1WiEKWgSE4BNg==", + "dev": true, + "requires": { + "compare-func": "^1.3.1", + "q": "^1.5.1" + } + }, + "conventional-changelog-atom": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/conventional-changelog-atom/-/conventional-changelog-atom-0.2.8.tgz", + "integrity": "sha512-8pPZqhMbrnltNBizjoDCb/Sz85KyUXNDQxuAEYAU5V/eHn0okMBVjqc8aHWYpHrytyZWvMGbayOlDv7i8kEf6g==", + "dev": true, + "requires": { + "q": "^1.5.1" + } + }, + "conventional-changelog-cli": { + "version": "1.3.22", + "resolved": "https://registry.npmjs.org/conventional-changelog-cli/-/conventional-changelog-cli-1.3.22.tgz", + "integrity": "sha512-pnjdIJbxjkZ5VdAX/H1wndr1G10CY8MuZgnXuJhIHglOXfIrXygb7KZC836GW9uo1u8PjEIvIw/bKX0lOmOzZg==", + "dev": true, + "requires": { + "add-stream": "^1.0.0", + "conventional-changelog": "^1.1.24", + "lodash": "^4.2.1", + "meow": "^4.0.0", + "tempfile": "^1.1.1" + } + }, + "conventional-changelog-codemirror": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/conventional-changelog-codemirror/-/conventional-changelog-codemirror-0.3.8.tgz", + "integrity": "sha512-3HFZKtBXTaUCHvz7ai6nk2+psRIkldDoNzCsom0egDtVmPsvvHZkzjynhdQyULfacRSsBTaiQ0ol6nBOL4dDiQ==", + "dev": true, + "requires": { + "q": "^1.5.1" + } + }, + "conventional-changelog-core": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-2.0.11.tgz", + "integrity": "sha512-HvTE6RlqeEZ/NFPtQeFLsIDOLrGP3bXYr7lFLMhCVsbduF1MXIe8OODkwMFyo1i9ku9NWBwVnVn0jDmIFXjDRg==", + "dev": true, + "requires": { + "conventional-changelog-writer": "^3.0.9", + "conventional-commits-parser": "^2.1.7", + "dateformat": "^3.0.0", + "get-pkg-repo": "^1.0.0", + "git-raw-commits": "^1.3.6", + "git-remote-origin-url": "^2.0.0", + "git-semver-tags": "^1.3.6", + "lodash": "^4.2.1", + "normalize-package-data": "^2.3.5", + "q": "^1.5.1", + "read-pkg": "^1.1.0", + "read-pkg-up": "^1.0.1", + "through2": "^2.0.0" + }, + "dependencies": { + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + } + } + }, + "conventional-changelog-ember": { + "version": "0.3.12", + "resolved": "https://registry.npmjs.org/conventional-changelog-ember/-/conventional-changelog-ember-0.3.12.tgz", + "integrity": "sha512-mmJzA7uzbrOqeF89dMMi6z17O07ORTXlTMArnLG9ZTX4oLaKNolUlxFUFlFm9JUoVWajVpaHQWjxH1EOQ+ARoQ==", + "dev": true, + "requires": { + "q": "^1.5.1" + } + }, + "conventional-changelog-eslint": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/conventional-changelog-eslint/-/conventional-changelog-eslint-1.0.9.tgz", + "integrity": "sha512-h87nfVh2fdk9fJIvz26wCBsbDC/KxqCc5wSlNMZbXcARtbgNbNDIF7Y7ctokFdnxkzVdaHsbINkh548T9eBA7Q==", + "dev": true, + "requires": { + "q": "^1.5.1" + } + }, + "conventional-changelog-express": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/conventional-changelog-express/-/conventional-changelog-express-0.3.6.tgz", + "integrity": "sha512-3iWVtBJZ9RnRnZveNDzOD8QRn6g6vUif0qVTWWyi5nUIAbuN1FfPVyKdAlJJfp5Im+dE8Kiy/d2SpaX/0X678Q==", + "dev": true, + "requires": { + "q": "^1.5.1" + } + }, + "conventional-changelog-jquery": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-jquery/-/conventional-changelog-jquery-0.1.0.tgz", + "integrity": "sha1-Agg5cWLjhGmG5xJztsecW1+A9RA=", + "dev": true, + "requires": { + "q": "^1.4.1" + } + }, + "conventional-changelog-jscs": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-jscs/-/conventional-changelog-jscs-0.1.0.tgz", + "integrity": "sha1-BHnrRDzH1yxYvwvPDvHURKkvDlw=", + "dev": true, + "requires": { + "q": "^1.4.1" + } + }, + "conventional-changelog-jshint": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/conventional-changelog-jshint/-/conventional-changelog-jshint-0.3.8.tgz", + "integrity": "sha512-hn9QU4ZI/5V50wKPJNPGT4gEWgiBFpV6adieILW4MaUFynuDYOvQ71EMSj3EznJyKi/KzuXpc9dGmX8njZMjig==", + "dev": true, + "requires": { + "compare-func": "^1.3.1", + "q": "^1.5.1" + } + }, + "conventional-changelog-preset-loader": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-1.1.8.tgz", + "integrity": "sha512-MkksM4G4YdrMlT2MbTsV2F6LXu/hZR0Tc/yenRrDIKRwBl/SP7ER4ZDlglqJsCzLJi4UonBc52Bkm5hzrOVCcw==", + "dev": true + }, + "conventional-changelog-writer": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-3.0.9.tgz", + "integrity": "sha512-n9KbsxlJxRQsUnK6wIBRnARacvNnN4C/nxnxCkH+B/R1JS2Fa+DiP1dU4I59mEDEjgnFaN2+9wr1P1s7GYB5/Q==", + "dev": true, + "requires": { + "compare-func": "^1.3.1", + "conventional-commits-filter": "^1.1.6", + "dateformat": "^3.0.0", + "handlebars": "^4.0.2", + "json-stringify-safe": "^5.0.1", + "lodash": "^4.2.1", + "meow": "^4.0.0", + "semver": "^5.5.0", + "split": "^1.0.0", + "through2": "^2.0.0" + } + }, + "conventional-commits-filter": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-1.1.6.tgz", + "integrity": "sha512-KcDgtCRKJCQhyk6VLT7zR+ZOyCnerfemE/CsR3iQpzRRFbLEs0Y6rwk3mpDvtOh04X223z+1xyJ582Stfct/0Q==", + "dev": true, + "requires": { + "is-subset": "^0.1.1", + "modify-values": "^1.0.0" + } + }, + "conventional-commits-parser": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-2.1.7.tgz", + "integrity": "sha512-BoMaddIEJ6B4QVMSDu9IkVImlGOSGA1I2BQyOZHeLQ6qVOJLcLKn97+fL6dGbzWEiqDzfH4OkcveULmeq2MHFQ==", + "dev": true, + "requires": { + "JSONStream": "^1.0.4", + "is-text-path": "^1.0.0", + "lodash": "^4.2.1", + "meow": "^4.0.0", + "split2": "^2.0.0", + "through2": "^2.0.0", + "trim-off-newlines": "^1.0.0" + } + }, + "conventional-recommended-bump": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/conventional-recommended-bump/-/conventional-recommended-bump-1.2.1.tgz", + "integrity": "sha512-oJjG6DkRgtnr/t/VrPdzmf4XZv8c4xKVJrVT4zrSHd92KEL+EYxSbYoKq8lQ7U5yLMw7130wrcQTLRjM/T+d4w==", + "dev": true, + "requires": { + "concat-stream": "^1.4.10", + "conventional-commits-filter": "^1.1.1", + "conventional-commits-parser": "^2.1.1", + "git-raw-commits": "^1.3.0", + "git-semver-tags": "^1.3.0", + "meow": "^3.3.0", + "object-assign": "^4.0.1" + }, + "dependencies": { + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true + }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "dev": true, + "requires": { + "camelcase": "^2.0.0", + "map-obj": "^1.0.0" + } + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "dev": true, + "requires": { + "repeating": "^2.0.0" + } + }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + }, + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "dev": true, + "requires": { + "camelcase-keys": "^2.0.0", + "decamelize": "^1.1.2", + "loud-rejection": "^1.0.0", + "map-obj": "^1.0.1", + "minimist": "^1.1.3", + "normalize-package-data": "^2.3.4", + "object-assign": "^4.0.1", + "read-pkg-up": "^1.0.1", + "redent": "^1.0.0", + "trim-newlines": "^1.0.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "dev": true, + "requires": { + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" + } + }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "dev": true, + "requires": { + "get-stdin": "^4.0.1" + } + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true + } + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "create-error-class": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", + "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", + "dev": true, + "requires": { + "capture-stack-trace": "^1.0.0" + } + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "dev": true, + "requires": { + "array-find-index": "^1.0.1" + } + }, + "dargs": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-4.1.0.tgz", + "integrity": "sha1-A6nbtLXC8Tm/FK5T8LiipqhvThc=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "dateformat": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", + "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", + "dev": true + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decamelize-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", + "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", + "dev": true, + "requires": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "dependencies": { + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + } + } + }, + "dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", + "dev": true + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true + }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "dev": true, + "requires": { + "clone": "^1.0.2" + } + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "dev": true + }, + "detect-indent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-5.0.0.tgz", + "integrity": "sha1-OHHMCmoALow+Wzz38zYmRnXwa50=", + "dev": true + }, + "dot-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-3.0.0.tgz", + "integrity": "sha1-G3CK8JSknJoOfbyteQq6U52sEXc=", + "dev": true, + "requires": { + "is-obj": "^1.0.0" + } + }, + "duplexer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", + "dev": true + }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", + "dev": true + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "execa": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.8.0.tgz", + "integrity": "sha1-2NdrvBtVIX7RkP1t1J08d07PyNo=", + "dev": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "external-editor": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", + "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", + "dev": true, + "requires": { + "chardet": "^0.4.0", + "iconv-lite": "^0.4.17", + "tmp": "^0.0.33" + } + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "fs-extra": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", + "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "dev": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, + "get-pkg-repo": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/get-pkg-repo/-/get-pkg-repo-1.4.0.tgz", + "integrity": "sha1-xztInAbYDMVTbCyFP54FIyBWly0=", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "meow": "^3.3.0", + "normalize-package-data": "^2.3.0", + "parse-github-repo-url": "^1.3.0", + "through2": "^2.0.0" + }, + "dependencies": { + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true + }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "dev": true, + "requires": { + "camelcase": "^2.0.0", + "map-obj": "^1.0.0" + } + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "dev": true, + "requires": { + "repeating": "^2.0.0" + } + }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + }, + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "dev": true, + "requires": { + "camelcase-keys": "^2.0.0", + "decamelize": "^1.1.2", + "loud-rejection": "^1.0.0", + "map-obj": "^1.0.1", + "minimist": "^1.1.3", + "normalize-package-data": "^2.3.4", + "object-assign": "^4.0.1", + "read-pkg-up": "^1.0.1", + "redent": "^1.0.0", + "trim-newlines": "^1.0.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "dev": true, + "requires": { + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" + } + }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "dev": true, + "requires": { + "get-stdin": "^4.0.1" + } + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true + } + } + }, + "get-port": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz", + "integrity": "sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw=", + "dev": true + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, + "git-raw-commits": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-1.3.6.tgz", + "integrity": "sha512-svsK26tQ8vEKnMshTDatSIQSMDdz8CxIIqKsvPqbtV23Etmw6VNaFAitu8zwZ0VrOne7FztwPyRLxK7/DIUTQg==", + "dev": true, + "requires": { + "dargs": "^4.0.1", + "lodash.template": "^4.0.2", + "meow": "^4.0.0", + "split2": "^2.0.0", + "through2": "^2.0.0" + } + }, + "git-remote-origin-url": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz", + "integrity": "sha1-UoJlna4hBxRaERJhEq0yFuxfpl8=", + "dev": true, + "requires": { + "gitconfiglocal": "^1.0.0", + "pify": "^2.3.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "git-semver-tags": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-1.3.6.tgz", + "integrity": "sha512-2jHlJnln4D/ECk9FxGEBh3k44wgYdWjWDtMmJPaecjoRmxKo3Y1Lh8GMYuOPu04CHw86NTAODchYjC5pnpMQig==", + "dev": true, + "requires": { + "meow": "^4.0.0", + "semver": "^5.5.0" + } + }, + "gitconfiglocal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz", + "integrity": "sha1-QdBF84UaXqiPA/JMocYXgRRGS5s=", + "dev": true, + "requires": { + "ini": "^1.3.2" + } + }, + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "got": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz", + "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", + "dev": true, + "requires": { + "create-error-class": "^3.0.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "is-redirect": "^1.0.0", + "is-retry-allowed": "^1.0.0", + "is-stream": "^1.0.0", + "lowercase-keys": "^1.0.0", + "safe-buffer": "^5.0.1", + "timed-out": "^4.0.0", + "unzip-response": "^2.0.1", + "url-parse-lax": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "dev": true + }, + "handlebars": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.2.tgz", + "integrity": "sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==", + "dev": true, + "requires": { + "neo-async": "^2.6.0", + "optimist": "^0.6.1", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "dev": true + }, + "hosted-git-info": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", + "dev": true + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true + }, + "inquirer": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", + "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", + "dev": true, + "requires": { + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.0", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^2.0.4", + "figures": "^2.0.0", + "lodash": "^4.3.0", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rx-lite": "^4.0.8", + "rx-lite-aggregates": "^4.0.8", + "string-width": "^2.1.0", + "strip-ansi": "^4.0.0", + "through": "^2.3.6" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-ci": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz", + "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==", + "dev": true, + "requires": { + "ci-info": "^1.5.0" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "dev": true + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "dev": true + }, + "is-redirect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", + "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=", + "dev": true + }, + "is-retry-allowed": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", + "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=", + "dev": true + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-subset": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-subset/-/is-subset-0.1.1.tgz", + "integrity": "sha1-ilkRfZMt4d4A8kX83TnOQ/HpOaY=", + "dev": true + }, + "is-text-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", + "integrity": "sha1-Thqg+1G/vLPpJogAE5cgLBd1tm4=", + "dev": true, + "requires": { + "text-extensions": "^1.0.0" + } + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, + "lerna": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/lerna/-/lerna-2.11.0.tgz", + "integrity": "sha512-kgM6zwe2P2tR30MYvgiLLW+9buFCm6E7o8HnRlhTgm70WVBvXVhydqv+q/MF2HrVZkCawfVtCfetyQmtd4oHhQ==", + "dev": true, + "requires": { + "async": "^1.5.0", + "chalk": "^2.1.0", + "cmd-shim": "^2.0.2", + "columnify": "^1.5.4", + "command-join": "^2.0.0", + "conventional-changelog-cli": "^1.3.13", + "conventional-recommended-bump": "^1.2.1", + "dedent": "^0.7.0", + "execa": "^0.8.0", + "find-up": "^2.1.0", + "fs-extra": "^4.0.1", + "get-port": "^3.2.0", + "glob": "^7.1.2", + "glob-parent": "^3.1.0", + "globby": "^6.1.0", + "graceful-fs": "^4.1.11", + "hosted-git-info": "^2.5.0", + "inquirer": "^3.2.2", + "is-ci": "^1.0.10", + "load-json-file": "^4.0.0", + "lodash": "^4.17.4", + "minimatch": "^3.0.4", + "npmlog": "^4.1.2", + "p-finally": "^1.0.0", + "package-json": "^4.0.1", + "path-exists": "^3.0.0", + "read-cmd-shim": "^1.0.1", + "read-pkg": "^3.0.0", + "rimraf": "^2.6.1", + "safe-buffer": "^5.1.1", + "semver": "^5.4.1", + "signal-exit": "^3.0.2", + "slash": "^1.0.0", + "strong-log-transformer": "^1.0.6", + "temp-write": "^3.3.0", + "write-file-atomic": "^2.3.0", + "write-json-file": "^2.2.0", + "write-pkg": "^3.1.0", + "yargs": "^8.0.2" + } + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "dev": true + }, + "lodash.template": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.4.0.tgz", + "integrity": "sha1-5zoDhcg1VZF0bgILmWecaQ5o+6A=", + "dev": true, + "requires": { + "lodash._reinterpolate": "~3.0.0", + "lodash.templatesettings": "^4.0.0" + } + }, + "lodash.templatesettings": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz", + "integrity": "sha1-K01OlbpEDZFf8IvImeRVNmZxMxY=", + "dev": true, + "requires": { + "lodash._reinterpolate": "~3.0.0" + } + }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "dev": true, + "requires": { + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" + } + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "map-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz", + "integrity": "sha1-plzSkIepJZi4eRJXpSPgISIqwfk=", + "dev": true + }, + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "meow": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/meow/-/meow-4.0.1.tgz", + "integrity": "sha512-xcSBHD5Z86zaOc+781KrupuHAzeGXSLtiAOmBsiLDiPSaYSB6hdew2ng9EBAnZ62jagG9MHAOdxpDi/lWBFJ/A==", + "dev": true, + "requires": { + "camelcase-keys": "^4.0.0", + "decamelize-keys": "^1.0.0", + "loud-rejection": "^1.0.0", + "minimist": "^1.1.3", + "minimist-options": "^3.0.1", + "normalize-package-data": "^2.3.4", + "read-pkg-up": "^3.0.0", + "redent": "^2.0.0", + "trim-newlines": "^2.0.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "read-pkg-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^3.0.0" + } + } + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "minimist-options": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-3.0.2.tgz", + "integrity": "sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ==", + "dev": true, + "requires": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0" + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "modify-values": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz", + "integrity": "sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==", + "dev": true + }, + "moment": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", + "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==", + "dev": true + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "neo-async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", + "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==", + "dev": true + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dev": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + } + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "dev": true, + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + }, + "dependencies": { + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + } + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "package-json": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz", + "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=", + "dev": true, + "requires": { + "got": "^6.7.1", + "registry-auth-token": "^3.0.1", + "registry-url": "^3.0.3", + "semver": "^5.1.0" + } + }, + "parse-github-repo-url": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/parse-github-repo-url/-/parse-github-repo-url-1.4.1.tgz", + "integrity": "sha1-nn2LslKmy2ukJZUGC3v23z28H1A=", + "dev": true + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true + }, + "quick-lru": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz", + "integrity": "sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=", + "dev": true + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "read-cmd-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-1.0.1.tgz", + "integrity": "sha1-LV0Vd4ajfAVdIgd8MsU/gynpHHs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2" + } + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + } + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "redent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz", + "integrity": "sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=", + "dev": true, + "requires": { + "indent-string": "^3.0.0", + "strip-indent": "^2.0.0" + } + }, + "registry-auth-token": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.4.0.tgz", + "integrity": "sha512-4LM6Fw8eBQdwMYcES4yTnn2TqIasbXuwDx3um+QRs7S55aMKCBKBxvPXl2RiUjHwuJLTyYfxSpmfSAjQpcuP+A==", + "dev": true, + "requires": { + "rc": "^1.1.6", + "safe-buffer": "^5.0.1" + } + }, + "registry-url": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", + "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", + "dev": true, + "requires": { + "rc": "^1.0.1" + } + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "^1.0.0" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "resolve": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.0.tgz", + "integrity": "sha512-WL2pBDjqT6pGUNSUzMw00o4T7If+z4H2x3Gz893WoUQ5KW8Vr9txp00ykiP16VBaZF5+j/OcXJHZ9+PCvdiDKw==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "dev": true, + "requires": { + "is-promise": "^2.1.0" + } + }, + "rx-lite": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", + "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", + "dev": true + }, + "rx-lite-aggregates": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", + "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", + "dev": true, + "requires": { + "rx-lite": "*" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "dev": true + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "sort-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", + "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", + "dev": true, + "requires": { + "is-plain-obj": "^1.0.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "spdx-correct": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.4.tgz", + "integrity": "sha512-7j8LYJLeY/Yb6ACbQ7F76qy5jHkp0U6jgBfJsk97bwWlVUnUWsAgpyaCvo17h0/RQGnQ036tVDomiwoI4pDkQA==", + "dev": true + }, + "split": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", + "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "dev": true, + "requires": { + "through": "2" + } + }, + "split2": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-2.2.0.tgz", + "integrity": "sha512-RAb22TG39LhI31MbreBgIuKiIKhVsawfTgEGqKHTK87aG+ul/PB8Sqoi3I7kVdRWiCfrKxK3uo4/YUkpNvhPbw==", + "dev": true, + "requires": { + "through2": "^2.0.2" + } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, + "strip-indent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", + "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", + "dev": true + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "strong-log-transformer": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/strong-log-transformer/-/strong-log-transformer-1.0.6.tgz", + "integrity": "sha1-9/uTdYpppXEUAYEnfuoMLrEwH6M=", + "dev": true, + "requires": { + "byline": "^5.0.0", + "duplexer": "^0.1.1", + "minimist": "^0.1.0", + "moment": "^2.6.0", + "through": "^2.3.4" + }, + "dependencies": { + "minimist": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.1.0.tgz", + "integrity": "sha1-md9lelJXTCHJBXSX33QnkLK0wN4=", + "dev": true + } + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "temp-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-1.0.0.tgz", + "integrity": "sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0=", + "dev": true + }, + "temp-write": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/temp-write/-/temp-write-3.4.0.tgz", + "integrity": "sha1-jP9jD7fp2gXwR8dM5M5NaFRX1JI=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "is-stream": "^1.1.0", + "make-dir": "^1.0.0", + "pify": "^3.0.0", + "temp-dir": "^1.0.0", + "uuid": "^3.0.1" + }, + "dependencies": { + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "dev": true + } + } + }, + "tempfile": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tempfile/-/tempfile-1.1.1.tgz", + "integrity": "sha1-W8xOrsxKsscH2LwR2ZzMmiyyh/I=", + "dev": true, + "requires": { + "os-tmpdir": "^1.0.0", + "uuid": "^2.0.1" + } + }, + "text-extensions": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", + "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "timed-out": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", + "dev": true + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "trim-newlines": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz", + "integrity": "sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=", + "dev": true + }, + "trim-off-newlines": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-off-newlines/-/trim-off-newlines-1.0.1.tgz", + "integrity": "sha1-n5up2e+odkw4dpi8v+sshI8RrbM=", + "dev": true + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "uglify-js": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.0.tgz", + "integrity": "sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg==", + "dev": true, + "optional": true, + "requires": { + "commander": "~2.20.0", + "source-map": "~0.6.1" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + }, + "unzip-response": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz", + "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=", + "dev": true + }, + "url-parse-lax": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", + "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "dev": true, + "requires": { + "prepend-http": "^1.0.1" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "uuid": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", + "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "dev": true, + "requires": { + "defaults": "^1.0.3" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "write-json-file": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-2.3.0.tgz", + "integrity": "sha1-K2TIozAE1UuGmMdtWFp3zrYdoy8=", + "dev": true, + "requires": { + "detect-indent": "^5.0.0", + "graceful-fs": "^4.1.2", + "make-dir": "^1.0.0", + "pify": "^3.0.0", + "sort-keys": "^2.0.0", + "write-file-atomic": "^2.0.0" + } + }, + "write-pkg": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/write-pkg/-/write-pkg-3.2.0.tgz", + "integrity": "sha512-tX2ifZ0YqEFOF1wjRW2Pk93NLsj02+n1UP5RvO6rCs0K6R2g1padvf006cY74PQJKMGS2r42NK7FD0dG6Y6paw==", + "dev": true, + "requires": { + "sort-keys": "^2.0.0", + "write-json-file": "^2.2.0" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "yargs": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", + "integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=", + "dev": true, + "requires": { + "camelcase": "^4.1.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "read-pkg-up": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^7.0.0" + }, + "dependencies": { + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } + } + } + }, + "yargs-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", + "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", + "dev": true, + "requires": { + "camelcase": "^4.1.0" + } + } + } +} diff --git a/npm/packs/anchor-js/package.json b/npm/packs/anchor-js/package.json index 49de358f72..8b784032db 100644 --- a/npm/packs/anchor-js/package.json +++ b/npm/packs/anchor-js/package.json @@ -1,11 +1,11 @@ { - "version": "0.5.1", + "version": "0.6.2", "name": "@abp/anchor-js", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/core": "^0.4.9", + "@abp/core": "^0.6.2", "anchor-js": "^4.1.1" }, "gitHead": "2e846ad3e5a8cbe04100484865335fbcd845a342" diff --git a/npm/packs/aspnetcore.mvc.ui.theme.basic/package.json b/npm/packs/aspnetcore.mvc.ui.theme.basic/package.json index 03572eeffe..ca2bec81ac 100644 --- a/npm/packs/aspnetcore.mvc.ui.theme.basic/package.json +++ b/npm/packs/aspnetcore.mvc.ui.theme.basic/package.json @@ -1,11 +1,11 @@ { - "version": "0.4.9", + "version": "0.6.2", "name": "@abp/aspnetcore.mvc.ui.theme.basic", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/aspnetcore.mvc.ui.theme.shared": "^0.4.9" + "@abp/aspnetcore.mvc.ui.theme.shared": "^0.6.2" }, "gitHead": "2e846ad3e5a8cbe04100484865335fbcd845a342" } diff --git a/npm/packs/aspnetcore.mvc.ui.theme.shared/package.json b/npm/packs/aspnetcore.mvc.ui.theme.shared/package.json index e8fdce70e0..3fa842fee8 100644 --- a/npm/packs/aspnetcore.mvc.ui.theme.shared/package.json +++ b/npm/packs/aspnetcore.mvc.ui.theme.shared/package.json @@ -1,21 +1,22 @@ { - "version": "0.4.9", + "version": "0.6.2", "name": "@abp/aspnetcore.mvc.ui.theme.shared", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/aspnetcore.mvc.ui": "^0.4.9", - "@abp/bootstrap": "^0.4.9", - "@abp/datatables.net-bs4": "^0.4.9", - "@abp/font-awesome": "^0.4.9", - "@abp/jquery-form": "^0.4.9", - "@abp/jquery-validation-unobtrusive": "^0.4.9", - "@abp/lodash": "^0.4.9", - "@abp/select2": "^0.4.9", - "@abp/sweetalert": "^0.4.9", - "@abp/timeago": "^0.4.9", - "@abp/toastr": "^0.4.9" + "@abp/aspnetcore.mvc.ui": "^0.6.2", + "@abp/bootstrap": "^0.6.2", + "@abp/datatables.net-bs4": "^0.6.2", + "@abp/font-awesome": "^0.6.2", + "@abp/freeze-ui": "^0.6.2", + "@abp/jquery-form": "^0.6.2", + "@abp/jquery-validation-unobtrusive": "^0.6.2", + "@abp/lodash": "^0.6.2", + "@abp/select2": "^0.6.2", + "@abp/sweetalert": "^0.6.2", + "@abp/timeago": "^0.6.2", + "@abp/toastr": "^0.6.2" }, "gitHead": "2e846ad3e5a8cbe04100484865335fbcd845a342" } diff --git a/npm/packs/aspnetcore.mvc.ui/package.json b/npm/packs/aspnetcore.mvc.ui/package.json index cc2c2b6581..1f26612a2e 100644 --- a/npm/packs/aspnetcore.mvc.ui/package.json +++ b/npm/packs/aspnetcore.mvc.ui/package.json @@ -1,5 +1,5 @@ { - "version": "0.4.9", + "version": "0.6.2", "name": "@abp/aspnetcore.mvc.ui", "publishConfig": { "access": "public" diff --git a/npm/packs/blogging/package.json b/npm/packs/blogging/package.json index f609f13857..bde917290c 100644 --- a/npm/packs/blogging/package.json +++ b/npm/packs/blogging/package.json @@ -1,12 +1,12 @@ { - "version": "0.4.9", + "version": "0.6.2", "name": "@abp/blogging", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/aspnetcore.mvc.ui.theme.shared": "^0.4.9", - "@abp/owl.carousel": "^0.4.9", - "@abp/tui-editor": "^0.4.9" + "@abp/aspnetcore.mvc.ui.theme.shared": "^0.6.2", + "@abp/owl.carousel": "^0.6.2", + "@abp/tui-editor": "^0.6.2" } } diff --git a/npm/packs/bootstrap/package.json b/npm/packs/bootstrap/package.json index 16f28145b1..2ba3067da7 100644 --- a/npm/packs/bootstrap/package.json +++ b/npm/packs/bootstrap/package.json @@ -1,11 +1,11 @@ { - "version": "0.4.9", + "version": "0.6.2", "name": "@abp/bootstrap", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/core": "^0.4.9", + "@abp/core": "^0.6.2", "bootstrap": "^4.1.1" }, "gitHead": "2e846ad3e5a8cbe04100484865335fbcd845a342" diff --git a/npm/packs/clipboard/package.json b/npm/packs/clipboard/package.json index 4a848656b2..5227059f25 100644 --- a/npm/packs/clipboard/package.json +++ b/npm/packs/clipboard/package.json @@ -1,11 +1,11 @@ { - "version": "0.5.1", + "version": "0.6.2", "name": "@abp/clipboard", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/core": "^0.4.9", + "@abp/core": "^0.6.2", "clipboard": "^2.0.4" }, "gitHead": "2e846ad3e5a8cbe04100484865335fbcd845a342" diff --git a/npm/packs/codemirror/package.json b/npm/packs/codemirror/package.json index 5a29ea6593..1eb1af3464 100644 --- a/npm/packs/codemirror/package.json +++ b/npm/packs/codemirror/package.json @@ -1,11 +1,11 @@ { - "version": "0.4.9", + "version": "0.6.2", "name": "@abp/codemirror", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/core": "^0.4.9", + "@abp/core": "^0.6.2", "codemirror": "^5.38.0" }, "gitHead": "2e846ad3e5a8cbe04100484865335fbcd845a342" diff --git a/npm/packs/core/package.json b/npm/packs/core/package.json index 0ddd08be20..336dd20dac 100644 --- a/npm/packs/core/package.json +++ b/npm/packs/core/package.json @@ -1,5 +1,5 @@ { - "version": "0.4.9", + "version": "0.6.2", "name": "@abp/core", "publishConfig": { "access": "public" diff --git a/npm/packs/datatables.net-bs4/package.json b/npm/packs/datatables.net-bs4/package.json index 76d8471864..3bc44fee7c 100644 --- a/npm/packs/datatables.net-bs4/package.json +++ b/npm/packs/datatables.net-bs4/package.json @@ -1,11 +1,11 @@ { - "version": "0.4.9", + "version": "0.6.2", "name": "@abp/datatables.net-bs4", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/datatables.net": "^0.4.9", + "@abp/datatables.net": "^0.6.2", "datatables.net-bs4": "^1.10.16" }, "gitHead": "2e846ad3e5a8cbe04100484865335fbcd845a342" diff --git a/npm/packs/datatables.net/package.json b/npm/packs/datatables.net/package.json index 5f951c3460..805a3d7d82 100644 --- a/npm/packs/datatables.net/package.json +++ b/npm/packs/datatables.net/package.json @@ -1,11 +1,11 @@ { - "version": "0.4.9", + "version": "0.6.2", "name": "@abp/datatables.net", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/core": "^0.4.9", + "@abp/core": "^0.6.2", "datatables.net": "^1.10.16" }, "gitHead": "2e846ad3e5a8cbe04100484865335fbcd845a342" diff --git a/npm/packs/docs/package.json b/npm/packs/docs/package.json index 85029d409e..78f2d397ea 100644 --- a/npm/packs/docs/package.json +++ b/npm/packs/docs/package.json @@ -1,15 +1,15 @@ { - "version": "0.5.1", + "version": "0.6.2", "name": "@abp/docs", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/anchor-js": "^0.5.1", - "@abp/clipboard": "^0.5.1", - "@abp/malihu-custom-scrollbar-plugin": "^0.5.1", - "@abp/popper.js": "^0.5.1", - "@abp/prismjs": "^0.5.1" + "@abp/anchor-js": "^0.6.2", + "@abp/clipboard": "^0.6.2", + "@abp/malihu-custom-scrollbar-plugin": "^0.6.2", + "@abp/popper.js": "^0.6.2", + "@abp/prismjs": "^0.6.2" }, "gitHead": "2e846ad3e5a8cbe04100484865335fbcd845a342" } diff --git a/npm/packs/flag-icon-css/package.json b/npm/packs/flag-icon-css/package.json index 9a151e3b41..a4463971d0 100644 --- a/npm/packs/flag-icon-css/package.json +++ b/npm/packs/flag-icon-css/package.json @@ -1,5 +1,5 @@ { - "version": "0.5.2", + "version": "0.6.2", "name": "@abp/flag-icon-css", "publishConfig": { "access": "public" diff --git a/npm/packs/font-awesome/package.json b/npm/packs/font-awesome/package.json index 01b9188e60..f211738c9d 100644 --- a/npm/packs/font-awesome/package.json +++ b/npm/packs/font-awesome/package.json @@ -1,11 +1,11 @@ { - "version": "0.4.9", + "version": "0.6.2", "name": "@abp/font-awesome", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/core": "^0.4.9", + "@abp/core": "^0.6.2", "font-awesome": "^4.7.0" }, "gitHead": "2e846ad3e5a8cbe04100484865335fbcd845a342" diff --git a/npm/packs/freeze-ui/abp.resourcemapping.js b/npm/packs/freeze-ui/abp.resourcemapping.js new file mode 100644 index 0000000000..b027f07c88 --- /dev/null +++ b/npm/packs/freeze-ui/abp.resourcemapping.js @@ -0,0 +1,6 @@ +module.exports = { + mappings: { + "@node_modules/@abp/freeze-ui/lib/freeze-ui.min.js": "@libs/freeze-ui/", + "@node_modules/@abp/freeze-ui/lib/freeze-ui.min.css": "@libs/freeze-ui/" + } +} \ No newline at end of file diff --git a/npm/packs/freeze-ui/lib/freeze-ui.min.css b/npm/packs/freeze-ui/lib/freeze-ui.min.css new file mode 100644 index 0000000000..0f85b42513 --- /dev/null +++ b/npm/packs/freeze-ui/lib/freeze-ui.min.css @@ -0,0 +1 @@ +@keyframes spin{0%{transform:translateZ(0) rotate(0)}100%{transform:translateZ(0) rotate(360deg)}}.freeze-ui{position:fixed;top:0;left:0;width:100%;height:100%;z-index:999999999;background-color:#fff;opacity:.8;transition:opacity .25s}.freeze-ui.is-unfreezing{opacity:0}.freeze-ui:after{content:attr(data-text);display:block;max-width:125px;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);font-size:20px;font-family:sans-serif;color:#343a40;text-align:center;text-transform:uppercase}.freeze-ui:before{content:"";display:block;width:150px;height:150px;border-radius:50%;border-width:2px;border-style:solid;border-color:transparent #228ae6 #228ae6;position:absolute;top:calc(50% - 75px);left:calc(50% - 75px);will-change:transform;animation:spin .75s infinite ease-in-out} \ No newline at end of file diff --git a/npm/packs/freeze-ui/lib/freeze-ui.min.js b/npm/packs/freeze-ui/lib/freeze-ui.min.js new file mode 100644 index 0000000000..991416917c --- /dev/null +++ b/npm/packs/freeze-ui/lib/freeze-ui.min.js @@ -0,0 +1 @@ +(()=>{let a=document.createElement('div');a.classList.add('freeze-ui'),window.FreezeUI=(b={})=>{let c=document.querySelector(b.selector)||document.body;a.setAttribute('data-text',b.text||'Loading'),document.querySelector(b.selector)&&(a.style.position='absolute'),c.appendChild(a)},window.UnFreezeUI=()=>{let b=document.querySelector('.freeze-ui');b&&(b.classList.add('is-unfreezing'),setTimeout(()=>{b&&(b.classList.remove('is-unfreezing'),b.parentElement.removeChild(b))},250))}})(); \ No newline at end of file diff --git a/npm/packs/freeze-ui/package.json b/npm/packs/freeze-ui/package.json new file mode 100644 index 0000000000..ec9b01090e --- /dev/null +++ b/npm/packs/freeze-ui/package.json @@ -0,0 +1,11 @@ +{ + "version": "0.6.2", + "name": "@abp/freeze-ui", + "publishConfig": { + "access": "public" + }, + "dependencies": { + "@abp/core": "^0.5.3" + }, + "gitHead": "824de4c615c1d4d1d7f07d6ec1e8d0cb3a303c72" +} diff --git a/npm/packs/highlight.js/package.json b/npm/packs/highlight.js/package.json index ad687d68c3..5a099da564 100644 --- a/npm/packs/highlight.js/package.json +++ b/npm/packs/highlight.js/package.json @@ -1,11 +1,11 @@ { - "version": "0.4.9", + "version": "0.6.2", "name": "@abp/highlight.js", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/core": "^0.4.9" + "@abp/core": "^0.6.2" }, "gitHead": "2e846ad3e5a8cbe04100484865335fbcd845a342" } diff --git a/npm/packs/jquery-form/package.json b/npm/packs/jquery-form/package.json index 4f7024cad7..fcbbc47fe4 100644 --- a/npm/packs/jquery-form/package.json +++ b/npm/packs/jquery-form/package.json @@ -1,11 +1,11 @@ { - "version": "0.4.9", + "version": "0.6.2", "name": "@abp/jquery-form", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/jquery": "^0.4.9", + "@abp/jquery": "^0.6.2", "jquery-form": "^4.2.2" }, "gitHead": "2e846ad3e5a8cbe04100484865335fbcd845a342" diff --git a/npm/packs/jquery-validation-unobtrusive/package.json b/npm/packs/jquery-validation-unobtrusive/package.json index ab39d95cf0..f1f73536b0 100644 --- a/npm/packs/jquery-validation-unobtrusive/package.json +++ b/npm/packs/jquery-validation-unobtrusive/package.json @@ -1,11 +1,11 @@ { - "version": "0.4.9", + "version": "0.6.2", "name": "@abp/jquery-validation-unobtrusive", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/jquery-validation": "^0.4.9", + "@abp/jquery-validation": "^0.6.2", "jquery-validation-unobtrusive": "^3.2.9" }, "gitHead": "2e846ad3e5a8cbe04100484865335fbcd845a342" diff --git a/npm/packs/jquery-validation/package.json b/npm/packs/jquery-validation/package.json index 7a11e12877..c0d2f59cb0 100644 --- a/npm/packs/jquery-validation/package.json +++ b/npm/packs/jquery-validation/package.json @@ -1,11 +1,11 @@ { - "version": "0.4.9", + "version": "0.6.2", "name": "@abp/jquery-validation", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/jquery": "^0.4.9", + "@abp/jquery": "^0.6.2", "jquery-validation": "^1.17.0" }, "gitHead": "2e846ad3e5a8cbe04100484865335fbcd845a342" diff --git a/npm/packs/jquery/package.json b/npm/packs/jquery/package.json index b2add4bcd8..7f629514b6 100644 --- a/npm/packs/jquery/package.json +++ b/npm/packs/jquery/package.json @@ -1,11 +1,11 @@ { - "version": "0.4.9", + "version": "0.6.2", "name": "@abp/jquery", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/core": "^0.4.9", + "@abp/core": "^0.6.2", "jquery": "^3.3.1" }, "gitHead": "2e846ad3e5a8cbe04100484865335fbcd845a342" diff --git a/npm/packs/lodash/package.json b/npm/packs/lodash/package.json index cc57ead5dc..224487726d 100644 --- a/npm/packs/lodash/package.json +++ b/npm/packs/lodash/package.json @@ -1,11 +1,11 @@ { - "version": "0.4.9", + "version": "0.6.2", "name": "@abp/lodash", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/core": "^0.4.9", + "@abp/core": "^0.6.2", "lodash": "^4.17.10" }, "gitHead": "2e846ad3e5a8cbe04100484865335fbcd845a342" diff --git a/npm/packs/malihu-custom-scrollbar-plugin/package.json b/npm/packs/malihu-custom-scrollbar-plugin/package.json index 53df8ffc63..2f3c007a34 100644 --- a/npm/packs/malihu-custom-scrollbar-plugin/package.json +++ b/npm/packs/malihu-custom-scrollbar-plugin/package.json @@ -1,11 +1,11 @@ { - "version": "0.5.1", + "version": "0.6.2", "name": "@abp/malihu-custom-scrollbar-plugin", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/core": "^0.4.9", + "@abp/core": "^0.6.2", "malihu-custom-scrollbar-plugin": "^3.1.5" }, "gitHead": "2e846ad3e5a8cbe04100484865335fbcd845a342" diff --git a/npm/packs/markdown-it/package.json b/npm/packs/markdown-it/package.json index 97da6d8566..a6bdc3de95 100644 --- a/npm/packs/markdown-it/package.json +++ b/npm/packs/markdown-it/package.json @@ -1,11 +1,11 @@ { - "version": "0.4.9", + "version": "0.6.2", "name": "@abp/markdown-it", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/core": "^0.4.9", + "@abp/core": "^0.6.2", "markdown-it": "^8.4.1" }, "gitHead": "2e846ad3e5a8cbe04100484865335fbcd845a342" diff --git a/npm/packs/owl.carousel/package.json b/npm/packs/owl.carousel/package.json index 1ac7c1de6d..ab0a79c7f5 100644 --- a/npm/packs/owl.carousel/package.json +++ b/npm/packs/owl.carousel/package.json @@ -1,11 +1,11 @@ { - "version": "0.4.9", + "version": "0.6.2", "name": "@abp/owl.carousel", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/core": "^0.4.9", + "@abp/core": "^0.6.2", "owl.carousel": "^2.3.4" } } diff --git a/npm/packs/popper.js/package.json b/npm/packs/popper.js/package.json index b37ad96923..2d41ceef4f 100644 --- a/npm/packs/popper.js/package.json +++ b/npm/packs/popper.js/package.json @@ -1,11 +1,11 @@ { - "version": "0.5.1", + "version": "0.6.2", "name": "@abp/popper.js", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/core": "^0.4.9", + "@abp/core": "^0.6.2", "popper.js": "^1.14.6" }, "gitHead": "2e846ad3e5a8cbe04100484865335fbcd845a342" diff --git a/npm/packs/prismjs/package.json b/npm/packs/prismjs/package.json index e9935289c7..f404a5d2c2 100644 --- a/npm/packs/prismjs/package.json +++ b/npm/packs/prismjs/package.json @@ -1,11 +1,11 @@ { - "version": "0.5.1", + "version": "0.6.2", "name": "@abp/prismjs", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/core": "^0.4.9", + "@abp/core": "^0.6.2", "prismjs": "^1.15.0" }, "gitHead": "2e846ad3e5a8cbe04100484865335fbcd845a342" diff --git a/npm/packs/select2/package.json b/npm/packs/select2/package.json index a240b6976c..62518a0281 100644 --- a/npm/packs/select2/package.json +++ b/npm/packs/select2/package.json @@ -1,11 +1,11 @@ { - "version": "0.4.9", + "version": "0.6.2", "name": "@abp/select2", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/core": "^0.4.9", + "@abp/core": "^0.6.2", "select2": "^4.0.5" }, "gitHead": "2e846ad3e5a8cbe04100484865335fbcd845a342" diff --git a/npm/packs/sweetalert/package.json b/npm/packs/sweetalert/package.json index 78e077fb8a..ea6badbe81 100644 --- a/npm/packs/sweetalert/package.json +++ b/npm/packs/sweetalert/package.json @@ -1,11 +1,11 @@ { - "version": "0.4.9", + "version": "0.6.2", "name": "@abp/sweetalert", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/core": "^0.4.9", + "@abp/core": "^0.6.2", "sweetalert": "^2.1.0" }, "gitHead": "2e846ad3e5a8cbe04100484865335fbcd845a342" diff --git a/npm/packs/timeago/package.json b/npm/packs/timeago/package.json index 0ee2fb7e09..bc0818079b 100644 --- a/npm/packs/timeago/package.json +++ b/npm/packs/timeago/package.json @@ -1,11 +1,11 @@ { - "version": "0.4.9", + "version": "0.6.2", "name": "@abp/timeago", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/jquery": "^0.4.9", + "@abp/jquery": "^0.6.2", "timeago": "^1.6.3" }, "gitHead": "2e846ad3e5a8cbe04100484865335fbcd845a342" diff --git a/npm/packs/toastr/package.json b/npm/packs/toastr/package.json index 78eb013622..75625d0718 100644 --- a/npm/packs/toastr/package.json +++ b/npm/packs/toastr/package.json @@ -1,11 +1,11 @@ { - "version": "0.4.9", + "version": "0.6.2", "name": "@abp/toastr", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/jquery": "^0.4.9", + "@abp/jquery": "^0.6.2", "toastr": "^2.1.4" }, "gitHead": "2e846ad3e5a8cbe04100484865335fbcd845a342" diff --git a/npm/packs/tui-editor/package.json b/npm/packs/tui-editor/package.json index 4124554e27..464301fe89 100644 --- a/npm/packs/tui-editor/package.json +++ b/npm/packs/tui-editor/package.json @@ -1,14 +1,14 @@ { - "version": "0.4.9", + "version": "0.6.2", "name": "@abp/tui-editor", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/codemirror": "^0.4.9", - "@abp/highlight.js": "^0.4.9", - "@abp/jquery": "^0.4.9", - "@abp/markdown-it": "^0.4.9", + "@abp/codemirror": "^0.6.2", + "@abp/highlight.js": "^0.6.2", + "@abp/jquery": "^0.6.2", + "@abp/markdown-it": "^0.6.2", "tui-editor": "^1.2.6" }, "gitHead": "2e846ad3e5a8cbe04100484865335fbcd845a342" diff --git a/npm/publish.bat b/npm/publish.bat index 30d32c4a65..5e83340c49 100644 --- a/npm/publish.bat +++ b/npm/publish.bat @@ -1 +1 @@ -lerna publish --skip-git \ No newline at end of file +lerna publish --no-push \ No newline at end of file diff --git a/samples/BookStore/.gitignore b/samples/BookStore/.gitignore index 78d93c60d8..5e2a431b54 100644 --- a/samples/BookStore/.gitignore +++ b/samples/BookStore/.gitignore @@ -252,4 +252,7 @@ paket-files/ *.sln.iml # BookStore -src/Acme.BookStore.Web/Logs/logs.txt +src/Acme.BookStore.Web/Logs/* +src/Acme.BookStore.Web.Host/Logs/* +src/Acme.BookStore.IdentityServer/Logs/* +src/Acme.BookStore.HttpApi.Host/Logs/* \ No newline at end of file diff --git a/samples/BookStore/Acme.BookStore.sln b/samples/BookStore/Acme.BookStore.sln index 74836646a2..1de66eeb59 100644 --- a/samples/BookStore/Acme.BookStore.sln +++ b/samples/BookStore/Acme.BookStore.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.28922.388 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Acme.BookStore.Domain", "src\Acme.BookStore.Domain\Acme.BookStore.Domain.csproj", "{554AD327-6DBA-4F8F-96F8-81CE7A0C863F}" EndProject @@ -19,7 +19,25 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Acme.BookStore.Application. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Acme.BookStore.Web.Tests", "test\Acme.BookStore.Web.Tests\Acme.BookStore.Web.Tests.csproj", "{5F1B28C6-8D0C-4155-92D0-252F7EA5F674}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Acme.BookStore.EntityFrameworkCore.DbMigrations", "src\Acme.BookStore.EntityFrameworkCore.DbMigrations\Acme.BookStore.EntityFrameworkCore.DbMigrations.csproj", "{0372FA84-C517-4EB3-9A9F-B9ACAC0CA5E0}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Acme.BookStore.EntityFrameworkCore.DbMigrations", "src\Acme.BookStore.EntityFrameworkCore.DbMigrations\Acme.BookStore.EntityFrameworkCore.DbMigrations.csproj", "{0372FA84-C517-4EB3-9A9F-B9ACAC0CA5E0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Acme.BookStore.Domain.Shared", "src\Acme.BookStore.Domain.Shared\Acme.BookStore.Domain.Shared.csproj", "{42F719ED-8413-4895-B5B4-5AB56079BC66}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Acme.BookStore.Application.Contracts", "src\Acme.BookStore.Application.Contracts\Acme.BookStore.Application.Contracts.csproj", "{520659C8-C734-4298-A3DA-B539DB9DFC0B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Acme.BookStore.HttpApi", "src\Acme.BookStore.HttpApi\Acme.BookStore.HttpApi.csproj", "{4164BDF7-F527-4E85-9CE6-E3C2D7426A27}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Acme.BookStore.HttpApi.Client", "src\Acme.BookStore.HttpApi.Client\Acme.BookStore.HttpApi.Client.csproj", "{3B5A0094-670D-4BB1-BFDD-61B88A8773DC}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Acme.BookStore.EntityFrameworkCore.Tests", "test\Acme.BookStore.EntityFrameworkCore.Tests\Acme.BookStore.EntityFrameworkCore.Tests.csproj", "{1FE30EB9-74A9-47F5-A9F6-7B1FAB672D81}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Acme.BookStore.TestBase", "test\Acme.BookStore.TestBase\Acme.BookStore.TestBase.csproj", "{91853F21-9CD9-4132-BC29-A7D5D84FFFE7}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Acme.BookStore.Domain.Tests", "test\Acme.BookStore.Domain.Tests\Acme.BookStore.Domain.Tests.csproj", "{E512F4D9-9375-480F-A2F6-A46509F9D824}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Acme.BookStore.HttpApi.Client.ConsoleTestApp", "test\Acme.BookStore.HttpApi.Client.ConsoleTestApp\Acme.BookStore.HttpApi.Client.ConsoleTestApp.csproj", "{EF480016-9127-4916-8735-D2466BDBC582}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Acme.BookStore.DbMigrator", "src\Acme.BookStore.DbMigrator\Acme.BookStore.DbMigrator.csproj", "{AA94D832-1CCC-4715-95A9-A483F23A1A5D}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -55,6 +73,42 @@ Global {0372FA84-C517-4EB3-9A9F-B9ACAC0CA5E0}.Debug|Any CPU.Build.0 = Debug|Any CPU {0372FA84-C517-4EB3-9A9F-B9ACAC0CA5E0}.Release|Any CPU.ActiveCfg = Release|Any CPU {0372FA84-C517-4EB3-9A9F-B9ACAC0CA5E0}.Release|Any CPU.Build.0 = Release|Any CPU + {42F719ED-8413-4895-B5B4-5AB56079BC66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {42F719ED-8413-4895-B5B4-5AB56079BC66}.Debug|Any CPU.Build.0 = Debug|Any CPU + {42F719ED-8413-4895-B5B4-5AB56079BC66}.Release|Any CPU.ActiveCfg = Release|Any CPU + {42F719ED-8413-4895-B5B4-5AB56079BC66}.Release|Any CPU.Build.0 = Release|Any CPU + {520659C8-C734-4298-A3DA-B539DB9DFC0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {520659C8-C734-4298-A3DA-B539DB9DFC0B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {520659C8-C734-4298-A3DA-B539DB9DFC0B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {520659C8-C734-4298-A3DA-B539DB9DFC0B}.Release|Any CPU.Build.0 = Release|Any CPU + {4164BDF7-F527-4E85-9CE6-E3C2D7426A27}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4164BDF7-F527-4E85-9CE6-E3C2D7426A27}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4164BDF7-F527-4E85-9CE6-E3C2D7426A27}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4164BDF7-F527-4E85-9CE6-E3C2D7426A27}.Release|Any CPU.Build.0 = Release|Any CPU + {3B5A0094-670D-4BB1-BFDD-61B88A8773DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3B5A0094-670D-4BB1-BFDD-61B88A8773DC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3B5A0094-670D-4BB1-BFDD-61B88A8773DC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3B5A0094-670D-4BB1-BFDD-61B88A8773DC}.Release|Any CPU.Build.0 = Release|Any CPU + {1FE30EB9-74A9-47F5-A9F6-7B1FAB672D81}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1FE30EB9-74A9-47F5-A9F6-7B1FAB672D81}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1FE30EB9-74A9-47F5-A9F6-7B1FAB672D81}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1FE30EB9-74A9-47F5-A9F6-7B1FAB672D81}.Release|Any CPU.Build.0 = Release|Any CPU + {91853F21-9CD9-4132-BC29-A7D5D84FFFE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {91853F21-9CD9-4132-BC29-A7D5D84FFFE7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {91853F21-9CD9-4132-BC29-A7D5D84FFFE7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {91853F21-9CD9-4132-BC29-A7D5D84FFFE7}.Release|Any CPU.Build.0 = Release|Any CPU + {E512F4D9-9375-480F-A2F6-A46509F9D824}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E512F4D9-9375-480F-A2F6-A46509F9D824}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E512F4D9-9375-480F-A2F6-A46509F9D824}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E512F4D9-9375-480F-A2F6-A46509F9D824}.Release|Any CPU.Build.0 = Release|Any CPU + {EF480016-9127-4916-8735-D2466BDBC582}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EF480016-9127-4916-8735-D2466BDBC582}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EF480016-9127-4916-8735-D2466BDBC582}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EF480016-9127-4916-8735-D2466BDBC582}.Release|Any CPU.Build.0 = Release|Any CPU + {AA94D832-1CCC-4715-95A9-A483F23A1A5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AA94D832-1CCC-4715-95A9-A483F23A1A5D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AA94D832-1CCC-4715-95A9-A483F23A1A5D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AA94D832-1CCC-4715-95A9-A483F23A1A5D}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -67,6 +121,15 @@ Global {50B2631D-129C-47B3-A587-029CCD6099BC} = {04DBDB01-70F4-4E06-B468-8F87850B22BE} {5F1B28C6-8D0C-4155-92D0-252F7EA5F674} = {04DBDB01-70F4-4E06-B468-8F87850B22BE} {0372FA84-C517-4EB3-9A9F-B9ACAC0CA5E0} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0} + {42F719ED-8413-4895-B5B4-5AB56079BC66} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0} + {520659C8-C734-4298-A3DA-B539DB9DFC0B} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0} + {4164BDF7-F527-4E85-9CE6-E3C2D7426A27} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0} + {3B5A0094-670D-4BB1-BFDD-61B88A8773DC} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0} + {1FE30EB9-74A9-47F5-A9F6-7B1FAB672D81} = {04DBDB01-70F4-4E06-B468-8F87850B22BE} + {91853F21-9CD9-4132-BC29-A7D5D84FFFE7} = {04DBDB01-70F4-4E06-B468-8F87850B22BE} + {E512F4D9-9375-480F-A2F6-A46509F9D824} = {04DBDB01-70F4-4E06-B468-8F87850B22BE} + {EF480016-9127-4916-8735-D2466BDBC582} = {04DBDB01-70F4-4E06-B468-8F87850B22BE} + {AA94D832-1CCC-4715-95A9-A483F23A1A5D} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {28315BFD-90E7-4E14-A2EA-F3D23AF4126F} diff --git a/samples/BookStore/common.props b/samples/BookStore/common.props index 771bc6bd29..7585f303ba 100644 --- a/samples/BookStore/common.props +++ b/samples/BookStore/common.props @@ -1,7 +1,7 @@ latest - 0.16.0 + 1.0.0 $(NoWarn);CS1591 \ No newline at end of file diff --git a/samples/BookStore/src/Acme.BookStore.Application.Contracts/Acme.BookStore.Application.Contracts.csproj b/samples/BookStore/src/Acme.BookStore.Application.Contracts/Acme.BookStore.Application.Contracts.csproj new file mode 100644 index 0000000000..f08af2efac --- /dev/null +++ b/samples/BookStore/src/Acme.BookStore.Application.Contracts/Acme.BookStore.Application.Contracts.csproj @@ -0,0 +1,21 @@ + + + + + + netstandard2.0 + Acme.BookStore + + + + + + + + + + + + + + diff --git a/samples/BookStore/src/Acme.BookStore.Application/BookDto.cs b/samples/BookStore/src/Acme.BookStore.Application.Contracts/BookDto.cs similarity index 84% rename from samples/BookStore/src/Acme.BookStore.Application/BookDto.cs rename to samples/BookStore/src/Acme.BookStore.Application.Contracts/BookDto.cs index 42581b95fb..5a94fbce1e 100644 --- a/samples/BookStore/src/Acme.BookStore.Application/BookDto.cs +++ b/samples/BookStore/src/Acme.BookStore.Application.Contracts/BookDto.cs @@ -1,10 +1,8 @@ using System; using Volo.Abp.Application.Dtos; -using Volo.Abp.AutoMapper; namespace Acme.BookStore { - [AutoMapFrom(typeof(Book))] public class BookDto : AuditedEntityDto { public string Name { get; set; } diff --git a/samples/BookStore/src/Acme.BookStore.Application.Contracts/BookStoreApplicationContractsModule.cs b/samples/BookStore/src/Acme.BookStore.Application.Contracts/BookStoreApplicationContractsModule.cs new file mode 100644 index 0000000000..f8af658d37 --- /dev/null +++ b/samples/BookStore/src/Acme.BookStore.Application.Contracts/BookStoreApplicationContractsModule.cs @@ -0,0 +1,20 @@ +using Volo.Abp.FeatureManagement; +using Volo.Abp.Identity; +using Volo.Abp.Modularity; +using Volo.Abp.PermissionManagement; +using Volo.Abp.TenantManagement; + +namespace Acme.BookStore +{ + [DependsOn( + typeof(BookStoreDomainSharedModule), + typeof(AbpFeatureManagementApplicationContractsModule), + typeof(AbpIdentityApplicationContractsModule), + typeof(AbpPermissionManagementApplicationContractsModule), + typeof(AbpTenantManagementApplicationContractsModule) + )] + public class BookStoreApplicationContractsModule : AbpModule + { + + } +} diff --git a/samples/BookStore/src/Acme.BookStore.Application/CreateUpdateBookDto.cs b/samples/BookStore/src/Acme.BookStore.Application.Contracts/CreateUpdateBookDto.cs similarity index 79% rename from samples/BookStore/src/Acme.BookStore.Application/CreateUpdateBookDto.cs rename to samples/BookStore/src/Acme.BookStore.Application.Contracts/CreateUpdateBookDto.cs index 0d5dae71cb..8dc38a9e31 100644 --- a/samples/BookStore/src/Acme.BookStore.Application/CreateUpdateBookDto.cs +++ b/samples/BookStore/src/Acme.BookStore.Application.Contracts/CreateUpdateBookDto.cs @@ -1,11 +1,8 @@ using System; using System.ComponentModel.DataAnnotations; -using Volo.Abp.AutoMapper; namespace Acme.BookStore { - [AutoMapTo(typeof(Book))] - [AutoMapFrom(typeof(BookDto))] public class CreateUpdateBookDto { [Required] @@ -14,10 +11,10 @@ namespace Acme.BookStore [Required] public BookType Type { get; set; } = BookType.Undefined; - + [Required] public DateTime PublishDate { get; set; } - + [Required] public float Price { get; set; } } diff --git a/samples/BookStore/src/Acme.BookStore.Application/IBookAppService.cs b/samples/BookStore/src/Acme.BookStore.Application.Contracts/IBookAppService.cs similarity index 100% rename from samples/BookStore/src/Acme.BookStore.Application/IBookAppService.cs rename to samples/BookStore/src/Acme.BookStore.Application.Contracts/IBookAppService.cs diff --git a/samples/BookStore/src/Acme.BookStore.Application/Acme.BookStore.Application.csproj b/samples/BookStore/src/Acme.BookStore.Application/Acme.BookStore.Application.csproj index 9926530966..4b924ed040 100644 --- a/samples/BookStore/src/Acme.BookStore.Application/Acme.BookStore.Application.csproj +++ b/samples/BookStore/src/Acme.BookStore.Application/Acme.BookStore.Application.csproj @@ -9,10 +9,14 @@ - - - - + + + + + + + + diff --git a/samples/BookStore/src/Acme.BookStore.Application/BookStoreApplicationAutoMapperProfile.cs b/samples/BookStore/src/Acme.BookStore.Application/BookStoreApplicationAutoMapperProfile.cs index 2d1a44a8c5..9bc08930cf 100644 --- a/samples/BookStore/src/Acme.BookStore.Application/BookStoreApplicationAutoMapperProfile.cs +++ b/samples/BookStore/src/Acme.BookStore.Application/BookStoreApplicationAutoMapperProfile.cs @@ -6,7 +6,8 @@ namespace Acme.BookStore { public BookStoreApplicationAutoMapperProfile() { - //Configure your AutoMapper mapping configuration here... + CreateMap(); + CreateMap(); } } } diff --git a/samples/BookStore/src/Acme.BookStore.Application/BookStoreApplicationModule.cs b/samples/BookStore/src/Acme.BookStore.Application/BookStoreApplicationModule.cs index 4203ef0ccd..a97917f774 100644 --- a/samples/BookStore/src/Acme.BookStore.Application/BookStoreApplicationModule.cs +++ b/samples/BookStore/src/Acme.BookStore.Application/BookStoreApplicationModule.cs @@ -9,6 +9,7 @@ namespace Acme.BookStore { [DependsOn( typeof(BookStoreDomainModule), + typeof(BookStoreApplicationContractsModule), typeof(AbpIdentityApplicationModule), typeof(AbpPermissionManagementApplicationModule), typeof(AbpTenantManagementApplicationModule), @@ -20,6 +21,10 @@ namespace Acme.BookStore { Configure(options => { + /* Use `true` for the `validate` parameter if you want to + * validate the profile on application startup. + * See http://docs.automapper.org/en/stable/Configuration-validation.html for more info + * about the configuration validation. */ options.AddProfile(); }); } diff --git a/samples/BookStore/src/Acme.BookStore.Application/Permissions/BookStorePermissionDefinitionProvider.cs b/samples/BookStore/src/Acme.BookStore.Application/Permissions/BookStorePermissionDefinitionProvider.cs index 9a3c6bf18f..aaf784e56e 100644 --- a/samples/BookStore/src/Acme.BookStore.Application/Permissions/BookStorePermissionDefinitionProvider.cs +++ b/samples/BookStore/src/Acme.BookStore.Application/Permissions/BookStorePermissionDefinitionProvider.cs @@ -1,4 +1,4 @@ -using Acme.BookStore.Localization.BookStore; +using Acme.BookStore.Localization; using Volo.Abp.Authorization.Permissions; using Volo.Abp.Localization; diff --git a/samples/BookStore/src/Acme.BookStore.Application/Permissions/BookStorePermissions.cs b/samples/BookStore/src/Acme.BookStore.Application/Permissions/BookStorePermissions.cs index b1ec575904..b05c4883bd 100644 --- a/samples/BookStore/src/Acme.BookStore.Application/Permissions/BookStorePermissions.cs +++ b/samples/BookStore/src/Acme.BookStore.Application/Permissions/BookStorePermissions.cs @@ -1,6 +1,4 @@ -using System; - -namespace Acme.BookStore.Permissions +namespace Acme.BookStore.Permissions { public static class BookStorePermissions { @@ -8,11 +6,5 @@ namespace Acme.BookStore.Permissions //Add your own permission names. Example: //public const string MyPermission1 = GroupName + ".MyPermission1"; - - public static string[] GetAll() - { - //Return an array of all permissions - return Array.Empty(); - } } } \ No newline at end of file diff --git a/samples/BookStore/src/Acme.BookStore.DbMigrator/Acme.BookStore.DbMigrator.csproj b/samples/BookStore/src/Acme.BookStore.DbMigrator/Acme.BookStore.DbMigrator.csproj new file mode 100644 index 0000000000..7df37ca0a7 --- /dev/null +++ b/samples/BookStore/src/Acme.BookStore.DbMigrator/Acme.BookStore.DbMigrator.csproj @@ -0,0 +1,34 @@ + + + + + + Exe + netcoreapp2.2 + + + + + + + + + PreserveNewest + Always + + + + + + + + + + + + + + + + + diff --git a/samples/BookStore/src/Acme.BookStore.DbMigrator/BookStoreDbMigratorModule.cs b/samples/BookStore/src/Acme.BookStore.DbMigrator/BookStoreDbMigratorModule.cs new file mode 100644 index 0000000000..26b843d34c --- /dev/null +++ b/samples/BookStore/src/Acme.BookStore.DbMigrator/BookStoreDbMigratorModule.cs @@ -0,0 +1,16 @@ +using Acme.BookStore.EntityFrameworkCore; +using Volo.Abp.Autofac; +using Volo.Abp.Modularity; + +namespace Acme.BookStore.DbMigrator +{ + [DependsOn( + typeof(AbpAutofacModule), + typeof(BookStoreEntityFrameworkCoreDbMigrationsModule), + typeof(BookStoreApplicationContractsModule) + )] + public class BookStoreDbMigratorModule : AbpModule + { + + } +} diff --git a/samples/BookStore/src/Acme.BookStore.DbMigrator/Program.cs b/samples/BookStore/src/Acme.BookStore.DbMigrator/Program.cs new file mode 100644 index 0000000000..d3c4034c8a --- /dev/null +++ b/samples/BookStore/src/Acme.BookStore.DbMigrator/Program.cs @@ -0,0 +1,53 @@ +using System.IO; +using Microsoft.Extensions.DependencyInjection; +using Acme.BookStore.Data; +using Serilog; +using Serilog.Events; +using Volo.Abp; +using Volo.Abp.Threading; + +namespace Acme.BookStore.DbMigrator +{ + class Program + { + static void Main(string[] args) + { + ConfigureLogging(); + + using (var application = AbpApplicationFactory.Create(options => + { + options.UseAutofac(); + options.Services.AddLogging(c => c.AddSerilog()); + })) + { + application.Initialize(); + + AsyncHelper.RunSync( + () => application + .ServiceProvider + .GetRequiredService() + .MigrateAsync() + ); + + application.Shutdown(); + } + } + + private static void ConfigureLogging() + { + Log.Logger = new LoggerConfiguration() + .MinimumLevel.Information() + .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) + .MinimumLevel.Override("Volo.Abp", LogEventLevel.Warning) +#if DEBUG + .MinimumLevel.Override("Acme.BookStore", LogEventLevel.Debug) +#else + .MinimumLevel.Override("Acme.BookStore", LogEventLevel.Information) +#endif + .Enrich.FromLogContext() + .WriteTo.File(Path.Combine(Directory.GetCurrentDirectory(), "Logs/logs.txt")) + .WriteTo.Console() + .CreateLogger(); + } + } +} diff --git a/samples/BookStore/src/Acme.BookStore.DbMigrator/appsettings.json b/samples/BookStore/src/Acme.BookStore.DbMigrator/appsettings.json new file mode 100644 index 0000000000..05d7313b10 --- /dev/null +++ b/samples/BookStore/src/Acme.BookStore.DbMigrator/appsettings.json @@ -0,0 +1,16 @@ +{ + "ConnectionStrings": { + "Default": "Server=localhost;Database=BookStore;Trusted_Connection=True;MultipleActiveResultSets=true" + }, + "IdentityServer": { + "Clients": { + "BookStore_Web": { + "ClientId": "BookStore_Web", + "RootUrl": "https://localhost:44314/" + }, + "BookStore_ConsoleTestApp": { + "ClientId": "BookStore_ConsoleTestApp" + } + } + } +} diff --git a/samples/BookStore/src/Acme.BookStore.Domain.Shared/Acme.BookStore.Domain.Shared.csproj b/samples/BookStore/src/Acme.BookStore.Domain.Shared/Acme.BookStore.Domain.Shared.csproj new file mode 100644 index 0000000000..aba9ffbd3a --- /dev/null +++ b/samples/BookStore/src/Acme.BookStore.Domain.Shared/Acme.BookStore.Domain.Shared.csproj @@ -0,0 +1,26 @@ + + + + + + netstandard2.0 + Acme.BookStore + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/samples/BookStore/src/Acme.BookStore.Domain.Shared/BookStoreDomainErrorCodes.cs b/samples/BookStore/src/Acme.BookStore.Domain.Shared/BookStoreDomainErrorCodes.cs new file mode 100644 index 0000000000..30f124fbed --- /dev/null +++ b/samples/BookStore/src/Acme.BookStore.Domain.Shared/BookStoreDomainErrorCodes.cs @@ -0,0 +1,7 @@ +namespace Acme.BookStore +{ + public static class BookStoreDomainErrorCodes + { + /* You can add your business exception error codes here, as constants */ + } +} diff --git a/samples/BookStore/src/Acme.BookStore.Domain.Shared/BookStoreDomainSharedModule.cs b/samples/BookStore/src/Acme.BookStore.Domain.Shared/BookStoreDomainSharedModule.cs new file mode 100644 index 0000000000..f0a6ad7964 --- /dev/null +++ b/samples/BookStore/src/Acme.BookStore.Domain.Shared/BookStoreDomainSharedModule.cs @@ -0,0 +1,45 @@ +using Acme.BookStore.Localization; +using Volo.Abp.AuditLogging; +using Volo.Abp.BackgroundJobs; +using Volo.Abp.FeatureManagement; +using Volo.Abp.Identity; +using Volo.Abp.IdentityServer; +using Volo.Abp.Localization; +using Volo.Abp.Localization.Resources.AbpValidation; +using Volo.Abp.Modularity; +using Volo.Abp.PermissionManagement; +using Volo.Abp.SettingManagement; +using Volo.Abp.TenantManagement; +using Volo.Abp.VirtualFileSystem; + +namespace Acme.BookStore +{ + [DependsOn( + typeof(AbpAuditLoggingDomainSharedModule), + typeof(BackgroundJobsDomainSharedModule), + typeof(AbpFeatureManagementDomainSharedModule), + typeof(AbpIdentityDomainSharedModule), + typeof(AbpIdentityServerDomainSharedModule), + typeof(AbpPermissionManagementDomainSharedModule), + typeof(AbpSettingManagementDomainSharedModule), + typeof(AbpTenantManagementDomainSharedModule) + )] + public class BookStoreDomainSharedModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.FileSets.AddEmbedded("Acme.BookStore"); + }); + + Configure(options => + { + options.Resources + .Add("en") + .AddBaseTypes(typeof(AbpValidationResource)) + .AddVirtualJson("/Localization/BookStore"); + }); + } + } +} diff --git a/samples/BookStore/src/Acme.BookStore.Domain/BookType.cs b/samples/BookStore/src/Acme.BookStore.Domain.Shared/BookType.cs similarity index 78% rename from samples/BookStore/src/Acme.BookStore.Domain/BookType.cs rename to samples/BookStore/src/Acme.BookStore.Domain.Shared/BookType.cs index 75d124d915..ba84b4fe2a 100644 --- a/samples/BookStore/src/Acme.BookStore.Domain/BookType.cs +++ b/samples/BookStore/src/Acme.BookStore.Domain.Shared/BookType.cs @@ -1,9 +1,9 @@ namespace Acme.BookStore { - public enum BookType : byte + public enum BookType { Undefined, - Advanture, + Adventure, Biography, Dystopia, Fantastic, diff --git a/samples/BookStore/src/Acme.BookStore.Domain.Shared/Localization/BookStore/cs.json b/samples/BookStore/src/Acme.BookStore.Domain.Shared/Localization/BookStore/cs.json new file mode 100644 index 0000000000..3e93b9d267 --- /dev/null +++ b/samples/BookStore/src/Acme.BookStore.Domain.Shared/Localization/BookStore/cs.json @@ -0,0 +1,20 @@ +{ + "culture": "cs", + "texts": { + "Menu:Home": "Úvod", + "Welcome": "Vítejte", + "LongWelcomeMessage": "Vítejte v aplikaci. Toto je startovací projekt založený na ABP frameworku. Pro více informací, navštivte abp.io.", + "Menu:BookStore": "Knihkupectví", + "Menu:Books": "Knihy", + "Name": "Název", + "Type": "Typ", + "PublishDate": "Publikováno", + "Price": "Cena", + "CreationTime": "Vytvořeno", + "NewBook": "Nová kniha", + "Books": "Knihy", + "Update": "Aktualizovat", + "BookDeletionConfirmationMessage": "Opravdu chcete smazat knihu {0}?", + "SuccessfullyDeleted": "Úspěšně smazáno." + } +} \ No newline at end of file diff --git a/samples/BookStore/src/Acme.BookStore.Domain/Localization/BookStore/en.json b/samples/BookStore/src/Acme.BookStore.Domain.Shared/Localization/BookStore/en.json similarity index 97% rename from samples/BookStore/src/Acme.BookStore.Domain/Localization/BookStore/en.json rename to samples/BookStore/src/Acme.BookStore.Domain.Shared/Localization/BookStore/en.json index 15dcae40ee..9db906dad7 100644 --- a/samples/BookStore/src/Acme.BookStore.Domain/Localization/BookStore/en.json +++ b/samples/BookStore/src/Acme.BookStore.Domain.Shared/Localization/BookStore/en.json @@ -14,7 +14,7 @@ "NewBook": "New book", "Books": "Books", "Update": "Update", - "BookDeletionConfirmationMessage": "Are you sure to delete this book: {0}", + "BookDeletionConfirmationMessage": "Are you sure to delete the book {0}?", "SuccessfullyDeleted": "Successfully deleted." } } \ No newline at end of file diff --git a/samples/BookStore/src/Acme.BookStore.Domain.Shared/Localization/BookStore/pl.json b/samples/BookStore/src/Acme.BookStore.Domain.Shared/Localization/BookStore/pl.json new file mode 100644 index 0000000000..a018dc2126 --- /dev/null +++ b/samples/BookStore/src/Acme.BookStore.Domain.Shared/Localization/BookStore/pl.json @@ -0,0 +1,20 @@ +{ + "culture": "pl", + "texts": { + "Menu:Home": "Home", + "Welcome": "Witaj", + "LongWelcomeMessage": "Witaj w aplikacji. To jest inicjalny projekt bazujący na ABP framework. Po więcej informacji odwiedź stronę abp.io.", + "Menu:BookStore": "Sklep z ksiąkami", + "Menu:Books": "Ksiąki", + "Name": "Nazwa", + "Type": "Typ", + "PublishDate": "Data publikacji", + "Price": "Cena", + "CreationTime": "Data utworzenia", + "NewBook": "Nowa ksiąka", + "Books": "Ksiąki", + "Update": "Aktualizuj", + "BookDeletionConfirmationMessage": "Czy jesteś pewien, że chcesz usunąć {0}?", + "SuccessfullyDeleted": "Usunięto pomyślnie." + } +} \ No newline at end of file diff --git a/samples/BookStore/src/Acme.BookStore.Domain/Localization/BookStore/pt-BR.json b/samples/BookStore/src/Acme.BookStore.Domain.Shared/Localization/BookStore/pt-BR.json similarity index 100% rename from samples/BookStore/src/Acme.BookStore.Domain/Localization/BookStore/pt-BR.json rename to samples/BookStore/src/Acme.BookStore.Domain.Shared/Localization/BookStore/pt-BR.json diff --git a/samples/BookStore/src/Acme.BookStore.Domain/Localization/BookStore/tr.json b/samples/BookStore/src/Acme.BookStore.Domain.Shared/Localization/BookStore/tr.json similarity index 100% rename from samples/BookStore/src/Acme.BookStore.Domain/Localization/BookStore/tr.json rename to samples/BookStore/src/Acme.BookStore.Domain.Shared/Localization/BookStore/tr.json diff --git a/samples/BookStore/src/Acme.BookStore.Domain.Shared/Localization/BookStore/vi.json b/samples/BookStore/src/Acme.BookStore.Domain.Shared/Localization/BookStore/vi.json new file mode 100644 index 0000000000..3aad66a64a --- /dev/null +++ b/samples/BookStore/src/Acme.BookStore.Domain.Shared/Localization/BookStore/vi.json @@ -0,0 +1,20 @@ +{ + "culture": "vi", + "texts": { + "Menu:Home": "Trang chủ", + "Welcome": "Chào mừng bạn", + "LongWelcomeMessage": "Chào mừng bạn đến ứng dụng. Đây là một dự án mẫu dựa trên khung ABP. Để biết thêm thông tin, hãy truy cập abp.io.", + "Menu:BookStore": "Cửa hàng sách", + "Menu:Books": "Sách", + "Name": "Tên", + "Type": "Loại", + "PublishDate": "Ngày xuất bản", + "Price": "Giá", + "CreationTime": "Thời gian tạo", + "NewBook": "Sách mới", + "Books": "Sách", + "Update": "Cập nhật", + "BookDeletionConfirmationMessage": "Bạn có chắc chắn xóa sách {0}?", + "SuccessfullyDeleted": "Xóa thành công." + } +} diff --git a/samples/BookStore/src/Acme.BookStore.Domain/Localization/BookStore/zh-Hans.json b/samples/BookStore/src/Acme.BookStore.Domain.Shared/Localization/BookStore/zh-Hans.json similarity index 95% rename from samples/BookStore/src/Acme.BookStore.Domain/Localization/BookStore/zh-Hans.json rename to samples/BookStore/src/Acme.BookStore.Domain.Shared/Localization/BookStore/zh-Hans.json index be57798695..86fe3582bb 100644 --- a/samples/BookStore/src/Acme.BookStore.Domain/Localization/BookStore/zh-Hans.json +++ b/samples/BookStore/src/Acme.BookStore.Domain.Shared/Localization/BookStore/zh-Hans.json @@ -1,5 +1,5 @@ { - "culture": "zh-Hans", + "culture": "zh-Hans", "texts": { "Menu:Home": "首页", "Welcome": "欢迎", @@ -17,4 +17,4 @@ "BookDeletionConfirmationMessage": "你确定删除书箱: {0} 吗", "SuccessfullyDeleted": "删除成功." } - } \ No newline at end of file +} \ No newline at end of file diff --git a/samples/BookStore/src/Acme.BookStore.Domain/Localization/BookStore/BookStoreResource.cs b/samples/BookStore/src/Acme.BookStore.Domain.Shared/Localization/BookStoreResource.cs similarity index 72% rename from samples/BookStore/src/Acme.BookStore.Domain/Localization/BookStore/BookStoreResource.cs rename to samples/BookStore/src/Acme.BookStore.Domain.Shared/Localization/BookStoreResource.cs index 068968babf..cc4b935e58 100644 --- a/samples/BookStore/src/Acme.BookStore.Domain/Localization/BookStore/BookStoreResource.cs +++ b/samples/BookStore/src/Acme.BookStore.Domain.Shared/Localization/BookStoreResource.cs @@ -1,6 +1,6 @@ using Volo.Abp.Localization; -namespace Acme.BookStore.Localization.BookStore +namespace Acme.BookStore.Localization { [LocalizationResourceName("BookStore")] public class BookStoreResource diff --git a/samples/BookStore/src/Acme.BookStore.Domain.Shared/MultiTenancy/MultiTenancyConsts.cs b/samples/BookStore/src/Acme.BookStore.Domain.Shared/MultiTenancy/MultiTenancyConsts.cs new file mode 100644 index 0000000000..9ece5cc53e --- /dev/null +++ b/samples/BookStore/src/Acme.BookStore.Domain.Shared/MultiTenancy/MultiTenancyConsts.cs @@ -0,0 +1,11 @@ +namespace Acme.BookStore.MultiTenancy +{ + public static class MultiTenancyConsts + { + /* Enable/disable multi-tenancy easily in a single point. + * If you will never need to multi-tenancy, you can remove + * related modules and code parts, including this file. + */ + public const bool IsEnabled = true; + } +} diff --git a/samples/BookStore/src/Acme.BookStore.Domain/Acme.BookStore.Domain.csproj b/samples/BookStore/src/Acme.BookStore.Domain/Acme.BookStore.Domain.csproj index c358910b01..9efa77aa9a 100644 --- a/samples/BookStore/src/Acme.BookStore.Domain/Acme.BookStore.Domain.csproj +++ b/samples/BookStore/src/Acme.BookStore.Domain/Acme.BookStore.Domain.csproj @@ -1,25 +1,27 @@  - + netcoreapp2.2 Acme.BookStore - - - - - - - - + - + + + + + + + + + + diff --git a/samples/BookStore/src/Acme.BookStore.Domain/Book.cs b/samples/BookStore/src/Acme.BookStore.Domain/Book.cs index 12984a1896..93dd6d9adc 100644 --- a/samples/BookStore/src/Acme.BookStore.Domain/Book.cs +++ b/samples/BookStore/src/Acme.BookStore.Domain/Book.cs @@ -1,15 +1,10 @@ using System; -using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; using Volo.Abp.Domain.Entities.Auditing; namespace Acme.BookStore { - [Table("Books")] public class Book : AuditedAggregateRoot { - [Required] - [StringLength(128)] public string Name { get; set; } public BookType Type { get; set; } diff --git a/samples/BookStore/src/Acme.BookStore.Domain/BookStoreConsts.cs b/samples/BookStore/src/Acme.BookStore.Domain/BookStoreConsts.cs index 5c8cab1e72..96556e1b85 100644 --- a/samples/BookStore/src/Acme.BookStore.Domain/BookStoreConsts.cs +++ b/samples/BookStore/src/Acme.BookStore.Domain/BookStoreConsts.cs @@ -5,7 +5,5 @@ public const string DbTablePrefix = "App"; public const string DbSchema = null; - - public const bool IsMultiTenancyEnabled = true; } } diff --git a/samples/BookStore/src/Acme.BookStore.Domain/BookStoreDomainModule.cs b/samples/BookStore/src/Acme.BookStore.Domain/BookStoreDomainModule.cs index 7575b109e2..950bd62d1b 100644 --- a/samples/BookStore/src/Acme.BookStore.Domain/BookStoreDomainModule.cs +++ b/samples/BookStore/src/Acme.BookStore.Domain/BookStoreDomainModule.cs @@ -1,48 +1,37 @@ -using Acme.BookStore.Localization.BookStore; -using Volo.Abp.Auditing; +using Acme.BookStore.MultiTenancy; using Volo.Abp.AuditLogging; using Volo.Abp.BackgroundJobs; using Volo.Abp.FeatureManagement; using Volo.Abp.Identity; -using Volo.Abp.Localization; -using Volo.Abp.Localization.Resources.AbpValidation; +using Volo.Abp.IdentityServer; using Volo.Abp.Modularity; using Volo.Abp.MultiTenancy; using Volo.Abp.PermissionManagement.Identity; +using Volo.Abp.PermissionManagement.IdentityServer; +using Volo.Abp.SettingManagement; using Volo.Abp.TenantManagement; -using Volo.Abp.VirtualFileSystem; namespace Acme.BookStore { [DependsOn( + typeof(BookStoreDomainSharedModule), + typeof(AbpAuditLoggingDomainModule), + typeof(BackgroundJobsDomainModule), + typeof(AbpFeatureManagementDomainModule), typeof(AbpIdentityDomainModule), typeof(AbpPermissionManagementDomainIdentityModule), - typeof(AbpAuditingModule), - typeof(BackgroundJobsDomainModule), - typeof(AbpAuditLoggingDomainModule), - typeof(AbpTenantManagementDomainModule), - typeof(AbpFeatureManagementDomainModule) + typeof(AbpIdentityServerDomainModule), + typeof(AbpPermissionManagementDomainIdentityServerModule), + typeof(AbpSettingManagementDomainModule), + typeof(AbpTenantManagementDomainModule) )] public class BookStoreDomainModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) { - Configure(options => - { - options.FileSets.AddEmbedded("Acme.BookStore"); - }); - - Configure(options => - { - options.Resources - .Add("en") - .AddBaseTypes(typeof(AbpValidationResource)) - .AddVirtualJson("/Localization/BookStore"); - }); - Configure(options => { - options.IsEnabled = BookStoreConsts.IsMultiTenancyEnabled; + options.IsEnabled = MultiTenancyConsts.IsEnabled; }); } } diff --git a/samples/BookStore/src/Acme.BookStore.Domain/Data/BookStoreDbMigrationService.cs b/samples/BookStore/src/Acme.BookStore.Domain/Data/BookStoreDbMigrationService.cs new file mode 100644 index 0000000000..4db6b4af83 --- /dev/null +++ b/samples/BookStore/src/Acme.BookStore.Domain/Data/BookStoreDbMigrationService.cs @@ -0,0 +1,39 @@ +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; + +namespace Acme.BookStore.Data +{ + public class BookStoreDbMigrationService : ITransientDependency + { + public ILogger Logger { get; set; } + + private readonly IDataSeeder _dataSeeder; + private readonly IBookStoreDbSchemaMigrator _dbSchemaMigrator; + + public BookStoreDbMigrationService( + IDataSeeder dataSeeder, + IBookStoreDbSchemaMigrator dbSchemaMigrator) + { + _dataSeeder = dataSeeder; + _dbSchemaMigrator = dbSchemaMigrator; + + Logger = NullLogger.Instance; + } + + public async Task MigrateAsync() + { + Logger.LogInformation("Started database migrations..."); + + Logger.LogInformation("Migrating database schema..."); + await _dbSchemaMigrator.MigrateAsync(); + + Logger.LogInformation("Executing database seed..."); + await _dataSeeder.SeedAsync(); + + Logger.LogInformation("Successfully completed database migrations."); + } + } +} \ No newline at end of file diff --git a/samples/BookStore/src/Acme.BookStore.Domain/Data/IBookStoreDbSchemaMigrator.cs b/samples/BookStore/src/Acme.BookStore.Domain/Data/IBookStoreDbSchemaMigrator.cs new file mode 100644 index 0000000000..5c94a6918e --- /dev/null +++ b/samples/BookStore/src/Acme.BookStore.Domain/Data/IBookStoreDbSchemaMigrator.cs @@ -0,0 +1,9 @@ +using System.Threading.Tasks; + +namespace Acme.BookStore.Data +{ + public interface IBookStoreDbSchemaMigrator + { + Task MigrateAsync(); + } +} diff --git a/samples/BookStore/src/Acme.BookStore.Domain/Data/NullBookStoreDbSchemaMigrator.cs b/samples/BookStore/src/Acme.BookStore.Domain/Data/NullBookStoreDbSchemaMigrator.cs new file mode 100644 index 0000000000..f6ed8fc8de --- /dev/null +++ b/samples/BookStore/src/Acme.BookStore.Domain/Data/NullBookStoreDbSchemaMigrator.cs @@ -0,0 +1,16 @@ +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace Acme.BookStore.Data +{ + /* This is used if database provider does't define + * IBookStoreDbSchemaMigrator implementation. + */ + public class NullBookStoreDbSchemaMigrator : IBookStoreDbSchemaMigrator, ITransientDependency + { + public Task MigrateAsync() + { + return Task.CompletedTask; + } + } +} \ No newline at end of file diff --git a/samples/BookStore/src/Acme.BookStore.Domain/IdentityServer/IdentityServerDataSeedContributor.cs b/samples/BookStore/src/Acme.BookStore.Domain/IdentityServer/IdentityServerDataSeedContributor.cs new file mode 100644 index 0000000000..45c2420501 --- /dev/null +++ b/samples/BookStore/src/Acme.BookStore.Domain/IdentityServer/IdentityServerDataSeedContributor.cs @@ -0,0 +1,222 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.Configuration; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Guids; +using Volo.Abp.IdentityServer.ApiResources; +using Volo.Abp.IdentityServer.Clients; +using Volo.Abp.IdentityServer.IdentityResources; +using Volo.Abp.PermissionManagement; +using Volo.Abp.Uow; + +namespace Acme.BookStore.IdentityServer +{ + public class IdentityServerDataSeedContributor : IDataSeedContributor, ITransientDependency + { + private readonly IApiResourceRepository _apiResourceRepository; + private readonly IClientRepository _clientRepository; + private readonly IIdentityResourceDataSeeder _identityResourceDataSeeder; + private readonly IGuidGenerator _guidGenerator; + private readonly IPermissionDataSeeder _permissionDataSeeder; + private readonly IConfigurationAccessor _configurationAccessor; + + public IdentityServerDataSeedContributor( + IClientRepository clientRepository, + IApiResourceRepository apiResourceRepository, + IIdentityResourceDataSeeder identityResourceDataSeeder, + IGuidGenerator guidGenerator, + IPermissionDataSeeder permissionDataSeeder, + IConfigurationAccessor configurationAccessor) + { + _clientRepository = clientRepository; + _apiResourceRepository = apiResourceRepository; + _identityResourceDataSeeder = identityResourceDataSeeder; + _guidGenerator = guidGenerator; + _permissionDataSeeder = permissionDataSeeder; + _configurationAccessor = configurationAccessor; + } + + [UnitOfWork] + public virtual async Task SeedAsync(DataSeedContext context) + { + await _identityResourceDataSeeder.CreateStandardResourcesAsync(); + await CreateApiResourcesAsync(); + await CreateClientsAsync(); + } + + private async Task CreateApiResourcesAsync() + { + var commonApiUserClaims = new[] + { + "email", + "email_verified", + "name", + "phone_number", + "phone_number_verified", + "role" + }; + + await CreateApiResourceAsync("BookStore", commonApiUserClaims); + } + + private async Task CreateApiResourceAsync(string name, IEnumerable claims) + { + var apiResource = await _apiResourceRepository.FindByNameAsync(name); + if (apiResource == null) + { + apiResource = await _apiResourceRepository.InsertAsync( + new ApiResource( + _guidGenerator.Create(), + name, + name + " API" + ), + autoSave: true + ); + } + + foreach (var claim in claims) + { + if (apiResource.FindClaim(claim) == null) + { + apiResource.AddUserClaim(claim); + } + } + + return await _apiResourceRepository.UpdateAsync(apiResource); + } + + private async Task CreateClientsAsync() + { + const string commonSecret = "E5Xd4yMqjP5kjWFKrYgySBju6JVfCzMyFp7n2QmMrME="; + + var commonScopes = new[] + { + "email", + "openid", + "profile", + "role", + "phone", + "address", + "BookStore" + }; + + var configurationSection = _configurationAccessor.Configuration.GetSection("IdentityServer:Clients"); + + //Web Client + var webClientId = configurationSection["BookStore_Web:ClientId"]; + if (!webClientId.IsNullOrWhiteSpace()) + { + var webClientRootUrl = configurationSection["BookStore_Web:RootUrl"].EnsureEndsWith('/'); + + /* BookStore_Web client is only needed if you created a tiered + * solution. Otherwise, you can delete this client. */ + + await CreateClientAsync( + webClientId, + commonScopes, + new[] { "hybrid" }, + commonSecret, + redirectUri: $"{webClientRootUrl}signin-oidc", + postLogoutRedirectUri: $"{webClientRootUrl}signout-callback-oidc" + ); + } + + //Console Test Client + var consoleClientId = configurationSection["BookStore_ConsoleTestApp:ClientId"]; + if (!consoleClientId.IsNullOrWhiteSpace()) + { + await CreateClientAsync( + consoleClientId, + commonScopes, + new[] { "password", "client_credentials" }, + commonSecret + ); + } + } + + private async Task CreateClientAsync( + string name, + IEnumerable scopes, + IEnumerable grantTypes, + string secret, + string redirectUri = null, + string postLogoutRedirectUri = null, + IEnumerable permissions = null) + { + var client = await _clientRepository.FindByCliendIdAsync(name); + if (client == null) + { + client = await _clientRepository.InsertAsync( + new Client( + _guidGenerator.Create(), + name + ) + { + ClientName = name, + ProtocolType = "oidc", + Description = name, + AlwaysIncludeUserClaimsInIdToken = true, + AllowOfflineAccess = true, + AbsoluteRefreshTokenLifetime = 31536000, //365 days + AccessTokenLifetime = 31536000, //365 days + AuthorizationCodeLifetime = 300, + IdentityTokenLifetime = 300, + RequireConsent = false + }, + autoSave: true + ); + } + + foreach (var scope in scopes) + { + if (client.FindScope(scope) == null) + { + client.AddScope(scope); + } + } + + foreach (var grantType in grantTypes) + { + if (client.FindGrantType(grantType) == null) + { + client.AddGrantType(grantType); + } + } + + if (client.FindSecret(secret) == null) + { + client.AddSecret(secret); + } + + if (redirectUri != null) + { + if (client.FindRedirectUri(redirectUri) == null) + { + client.AddRedirectUri(redirectUri); + } + } + + if (postLogoutRedirectUri != null) + { + if (client.FindPostLogoutRedirectUri(postLogoutRedirectUri) == null) + { + client.AddPostLogoutRedirectUri(postLogoutRedirectUri); + } + } + + if (permissions != null) + { + await _permissionDataSeeder.SeedAsync( + ClientPermissionValueProvider.ProviderName, + name, + permissions + ); + } + + return await _clientRepository.UpdateAsync(client); + } + } +} diff --git a/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Acme.BookStore.EntityFrameworkCore.DbMigrations.csproj b/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Acme.BookStore.EntityFrameworkCore.DbMigrations.csproj index da6638173c..3b0318a10c 100644 --- a/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Acme.BookStore.EntityFrameworkCore.DbMigrations.csproj +++ b/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Acme.BookStore.EntityFrameworkCore.DbMigrations.csproj @@ -7,10 +7,6 @@ Acme.BookStore - - - - diff --git a/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreEntityFrameworkCoreDbMigrationsModule.cs b/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreEntityFrameworkCoreDbMigrationsModule.cs new file mode 100644 index 0000000000..88e21f2ce8 --- /dev/null +++ b/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreEntityFrameworkCoreDbMigrationsModule.cs @@ -0,0 +1,16 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Modularity; + +namespace Acme.BookStore.EntityFrameworkCore +{ + [DependsOn( + typeof(BookStoreEntityFrameworkCoreModule) + )] + public class BookStoreEntityFrameworkCoreDbMigrationsModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddAbpDbContext(); + } + } +} diff --git a/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContext.cs b/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContext.cs index a43cc52fb6..541a91a0fd 100644 --- a/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContext.cs +++ b/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContext.cs @@ -2,14 +2,21 @@ using Volo.Abp.AuditLogging.EntityFrameworkCore; using Volo.Abp.BackgroundJobs.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.FeatureManagement.EntityFrameworkCore; using Volo.Abp.Identity; using Volo.Abp.Identity.EntityFrameworkCore; +using Volo.Abp.IdentityServer.EntityFrameworkCore; using Volo.Abp.PermissionManagement.EntityFrameworkCore; using Volo.Abp.SettingManagement.EntityFrameworkCore; using Volo.Abp.TenantManagement.EntityFrameworkCore; namespace Acme.BookStore.EntityFrameworkCore { + /* This DbContext is only used for database migrations. + * It is not used on runtime. See BookStoreDbContext for the runtime DbContext. + * It is a unified model that includes configuration for + * all used modules and your application. + */ public class BookStoreMigrationsDbContext : AbpDbContext { public BookStoreMigrationsDbContext(DbContextOptions options) @@ -29,6 +36,8 @@ namespace Acme.BookStore.EntityFrameworkCore builder.ConfigureBackgroundJobs(); builder.ConfigureAuditLogging(); builder.ConfigureIdentity(); + builder.ConfigureIdentityServer(); + builder.ConfigureFeatureManagement(); builder.ConfigureTenantManagement(); /* Configure customizations for entities from the modules included */ diff --git a/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContextFactory.cs b/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContextFactory.cs index bc1006d729..da72e6fb21 100644 --- a/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContextFactory.cs +++ b/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContextFactory.cs @@ -5,6 +5,8 @@ using Microsoft.Extensions.Configuration; namespace Acme.BookStore.EntityFrameworkCore { + /* This class is needed for EF Core console commands + * (like Add-Migration and Update-Database commands) */ public class BookStoreMigrationsDbContextFactory : IDesignTimeDbContextFactory { public BookStoreMigrationsDbContext CreateDbContext(string[] args) diff --git a/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/EntityFrameworkCoreBookStoreDbSchemaMigrator.cs b/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/EntityFrameworkCoreBookStoreDbSchemaMigrator.cs new file mode 100644 index 0000000000..954c8f7a13 --- /dev/null +++ b/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/EntityFrameworkCoreBookStoreDbSchemaMigrator.cs @@ -0,0 +1,24 @@ +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Acme.BookStore.Data; +using Volo.Abp.DependencyInjection; + +namespace Acme.BookStore.EntityFrameworkCore +{ + [Dependency(ReplaceServices = true)] + public class EntityFrameworkCoreBookStoreDbSchemaMigrator + : IBookStoreDbSchemaMigrator, ITransientDependency + { + private readonly BookStoreMigrationsDbContext _dbContext; + + public EntityFrameworkCoreBookStoreDbSchemaMigrator(BookStoreMigrationsDbContext dbContext) + { + _dbContext = dbContext; + } + + public async Task MigrateAsync() + { + await _dbContext.Database.MigrateAsync(); + } + } +} \ No newline at end of file diff --git a/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Migrations/20190416070050_Created_Book_Entity.Designer.cs b/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Migrations/20190603112909_Initial.Designer.cs similarity index 55% rename from samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Migrations/20190416070050_Created_Book_Entity.Designer.cs rename to samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Migrations/20190603112909_Initial.Designer.cs index 2ec683d7ed..53187bf54d 100644 --- a/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Migrations/20190416070050_Created_Book_Entity.Designer.cs +++ b/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Migrations/20190603112909_Initial.Designer.cs @@ -10,50 +10,17 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion; namespace Acme.BookStore.Migrations { [DbContext(typeof(BookStoreMigrationsDbContext))] - [Migration("20190416070050_Created_Book_Entity")] - partial class Created_Book_Entity + [Migration("20190603112909_Initial")] + partial class Initial { protected override void BuildTargetModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "2.2.3-servicing-35854") + .HasAnnotation("ProductVersion", "2.2.4-servicing-10062") .HasAnnotation("Relational:MaxIdentifierLength", 128) .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - modelBuilder.Entity("Acme.BookStore.Book", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ConcurrencyStamp"); - - b.Property("CreationTime"); - - b.Property("CreatorId"); - - b.Property("ExtraProperties") - .HasColumnName("ExtraProperties"); - - b.Property("LastModificationTime"); - - b.Property("LastModifierId"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128); - - b.Property("Price"); - - b.Property("PublishDate"); - - b.Property("Type"); - - b.HasKey("Id"); - - b.ToTable("AppBooks"); - }); - modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => { b.Property("Id") @@ -298,6 +265,32 @@ namespace Acme.BookStore.Migrations b.ToTable("AbpBackgroundJobs"); }); + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureValue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128); + + b.Property("ProviderKey") + .HasMaxLength(64); + + b.Property("ProviderName") + .HasMaxLength(64); + + b.Property("Value") + .IsRequired() + .HasMaxLength(128); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey"); + + b.ToTable("AbpFeatureValues"); + }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => { b.Property("Id") @@ -596,6 +589,482 @@ namespace Acme.BookStore.Migrations b.ToTable("AbpUserTokens"); }); + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResource", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasMaxLength(1000); + + b.Property("DisplayName") + .HasMaxLength(200); + + b.Property("Enabled"); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnName("IsDeleted") + .HasDefaultValue(false); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200); + + b.HasKey("Id"); + + b.ToTable("IdentityServerApiResources"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResourceClaim", b => + { + b.Property("ApiResourceId"); + + b.Property("Type") + .HasMaxLength(196); + + b.HasKey("ApiResourceId", "Type"); + + b.ToTable("IdentityServerApiClaims"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiScope", b => + { + b.Property("ApiResourceId"); + + b.Property("Name") + .HasMaxLength(196); + + b.Property("Description") + .HasMaxLength(256); + + b.Property("DisplayName") + .HasMaxLength(128); + + b.Property("Emphasize"); + + b.Property("Required"); + + b.Property("ShowInDiscoveryDocument"); + + b.HasKey("ApiResourceId", "Name"); + + b.ToTable("IdentityServerApiScopes"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiScopeClaim", b => + { + b.Property("ApiResourceId"); + + b.Property("Name") + .HasMaxLength(196); + + b.Property("Type") + .HasMaxLength(196); + + b.HasKey("ApiResourceId", "Name", "Type"); + + b.ToTable("IdentityServerApiScopeClaims"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiSecret", b => + { + b.Property("ApiResourceId"); + + b.Property("Type") + .HasMaxLength(32); + + b.Property("Value") + .HasMaxLength(196); + + b.Property("Description") + .HasMaxLength(256); + + b.Property("Expiration"); + + b.HasKey("ApiResourceId", "Type", "Value"); + + b.ToTable("IdentityServerApiSecrets"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.Client", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AbsoluteRefreshTokenLifetime"); + + b.Property("AccessTokenLifetime"); + + b.Property("AccessTokenType"); + + b.Property("AllowAccessTokensViaBrowser"); + + b.Property("AllowOfflineAccess"); + + b.Property("AllowPlainTextPkce"); + + b.Property("AllowRememberConsent"); + + b.Property("AlwaysIncludeUserClaimsInIdToken"); + + b.Property("AlwaysSendClientClaims"); + + b.Property("AuthorizationCodeLifetime"); + + b.Property("BackChannelLogoutSessionRequired"); + + b.Property("BackChannelLogoutUri") + .HasMaxLength(300); + + b.Property("ClientClaimsPrefix") + .HasMaxLength(200); + + b.Property("ClientId") + .IsRequired() + .HasMaxLength(200); + + b.Property("ClientName") + .HasMaxLength(200); + + b.Property("ClientUri") + .HasMaxLength(300); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp"); + + b.Property("ConsentLifetime"); + + b.Property("CreationTime") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasMaxLength(1000); + + b.Property("EnableLocalLogin"); + + b.Property("Enabled"); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties"); + + b.Property("FrontChannelLogoutSessionRequired"); + + b.Property("FrontChannelLogoutUri") + .HasMaxLength(300); + + b.Property("IdentityTokenLifetime"); + + b.Property("IncludeJwtId"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnName("IsDeleted") + .HasDefaultValue(false); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId"); + + b.Property("LogoUri") + .HasMaxLength(300); + + b.Property("PairWiseSubjectSalt") + .HasMaxLength(200); + + b.Property("ProtocolType") + .IsRequired() + .HasMaxLength(200); + + b.Property("RefreshTokenExpiration"); + + b.Property("RefreshTokenUsage"); + + b.Property("RequireClientSecret"); + + b.Property("RequireConsent"); + + b.Property("RequirePkce"); + + b.Property("SlidingRefreshTokenLifetime"); + + b.Property("UpdateAccessTokenClaimsOnRefresh"); + + b.HasKey("Id"); + + b.HasIndex("ClientId") + .IsUnique(); + + b.ToTable("IdentityServerClients"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientClaim", b => + { + b.Property("ClientId"); + + b.Property("Type") + .HasMaxLength(250); + + b.Property("Value") + .HasMaxLength(250); + + b.HasKey("ClientId", "Type", "Value"); + + b.ToTable("IdentityServerClientClaims"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientCorsOrigin", b => + { + b.Property("ClientId"); + + b.Property("Origin") + .HasMaxLength(150); + + b.HasKey("ClientId", "Origin"); + + b.ToTable("IdentityServerClientCorsOrigins"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientGrantType", b => + { + b.Property("ClientId"); + + b.Property("GrantType") + .HasMaxLength(196); + + b.HasKey("ClientId", "GrantType"); + + b.ToTable("IdentityServerClientGrantTypes"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientIdPRestriction", b => + { + b.Property("ClientId"); + + b.Property("Provider") + .HasMaxLength(64); + + b.HasKey("ClientId", "Provider"); + + b.ToTable("IdentityServerClientIdPRestrictions"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientPostLogoutRedirectUri", b => + { + b.Property("ClientId"); + + b.Property("PostLogoutRedirectUri") + .HasMaxLength(200); + + b.HasKey("ClientId", "PostLogoutRedirectUri"); + + b.ToTable("IdentityServerClientPostLogoutRedirectUris"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientProperty", b => + { + b.Property("ClientId"); + + b.Property("Key") + .HasMaxLength(64); + + b.Property("Value") + .IsRequired() + .HasMaxLength(128); + + b.HasKey("ClientId", "Key"); + + b.ToTable("IdentityServerClientProperties"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientRedirectUri", b => + { + b.Property("ClientId"); + + b.Property("RedirectUri") + .HasMaxLength(200); + + b.HasKey("ClientId", "RedirectUri"); + + b.ToTable("IdentityServerClientRedirectUris"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientScope", b => + { + b.Property("ClientId"); + + b.Property("Scope") + .HasMaxLength(196); + + b.HasKey("ClientId", "Scope"); + + b.ToTable("IdentityServerClientScopes"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientSecret", b => + { + b.Property("ClientId"); + + b.Property("Type") + .HasMaxLength(32); + + b.Property("Value") + .HasMaxLength(196); + + b.Property("Description") + .HasMaxLength(256); + + b.Property("Expiration"); + + b.HasKey("ClientId", "Type", "Value"); + + b.ToTable("IdentityServerClientSecrets"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Grants.PersistedGrant", b => + { + b.Property("Key") + .HasMaxLength(200); + + b.Property("ClientId") + .IsRequired() + .HasMaxLength(200); + + b.Property("ConcurrencyStamp"); + + b.Property("CreationTime"); + + b.Property("Data") + .IsRequired(); + + b.Property("Expiration"); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties"); + + b.Property("Id"); + + b.Property("SubjectId") + .HasMaxLength(200); + + b.Property("Type") + .IsRequired() + .HasMaxLength(50); + + b.HasKey("Key"); + + b.HasIndex("SubjectId", "ClientId", "Type"); + + b.ToTable("IdentityServerPersistedGrants"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.IdentityResources.IdentityClaim", b => + { + b.Property("IdentityResourceId"); + + b.Property("Type") + .HasMaxLength(196); + + b.HasKey("IdentityResourceId", "Type"); + + b.ToTable("IdentityServerIdentityClaims"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.IdentityResources.IdentityResource", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasMaxLength(1000); + + b.Property("DisplayName") + .HasMaxLength(200); + + b.Property("Emphasize"); + + b.Property("Enabled"); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnName("IsDeleted") + .HasDefaultValue(false); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200); + + b.Property("Required"); + + b.Property("ShowInDiscoveryDocument"); + + b.HasKey("Id"); + + b.ToTable("IdentityServerIdentityResources"); + }); + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => { b.Property("Id") @@ -780,6 +1249,118 @@ namespace Acme.BookStore.Migrations .OnDelete(DeleteBehavior.Cascade); }); + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResourceClaim", b => + { + b.HasOne("Volo.Abp.IdentityServer.ApiResources.ApiResource") + .WithMany("UserClaims") + .HasForeignKey("ApiResourceId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiScope", b => + { + b.HasOne("Volo.Abp.IdentityServer.ApiResources.ApiResource") + .WithMany("Scopes") + .HasForeignKey("ApiResourceId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiScopeClaim", b => + { + b.HasOne("Volo.Abp.IdentityServer.ApiResources.ApiScope") + .WithMany("UserClaims") + .HasForeignKey("ApiResourceId", "Name") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiSecret", b => + { + b.HasOne("Volo.Abp.IdentityServer.ApiResources.ApiResource") + .WithMany("Secrets") + .HasForeignKey("ApiResourceId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientClaim", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client") + .WithMany("Claims") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientCorsOrigin", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client") + .WithMany("AllowedCorsOrigins") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientGrantType", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client") + .WithMany("AllowedGrantTypes") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientIdPRestriction", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client") + .WithMany("IdentityProviderRestrictions") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientPostLogoutRedirectUri", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client") + .WithMany("PostLogoutRedirectUris") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientProperty", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client") + .WithMany("Properties") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientRedirectUri", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client") + .WithMany("RedirectUris") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientScope", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client") + .WithMany("AllowedScopes") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientSecret", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client") + .WithMany("ClientSecrets") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.IdentityResources.IdentityClaim", b => + { + b.HasOne("Volo.Abp.IdentityServer.IdentityResources.IdentityResource") + .WithMany("UserClaims") + .HasForeignKey("IdentityResourceId") + .OnDelete(DeleteBehavior.Cascade); + }); + modelBuilder.Entity("Volo.Abp.TenantManagement.TenantConnectionString", b => { b.HasOne("Volo.Abp.TenantManagement.Tenant") diff --git a/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Migrations/20190402131334_Initial.cs b/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Migrations/20190603112909_Initial.cs similarity index 51% rename from samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Migrations/20190402131334_Initial.cs rename to samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Migrations/20190603112909_Initial.cs index fb85c4cc6d..45cd778b73 100644 --- a/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Migrations/20190402131334_Initial.cs +++ b/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Migrations/20190603112909_Initial.cs @@ -80,6 +80,21 @@ namespace Acme.BookStore.Migrations table.PrimaryKey("PK_AbpClaimTypes", x => x.Id); }); + migrationBuilder.CreateTable( + name: "AbpFeatureValues", + columns: table => new + { + Id = table.Column(nullable: false), + Name = table.Column(maxLength: 128, nullable: false), + Value = table.Column(maxLength: 128, nullable: false), + ProviderName = table.Column(maxLength: 64, nullable: true), + ProviderKey = table.Column(maxLength: 64, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpFeatureValues", x => x.Id); + }); + migrationBuilder.CreateTable( name: "AbpPermissionGrants", columns: table => new @@ -186,6 +201,131 @@ namespace Acme.BookStore.Migrations table.PrimaryKey("PK_AbpUsers", x => x.Id); }); + migrationBuilder.CreateTable( + name: "IdentityServerApiResources", + columns: table => new + { + Id = table.Column(nullable: false), + ExtraProperties = table.Column(nullable: true), + ConcurrencyStamp = table.Column(nullable: true), + CreationTime = table.Column(nullable: false), + CreatorId = table.Column(nullable: true), + LastModificationTime = table.Column(nullable: true), + LastModifierId = table.Column(nullable: true), + IsDeleted = table.Column(nullable: false, defaultValue: false), + DeleterId = table.Column(nullable: true), + DeletionTime = table.Column(nullable: true), + Name = table.Column(maxLength: 200, nullable: false), + DisplayName = table.Column(maxLength: 200, nullable: true), + Description = table.Column(maxLength: 1000, nullable: true), + Enabled = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_IdentityServerApiResources", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "IdentityServerClients", + columns: table => new + { + Id = table.Column(nullable: false), + ExtraProperties = table.Column(nullable: true), + ConcurrencyStamp = table.Column(nullable: true), + CreationTime = table.Column(nullable: false), + CreatorId = table.Column(nullable: true), + LastModificationTime = table.Column(nullable: true), + LastModifierId = table.Column(nullable: true), + IsDeleted = table.Column(nullable: false, defaultValue: false), + DeleterId = table.Column(nullable: true), + DeletionTime = table.Column(nullable: true), + ClientId = table.Column(maxLength: 200, nullable: false), + ClientName = table.Column(maxLength: 200, nullable: true), + Description = table.Column(maxLength: 1000, nullable: true), + ClientUri = table.Column(maxLength: 300, nullable: true), + LogoUri = table.Column(maxLength: 300, nullable: true), + Enabled = table.Column(nullable: false), + ProtocolType = table.Column(maxLength: 200, nullable: false), + RequireClientSecret = table.Column(nullable: false), + RequireConsent = table.Column(nullable: false), + AllowRememberConsent = table.Column(nullable: false), + AlwaysIncludeUserClaimsInIdToken = table.Column(nullable: false), + RequirePkce = table.Column(nullable: false), + AllowPlainTextPkce = table.Column(nullable: false), + AllowAccessTokensViaBrowser = table.Column(nullable: false), + FrontChannelLogoutUri = table.Column(maxLength: 300, nullable: true), + FrontChannelLogoutSessionRequired = table.Column(nullable: false), + BackChannelLogoutUri = table.Column(maxLength: 300, nullable: true), + BackChannelLogoutSessionRequired = table.Column(nullable: false), + AllowOfflineAccess = table.Column(nullable: false), + IdentityTokenLifetime = table.Column(nullable: false), + AccessTokenLifetime = table.Column(nullable: false), + AuthorizationCodeLifetime = table.Column(nullable: false), + ConsentLifetime = table.Column(nullable: true), + AbsoluteRefreshTokenLifetime = table.Column(nullable: false), + SlidingRefreshTokenLifetime = table.Column(nullable: false), + RefreshTokenUsage = table.Column(nullable: false), + UpdateAccessTokenClaimsOnRefresh = table.Column(nullable: false), + RefreshTokenExpiration = table.Column(nullable: false), + AccessTokenType = table.Column(nullable: false), + EnableLocalLogin = table.Column(nullable: false), + IncludeJwtId = table.Column(nullable: false), + AlwaysSendClientClaims = table.Column(nullable: false), + ClientClaimsPrefix = table.Column(maxLength: 200, nullable: true), + PairWiseSubjectSalt = table.Column(maxLength: 200, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_IdentityServerClients", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "IdentityServerIdentityResources", + columns: table => new + { + Id = table.Column(nullable: false), + ExtraProperties = table.Column(nullable: true), + ConcurrencyStamp = table.Column(nullable: true), + CreationTime = table.Column(nullable: false), + CreatorId = table.Column(nullable: true), + LastModificationTime = table.Column(nullable: true), + LastModifierId = table.Column(nullable: true), + IsDeleted = table.Column(nullable: false, defaultValue: false), + DeleterId = table.Column(nullable: true), + DeletionTime = table.Column(nullable: true), + Name = table.Column(maxLength: 200, nullable: false), + DisplayName = table.Column(maxLength: 200, nullable: true), + Description = table.Column(maxLength: 1000, nullable: true), + Enabled = table.Column(nullable: false), + Required = table.Column(nullable: false), + Emphasize = table.Column(nullable: false), + ShowInDiscoveryDocument = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_IdentityServerIdentityResources", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "IdentityServerPersistedGrants", + columns: table => new + { + Key = table.Column(maxLength: 200, nullable: false), + Id = table.Column(nullable: false), + ExtraProperties = table.Column(nullable: true), + ConcurrencyStamp = table.Column(nullable: true), + Type = table.Column(maxLength: 50, nullable: false), + SubjectId = table.Column(maxLength: 200, nullable: true), + ClientId = table.Column(maxLength: 200, nullable: false), + CreationTime = table.Column(nullable: false), + Expiration = table.Column(nullable: true), + Data = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_IdentityServerPersistedGrants", x => x.Key); + }); + migrationBuilder.CreateTable( name: "AbpAuditLogActions", columns: table => new @@ -364,6 +504,253 @@ namespace Acme.BookStore.Migrations onDelete: ReferentialAction.Cascade); }); + migrationBuilder.CreateTable( + name: "IdentityServerApiClaims", + columns: table => new + { + Type = table.Column(maxLength: 196, nullable: false), + ApiResourceId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_IdentityServerApiClaims", x => new { x.ApiResourceId, x.Type }); + table.ForeignKey( + name: "FK_IdentityServerApiClaims_IdentityServerApiResources_ApiResourceId", + column: x => x.ApiResourceId, + principalTable: "IdentityServerApiResources", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "IdentityServerApiScopes", + columns: table => new + { + ApiResourceId = table.Column(nullable: false), + Name = table.Column(maxLength: 196, nullable: false), + DisplayName = table.Column(maxLength: 128, nullable: true), + Description = table.Column(maxLength: 256, nullable: true), + Required = table.Column(nullable: false), + Emphasize = table.Column(nullable: false), + ShowInDiscoveryDocument = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_IdentityServerApiScopes", x => new { x.ApiResourceId, x.Name }); + table.ForeignKey( + name: "FK_IdentityServerApiScopes_IdentityServerApiResources_ApiResourceId", + column: x => x.ApiResourceId, + principalTable: "IdentityServerApiResources", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "IdentityServerApiSecrets", + columns: table => new + { + Type = table.Column(maxLength: 32, nullable: false), + Value = table.Column(maxLength: 196, nullable: false), + ApiResourceId = table.Column(nullable: false), + Description = table.Column(maxLength: 256, nullable: true), + Expiration = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_IdentityServerApiSecrets", x => new { x.ApiResourceId, x.Type, x.Value }); + table.ForeignKey( + name: "FK_IdentityServerApiSecrets_IdentityServerApiResources_ApiResourceId", + column: x => x.ApiResourceId, + principalTable: "IdentityServerApiResources", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "IdentityServerClientClaims", + columns: table => new + { + ClientId = table.Column(nullable: false), + Type = table.Column(maxLength: 250, nullable: false), + Value = table.Column(maxLength: 250, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_IdentityServerClientClaims", x => new { x.ClientId, x.Type, x.Value }); + table.ForeignKey( + name: "FK_IdentityServerClientClaims_IdentityServerClients_ClientId", + column: x => x.ClientId, + principalTable: "IdentityServerClients", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "IdentityServerClientCorsOrigins", + columns: table => new + { + ClientId = table.Column(nullable: false), + Origin = table.Column(maxLength: 150, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_IdentityServerClientCorsOrigins", x => new { x.ClientId, x.Origin }); + table.ForeignKey( + name: "FK_IdentityServerClientCorsOrigins_IdentityServerClients_ClientId", + column: x => x.ClientId, + principalTable: "IdentityServerClients", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "IdentityServerClientGrantTypes", + columns: table => new + { + ClientId = table.Column(nullable: false), + GrantType = table.Column(maxLength: 196, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_IdentityServerClientGrantTypes", x => new { x.ClientId, x.GrantType }); + table.ForeignKey( + name: "FK_IdentityServerClientGrantTypes_IdentityServerClients_ClientId", + column: x => x.ClientId, + principalTable: "IdentityServerClients", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "IdentityServerClientIdPRestrictions", + columns: table => new + { + ClientId = table.Column(nullable: false), + Provider = table.Column(maxLength: 64, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_IdentityServerClientIdPRestrictions", x => new { x.ClientId, x.Provider }); + table.ForeignKey( + name: "FK_IdentityServerClientIdPRestrictions_IdentityServerClients_ClientId", + column: x => x.ClientId, + principalTable: "IdentityServerClients", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "IdentityServerClientPostLogoutRedirectUris", + columns: table => new + { + ClientId = table.Column(nullable: false), + PostLogoutRedirectUri = table.Column(maxLength: 200, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_IdentityServerClientPostLogoutRedirectUris", x => new { x.ClientId, x.PostLogoutRedirectUri }); + table.ForeignKey( + name: "FK_IdentityServerClientPostLogoutRedirectUris_IdentityServerClients_ClientId", + column: x => x.ClientId, + principalTable: "IdentityServerClients", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "IdentityServerClientProperties", + columns: table => new + { + ClientId = table.Column(nullable: false), + Key = table.Column(maxLength: 64, nullable: false), + Value = table.Column(maxLength: 128, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_IdentityServerClientProperties", x => new { x.ClientId, x.Key }); + table.ForeignKey( + name: "FK_IdentityServerClientProperties_IdentityServerClients_ClientId", + column: x => x.ClientId, + principalTable: "IdentityServerClients", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "IdentityServerClientRedirectUris", + columns: table => new + { + ClientId = table.Column(nullable: false), + RedirectUri = table.Column(maxLength: 200, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_IdentityServerClientRedirectUris", x => new { x.ClientId, x.RedirectUri }); + table.ForeignKey( + name: "FK_IdentityServerClientRedirectUris_IdentityServerClients_ClientId", + column: x => x.ClientId, + principalTable: "IdentityServerClients", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "IdentityServerClientScopes", + columns: table => new + { + ClientId = table.Column(nullable: false), + Scope = table.Column(maxLength: 196, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_IdentityServerClientScopes", x => new { x.ClientId, x.Scope }); + table.ForeignKey( + name: "FK_IdentityServerClientScopes_IdentityServerClients_ClientId", + column: x => x.ClientId, + principalTable: "IdentityServerClients", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "IdentityServerClientSecrets", + columns: table => new + { + Type = table.Column(maxLength: 32, nullable: false), + Value = table.Column(maxLength: 196, nullable: false), + ClientId = table.Column(nullable: false), + Description = table.Column(maxLength: 256, nullable: true), + Expiration = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_IdentityServerClientSecrets", x => new { x.ClientId, x.Type, x.Value }); + table.ForeignKey( + name: "FK_IdentityServerClientSecrets_IdentityServerClients_ClientId", + column: x => x.ClientId, + principalTable: "IdentityServerClients", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "IdentityServerIdentityClaims", + columns: table => new + { + Type = table.Column(maxLength: 196, nullable: false), + IdentityResourceId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_IdentityServerIdentityClaims", x => new { x.IdentityResourceId, x.Type }); + table.ForeignKey( + name: "FK_IdentityServerIdentityClaims_IdentityServerIdentityResources_IdentityResourceId", + column: x => x.IdentityResourceId, + principalTable: "IdentityServerIdentityResources", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + migrationBuilder.CreateTable( name: "AbpEntityPropertyChanges", columns: table => new @@ -387,6 +774,25 @@ namespace Acme.BookStore.Migrations onDelete: ReferentialAction.Cascade); }); + migrationBuilder.CreateTable( + name: "IdentityServerApiScopeClaims", + columns: table => new + { + Type = table.Column(maxLength: 196, nullable: false), + ApiResourceId = table.Column(nullable: false), + Name = table.Column(maxLength: 196, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_IdentityServerApiScopeClaims", x => new { x.ApiResourceId, x.Name, x.Type }); + table.ForeignKey( + name: "FK_IdentityServerApiScopeClaims_IdentityServerApiScopes_ApiResourceId_Name", + columns: x => new { x.ApiResourceId, x.Name }, + principalTable: "IdentityServerApiScopes", + principalColumns: new[] { "ApiResourceId", "Name" }, + onDelete: ReferentialAction.Cascade); + }); + migrationBuilder.CreateIndex( name: "IX_AbpAuditLogActions_AuditLogId", table: "AbpAuditLogActions", @@ -427,6 +833,11 @@ namespace Acme.BookStore.Migrations table: "AbpEntityPropertyChanges", column: "EntityChangeId"); + migrationBuilder.CreateIndex( + name: "IX_AbpFeatureValues_Name_ProviderName_ProviderKey", + table: "AbpFeatureValues", + columns: new[] { "Name", "ProviderName", "ProviderKey" }); + migrationBuilder.CreateIndex( name: "IX_AbpPermissionGrants_Name_ProviderName_ProviderKey", table: "AbpPermissionGrants", @@ -487,6 +898,17 @@ namespace Acme.BookStore.Migrations name: "IX_AbpUsers_UserName", table: "AbpUsers", column: "UserName"); + + migrationBuilder.CreateIndex( + name: "IX_IdentityServerClients_ClientId", + table: "IdentityServerClients", + column: "ClientId", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_IdentityServerPersistedGrants_SubjectId_ClientId_Type", + table: "IdentityServerPersistedGrants", + columns: new[] { "SubjectId", "ClientId", "Type" }); } protected override void Down(MigrationBuilder migrationBuilder) @@ -503,6 +925,9 @@ namespace Acme.BookStore.Migrations migrationBuilder.DropTable( name: "AbpEntityPropertyChanges"); + migrationBuilder.DropTable( + name: "AbpFeatureValues"); + migrationBuilder.DropTable( name: "AbpPermissionGrants"); @@ -527,6 +952,48 @@ namespace Acme.BookStore.Migrations migrationBuilder.DropTable( name: "AbpUserTokens"); + migrationBuilder.DropTable( + name: "IdentityServerApiClaims"); + + migrationBuilder.DropTable( + name: "IdentityServerApiScopeClaims"); + + migrationBuilder.DropTable( + name: "IdentityServerApiSecrets"); + + migrationBuilder.DropTable( + name: "IdentityServerClientClaims"); + + migrationBuilder.DropTable( + name: "IdentityServerClientCorsOrigins"); + + migrationBuilder.DropTable( + name: "IdentityServerClientGrantTypes"); + + migrationBuilder.DropTable( + name: "IdentityServerClientIdPRestrictions"); + + migrationBuilder.DropTable( + name: "IdentityServerClientPostLogoutRedirectUris"); + + migrationBuilder.DropTable( + name: "IdentityServerClientProperties"); + + migrationBuilder.DropTable( + name: "IdentityServerClientRedirectUris"); + + migrationBuilder.DropTable( + name: "IdentityServerClientScopes"); + + migrationBuilder.DropTable( + name: "IdentityServerClientSecrets"); + + migrationBuilder.DropTable( + name: "IdentityServerIdentityClaims"); + + migrationBuilder.DropTable( + name: "IdentityServerPersistedGrants"); + migrationBuilder.DropTable( name: "AbpEntityChanges"); @@ -539,8 +1006,20 @@ namespace Acme.BookStore.Migrations migrationBuilder.DropTable( name: "AbpUsers"); + migrationBuilder.DropTable( + name: "IdentityServerApiScopes"); + + migrationBuilder.DropTable( + name: "IdentityServerClients"); + + migrationBuilder.DropTable( + name: "IdentityServerIdentityResources"); + migrationBuilder.DropTable( name: "AbpAuditLogs"); + + migrationBuilder.DropTable( + name: "IdentityServerApiResources"); } } } diff --git a/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Migrations/20190402131334_Initial.Designer.cs b/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Migrations/20190603113122_Created_Book_Entity.Designer.cs similarity index 52% rename from samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Migrations/20190402131334_Initial.Designer.cs rename to samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Migrations/20190603113122_Created_Book_Entity.Designer.cs index 37937a0bb6..de5a467a66 100644 --- a/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Migrations/20190402131334_Initial.Designer.cs +++ b/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Migrations/20190603113122_Created_Book_Entity.Designer.cs @@ -1,26 +1,65 @@ // using System; +using Acme.BookStore.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Acme.BookStore.EntityFrameworkCore; namespace Acme.BookStore.Migrations { [DbContext(typeof(BookStoreMigrationsDbContext))] - [Migration("20190402131334_Initial")] - partial class Initial + [Migration("20190603113122_Created_Book_Entity")] + partial class Created_Book_Entity { protected override void BuildTargetModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "2.2.0-rtm-35687") + .HasAnnotation("ProductVersion", "2.2.4-servicing-10062") .HasAnnotation("Relational:MaxIdentifierLength", 128) .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + modelBuilder.Entity("Acme.BookStore.Book", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128); + + b.Property("Price"); + + b.Property("PublishDate"); + + b.Property("Type"); + + b.HasKey("Id"); + + b.ToTable("AppBooks"); + }); + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => { b.Property("Id") @@ -265,6 +304,32 @@ namespace Acme.BookStore.Migrations b.ToTable("AbpBackgroundJobs"); }); + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureValue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128); + + b.Property("ProviderKey") + .HasMaxLength(64); + + b.Property("ProviderName") + .HasMaxLength(64); + + b.Property("Value") + .IsRequired() + .HasMaxLength(128); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey"); + + b.ToTable("AbpFeatureValues"); + }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => { b.Property("Id") @@ -563,6 +628,482 @@ namespace Acme.BookStore.Migrations b.ToTable("AbpUserTokens"); }); + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResource", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasMaxLength(1000); + + b.Property("DisplayName") + .HasMaxLength(200); + + b.Property("Enabled"); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnName("IsDeleted") + .HasDefaultValue(false); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200); + + b.HasKey("Id"); + + b.ToTable("IdentityServerApiResources"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResourceClaim", b => + { + b.Property("ApiResourceId"); + + b.Property("Type") + .HasMaxLength(196); + + b.HasKey("ApiResourceId", "Type"); + + b.ToTable("IdentityServerApiClaims"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiScope", b => + { + b.Property("ApiResourceId"); + + b.Property("Name") + .HasMaxLength(196); + + b.Property("Description") + .HasMaxLength(256); + + b.Property("DisplayName") + .HasMaxLength(128); + + b.Property("Emphasize"); + + b.Property("Required"); + + b.Property("ShowInDiscoveryDocument"); + + b.HasKey("ApiResourceId", "Name"); + + b.ToTable("IdentityServerApiScopes"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiScopeClaim", b => + { + b.Property("ApiResourceId"); + + b.Property("Name") + .HasMaxLength(196); + + b.Property("Type") + .HasMaxLength(196); + + b.HasKey("ApiResourceId", "Name", "Type"); + + b.ToTable("IdentityServerApiScopeClaims"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiSecret", b => + { + b.Property("ApiResourceId"); + + b.Property("Type") + .HasMaxLength(32); + + b.Property("Value") + .HasMaxLength(196); + + b.Property("Description") + .HasMaxLength(256); + + b.Property("Expiration"); + + b.HasKey("ApiResourceId", "Type", "Value"); + + b.ToTable("IdentityServerApiSecrets"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.Client", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AbsoluteRefreshTokenLifetime"); + + b.Property("AccessTokenLifetime"); + + b.Property("AccessTokenType"); + + b.Property("AllowAccessTokensViaBrowser"); + + b.Property("AllowOfflineAccess"); + + b.Property("AllowPlainTextPkce"); + + b.Property("AllowRememberConsent"); + + b.Property("AlwaysIncludeUserClaimsInIdToken"); + + b.Property("AlwaysSendClientClaims"); + + b.Property("AuthorizationCodeLifetime"); + + b.Property("BackChannelLogoutSessionRequired"); + + b.Property("BackChannelLogoutUri") + .HasMaxLength(300); + + b.Property("ClientClaimsPrefix") + .HasMaxLength(200); + + b.Property("ClientId") + .IsRequired() + .HasMaxLength(200); + + b.Property("ClientName") + .HasMaxLength(200); + + b.Property("ClientUri") + .HasMaxLength(300); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp"); + + b.Property("ConsentLifetime"); + + b.Property("CreationTime") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasMaxLength(1000); + + b.Property("EnableLocalLogin"); + + b.Property("Enabled"); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties"); + + b.Property("FrontChannelLogoutSessionRequired"); + + b.Property("FrontChannelLogoutUri") + .HasMaxLength(300); + + b.Property("IdentityTokenLifetime"); + + b.Property("IncludeJwtId"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnName("IsDeleted") + .HasDefaultValue(false); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId"); + + b.Property("LogoUri") + .HasMaxLength(300); + + b.Property("PairWiseSubjectSalt") + .HasMaxLength(200); + + b.Property("ProtocolType") + .IsRequired() + .HasMaxLength(200); + + b.Property("RefreshTokenExpiration"); + + b.Property("RefreshTokenUsage"); + + b.Property("RequireClientSecret"); + + b.Property("RequireConsent"); + + b.Property("RequirePkce"); + + b.Property("SlidingRefreshTokenLifetime"); + + b.Property("UpdateAccessTokenClaimsOnRefresh"); + + b.HasKey("Id"); + + b.HasIndex("ClientId") + .IsUnique(); + + b.ToTable("IdentityServerClients"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientClaim", b => + { + b.Property("ClientId"); + + b.Property("Type") + .HasMaxLength(250); + + b.Property("Value") + .HasMaxLength(250); + + b.HasKey("ClientId", "Type", "Value"); + + b.ToTable("IdentityServerClientClaims"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientCorsOrigin", b => + { + b.Property("ClientId"); + + b.Property("Origin") + .HasMaxLength(150); + + b.HasKey("ClientId", "Origin"); + + b.ToTable("IdentityServerClientCorsOrigins"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientGrantType", b => + { + b.Property("ClientId"); + + b.Property("GrantType") + .HasMaxLength(196); + + b.HasKey("ClientId", "GrantType"); + + b.ToTable("IdentityServerClientGrantTypes"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientIdPRestriction", b => + { + b.Property("ClientId"); + + b.Property("Provider") + .HasMaxLength(64); + + b.HasKey("ClientId", "Provider"); + + b.ToTable("IdentityServerClientIdPRestrictions"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientPostLogoutRedirectUri", b => + { + b.Property("ClientId"); + + b.Property("PostLogoutRedirectUri") + .HasMaxLength(200); + + b.HasKey("ClientId", "PostLogoutRedirectUri"); + + b.ToTable("IdentityServerClientPostLogoutRedirectUris"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientProperty", b => + { + b.Property("ClientId"); + + b.Property("Key") + .HasMaxLength(64); + + b.Property("Value") + .IsRequired() + .HasMaxLength(128); + + b.HasKey("ClientId", "Key"); + + b.ToTable("IdentityServerClientProperties"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientRedirectUri", b => + { + b.Property("ClientId"); + + b.Property("RedirectUri") + .HasMaxLength(200); + + b.HasKey("ClientId", "RedirectUri"); + + b.ToTable("IdentityServerClientRedirectUris"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientScope", b => + { + b.Property("ClientId"); + + b.Property("Scope") + .HasMaxLength(196); + + b.HasKey("ClientId", "Scope"); + + b.ToTable("IdentityServerClientScopes"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientSecret", b => + { + b.Property("ClientId"); + + b.Property("Type") + .HasMaxLength(32); + + b.Property("Value") + .HasMaxLength(196); + + b.Property("Description") + .HasMaxLength(256); + + b.Property("Expiration"); + + b.HasKey("ClientId", "Type", "Value"); + + b.ToTable("IdentityServerClientSecrets"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Grants.PersistedGrant", b => + { + b.Property("Key") + .HasMaxLength(200); + + b.Property("ClientId") + .IsRequired() + .HasMaxLength(200); + + b.Property("ConcurrencyStamp"); + + b.Property("CreationTime"); + + b.Property("Data") + .IsRequired(); + + b.Property("Expiration"); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties"); + + b.Property("Id"); + + b.Property("SubjectId") + .HasMaxLength(200); + + b.Property("Type") + .IsRequired() + .HasMaxLength(50); + + b.HasKey("Key"); + + b.HasIndex("SubjectId", "ClientId", "Type"); + + b.ToTable("IdentityServerPersistedGrants"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.IdentityResources.IdentityClaim", b => + { + b.Property("IdentityResourceId"); + + b.Property("Type") + .HasMaxLength(196); + + b.HasKey("IdentityResourceId", "Type"); + + b.ToTable("IdentityServerIdentityClaims"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.IdentityResources.IdentityResource", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasMaxLength(1000); + + b.Property("DisplayName") + .HasMaxLength(200); + + b.Property("Emphasize"); + + b.Property("Enabled"); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnName("IsDeleted") + .HasDefaultValue(false); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200); + + b.Property("Required"); + + b.Property("ShowInDiscoveryDocument"); + + b.HasKey("Id"); + + b.ToTable("IdentityServerIdentityResources"); + }); + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => { b.Property("Id") @@ -747,6 +1288,118 @@ namespace Acme.BookStore.Migrations .OnDelete(DeleteBehavior.Cascade); }); + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResourceClaim", b => + { + b.HasOne("Volo.Abp.IdentityServer.ApiResources.ApiResource") + .WithMany("UserClaims") + .HasForeignKey("ApiResourceId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiScope", b => + { + b.HasOne("Volo.Abp.IdentityServer.ApiResources.ApiResource") + .WithMany("Scopes") + .HasForeignKey("ApiResourceId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiScopeClaim", b => + { + b.HasOne("Volo.Abp.IdentityServer.ApiResources.ApiScope") + .WithMany("UserClaims") + .HasForeignKey("ApiResourceId", "Name") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiSecret", b => + { + b.HasOne("Volo.Abp.IdentityServer.ApiResources.ApiResource") + .WithMany("Secrets") + .HasForeignKey("ApiResourceId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientClaim", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client") + .WithMany("Claims") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientCorsOrigin", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client") + .WithMany("AllowedCorsOrigins") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientGrantType", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client") + .WithMany("AllowedGrantTypes") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientIdPRestriction", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client") + .WithMany("IdentityProviderRestrictions") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientPostLogoutRedirectUri", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client") + .WithMany("PostLogoutRedirectUris") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientProperty", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client") + .WithMany("Properties") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientRedirectUri", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client") + .WithMany("RedirectUris") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientScope", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client") + .WithMany("AllowedScopes") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientSecret", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client") + .WithMany("ClientSecrets") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.IdentityResources.IdentityClaim", b => + { + b.HasOne("Volo.Abp.IdentityServer.IdentityResources.IdentityResource") + .WithMany("UserClaims") + .HasForeignKey("IdentityResourceId") + .OnDelete(DeleteBehavior.Cascade); + }); + modelBuilder.Entity("Volo.Abp.TenantManagement.TenantConnectionString", b => { b.HasOne("Volo.Abp.TenantManagement.Tenant") diff --git a/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Migrations/20190416070050_Created_Book_Entity.cs b/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Migrations/20190603113122_Created_Book_Entity.cs similarity index 95% rename from samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Migrations/20190416070050_Created_Book_Entity.cs rename to samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Migrations/20190603113122_Created_Book_Entity.cs index f4e67242e3..a1aef5d9da 100644 --- a/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Migrations/20190416070050_Created_Book_Entity.cs +++ b/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Migrations/20190603113122_Created_Book_Entity.cs @@ -19,7 +19,7 @@ namespace Acme.BookStore.Migrations LastModificationTime = table.Column(nullable: true), LastModifierId = table.Column(nullable: true), Name = table.Column(maxLength: 128, nullable: false), - Type = table.Column(nullable: false), + Type = table.Column(nullable: false), PublishDate = table.Column(nullable: false), Price = table.Column(nullable: false) }, diff --git a/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Migrations/BookStoreMigrationsDbContextModelSnapshot.cs b/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Migrations/BookStoreMigrationsDbContextModelSnapshot.cs index fcd623b85e..80e730e081 100644 --- a/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Migrations/BookStoreMigrationsDbContextModelSnapshot.cs +++ b/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Migrations/BookStoreMigrationsDbContextModelSnapshot.cs @@ -15,7 +15,7 @@ namespace Acme.BookStore.Migrations { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "2.2.3-servicing-35854") + .HasAnnotation("ProductVersion", "2.2.4-servicing-10062") .HasAnnotation("Relational:MaxIdentifierLength", 128) .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); @@ -24,18 +24,24 @@ namespace Acme.BookStore.Migrations b.Property("Id") .ValueGeneratedOnAdd(); - b.Property("ConcurrencyStamp"); + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp"); - b.Property("CreationTime"); + b.Property("CreationTime") + .HasColumnName("CreationTime"); - b.Property("CreatorId"); + b.Property("CreatorId") + .HasColumnName("CreatorId"); b.Property("ExtraProperties") .HasColumnName("ExtraProperties"); - b.Property("LastModificationTime"); + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime"); - b.Property("LastModifierId"); + b.Property("LastModifierId") + .HasColumnName("LastModifierId"); b.Property("Name") .IsRequired() @@ -45,7 +51,7 @@ namespace Acme.BookStore.Migrations b.Property("PublishDate"); - b.Property("Type"); + b.Property("Type"); b.HasKey("Id"); @@ -296,6 +302,32 @@ namespace Acme.BookStore.Migrations b.ToTable("AbpBackgroundJobs"); }); + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureValue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128); + + b.Property("ProviderKey") + .HasMaxLength(64); + + b.Property("ProviderName") + .HasMaxLength(64); + + b.Property("Value") + .IsRequired() + .HasMaxLength(128); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey"); + + b.ToTable("AbpFeatureValues"); + }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => { b.Property("Id") @@ -594,6 +626,482 @@ namespace Acme.BookStore.Migrations b.ToTable("AbpUserTokens"); }); + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResource", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasMaxLength(1000); + + b.Property("DisplayName") + .HasMaxLength(200); + + b.Property("Enabled"); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnName("IsDeleted") + .HasDefaultValue(false); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200); + + b.HasKey("Id"); + + b.ToTable("IdentityServerApiResources"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResourceClaim", b => + { + b.Property("ApiResourceId"); + + b.Property("Type") + .HasMaxLength(196); + + b.HasKey("ApiResourceId", "Type"); + + b.ToTable("IdentityServerApiClaims"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiScope", b => + { + b.Property("ApiResourceId"); + + b.Property("Name") + .HasMaxLength(196); + + b.Property("Description") + .HasMaxLength(256); + + b.Property("DisplayName") + .HasMaxLength(128); + + b.Property("Emphasize"); + + b.Property("Required"); + + b.Property("ShowInDiscoveryDocument"); + + b.HasKey("ApiResourceId", "Name"); + + b.ToTable("IdentityServerApiScopes"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiScopeClaim", b => + { + b.Property("ApiResourceId"); + + b.Property("Name") + .HasMaxLength(196); + + b.Property("Type") + .HasMaxLength(196); + + b.HasKey("ApiResourceId", "Name", "Type"); + + b.ToTable("IdentityServerApiScopeClaims"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiSecret", b => + { + b.Property("ApiResourceId"); + + b.Property("Type") + .HasMaxLength(32); + + b.Property("Value") + .HasMaxLength(196); + + b.Property("Description") + .HasMaxLength(256); + + b.Property("Expiration"); + + b.HasKey("ApiResourceId", "Type", "Value"); + + b.ToTable("IdentityServerApiSecrets"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.Client", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AbsoluteRefreshTokenLifetime"); + + b.Property("AccessTokenLifetime"); + + b.Property("AccessTokenType"); + + b.Property("AllowAccessTokensViaBrowser"); + + b.Property("AllowOfflineAccess"); + + b.Property("AllowPlainTextPkce"); + + b.Property("AllowRememberConsent"); + + b.Property("AlwaysIncludeUserClaimsInIdToken"); + + b.Property("AlwaysSendClientClaims"); + + b.Property("AuthorizationCodeLifetime"); + + b.Property("BackChannelLogoutSessionRequired"); + + b.Property("BackChannelLogoutUri") + .HasMaxLength(300); + + b.Property("ClientClaimsPrefix") + .HasMaxLength(200); + + b.Property("ClientId") + .IsRequired() + .HasMaxLength(200); + + b.Property("ClientName") + .HasMaxLength(200); + + b.Property("ClientUri") + .HasMaxLength(300); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp"); + + b.Property("ConsentLifetime"); + + b.Property("CreationTime") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasMaxLength(1000); + + b.Property("EnableLocalLogin"); + + b.Property("Enabled"); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties"); + + b.Property("FrontChannelLogoutSessionRequired"); + + b.Property("FrontChannelLogoutUri") + .HasMaxLength(300); + + b.Property("IdentityTokenLifetime"); + + b.Property("IncludeJwtId"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnName("IsDeleted") + .HasDefaultValue(false); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId"); + + b.Property("LogoUri") + .HasMaxLength(300); + + b.Property("PairWiseSubjectSalt") + .HasMaxLength(200); + + b.Property("ProtocolType") + .IsRequired() + .HasMaxLength(200); + + b.Property("RefreshTokenExpiration"); + + b.Property("RefreshTokenUsage"); + + b.Property("RequireClientSecret"); + + b.Property("RequireConsent"); + + b.Property("RequirePkce"); + + b.Property("SlidingRefreshTokenLifetime"); + + b.Property("UpdateAccessTokenClaimsOnRefresh"); + + b.HasKey("Id"); + + b.HasIndex("ClientId") + .IsUnique(); + + b.ToTable("IdentityServerClients"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientClaim", b => + { + b.Property("ClientId"); + + b.Property("Type") + .HasMaxLength(250); + + b.Property("Value") + .HasMaxLength(250); + + b.HasKey("ClientId", "Type", "Value"); + + b.ToTable("IdentityServerClientClaims"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientCorsOrigin", b => + { + b.Property("ClientId"); + + b.Property("Origin") + .HasMaxLength(150); + + b.HasKey("ClientId", "Origin"); + + b.ToTable("IdentityServerClientCorsOrigins"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientGrantType", b => + { + b.Property("ClientId"); + + b.Property("GrantType") + .HasMaxLength(196); + + b.HasKey("ClientId", "GrantType"); + + b.ToTable("IdentityServerClientGrantTypes"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientIdPRestriction", b => + { + b.Property("ClientId"); + + b.Property("Provider") + .HasMaxLength(64); + + b.HasKey("ClientId", "Provider"); + + b.ToTable("IdentityServerClientIdPRestrictions"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientPostLogoutRedirectUri", b => + { + b.Property("ClientId"); + + b.Property("PostLogoutRedirectUri") + .HasMaxLength(200); + + b.HasKey("ClientId", "PostLogoutRedirectUri"); + + b.ToTable("IdentityServerClientPostLogoutRedirectUris"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientProperty", b => + { + b.Property("ClientId"); + + b.Property("Key") + .HasMaxLength(64); + + b.Property("Value") + .IsRequired() + .HasMaxLength(128); + + b.HasKey("ClientId", "Key"); + + b.ToTable("IdentityServerClientProperties"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientRedirectUri", b => + { + b.Property("ClientId"); + + b.Property("RedirectUri") + .HasMaxLength(200); + + b.HasKey("ClientId", "RedirectUri"); + + b.ToTable("IdentityServerClientRedirectUris"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientScope", b => + { + b.Property("ClientId"); + + b.Property("Scope") + .HasMaxLength(196); + + b.HasKey("ClientId", "Scope"); + + b.ToTable("IdentityServerClientScopes"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientSecret", b => + { + b.Property("ClientId"); + + b.Property("Type") + .HasMaxLength(32); + + b.Property("Value") + .HasMaxLength(196); + + b.Property("Description") + .HasMaxLength(256); + + b.Property("Expiration"); + + b.HasKey("ClientId", "Type", "Value"); + + b.ToTable("IdentityServerClientSecrets"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Grants.PersistedGrant", b => + { + b.Property("Key") + .HasMaxLength(200); + + b.Property("ClientId") + .IsRequired() + .HasMaxLength(200); + + b.Property("ConcurrencyStamp"); + + b.Property("CreationTime"); + + b.Property("Data") + .IsRequired(); + + b.Property("Expiration"); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties"); + + b.Property("Id"); + + b.Property("SubjectId") + .HasMaxLength(200); + + b.Property("Type") + .IsRequired() + .HasMaxLength(50); + + b.HasKey("Key"); + + b.HasIndex("SubjectId", "ClientId", "Type"); + + b.ToTable("IdentityServerPersistedGrants"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.IdentityResources.IdentityClaim", b => + { + b.Property("IdentityResourceId"); + + b.Property("Type") + .HasMaxLength(196); + + b.HasKey("IdentityResourceId", "Type"); + + b.ToTable("IdentityServerIdentityClaims"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.IdentityResources.IdentityResource", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasMaxLength(1000); + + b.Property("DisplayName") + .HasMaxLength(200); + + b.Property("Emphasize"); + + b.Property("Enabled"); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnName("IsDeleted") + .HasDefaultValue(false); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200); + + b.Property("Required"); + + b.Property("ShowInDiscoveryDocument"); + + b.HasKey("Id"); + + b.ToTable("IdentityServerIdentityResources"); + }); + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => { b.Property("Id") @@ -778,6 +1286,118 @@ namespace Acme.BookStore.Migrations .OnDelete(DeleteBehavior.Cascade); }); + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResourceClaim", b => + { + b.HasOne("Volo.Abp.IdentityServer.ApiResources.ApiResource") + .WithMany("UserClaims") + .HasForeignKey("ApiResourceId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiScope", b => + { + b.HasOne("Volo.Abp.IdentityServer.ApiResources.ApiResource") + .WithMany("Scopes") + .HasForeignKey("ApiResourceId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiScopeClaim", b => + { + b.HasOne("Volo.Abp.IdentityServer.ApiResources.ApiScope") + .WithMany("UserClaims") + .HasForeignKey("ApiResourceId", "Name") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiSecret", b => + { + b.HasOne("Volo.Abp.IdentityServer.ApiResources.ApiResource") + .WithMany("Secrets") + .HasForeignKey("ApiResourceId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientClaim", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client") + .WithMany("Claims") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientCorsOrigin", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client") + .WithMany("AllowedCorsOrigins") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientGrantType", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client") + .WithMany("AllowedGrantTypes") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientIdPRestriction", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client") + .WithMany("IdentityProviderRestrictions") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientPostLogoutRedirectUri", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client") + .WithMany("PostLogoutRedirectUris") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientProperty", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client") + .WithMany("Properties") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientRedirectUri", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client") + .WithMany("RedirectUris") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientScope", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client") + .WithMany("AllowedScopes") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientSecret", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client") + .WithMany("ClientSecrets") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.IdentityResources.IdentityClaim", b => + { + b.HasOne("Volo.Abp.IdentityServer.IdentityResources.IdentityResource") + .WithMany("UserClaims") + .HasForeignKey("IdentityResourceId") + .OnDelete(DeleteBehavior.Cascade); + }); + modelBuilder.Entity("Volo.Abp.TenantManagement.TenantConnectionString", b => { b.HasOne("Volo.Abp.TenantManagement.Tenant") diff --git a/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore/Acme.BookStore.EntityFrameworkCore.csproj b/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore/Acme.BookStore.EntityFrameworkCore.csproj index c42ea44516..967187059a 100644 --- a/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore/Acme.BookStore.EntityFrameworkCore.csproj +++ b/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore/Acme.BookStore.EntityFrameworkCore.csproj @@ -9,14 +9,15 @@ - - - - - - - - + + + + + + + + + diff --git a/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreDbContext.cs b/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreDbContext.cs index 1aebc9b1ae..386eb2623b 100644 --- a/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreDbContext.cs +++ b/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreDbContext.cs @@ -7,6 +7,15 @@ using Volo.Abp.Users.EntityFrameworkCore; namespace Acme.BookStore.EntityFrameworkCore { + /* This is your actual DbContext used on runtime. + * It includes only your entities. + * It does not include entities of the used modules, because each module has already + * its own DbContext class. If you want to share some database tables with the used modules, + * just create a structure like done for AppUser. + * + * Don't use this DbContext for database migrations since it does not contain tables of the + * used modules (as explained above). See BookStoreMigrationsDbContext for migrations. + */ [ConnectionStringName("Default")] public class BookStoreDbContext : AbpDbContext { @@ -14,6 +23,10 @@ namespace Acme.BookStore.EntityFrameworkCore public DbSet Books { get; set; } + /* Add DbSet properties for your Aggregate Roots / Entities here. + * Also map them inside BookStoreDbContextModelCreatingExtensions.ConfigureBookStore + */ + public BookStoreDbContext(DbContextOptions options) : base(options) { diff --git a/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreDbContextModelCreatingExtensions.cs b/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreDbContextModelCreatingExtensions.cs index b7cdd8705d..d14e33208d 100644 --- a/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreDbContextModelCreatingExtensions.cs +++ b/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreDbContextModelCreatingExtensions.cs @@ -1,8 +1,8 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; using Volo.Abp; -using Volo.Abp.Users; using Volo.Abp.EntityFrameworkCore.Modeling; +using Volo.Abp.Users; namespace Acme.BookStore.EntityFrameworkCore { @@ -17,7 +17,12 @@ namespace Acme.BookStore.EntityFrameworkCore builder.Entity(b => { b.ToTable(BookStoreConsts.DbTablePrefix + "Books", BookStoreConsts.DbSchema); + + b.ConfigureAudited(); b.ConfigureExtraProperties(); + b.ConfigureConcurrencyStamp(); + + b.Property(x => x.Name).IsRequired().HasMaxLength(128); }); } diff --git a/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreEntityFrameworkCoreModule.cs b/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreEntityFrameworkCoreModule.cs index a8e4d2de0c..efa5642632 100644 --- a/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreEntityFrameworkCoreModule.cs +++ b/samples/BookStore/src/Acme.BookStore.EntityFrameworkCore/EntityFrameworkCore/BookStoreEntityFrameworkCoreModule.cs @@ -1,9 +1,11 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.AuditLogging.EntityFrameworkCore; using Volo.Abp.BackgroundJobs.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore.SqlServer; using Volo.Abp.FeatureManagement.EntityFrameworkCore; using Volo.Abp.Identity.EntityFrameworkCore; +using Volo.Abp.IdentityServer.EntityFrameworkCore; using Volo.Abp.Modularity; using Volo.Abp.PermissionManagement.EntityFrameworkCore; using Volo.Abp.SettingManagement.EntityFrameworkCore; @@ -14,6 +16,7 @@ namespace Acme.BookStore.EntityFrameworkCore [DependsOn( typeof(BookStoreDomainModule), typeof(AbpIdentityEntityFrameworkCoreModule), + typeof(AbpIdentityServerEntityFrameworkCoreModule), typeof(AbpPermissionManagementEntityFrameworkCoreModule), typeof(AbpSettingManagementEntityFrameworkCoreModule), typeof(AbpEntityFrameworkCoreSqlServerModule), @@ -28,9 +31,17 @@ namespace Acme.BookStore.EntityFrameworkCore { context.Services.AddAbpDbContext(options => { - //Remove "includeAllEntities: true" to create default repositories only for aggregate roots + /* Remove "includeAllEntities: true" to create + * default repositories only for aggregate roots */ options.AddDefaultRepositories(includeAllEntities: true); }); + + Configure(options => + { + /* The main point to change your DBMS. + * See also BookStoreMigrationsDbContextFactory for EF Core tooling. */ + options.UseSqlServer(); + }); } } } diff --git a/samples/BookStore/src/Acme.BookStore.HttpApi.Client/Acme.BookStore.HttpApi.Client.csproj b/samples/BookStore/src/Acme.BookStore.HttpApi.Client/Acme.BookStore.HttpApi.Client.csproj new file mode 100644 index 0000000000..fd3ba12fe7 --- /dev/null +++ b/samples/BookStore/src/Acme.BookStore.HttpApi.Client/Acme.BookStore.HttpApi.Client.csproj @@ -0,0 +1,21 @@ + + + + + + netstandard2.0 + Acme.BookStore + + + + + + + + + + + + + + diff --git a/samples/BookStore/src/Acme.BookStore.HttpApi.Client/BookStoreHttpApiClientModule.cs b/samples/BookStore/src/Acme.BookStore.HttpApi.Client/BookStoreHttpApiClientModule.cs new file mode 100644 index 0000000000..0139522107 --- /dev/null +++ b/samples/BookStore/src/Acme.BookStore.HttpApi.Client/BookStoreHttpApiClientModule.cs @@ -0,0 +1,29 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.FeatureManagement; +using Volo.Abp.Identity; +using Volo.Abp.Modularity; +using Volo.Abp.PermissionManagement; +using Volo.Abp.TenantManagement; + +namespace Acme.BookStore +{ + [DependsOn( + typeof(BookStoreApplicationContractsModule), + typeof(AbpIdentityHttpApiClientModule), + typeof(AbpPermissionManagementHttpApiClientModule), + typeof(AbpTenantManagementHttpApiClientModule), + typeof(AbpFeatureManagementHttpApiClientModule) + )] + public class BookStoreHttpApiClientModule : AbpModule + { + public const string RemoteServiceName = "Default"; + + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddHttpClientProxies( + typeof(BookStoreApplicationContractsModule).Assembly, + RemoteServiceName + ); + } + } +} diff --git a/samples/BookStore/src/Acme.BookStore.HttpApi/Acme.BookStore.HttpApi.csproj b/samples/BookStore/src/Acme.BookStore.HttpApi/Acme.BookStore.HttpApi.csproj new file mode 100644 index 0000000000..7f819c039b --- /dev/null +++ b/samples/BookStore/src/Acme.BookStore.HttpApi/Acme.BookStore.HttpApi.csproj @@ -0,0 +1,21 @@ + + + + + + netcoreapp2.2 + Acme.BookStore + + + + + + + + + + + + + + diff --git a/samples/BookStore/src/Acme.BookStore.HttpApi/BookStoreHttpApiModule.cs b/samples/BookStore/src/Acme.BookStore.HttpApi/BookStoreHttpApiModule.cs new file mode 100644 index 0000000000..2f990bfe56 --- /dev/null +++ b/samples/BookStore/src/Acme.BookStore.HttpApi/BookStoreHttpApiModule.cs @@ -0,0 +1,20 @@ +using Volo.Abp.FeatureManagement; +using Volo.Abp.Identity; +using Volo.Abp.Modularity; +using Volo.Abp.PermissionManagement.HttpApi; +using Volo.Abp.TenantManagement; + +namespace Acme.BookStore +{ + [DependsOn( + typeof(BookStoreApplicationContractsModule), + typeof(AbpIdentityHttpApiModule), + typeof(AbpPermissionManagementHttpApiModule), + typeof(AbpTenantManagementHttpApiModule), + typeof(AbpFeatureManagementHttpApiModule) + )] + public class BookStoreHttpApiModule : AbpModule + { + + } +} diff --git a/samples/BookStore/src/Acme.BookStore.HttpApi/Controllers/BookStoreController.cs b/samples/BookStore/src/Acme.BookStore.HttpApi/Controllers/BookStoreController.cs new file mode 100644 index 0000000000..4489c61c3c --- /dev/null +++ b/samples/BookStore/src/Acme.BookStore.HttpApi/Controllers/BookStoreController.cs @@ -0,0 +1,13 @@ +using Acme.BookStore.Localization; +using Volo.Abp.AspNetCore.Mvc; + +namespace Acme.BookStore.Controllers +{ + public abstract class BookStoreController : AbpController + { + protected BookStoreController() + { + //LocalizationResource = typeof(BookStoreResource); + } + } +} \ No newline at end of file diff --git a/samples/BookStore/src/Acme.BookStore.HttpApi/Controllers/TestController.cs b/samples/BookStore/src/Acme.BookStore.HttpApi/Controllers/TestController.cs new file mode 100644 index 0000000000..5f06bcfb4f --- /dev/null +++ b/samples/BookStore/src/Acme.BookStore.HttpApi/Controllers/TestController.cs @@ -0,0 +1,28 @@ +using Microsoft.AspNetCore.Mvc; +using Acme.BookStore.Models.Test; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Acme.BookStore.Controllers +{ + [Route("api/test")] + public class TestController : BookStoreController + { + public TestController() + { + + } + + [HttpGet] + [Route("")] + public async Task> GetAsync() + { + return new List + { + new TestModel {Name = "John", BirthDate = new DateTime(1942, 11, 18)}, + new TestModel {Name = "Adams", BirthDate = new DateTime(1997, 05, 24)} + }; + } + } +} diff --git a/samples/BookStore/src/Acme.BookStore.HttpApi/Models/Test/TestModel.cs b/samples/BookStore/src/Acme.BookStore.HttpApi/Models/Test/TestModel.cs new file mode 100644 index 0000000000..05381a8371 --- /dev/null +++ b/samples/BookStore/src/Acme.BookStore.HttpApi/Models/Test/TestModel.cs @@ -0,0 +1,11 @@ +using System; + +namespace Acme.BookStore.Models.Test +{ + public class TestModel + { + public string Name { get; set; } + + public DateTime BirthDate { get; set; } + } +} \ No newline at end of file diff --git a/samples/BookStore/src/Acme.BookStore.Web/Acme.BookStore.Web.csproj b/samples/BookStore/src/Acme.BookStore.Web/Acme.BookStore.Web.csproj index 46616b452a..a6e1fb1b77 100644 --- a/samples/BookStore/src/Acme.BookStore.Web/Acme.BookStore.Web.csproj +++ b/samples/BookStore/src/Acme.BookStore.Web/Acme.BookStore.Web.csproj @@ -4,7 +4,6 @@ netcoreapp2.2 - Acme.BookStore $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; true true @@ -20,28 +19,27 @@ - - - - - - + + + + - - - - - - + + + + + + + diff --git a/samples/BookStore/src/Acme.BookStore.Web/Branding/BookStoreBrandingProvider.cs b/samples/BookStore/src/Acme.BookStore.Web/BookStoreBrandingProvider.cs similarity index 89% rename from samples/BookStore/src/Acme.BookStore.Web/Branding/BookStoreBrandingProvider.cs rename to samples/BookStore/src/Acme.BookStore.Web/BookStoreBrandingProvider.cs index e73cccf6ab..4ccc981e61 100644 --- a/samples/BookStore/src/Acme.BookStore.Web/Branding/BookStoreBrandingProvider.cs +++ b/samples/BookStore/src/Acme.BookStore.Web/BookStoreBrandingProvider.cs @@ -1,7 +1,7 @@ using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Components; using Volo.Abp.DependencyInjection; -namespace Acme.BookStore.Branding +namespace Acme.BookStore.Web { [Dependency(ReplaceServices = true)] public class BookStoreBrandingProvider : DefaultBrandingProvider diff --git a/samples/BookStore/src/Acme.BookStore.Web/BookStoreWebAutoMapperProfile.cs b/samples/BookStore/src/Acme.BookStore.Web/BookStoreWebAutoMapperProfile.cs index 86c57ce794..d2ae542615 100644 --- a/samples/BookStore/src/Acme.BookStore.Web/BookStoreWebAutoMapperProfile.cs +++ b/samples/BookStore/src/Acme.BookStore.Web/BookStoreWebAutoMapperProfile.cs @@ -1,12 +1,12 @@ using AutoMapper; -namespace Acme.BookStore +namespace Acme.BookStore.Web { public class BookStoreWebAutoMapperProfile : Profile { public BookStoreWebAutoMapperProfile() { - //Configure your AutoMapper mapping configuration here... + CreateMap(); } } } diff --git a/samples/BookStore/src/Acme.BookStore.Web/BookStoreWebModule.cs b/samples/BookStore/src/Acme.BookStore.Web/BookStoreWebModule.cs index 9f42c3d330..bbba8b543c 100644 --- a/samples/BookStore/src/Acme.BookStore.Web/BookStoreWebModule.cs +++ b/samples/BookStore/src/Acme.BookStore.Web/BookStoreWebModule.cs @@ -1,50 +1,42 @@ using System.IO; -using System.Linq; +using Acme.BookStore.EntityFrameworkCore; +using Acme.BookStore.Localization; +using Acme.BookStore.MultiTenancy; +using Acme.BookStore.Web.Menus; using Localization.Resources.AbpUi; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using Acme.BookStore.EntityFrameworkCore; -using Acme.BookStore.Localization.BookStore; -using Acme.BookStore.Menus; -using Acme.BookStore.Permissions; using Swashbuckle.AspNetCore.Swagger; using Volo.Abp; using Volo.Abp.Account.Web; +using Volo.Abp.AspNetCore.Authentication.JwtBearer; using Volo.Abp.AspNetCore.Mvc; using Volo.Abp.AspNetCore.Mvc.Localization; -using Volo.Abp.AspNetCore.Mvc.UI; -using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap; using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic; using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared; -using Volo.Abp.Authorization.Permissions; using Volo.Abp.Autofac; using Volo.Abp.AutoMapper; -using Volo.Abp.Data; -using Volo.Abp.Identity; using Volo.Abp.Identity.Web; using Volo.Abp.Localization; -using Volo.Abp.Localization.Resources.AbpValidation; using Volo.Abp.Modularity; -using Volo.Abp.PermissionManagement.Web; -using Volo.Abp.Threading; -using Volo.Abp.UI; +using Volo.Abp.TenantManagement.Web; using Volo.Abp.UI.Navigation; +using Volo.Abp.Ui.Navigation.Urls; using Volo.Abp.VirtualFileSystem; -using Volo.Abp.PermissionManagement; -using Volo.Abp.EntityFrameworkCore; -using Volo.Abp.TenantManagement.Web; - -namespace Acme.BookStore +namespace Acme.BookStore.Web { [DependsOn( + typeof(BookStoreHttpApiModule), typeof(BookStoreApplicationModule), - typeof(BookStoreEntityFrameworkCoreModule), + typeof(BookStoreEntityFrameworkCoreDbMigrationsModule), typeof(AbpAutofacModule), typeof(AbpIdentityWebModule), - typeof(AbpAccountWebModule), + typeof(AbpAccountWebIdentityServerModule), typeof(AbpAspNetCoreMvcUiBasicThemeModule), + typeof(AbpAspNetCoreAuthenticationJwtBearerModule), typeof(AbpTenantManagementWebModule) )] public class BookStoreWebModule : AbpModule @@ -56,7 +48,9 @@ namespace Acme.BookStore options.AddAssemblyResource( typeof(BookStoreResource), typeof(BookStoreDomainModule).Assembly, + typeof(BookStoreDomainSharedModule).Assembly, typeof(BookStoreApplicationModule).Assembly, + typeof(BookStoreApplicationContractsModule).Assembly, typeof(BookStoreWebModule).Assembly ); }); @@ -67,7 +61,8 @@ namespace Acme.BookStore var hostingEnvironment = context.Services.GetHostingEnvironment(); var configuration = context.Services.GetConfiguration(); - ConfigureDatabaseServices(); + ConfigureUrls(configuration); + ConfigureAuthentication(context, configuration); ConfigureAutoMapper(); ConfigureVirtualFileSystem(hostingEnvironment); ConfigureLocalizationServices(); @@ -76,18 +71,34 @@ namespace Acme.BookStore ConfigureSwaggerServices(context.Services); } - private void ConfigureDatabaseServices() + private void ConfigureUrls(IConfigurationRoot configuration) { - Configure(options => + Configure(options => { - options.UseSqlServer(); + options.Applications["MVC"].RootUrl = configuration["AppSelfUrl"]; }); } + private void ConfigureAuthentication(ServiceConfigurationContext context, IConfigurationRoot configuration) + { + context.Services.AddAuthentication() + .AddIdentityServerAuthentication(options => + { + options.Authority = configuration["AuthServer:Authority"]; + options.RequireHttpsMetadata = false; + options.ApiName = "BookStore"; + }); + } + private void ConfigureAutoMapper() { Configure(options => { + /* use `true` for the `validate` parameter if you want to + * validate the profile on application startup. + * See http://docs.automapper.org/en/stable/Configuration-validation.html for more + * about configuration validation. + */ options.AddProfile(); }); } @@ -98,7 +109,11 @@ namespace Acme.BookStore { Configure(options => { + options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}Acme.BookStore.Domain.Shared", Path.DirectorySeparatorChar))); options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}Acme.BookStore.Domain", Path.DirectorySeparatorChar))); + options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}Acme.BookStore.Application.Contracts", Path.DirectorySeparatorChar))); + options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}Acme.BookStore.Application", Path.DirectorySeparatorChar))); + options.FileSets.ReplaceEmbeddedByPhysical(hostingEnvironment.ContentRootPath); }); } } @@ -110,10 +125,10 @@ namespace Acme.BookStore options.Resources .Get() .AddBaseTypes( - typeof(AbpValidationResource), typeof(AbpUiResource) ); + options.Languages.Add(new LanguageInfo("cs", "cs", "Čeština")); options.Languages.Add(new LanguageInfo("en", "en", "English")); options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português")); options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe")); @@ -145,7 +160,8 @@ namespace Acme.BookStore options.SwaggerDoc("v1", new Info { Title = "BookStore API", Version = "v1" }); options.DocInclusionPredicate((docName, description) => true); options.CustomSchemaIds(type => type.FullName); - }); + } + ); } public override void OnApplicationInitialization(ApplicationInitializationContext context) @@ -164,38 +180,22 @@ namespace Acme.BookStore app.UseVirtualFiles(); app.UseAuthentication(); + app.UseJwtTokenMiddleware(); - if (BookStoreConsts.IsMultiTenancyEnabled) + if (MultiTenancyConsts.IsEnabled) { app.UseMultiTenancy(); } + app.UseIdentityServer(); app.UseAbpRequestLocalization(); - app.UseSwagger(); app.UseSwaggerUI(options => { options.SwaggerEndpoint("/swagger/v1/swagger.json", "BookStore API"); }); - app.UseAuditing(); - app.UseMvcWithDefaultRouteAndArea(); - - SeedDatabase(context); - } - - private static void SeedDatabase(ApplicationInitializationContext context) - { - using (var scope = context.ServiceProvider.CreateScope()) - { - AsyncHelper.RunSync(async () => - { - await scope.ServiceProvider - .GetRequiredService() - .SeedAsync(); - }); - } } } } diff --git a/samples/BookStore/src/Acme.BookStore.Web/Menus/BookStoreMenuContributor.cs b/samples/BookStore/src/Acme.BookStore.Web/Menus/BookStoreMenuContributor.cs index 4b6aa2821a..78459ebb41 100644 --- a/samples/BookStore/src/Acme.BookStore.Web/Menus/BookStoreMenuContributor.cs +++ b/samples/BookStore/src/Acme.BookStore.Web/Menus/BookStoreMenuContributor.cs @@ -1,11 +1,12 @@ using System.Threading.Tasks; +using Acme.BookStore.Localization; +using Acme.BookStore.MultiTenancy; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Localization; -using Acme.BookStore.Localization.BookStore; using Volo.Abp.TenantManagement.Web.Navigation; using Volo.Abp.UI.Navigation; -namespace Acme.BookStore.Menus +namespace Acme.BookStore.Web.Menus { public class BookStoreMenuContributor : IMenuContributor { @@ -19,19 +20,20 @@ namespace Acme.BookStore.Menus private async Task ConfigureMainMenuAsync(MenuConfigurationContext context) { - if (!BookStoreConsts.IsMultiTenancyEnabled) + if (!MultiTenancyConsts.IsEnabled) { - ApplicationMenuItem administration = context.Menu.GetAdministration(); + var administration = context.Menu.GetAdministration(); administration.TryRemoveMenuItem(TenantManagementMenuNames.GroupName); } var l = context.ServiceProvider.GetRequiredService>(); context.Menu.Items.Insert(0, new ApplicationMenuItem("BookStore.Home", l["Menu:Home"], "/")); + context.Menu.AddItem( new ApplicationMenuItem("BooksStore", l["Menu:BookStore"]) .AddItem(new ApplicationMenuItem("BooksStore.Books", l["Menu:Books"], url: "/Books")) - ); + ); } } } diff --git a/samples/BookStore/src/Acme.BookStore.Web/Pages/BookStorePageBase.cs b/samples/BookStore/src/Acme.BookStore.Web/Pages/BookStorePageBase.cs index 16aad9bfa4..57c9721951 100644 --- a/samples/BookStore/src/Acme.BookStore.Web/Pages/BookStorePageBase.cs +++ b/samples/BookStore/src/Acme.BookStore.Web/Pages/BookStorePageBase.cs @@ -1,9 +1,9 @@ -using Microsoft.AspNetCore.Mvc.Localization; +using Acme.BookStore.Localization; +using Microsoft.AspNetCore.Mvc.Localization; using Microsoft.AspNetCore.Mvc.Razor.Internal; -using Acme.BookStore.Localization.BookStore; using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; -namespace Acme.BookStore.Pages +namespace Acme.BookStore.Web.Pages { public abstract class BookStorePageBase : AbpPage { diff --git a/samples/BookStore/src/Acme.BookStore.Web/Pages/BookStorePageModelBase.cs b/samples/BookStore/src/Acme.BookStore.Web/Pages/BookStorePageModelBase.cs index 5dd1fc918c..0a213892e8 100644 --- a/samples/BookStore/src/Acme.BookStore.Web/Pages/BookStorePageModelBase.cs +++ b/samples/BookStore/src/Acme.BookStore.Web/Pages/BookStorePageModelBase.cs @@ -1,7 +1,7 @@ -using Acme.BookStore.Localization.BookStore; +using Acme.BookStore.Localization; using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; -namespace Acme.BookStore.Pages +namespace Acme.BookStore.Web.Pages { public abstract class BookStorePageModelBase : AbpPageModel { diff --git a/samples/BookStore/src/Acme.BookStore.Web/Pages/Books/CreateModal.cshtml b/samples/BookStore/src/Acme.BookStore.Web/Pages/Books/CreateModal.cshtml index 5766199fbc..04a6eee412 100644 --- a/samples/BookStore/src/Acme.BookStore.Web/Pages/Books/CreateModal.cshtml +++ b/samples/BookStore/src/Acme.BookStore.Web/Pages/Books/CreateModal.cshtml @@ -1,7 +1,7 @@ @page -@inherits Acme.BookStore.Pages.BookStorePageBase +@inherits Acme.BookStore.Web.Pages.BookStorePageBase @using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal -@model Acme.BookStore.Pages.Books.CreateModalModel +@model Acme.BookStore.Web.Pages.Books.CreateModalModel @{ Layout = null; } diff --git a/samples/BookStore/src/Acme.BookStore.Web/Pages/Books/CreateModal.cshtml.cs b/samples/BookStore/src/Acme.BookStore.Web/Pages/Books/CreateModal.cshtml.cs index 1dc5f368fe..cca77771bd 100644 --- a/samples/BookStore/src/Acme.BookStore.Web/Pages/Books/CreateModal.cshtml.cs +++ b/samples/BookStore/src/Acme.BookStore.Web/Pages/Books/CreateModal.cshtml.cs @@ -1,7 +1,7 @@ -using System.Threading.Tasks; +using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; -namespace Acme.BookStore.Pages.Books +namespace Acme.BookStore.Web.Pages.Books { public class CreateModalModel : BookStorePageModelBase { diff --git a/samples/BookStore/src/Acme.BookStore.Web/Pages/Books/EditModal.cshtml b/samples/BookStore/src/Acme.BookStore.Web/Pages/Books/EditModal.cshtml index dc03c197d6..6f1bb03494 100644 --- a/samples/BookStore/src/Acme.BookStore.Web/Pages/Books/EditModal.cshtml +++ b/samples/BookStore/src/Acme.BookStore.Web/Pages/Books/EditModal.cshtml @@ -1,6 +1,6 @@ @page -@inherits Acme.BookStore.Pages.BookStorePageBase -@using Acme.BookStore.Pages.Books +@inherits Acme.BookStore.Web.Pages.BookStorePageBase +@using Acme.BookStore.Web.Pages.Books @using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal @model EditModalModel @{ diff --git a/samples/BookStore/src/Acme.BookStore.Web/Pages/Books/EditModal.cshtml.cs b/samples/BookStore/src/Acme.BookStore.Web/Pages/Books/EditModal.cshtml.cs index 89a3e3bb13..21aef6d072 100644 --- a/samples/BookStore/src/Acme.BookStore.Web/Pages/Books/EditModal.cshtml.cs +++ b/samples/BookStore/src/Acme.BookStore.Web/Pages/Books/EditModal.cshtml.cs @@ -2,7 +2,7 @@ using System; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; -namespace Acme.BookStore.Pages.Books +namespace Acme.BookStore.Web.Pages.Books { public class EditModalModel : BookStorePageModelBase { diff --git a/samples/BookStore/src/Acme.BookStore.Web/Pages/Books/Index.cshtml b/samples/BookStore/src/Acme.BookStore.Web/Pages/Books/Index.cshtml index 641652edf2..abaed993ca 100644 --- a/samples/BookStore/src/Acme.BookStore.Web/Pages/Books/Index.cshtml +++ b/samples/BookStore/src/Acme.BookStore.Web/Pages/Books/Index.cshtml @@ -1,9 +1,8 @@ @page -@using Acme.BookStore.Pages.Books -@inherits Acme.BookStore.Pages.BookStorePageBase -@model IndexModel +@inherits Acme.BookStore.Web.Pages.BookStorePageBase +@model Acme.BookStore.Web.Pages.Books.IndexModel @section scripts - { +{ } @@ -23,14 +22,14 @@ - - @L["Actions"] - @L["Name"] - @L["Type"] - @L["PublishDate"] - @L["Price"] - @L["CreationTime"] - + + @L["Actions"] + @L["Name"] + @L["Type"] + @L["PublishDate"] + @L["Price"] + @L["CreationTime"] + diff --git a/samples/BookStore/src/Acme.BookStore.Web/Pages/Books/Index.cshtml.cs b/samples/BookStore/src/Acme.BookStore.Web/Pages/Books/Index.cshtml.cs index cc2b70329d..4d182bf266 100644 --- a/samples/BookStore/src/Acme.BookStore.Web/Pages/Books/Index.cshtml.cs +++ b/samples/BookStore/src/Acme.BookStore.Web/Pages/Books/Index.cshtml.cs @@ -1,16 +1,12 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.RazorPages; +using Microsoft.AspNetCore.Mvc.RazorPages; -namespace Acme.BookStore.Pages.Books +namespace Acme.BookStore.Web.Pages.Books { public class IndexModel : PageModel { public void OnGet() { + } } } \ No newline at end of file diff --git a/samples/BookStore/src/Acme.BookStore.Web/Pages/Books/index.js b/samples/BookStore/src/Acme.BookStore.Web/Pages/Books/index.js index e1f8e44804..b5c4da072d 100644 --- a/samples/BookStore/src/Acme.BookStore.Web/Pages/Books/index.js +++ b/samples/BookStore/src/Acme.BookStore.Web/Pages/Books/index.js @@ -18,28 +18,28 @@ { rowAction: { items: - [ - { - text: l('Edit'), - action: function (data) { - editModal.open({ id: data.record.id }); - } - }, - { - text: l('Delete'), - confirmMessage: function (data) { - return l('BookDeletionConfirmationMessage', data.record.name); + [ + { + text: l('Edit'), + action: function (data) { + editModal.open({ id: data.record.id }); + } }, - action: function (data) { - acme.bookStore.book - .delete(data.record.id) - .then(function() { - abp.notify.info(l('SuccessfullyDeleted')); - dataTable.ajax.reload(); - }); + { + text: l('Delete'), + confirmMessage: function (data) { + return l('BookDeletionConfirmationMessage', data.record.name); + }, + action: function (data) { + acme.bookStore.book + .delete(data.record.id) + .then(function () { + abp.notify.info(l('SuccessfullyDeleted')); + dataTable.ajax.reload(); + }); + } } - } - ] + ] } }, { data: "name" }, diff --git a/samples/BookStore/src/Acme.BookStore.Web/Pages/Index.cshtml b/samples/BookStore/src/Acme.BookStore.Web/Pages/Index.cshtml index e6e24beeae..0107052885 100644 --- a/samples/BookStore/src/Acme.BookStore.Web/Pages/Index.cshtml +++ b/samples/BookStore/src/Acme.BookStore.Web/Pages/Index.cshtml @@ -1,9 +1,15 @@ @page -@using Acme.BookStore.Pages -@inherits BookStorePageBase -@model IndexModel +@inherits Acme.BookStore.Web.Pages.BookStorePageBase +@model Acme.BookStore.Web.Pages.IndexModel @section styles { - + + + +} +@section scripts { + + + } @L["Welcome"] @@ -13,7 +19,7 @@ {

    @L["Login"]

    } -
    -

    abp.io

    +
    +

    abp.io

    \ No newline at end of file diff --git a/samples/BookStore/src/Acme.BookStore.Web/Pages/Index.cshtml.cs b/samples/BookStore/src/Acme.BookStore.Web/Pages/Index.cshtml.cs index 9425a3fbbd..89e1e770e8 100644 --- a/samples/BookStore/src/Acme.BookStore.Web/Pages/Index.cshtml.cs +++ b/samples/BookStore/src/Acme.BookStore.Web/Pages/Index.cshtml.cs @@ -1,4 +1,4 @@ -namespace Acme.BookStore.Pages +namespace Acme.BookStore.Web.Pages { public class IndexModel : BookStorePageModelBase { diff --git a/samples/BookStore/src/Acme.BookStore.Web/Pages/Index.css b/samples/BookStore/src/Acme.BookStore.Web/Pages/Index.css new file mode 100644 index 0000000000..3f73b78b9f --- /dev/null +++ b/samples/BookStore/src/Acme.BookStore.Web/Pages/Index.css @@ -0,0 +1,3 @@ +body { + +} diff --git a/samples/BookStore/src/Acme.BookStore.Web/Pages/Index.js b/samples/BookStore/src/Acme.BookStore.Web/Pages/Index.js new file mode 100644 index 0000000000..46f089b9c7 --- /dev/null +++ b/samples/BookStore/src/Acme.BookStore.Web/Pages/Index.js @@ -0,0 +1,3 @@ +$(function () { + abp.log.debug('Index.js initialized!'); +}); \ No newline at end of file diff --git a/samples/BookStore/src/Acme.BookStore.Web/Program.cs b/samples/BookStore/src/Acme.BookStore.Web/Program.cs index 40b58ff6b1..0ed9fd6438 100644 --- a/samples/BookStore/src/Acme.BookStore.Web/Program.cs +++ b/samples/BookStore/src/Acme.BookStore.Web/Program.cs @@ -4,14 +4,18 @@ using Microsoft.AspNetCore.Hosting; using Serilog; using Serilog.Events; -namespace Acme.BookStore +namespace Acme.BookStore.Web { public class Program { public static int Main(string[] args) { Log.Logger = new LoggerConfiguration() - .MinimumLevel.Debug() //TODO: Should be configurable! +#if DEBUG + .MinimumLevel.Debug() +#else + .MinimumLevel.Information() +#endif .MinimumLevel.Override("Microsoft", LogEventLevel.Information) .Enrich.FromLogContext() .WriteTo.File("Logs/logs.txt") diff --git a/samples/BookStore/src/Acme.BookStore.Web/Properties/launchSettings.json b/samples/BookStore/src/Acme.BookStore.Web/Properties/launchSettings.json index 6913413ef0..2503896399 100644 --- a/samples/BookStore/src/Acme.BookStore.Web/Properties/launchSettings.json +++ b/samples/BookStore/src/Acme.BookStore.Web/Properties/launchSettings.json @@ -4,7 +4,7 @@ "anonymousAuthentication": true, "iisExpress": { "applicationUrl": "http://localhost:53929/", - "sslPort": 0 + "sslPort": 44361 } }, "profiles": { diff --git a/samples/BookStore/src/Acme.BookStore.Web/Startup.cs b/samples/BookStore/src/Acme.BookStore.Web/Startup.cs index 0cd4c700d7..13db155180 100644 --- a/samples/BookStore/src/Acme.BookStore.Web/Startup.cs +++ b/samples/BookStore/src/Acme.BookStore.Web/Startup.cs @@ -4,7 +4,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Volo.Abp; -namespace Acme.BookStore +namespace Acme.BookStore.Web { public class Startup { diff --git a/samples/BookStore/src/Acme.BookStore.Web/Views/_ViewImports.cshtml b/samples/BookStore/src/Acme.BookStore.Web/Views/_ViewImports.cshtml index e4d518b1b8..c1da1f5f10 100644 --- a/samples/BookStore/src/Acme.BookStore.Web/Views/_ViewImports.cshtml +++ b/samples/BookStore/src/Acme.BookStore.Web/Views/_ViewImports.cshtml @@ -1,3 +1,4 @@ @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers @addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI @addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bootstrap +@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bundling \ No newline at end of file diff --git a/samples/BookStore/src/Acme.BookStore.Web/abp.resourcemapping.js b/samples/BookStore/src/Acme.BookStore.Web/abp.resourcemapping.js index 96f7c92778..122e8e926a 100644 --- a/samples/BookStore/src/Acme.BookStore.Web/abp.resourcemapping.js +++ b/samples/BookStore/src/Acme.BookStore.Web/abp.resourcemapping.js @@ -5,4 +5,4 @@ mappings: { } -} \ No newline at end of file +}; diff --git a/samples/BookStore/src/Acme.BookStore.Web/appsettings.Development.json b/samples/BookStore/src/Acme.BookStore.Web/appsettings.Development.json new file mode 100644 index 0000000000..2c63c08510 --- /dev/null +++ b/samples/BookStore/src/Acme.BookStore.Web/appsettings.Development.json @@ -0,0 +1,2 @@ +{ +} diff --git a/samples/BookStore/src/Acme.BookStore.Web/appsettings.json b/samples/BookStore/src/Acme.BookStore.Web/appsettings.json index 2e5ae70aaa..c4f8c54b9c 100644 --- a/samples/BookStore/src/Acme.BookStore.Web/appsettings.json +++ b/samples/BookStore/src/Acme.BookStore.Web/appsettings.json @@ -1,5 +1,16 @@ { + "AppSelfUrl": "https://localhost:44361", "ConnectionStrings": { "Default": "Server=localhost;Database=BookStore;Trusted_Connection=True;MultipleActiveResultSets=true" + }, + "AuthServer": { + "Authority": "https://localhost:44361" + }, + "IdentityServer": { + "Clients": { + "BookStore_ConsoleTestApp": { + "ClientId": "BookStore_ConsoleTestApp" + } + } } } \ No newline at end of file diff --git a/samples/BookStore/src/Acme.BookStore.Web/compilerconfig.json b/samples/BookStore/src/Acme.BookStore.Web/compilerconfig.json deleted file mode 100644 index 0f4f333f15..0000000000 --- a/samples/BookStore/src/Acme.BookStore.Web/compilerconfig.json +++ /dev/null @@ -1,6 +0,0 @@ -[ - { - "outputFile": "wwwroot/pages/index.css", - "inputFile": "wwwroot/pages/index.scss" - } -] \ No newline at end of file diff --git a/samples/BookStore/src/Acme.BookStore.Web/compilerconfig.json.defaults b/samples/BookStore/src/Acme.BookStore.Web/compilerconfig.json.defaults deleted file mode 100644 index c75eb7d519..0000000000 --- a/samples/BookStore/src/Acme.BookStore.Web/compilerconfig.json.defaults +++ /dev/null @@ -1,49 +0,0 @@ -{ - "compilers": { - "less": { - "autoPrefix": "", - "cssComb": "none", - "ieCompat": true, - "strictMath": false, - "strictUnits": false, - "relativeUrls": true, - "rootPath": "", - "sourceMapRoot": "", - "sourceMapBasePath": "", - "sourceMap": false - }, - "sass": { - "includePath": "", - "indentType": "space", - "indentWidth": 2, - "outputStyle": "nested", - "Precision": 5, - "relativeUrls": true, - "sourceMapRoot": "", - "sourceMap": false - }, - "stylus": { - "sourceMap": false - }, - "babel": { - "sourceMap": false - }, - "coffeescript": { - "bare": false, - "runtimeMode": "node", - "sourceMap": false - } - }, - "minifiers": { - "css": { - "enabled": true, - "termSemicolons": true, - "gzip": false - }, - "javascript": { - "enabled": true, - "termSemicolons": true, - "gzip": false - } - } -} \ No newline at end of file diff --git a/samples/BookStore/src/Acme.BookStore.Web/package.json b/samples/BookStore/src/Acme.BookStore.Web/package.json index 6d3170da8c..ef4fcf2350 100644 --- a/samples/BookStore/src/Acme.BookStore.Web/package.json +++ b/samples/BookStore/src/Acme.BookStore.Web/package.json @@ -1,6 +1,6 @@ { - "version": "0.1.0", - "name": "Acme.BookStore", + "version": "1.0.0", + "name": "my-app", "private": true, "dependencies": { "@abp/aspnetcore.mvc.ui.theme.basic": "^0.4.9" diff --git a/samples/BookStore/src/Acme.BookStore.Web/tempkey.rsa b/samples/BookStore/src/Acme.BookStore.Web/tempkey.rsa new file mode 100644 index 0000000000..f3b32de233 --- /dev/null +++ b/samples/BookStore/src/Acme.BookStore.Web/tempkey.rsa @@ -0,0 +1 @@ +{"KeyId":"ac0d2edf3c04d13cd95cc41b9b33ab03","Parameters":{"D":"FFymEWbX3XBT5YnTngOKwtz3XKsyaQbyDvvw9jbmkdvLKUmrb1hkmylqVYwU/3G1u79rrD8AZXJDoYVLegyZymK/iNeePMLI4i5vScF7PdQXn/g6CvQ8j3J60YYyfDWuxjBH8nCEUIfQIv14BpcH6CWi1BVZUbnbWcpe2ji8D5I3FHOZpvksQztst5eE836ODdN9jgk35kgrdUQ14MEFHA6m6fAzvFI1csFxD3Kwej4rI8RYZ0WYLkndz9ID88+v9VxqI8+wN6wR6tIOR510uT1FI5wONBVBUzgeZ6cCEpg0jC9tgqcP03gMDpmE7vKp34ExxH/iOWyhQ0gAxHOVlQ==","DP":"qSQfNZvEkepgY12d+uwTbRoOp+0g1CBiMU9kqyoIB56hAUnzENSCDzunjLRrvDLFPgXiUcoccskyVRnKKOGPOqPE6VjgzBrdLgA/hBf8hPg0GnTVoPyLxR9G6GsGUKsAYVn8G7cnK5wXzK4jCjsflkfxCzFfdASJ/+sa5QPWZMM=","DQ":"u+56T1+rhMvlurid9kBS2Ypfm4vOiNAXLD9kGz2wx8Ob0yYlWo55kn11qPs6Ej9bnQIY3N+TY2tXMamfhAhntoHaKrFjOpCmlHZ0GAeQOJVuWSlFvu/NBoxfjZzcUCNua22oJjy++wSdkkLLGEqau62byaQoSSqUxUzwL36RexM=","Exponent":"AQAB","InverseQ":"E+uq9g6D5LjUk+M7gtt0srnT8duwu8P83AgFqjtGOnSCy71omSboxb4zC9bGq/WaEFauFBwqxbkXwFyXuYNfIelfmSERulU9jgf0+KH6QmFdtjrJ5UO7VArqET1WUquwiDvOyO8udCxi8RRAiM5G3dTzIs5JTalGhlKEZSAgPtQ=","Modulus":"rgHACxzqvuE72RF/NdDTLsIEy3F/n6P4lkgrER60FU8uRNwSmAMRxvxYOaE3Ot/krRYcw2+MP8ewR1VBXywXVT1zuACA3SacMHJYmZQ2UkuwsD9bmpjvqoMhR/hjsI74jTzKpclHtEu7D7WYDZaIPAEIs/8+5H/z1mXVfgACaeaQt3C0OhwXSOPPDP71VKGfoFucXYED1keZ0PKxYAlhiHOe7cnSlfJseujwD2Rhyq8mUhe6aEMTYBjuruWgpfvnSOARAqu5vwzK35KpAirHwa1DJSZyanNMFdlLkVNKWUKEqd6PwRneiHacmaaDF6oQQstuSbf9cuJeSMbKh7WVQQ==","P":"0CJDit2NHk0Z1bN5ZVIYZRUYbrAI2bEOafAKqfffcA/Os7yXsY14Ye4pSpDxfdZGcPGRL04HPkJsogFtyI7k4ujrvsC66I5cg45+BhBMM0zyLJ7LZkD2HGwX2+a/xrXhhIIOnGWWy2zzW3dkayRhi1bR9krfTA5uBw1LX9qZ3Yc=","Q":"1gZITAaB+r0+PgOfyDCeVzSnTyQuKSkgbUkIgQP9jQZa6edrbAXogdJipxmUTrW7JaxifG1z9ubK+TOqhjZHqT4gd8U8Bh7jCBizZNVe60pez1OtNGpEOW2N+ZrXBSMNcV8PFaMg/B+fcaX+i7NWpTqmztR/V0DGXmD+XosuaPc="}} \ No newline at end of file diff --git a/samples/BookStore/src/Acme.BookStore.Web/wwwroot/pages/index.css b/samples/BookStore/src/Acme.BookStore.Web/wwwroot/pages/index.css deleted file mode 100644 index e02abfc9b0..0000000000 --- a/samples/BookStore/src/Acme.BookStore.Web/wwwroot/pages/index.css +++ /dev/null @@ -1 +0,0 @@ - diff --git a/samples/BookStore/src/Acme.BookStore.Web/wwwroot/pages/index.min.css b/samples/BookStore/src/Acme.BookStore.Web/wwwroot/pages/index.min.css deleted file mode 100644 index 5f282702bb..0000000000 --- a/samples/BookStore/src/Acme.BookStore.Web/wwwroot/pages/index.min.css +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/samples/BookStore/src/Acme.BookStore.Web/wwwroot/pages/index.scss b/samples/BookStore/src/Acme.BookStore.Web/wwwroot/pages/index.scss deleted file mode 100644 index b945ade091..0000000000 --- a/samples/BookStore/src/Acme.BookStore.Web/wwwroot/pages/index.scss +++ /dev/null @@ -1,3 +0,0 @@ -body{ - -} diff --git a/samples/BookStore/test/Acme.BookStore.Application.Tests/Acme.BookStore.Application.Tests.csproj b/samples/BookStore/test/Acme.BookStore.Application.Tests/Acme.BookStore.Application.Tests.csproj index 31415fb6c8..2ffa2d87a1 100644 --- a/samples/BookStore/test/Acme.BookStore.Application.Tests/Acme.BookStore.Application.Tests.csproj +++ b/samples/BookStore/test/Acme.BookStore.Application.Tests/Acme.BookStore.Application.Tests.csproj @@ -9,20 +9,11 @@ - - - + - - - - - - - - + diff --git a/samples/BookStore/test/Acme.BookStore.Application.Tests/BookStoreApplicationTestBase.cs b/samples/BookStore/test/Acme.BookStore.Application.Tests/BookStoreApplicationTestBase.cs index 24f530b735..5263dc5ea4 100644 --- a/samples/BookStore/test/Acme.BookStore.Application.Tests/BookStoreApplicationTestBase.cs +++ b/samples/BookStore/test/Acme.BookStore.Application.Tests/BookStoreApplicationTestBase.cs @@ -1,12 +1,7 @@ -using Volo.Abp; - -namespace Acme.BookStore +namespace Acme.BookStore { - public abstract class BookStoreApplicationTestBase : AbpIntegratedTest + public abstract class BookStoreApplicationTestBase : BookStoreTestBase { - protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) - { - options.UseAutofac(); - } + } } diff --git a/samples/BookStore/test/Acme.BookStore.Application.Tests/BookStoreApplicationTestModule.cs b/samples/BookStore/test/Acme.BookStore.Application.Tests/BookStoreApplicationTestModule.cs index 102a983013..40fee21794 100644 --- a/samples/BookStore/test/Acme.BookStore.Application.Tests/BookStoreApplicationTestModule.cs +++ b/samples/BookStore/test/Acme.BookStore.Application.Tests/BookStoreApplicationTestModule.cs @@ -1,78 +1,13 @@ -using Microsoft.Data.Sqlite; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Storage; -using Microsoft.Extensions.DependencyInjection; -using Acme.BookStore.EntityFrameworkCore; -using Volo.Abp; -using Volo.Abp.Autofac; -using Volo.Abp.EntityFrameworkCore; -using Volo.Abp.Modularity; +using Volo.Abp.Modularity; namespace Acme.BookStore { [DependsOn( typeof(BookStoreApplicationModule), - typeof(BookStoreEntityFrameworkCoreModule), - typeof(AbpAutofacModule), - typeof(AbpTestBaseModule) + typeof(BookStoreDomainTestModule) )] public class BookStoreApplicationTestModule : AbpModule { - private SqliteConnection _sqliteConnection; - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.AddAlwaysAllowAuthorization(); - - ConfigureInMemorySqlite(context.Services); - } - - private void ConfigureInMemorySqlite(IServiceCollection services) - { - _sqliteConnection = CreateDatabaseAndGetConnection(); - - services.Configure(options => - { - options.Configure(context => { context.DbContextOptions.UseSqlite(_sqliteConnection); }); - }); - } - - public override void OnApplicationInitialization(ApplicationInitializationContext context) - { - SeedTestData(context); - } - - public override void OnApplicationShutdown(ApplicationShutdownContext context) - { - _sqliteConnection.Dispose(); - } - - private static SqliteConnection CreateDatabaseAndGetConnection() - { - var connection = new SqliteConnection("Data Source=:memory:"); - connection.Open(); - - var options = new DbContextOptionsBuilder() - .UseSqlite(connection) - .Options; - - using (var context = new BookStoreMigrationsDbContext(options)) - { - context.GetService().CreateTables(); - } - - return connection; - } - - private static void SeedTestData(ApplicationInitializationContext context) - { - using (var scope = context.ServiceProvider.CreateScope()) - { - scope.ServiceProvider - .GetRequiredService() - .Build(); - } - } } } \ No newline at end of file diff --git a/samples/BookStore/test/Acme.BookStore.Application.Tests/Samples/SampleAppServiceTests.cs b/samples/BookStore/test/Acme.BookStore.Application.Tests/Samples/SampleAppServiceTests.cs new file mode 100644 index 0000000000..cd059e5639 --- /dev/null +++ b/samples/BookStore/test/Acme.BookStore.Application.Tests/Samples/SampleAppServiceTests.cs @@ -0,0 +1,33 @@ +using Shouldly; +using System.Threading.Tasks; +using Volo.Abp.Identity; +using Xunit; + +namespace Acme.BookStore.Samples +{ + /* This is just an example test class. + * Normally, you don't test code of the modules you are using + * (like IIdentityUserAppService here). + * Only test your own application services. + */ + public class SampleAppServiceTests : BookStoreApplicationTestBase + { + private readonly IIdentityUserAppService _userAppService; + + public SampleAppServiceTests() + { + _userAppService = GetRequiredService(); + } + + [Fact] + public async Task Initial_Data_Should_Contain_Admin_User() + { + //Act + var result = await _userAppService.GetListAsync(new GetIdentityUsersInput()); + + //Assert + result.TotalCount.ShouldBeGreaterThan(0); + result.Items.ShouldContain(u => u.UserName == "admin"); + } + } +} diff --git a/samples/BookStore/test/Acme.BookStore.Application.Tests/Samples/SampleTests.cs b/samples/BookStore/test/Acme.BookStore.Application.Tests/Samples/SampleTests.cs deleted file mode 100644 index 0470eaec1e..0000000000 --- a/samples/BookStore/test/Acme.BookStore.Application.Tests/Samples/SampleTests.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.DependencyInjection; -using Acme.BookStore.Users; -using Shouldly; -using Volo.Abp.Domain.Repositories; -using Volo.Abp.Identity; -using Volo.Abp.Uow; -using Xunit; - -namespace Acme.BookStore.Samples -{ - public class SampleTests : BookStoreApplicationTestBase - { - private readonly IIdentityUserAppService _userAppService; - private readonly IRepository _appUserRepository; - private readonly IUnitOfWorkManager _unitOfWorkManager; - - public SampleTests() - { - _userAppService = ServiceProvider.GetRequiredService(); - _appUserRepository = ServiceProvider.GetRequiredService>(); - _unitOfWorkManager = ServiceProvider.GetRequiredService(); - } - - [Fact] - public async Task Initial_Data_Should_Contain_Admin_User() - { - //Act - var result = await _userAppService.GetListAsync(new GetIdentityUsersInput()); - - //Assert - result.TotalCount.ShouldBeGreaterThan(0); - result.Items.ShouldContain(u => u.UserName == "admin"); - } - - [Fact] - public async Task Should_Query_AppUser() - { - /* Need to manually start Unit Of Work because - * FirstOrDefaultAsync should be executed while db connection / context is available. - */ - using (var uow = _unitOfWorkManager.Begin()) - { - //Act - var adminUser = await _appUserRepository - .Where(u => u.UserName == "admin") - .FirstOrDefaultAsync(); - - //Assert - adminUser.ShouldNotBeNull(); - - await uow.CompleteAsync(); - } - } - } -} diff --git a/samples/BookStore/test/Acme.BookStore.Domain.Tests/Acme.BookStore.Domain.Tests.csproj b/samples/BookStore/test/Acme.BookStore.Domain.Tests/Acme.BookStore.Domain.Tests.csproj new file mode 100644 index 0000000000..610d67b5bc --- /dev/null +++ b/samples/BookStore/test/Acme.BookStore.Domain.Tests/Acme.BookStore.Domain.Tests.csproj @@ -0,0 +1,18 @@ + + + + + + netcoreapp2.2 + Acme.BookStore + + + + + + + + + + + diff --git a/samples/BookStore/test/Acme.BookStore.Domain.Tests/BookStoreDomainTestBase.cs b/samples/BookStore/test/Acme.BookStore.Domain.Tests/BookStoreDomainTestBase.cs new file mode 100644 index 0000000000..a8d86b009d --- /dev/null +++ b/samples/BookStore/test/Acme.BookStore.Domain.Tests/BookStoreDomainTestBase.cs @@ -0,0 +1,7 @@ +namespace Acme.BookStore +{ + public abstract class BookStoreDomainTestBase : BookStoreTestBase + { + + } +} diff --git a/samples/BookStore/test/Acme.BookStore.Domain.Tests/BookStoreDomainTestModule.cs b/samples/BookStore/test/Acme.BookStore.Domain.Tests/BookStoreDomainTestModule.cs new file mode 100644 index 0000000000..7b3fb6fc79 --- /dev/null +++ b/samples/BookStore/test/Acme.BookStore.Domain.Tests/BookStoreDomainTestModule.cs @@ -0,0 +1,13 @@ +using Acme.BookStore.EntityFrameworkCore; +using Volo.Abp.Modularity; + +namespace Acme.BookStore +{ + [DependsOn( + typeof(BookStoreEntityFrameworkCoreTestModule) + )] + public class BookStoreDomainTestModule : AbpModule + { + + } +} \ No newline at end of file diff --git a/samples/BookStore/test/Acme.BookStore.Domain.Tests/Samples/SampleDomainTests.cs b/samples/BookStore/test/Acme.BookStore.Domain.Tests/Samples/SampleDomainTests.cs new file mode 100644 index 0000000000..0d8978e7f5 --- /dev/null +++ b/samples/BookStore/test/Acme.BookStore.Domain.Tests/Samples/SampleDomainTests.cs @@ -0,0 +1,45 @@ +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.Identity; +using Xunit; + +namespace Acme.BookStore.Samples +{ + /* This is just an example test class. + * Normally, you don't test code of the modules you are using + * (like IdentityUserManager here). + * Only test your own domain services. + */ + public class SampleDomainTests : BookStoreDomainTestBase + { + private readonly IIdentityUserRepository _identityUserRepository; + private readonly IdentityUserManager _identityUserManager; + + public SampleDomainTests() + { + _identityUserRepository = GetRequiredService(); + _identityUserManager = GetRequiredService(); + } + + [Fact] + public async Task Should_Set_Email_Of_A_User() + { + IdentityUser adminUser; + + /* Need to manually start Unit Of Work because + * FirstOrDefaultAsync should be executed while db connection / context is available. + */ + await WithUnitOfWorkAsync(async () => + { + adminUser = await _identityUserRepository + .FindByNormalizedUserNameAsync("ADMIN"); + + await _identityUserManager.SetEmailAsync(adminUser, "newemail@abp.io"); + await _identityUserRepository.UpdateAsync(adminUser); + }); + + adminUser = await _identityUserRepository.FindByNormalizedUserNameAsync("ADMIN"); + adminUser.Email.ShouldBe("newemail@abp.io"); + } + } +} diff --git a/samples/BookStore/test/Acme.BookStore.EntityFrameworkCore.Tests/Acme.BookStore.EntityFrameworkCore.Tests.csproj b/samples/BookStore/test/Acme.BookStore.EntityFrameworkCore.Tests/Acme.BookStore.EntityFrameworkCore.Tests.csproj new file mode 100644 index 0000000000..7c0705012f --- /dev/null +++ b/samples/BookStore/test/Acme.BookStore.EntityFrameworkCore.Tests/Acme.BookStore.EntityFrameworkCore.Tests.csproj @@ -0,0 +1,21 @@ + + + + + + netcoreapp2.2 + Acme.BookStore + + + + + + + + + + + + + + diff --git a/samples/BookStore/test/Acme.BookStore.EntityFrameworkCore.Tests/EntityFrameworkCore/BookStoreEntityFrameworkCoreTestBase.cs b/samples/BookStore/test/Acme.BookStore.EntityFrameworkCore.Tests/EntityFrameworkCore/BookStoreEntityFrameworkCoreTestBase.cs new file mode 100644 index 0000000000..792c2c3a12 --- /dev/null +++ b/samples/BookStore/test/Acme.BookStore.EntityFrameworkCore.Tests/EntityFrameworkCore/BookStoreEntityFrameworkCoreTestBase.cs @@ -0,0 +1,9 @@ +using Volo.Abp; + +namespace Acme.BookStore.EntityFrameworkCore +{ + public abstract class BookStoreEntityFrameworkCoreTestBase : BookStoreTestBase + { + + } +} diff --git a/samples/BookStore/test/Acme.BookStore.EntityFrameworkCore.Tests/EntityFrameworkCore/BookStoreEntityFrameworkCoreTestModule.cs b/samples/BookStore/test/Acme.BookStore.EntityFrameworkCore.Tests/EntityFrameworkCore/BookStoreEntityFrameworkCoreTestModule.cs new file mode 100644 index 0000000000..e1171d6d90 --- /dev/null +++ b/samples/BookStore/test/Acme.BookStore.EntityFrameworkCore.Tests/EntityFrameworkCore/BookStoreEntityFrameworkCoreTestModule.cs @@ -0,0 +1,57 @@ +using Microsoft.Data.Sqlite; +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; + +namespace Acme.BookStore.EntityFrameworkCore +{ + [DependsOn( + typeof(BookStoreEntityFrameworkCoreDbMigrationsModule), + typeof(BookStoreTestBaseModule) + )] + public class BookStoreEntityFrameworkCoreTestModule : AbpModule + { + private SqliteConnection _sqliteConnection; + + public override void ConfigureServices(ServiceConfigurationContext context) + { + ConfigureInMemorySqlite(context.Services); + } + + private void ConfigureInMemorySqlite(IServiceCollection services) + { + _sqliteConnection = CreateDatabaseAndGetConnection(); + + services.Configure(options => + { + options.Configure(context => { context.DbContextOptions.UseSqlite(_sqliteConnection); }); + }); + } + + public override void OnApplicationShutdown(ApplicationShutdownContext context) + { + _sqliteConnection.Dispose(); + } + + private static SqliteConnection CreateDatabaseAndGetConnection() + { + var connection = new SqliteConnection("Data Source=:memory:"); + connection.Open(); + + var options = new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options; + + using (var context = new BookStoreMigrationsDbContext(options)) + { + context.GetService().CreateTables(); + } + + return connection; + } + } +} diff --git a/samples/BookStore/test/Acme.BookStore.EntityFrameworkCore.Tests/EntityFrameworkCore/Samples/SampleRepositoryTests.cs b/samples/BookStore/test/Acme.BookStore.EntityFrameworkCore.Tests/EntityFrameworkCore/Samples/SampleRepositoryTests.cs new file mode 100644 index 0000000000..3cda13f3ea --- /dev/null +++ b/samples/BookStore/test/Acme.BookStore.EntityFrameworkCore.Tests/EntityFrameworkCore/Samples/SampleRepositoryTests.cs @@ -0,0 +1,44 @@ +using Microsoft.EntityFrameworkCore; +using Acme.BookStore.Users; +using Shouldly; +using System; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.Domain.Repositories; +using Xunit; + +namespace Acme.BookStore.EntityFrameworkCore.Samples +{ + /* This is just an example test class. + * Normally, you don't test ABP framework code + * (like default AppUser repository IRepository here). + * Only test your custom repository methods. + */ + public class SampleRepositoryTests : BookStoreEntityFrameworkCoreTestBase + { + private readonly IRepository _appUserRepository; + + public SampleRepositoryTests() + { + _appUserRepository = GetRequiredService>(); + } + + [Fact] + public async Task Should_Query_AppUser() + { + /* Need to manually start Unit Of Work because + * FirstOrDefaultAsync should be executed while db connection / context is available. + */ + await WithUnitOfWorkAsync(async () => + { + //Act + var adminUser = await _appUserRepository + .Where(u => u.UserName == "admin") + .FirstOrDefaultAsync(); + + //Assert + adminUser.ShouldNotBeNull(); + }); + } + } +} diff --git a/samples/BookStore/test/Acme.BookStore.HttpApi.Client.ConsoleTestApp/Acme.BookStore.HttpApi.Client.ConsoleTestApp.csproj b/samples/BookStore/test/Acme.BookStore.HttpApi.Client.ConsoleTestApp/Acme.BookStore.HttpApi.Client.ConsoleTestApp.csproj new file mode 100644 index 0000000000..325c7af448 --- /dev/null +++ b/samples/BookStore/test/Acme.BookStore.HttpApi.Client.ConsoleTestApp/Acme.BookStore.HttpApi.Client.ConsoleTestApp.csproj @@ -0,0 +1,24 @@ + + + + Exe + netcoreapp2.2 + + + + + + + + + PreserveNewest + Always + + + + + + + + + diff --git a/samples/BookStore/test/Acme.BookStore.HttpApi.Client.ConsoleTestApp/BookStoreConsoleApiClientModule.cs b/samples/BookStore/test/Acme.BookStore.HttpApi.Client.ConsoleTestApp/BookStoreConsoleApiClientModule.cs new file mode 100644 index 0000000000..4115bcd2ca --- /dev/null +++ b/samples/BookStore/test/Acme.BookStore.HttpApi.Client.ConsoleTestApp/BookStoreConsoleApiClientModule.cs @@ -0,0 +1,14 @@ +using Volo.Abp.Http.Client.IdentityModel; +using Volo.Abp.Modularity; + +namespace Acme.BookStore.HttpApi.Client.ConsoleTestApp +{ + [DependsOn( + typeof(BookStoreHttpApiClientModule), + typeof(AbpHttpClientIdentityModelModule) + )] + public class BookStoreConsoleApiClientModule : AbpModule + { + + } +} diff --git a/samples/BookStore/test/Acme.BookStore.HttpApi.Client.ConsoleTestApp/ClientDemoService.cs b/samples/BookStore/test/Acme.BookStore.HttpApi.Client.ConsoleTestApp/ClientDemoService.cs new file mode 100644 index 0000000000..edfde1aae6 --- /dev/null +++ b/samples/BookStore/test/Acme.BookStore.HttpApi.Client.ConsoleTestApp/ClientDemoService.cs @@ -0,0 +1,26 @@ +using System; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Identity; + +namespace Acme.BookStore.HttpApi.Client.ConsoleTestApp +{ + public class ClientDemoService : ITransientDependency + { + private readonly IProfileAppService _profileAppService; + + public ClientDemoService(IProfileAppService profileAppService) + { + _profileAppService = profileAppService; + } + + public async Task RunAsync() + { + var output = await _profileAppService.GetAsync(); + Console.WriteLine($"UserName : {output.UserName}"); + Console.WriteLine($"Email : {output.Email}"); + Console.WriteLine($"Name : {output.Name}"); + Console.WriteLine($"Surname : {output.Surname}"); + } + } +} \ No newline at end of file diff --git a/samples/BookStore/test/Acme.BookStore.HttpApi.Client.ConsoleTestApp/Program.cs b/samples/BookStore/test/Acme.BookStore.HttpApi.Client.ConsoleTestApp/Program.cs new file mode 100644 index 0000000000..ecef29d963 --- /dev/null +++ b/samples/BookStore/test/Acme.BookStore.HttpApi.Client.ConsoleTestApp/Program.cs @@ -0,0 +1,24 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp; +using Volo.Abp.Threading; + +namespace Acme.BookStore.HttpApi.Client.ConsoleTestApp +{ + class Program + { + static void Main(string[] args) + { + using (var application = AbpApplicationFactory.Create()) + { + application.Initialize(); + + var demo = application.ServiceProvider.GetRequiredService(); + AsyncHelper.RunSync(() => demo.RunAsync()); + + Console.WriteLine("Press ENTER to stop application..."); + Console.ReadLine(); + } + } + } +} diff --git a/samples/BookStore/test/Acme.BookStore.HttpApi.Client.ConsoleTestApp/appsettings.json b/samples/BookStore/test/Acme.BookStore.HttpApi.Client.ConsoleTestApp/appsettings.json new file mode 100644 index 0000000000..c220f47daf --- /dev/null +++ b/samples/BookStore/test/Acme.BookStore.HttpApi.Client.ConsoleTestApp/appsettings.json @@ -0,0 +1,18 @@ +{ + "RemoteServices": { + "Default": { + "BaseUrl": "https://localhost:44361/" + } + }, + "IdentityClients": { + "Default": { + "GrantType": "password", + "ClientId": "BookStore_ConsoleTestApp", + "ClientSecret": "1q2w3e*", + "UserName": "admin", + "UserPassword": "1q2w3E*", + "Authority": "https://localhost:44361", + "Scope": "BookStore" + } + } +} \ No newline at end of file diff --git a/samples/BookStore/test/Acme.BookStore.TestBase/Acme.BookStore.TestBase.csproj b/samples/BookStore/test/Acme.BookStore.TestBase/Acme.BookStore.TestBase.csproj new file mode 100644 index 0000000000..882396615e --- /dev/null +++ b/samples/BookStore/test/Acme.BookStore.TestBase/Acme.BookStore.TestBase.csproj @@ -0,0 +1,26 @@ + + + + + + netcoreapp2.2 + Acme.BookStore + + + + + + + + + + + + + + + + + + + diff --git a/samples/BookStore/test/Acme.BookStore.TestBase/BookStoreTestBase.cs b/samples/BookStore/test/Acme.BookStore.TestBase/BookStoreTestBase.cs new file mode 100644 index 0000000000..ba9d7c6b57 --- /dev/null +++ b/samples/BookStore/test/Acme.BookStore.TestBase/BookStoreTestBase.cs @@ -0,0 +1,100 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp; +using Volo.Abp.Modularity; +using Volo.Abp.Uow; + +namespace Acme.BookStore +{ + /* All test classes are derived from this class, directly or indirectly. + */ + public abstract class BookStoreTestBase : AbpIntegratedTest + where TStartupModule : IAbpModule + { + protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) + { + options.UseAutofac(); + } + + protected virtual void WithUnitOfWork(Action action) + { + WithUnitOfWork(new UnitOfWorkOptions(), action); + } + + protected virtual void WithUnitOfWork(UnitOfWorkOptions options, Action action) + { + using (var scope = ServiceProvider.CreateScope()) + { + var uowManager = scope.ServiceProvider.GetRequiredService(); + + using (var uow = uowManager.Begin(options)) + { + action(); + + uow.Complete(); + } + } + } + + protected virtual Task WithUnitOfWorkAsync(Func func) + { + return WithUnitOfWorkAsync(new UnitOfWorkOptions(), func); + } + + protected virtual async Task WithUnitOfWorkAsync(UnitOfWorkOptions options, Func action) + { + using (var scope = ServiceProvider.CreateScope()) + { + var uowManager = scope.ServiceProvider.GetRequiredService(); + + using (var uow = uowManager.Begin(options)) + { + await action(); + + await uow.CompleteAsync(); + } + } + } + + protected virtual TResult WithUnitOfWork(Func func) + { + return WithUnitOfWork(new UnitOfWorkOptions(), func); + } + + protected virtual TResult WithUnitOfWork(UnitOfWorkOptions options, Func func) + { + using (var scope = ServiceProvider.CreateScope()) + { + var uowManager = scope.ServiceProvider.GetRequiredService(); + + using (var uow = uowManager.Begin(options)) + { + var result = func(); + uow.Complete(); + return result; + } + } + } + + protected virtual Task WithUnitOfWorkAsync(Func> func) + { + return WithUnitOfWorkAsync(new UnitOfWorkOptions(), func); + } + + protected virtual async Task WithUnitOfWorkAsync(UnitOfWorkOptions options, Func> func) + { + using (var scope = ServiceProvider.CreateScope()) + { + var uowManager = scope.ServiceProvider.GetRequiredService(); + + using (var uow = uowManager.Begin(options)) + { + var result = await func(); + await uow.CompleteAsync(); + return result; + } + } + } + } +} diff --git a/samples/BookStore/test/Acme.BookStore.TestBase/BookStoreTestBaseModule.cs b/samples/BookStore/test/Acme.BookStore.TestBase/BookStoreTestBaseModule.cs new file mode 100644 index 0000000000..3674dd6503 --- /dev/null +++ b/samples/BookStore/test/Acme.BookStore.TestBase/BookStoreTestBaseModule.cs @@ -0,0 +1,48 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp; +using Volo.Abp.Authorization; +using Volo.Abp.Autofac; +using Volo.Abp.BackgroundJobs; +using Volo.Abp.Data; +using Volo.Abp.Modularity; +using Volo.Abp.Threading; + +namespace Acme.BookStore +{ + [DependsOn( + typeof(AbpAutofacModule), + typeof(AbpTestBaseModule), + typeof(AbpAuthorizationModule), + typeof(BookStoreDomainModule) + )] + public class BookStoreTestBaseModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.IsJobExecutionEnabled = false; + }); + + context.Services.AddAlwaysAllowAuthorization(); + } + + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + SeedTestData(context); + } + + private static void SeedTestData(ApplicationInitializationContext context) + { + AsyncHelper.RunSync(async () => + { + using (var scope = context.ServiceProvider.CreateScope()) + { + await scope.ServiceProvider + .GetRequiredService() + .SeedAsync(); + } + }); + } + } +} diff --git a/samples/BookStore/test/Acme.BookStore.Application.Tests/BookStoreTestDataBuilder.cs b/samples/BookStore/test/Acme.BookStore.TestBase/BookStoreTestDataSeedContributor.cs similarity index 61% rename from samples/BookStore/test/Acme.BookStore.Application.Tests/BookStoreTestDataBuilder.cs rename to samples/BookStore/test/Acme.BookStore.TestBase/BookStoreTestDataSeedContributor.cs index 4d31c1d4cb..eb11db2b11 100644 --- a/samples/BookStore/test/Acme.BookStore.Application.Tests/BookStoreTestDataBuilder.cs +++ b/samples/BookStore/test/Acme.BookStore.TestBase/BookStoreTestDataSeedContributor.cs @@ -3,34 +3,29 @@ using System.Threading.Tasks; using Volo.Abp.Data; using Volo.Abp.DependencyInjection; using Volo.Abp.Domain.Repositories; -using Volo.Abp.Identity; -using Volo.Abp.Threading; +using Volo.Abp.Guids; namespace Acme.BookStore { - public class BookStoreTestDataBuilder : ITransientDependency + public class BookStoreTestDataSeedContributor : IDataSeedContributor, ITransientDependency { - private readonly IDataSeeder _dataSeeder; private readonly IRepository _bookRepository; + private readonly IGuidGenerator _guidGenerator; - public BookStoreTestDataBuilder(IDataSeeder dataSeeder, IRepository bookRepository) + public BookStoreTestDataSeedContributor( + IRepository bookRepository, + IGuidGenerator guidGenerator) { - _dataSeeder = dataSeeder; _bookRepository = bookRepository; + _guidGenerator = guidGenerator; } - public void Build() + public async Task SeedAsync(DataSeedContext context) { - AsyncHelper.RunSync(BuildInternalAsync); - } - - public async Task BuildInternalAsync() - { - await _dataSeeder.SeedAsync(); await _bookRepository.InsertAsync( new Book { - Id = Guid.NewGuid(), + Id = _guidGenerator.Create(), Name = "Test book 1", Type = BookType.Fantastic, PublishDate = new DateTime(2015, 05, 24), @@ -41,7 +36,7 @@ namespace Acme.BookStore await _bookRepository.InsertAsync( new Book { - Id = Guid.NewGuid(), + Id = _guidGenerator.Create(), Name = "Test book 2", Type = BookType.Science, PublishDate = new DateTime(2014, 02, 11), diff --git a/samples/BookStore/test/Acme.BookStore.Web.Tests/Acme.BookStore.Web.Tests.csproj b/samples/BookStore/test/Acme.BookStore.Web.Tests/Acme.BookStore.Web.Tests.csproj index 263836714f..751672baee 100644 --- a/samples/BookStore/test/Acme.BookStore.Web.Tests/Acme.BookStore.Web.Tests.csproj +++ b/samples/BookStore/test/Acme.BookStore.Web.Tests/Acme.BookStore.Web.Tests.csproj @@ -14,10 +14,10 @@
    - + - + diff --git a/samples/BookStore/test/Acme.BookStore.Web.Tests/BookStoreWebTestModule.cs b/samples/BookStore/test/Acme.BookStore.Web.Tests/BookStoreWebTestModule.cs index efae3e3755..c544d97116 100644 --- a/samples/BookStore/test/Acme.BookStore.Web.Tests/BookStoreWebTestModule.cs +++ b/samples/BookStore/test/Acme.BookStore.Web.Tests/BookStoreWebTestModule.cs @@ -4,17 +4,13 @@ using Localization.Resources.AbpUi; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Localization; using Microsoft.AspNetCore.Mvc.ApplicationParts; -using Microsoft.AspNetCore.Mvc.Internal; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; -using Acme.BookStore.Localization.BookStore; -using Acme.BookStore.Menus; +using Acme.BookStore.Localization; +using Acme.BookStore.Web; +using Acme.BookStore.Web.Menus; using Volo.Abp; -using Volo.Abp.Account.Web; -using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic; -using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared; using Volo.Abp.AspNetCore.TestBase; -using Volo.Abp.Identity.Web; using Volo.Abp.Localization; using Volo.Abp.Localization.Resources.AbpValidation; using Volo.Abp.Modularity; @@ -24,10 +20,8 @@ namespace Acme.BookStore { [DependsOn( typeof(AbpAspNetCoreTestBaseModule), - typeof(BookStoreApplicationTestModule), - typeof(AbpIdentityWebModule), - typeof(AbpAccountWebModule), - typeof(AbpAspNetCoreMvcUiBasicThemeModule) + typeof(BookStoreWebModule), + typeof(BookStoreApplicationTestModule) )] public class BookStoreWebTestModule : AbpModule { diff --git a/samples/BookStore/test/Acme.BookStore.Web.Tests/Pages/Index_Tests.cs b/samples/BookStore/test/Acme.BookStore.Web.Tests/Pages/Index_Tests.cs new file mode 100644 index 0000000000..1964a8946e --- /dev/null +++ b/samples/BookStore/test/Acme.BookStore.Web.Tests/Pages/Index_Tests.cs @@ -0,0 +1,16 @@ +using System.Threading.Tasks; +using Shouldly; +using Xunit; + +namespace Acme.BookStore.Pages +{ + public class Index_Tests : BookStoreWebTestBase + { + [Fact] + public async Task Welcome_Page() + { + var response = await GetResponseAsStringAsync("/Books"); + response.ShouldNotBeNull(); + } + } +} diff --git a/samples/BookStore/test/Acme.BookStore.Web.Tests/Samples/SampleWebTest.cs b/samples/BookStore/test/Acme.BookStore.Web.Tests/Samples/SampleWebTest.cs deleted file mode 100644 index 2192ff8559..0000000000 --- a/samples/BookStore/test/Acme.BookStore.Web.Tests/Samples/SampleWebTest.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Threading.Tasks; -using Shouldly; -using Xunit; - -namespace Acme.BookStore.Samples -{ - public class SampleWebTest : BookStoreWebTestBase - { - [Fact(Skip = "This is disabled since not working")] - public async Task Welcome_Page() - { - var response = await GetResponseAsStringAsync("/"); - response.ShouldNotBeNull(); - } - - [Fact(Skip = "This is disabled since not working")] - public async Task Login_Page() - { - var response = await GetResponseAsStringAsync("/Account/Login/"); - response.ShouldNotBeNull(); - } - } -} diff --git a/samples/DashboardDemo/src/DashboardDemo.Domain/Localization/DashboardDemo/cs.json b/samples/DashboardDemo/src/DashboardDemo.Domain/Localization/DashboardDemo/cs.json new file mode 100644 index 0000000000..01438ba1e8 --- /dev/null +++ b/samples/DashboardDemo/src/DashboardDemo.Domain/Localization/DashboardDemo/cs.json @@ -0,0 +1,10 @@ +{ + "culture": "cs", + "texts": { + "Menu:Home": "Úvod", + "Welcome": "Vítejte", + "RolesInApplication": "Role v aplikaci", + "UserCount": "Počet uživatelů", + "LongWelcomeMessage": "Vítejte v aplikaci. Toto je startovací projekt založený na ABP frameworku. Pro více informací, navštivte abp.io." + } +} \ No newline at end of file diff --git a/samples/DashboardDemo/src/DashboardDemo.Domain/Localization/DashboardDemo/pl.json b/samples/DashboardDemo/src/DashboardDemo.Domain/Localization/DashboardDemo/pl.json new file mode 100644 index 0000000000..f1a26b3f9f --- /dev/null +++ b/samples/DashboardDemo/src/DashboardDemo.Domain/Localization/DashboardDemo/pl.json @@ -0,0 +1,10 @@ +{ + "culture": "pl", + "texts": { + "Menu:Home": "Home", + "Welcome": "Witaj", + "RolesInApplication": "Role w aplikacji", + "UserCount": "Ilość użytkowników", + "LongWelcomeMessage": "Witaj w aplikacji. To jest inicjalny projekt bazujący na ABP framework. Po więcej informacji odwiedź stronę abp.io." + } +} \ No newline at end of file diff --git a/samples/DashboardDemo/src/DashboardDemo.Domain/Localization/DashboardDemo/vi.json b/samples/DashboardDemo/src/DashboardDemo.Domain/Localization/DashboardDemo/vi.json new file mode 100644 index 0000000000..c629274a1b --- /dev/null +++ b/samples/DashboardDemo/src/DashboardDemo.Domain/Localization/DashboardDemo/vi.json @@ -0,0 +1,10 @@ +{ + "culture": "vi", + "texts": { + "Menu:Home": "Trang chủ", + "Welcome": "Xin chào bạn", + "RolesInApplication": "Vai trò trong ứng dụng", + "UserCount": "Số lượng người dùng", + "LongWelcomeMessage": "Chào mừng bạn đến ứng dụng. Đây là mẫu khởi động dự án dựa trên khung ABP. Để biết thêm thông tin, hãy truy cập abp.io." + } +} diff --git a/samples/DashboardDemo/src/DashboardDemo.Web/DashboardDemoWebModule.cs b/samples/DashboardDemo/src/DashboardDemo.Web/DashboardDemoWebModule.cs index e15e1245fd..c8d7bcc18b 100644 --- a/samples/DashboardDemo/src/DashboardDemo.Web/DashboardDemoWebModule.cs +++ b/samples/DashboardDemo/src/DashboardDemo.Web/DashboardDemoWebModule.cs @@ -159,6 +159,7 @@ namespace DashboardDemo typeof(AbpUiResource) ); + options.Languages.Add(new LanguageInfo("cs", "cs", "Čeština")); options.Languages.Add(new LanguageInfo("en", "en", "English")); options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português")); options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe")); diff --git a/samples/MicroserviceDemo/modules/product/src/ProductManagement.Application.Contracts/ProductManagement/Localization/ApplicationContracts/cs.json b/samples/MicroserviceDemo/modules/product/src/ProductManagement.Application.Contracts/ProductManagement/Localization/ApplicationContracts/cs.json new file mode 100644 index 0000000000..fb05fd06ac --- /dev/null +++ b/samples/MicroserviceDemo/modules/product/src/ProductManagement.Application.Contracts/ProductManagement/Localization/ApplicationContracts/cs.json @@ -0,0 +1,10 @@ +{ + "culture": "cs", + "texts": { + "Permission:ProductManagement": "Správa produktů", + "Permission:Products": "Produkty", + "Permission:Edit": "Upravit", + "Permission:Delete": "Smazat", + "Permission:Create": "Vytvořit" + } +} \ No newline at end of file diff --git a/samples/MicroserviceDemo/modules/product/src/ProductManagement.Application.Contracts/ProductManagement/Localization/ApplicationContracts/pl.json b/samples/MicroserviceDemo/modules/product/src/ProductManagement.Application.Contracts/ProductManagement/Localization/ApplicationContracts/pl.json new file mode 100644 index 0000000000..9181e35186 --- /dev/null +++ b/samples/MicroserviceDemo/modules/product/src/ProductManagement.Application.Contracts/ProductManagement/Localization/ApplicationContracts/pl.json @@ -0,0 +1,10 @@ +{ + "culture": "pl", + "texts": { + "Permission:ProductManagement": "Zarządzanie produktami", + "Permission:Products": "Produkty", + "Permission:Edit": "Edytuj", + "Permission:Delete": "Usuń", + "Permission:Create": "Utwórz" + } +} \ No newline at end of file diff --git a/samples/MicroserviceDemo/modules/product/src/ProductManagement.Application.Contracts/ProductManagement/Localization/ApplicationContracts/vi.json b/samples/MicroserviceDemo/modules/product/src/ProductManagement.Application.Contracts/ProductManagement/Localization/ApplicationContracts/vi.json new file mode 100644 index 0000000000..97cca61fd2 --- /dev/null +++ b/samples/MicroserviceDemo/modules/product/src/ProductManagement.Application.Contracts/ProductManagement/Localization/ApplicationContracts/vi.json @@ -0,0 +1,10 @@ +{ + "culture": "vi", + "texts": { + "Permission:ProductManagement": "Quản lý sản phẩm", + "Permission:Products": "Sản phẩm", + "Permission:Edit": "Sửa", + "Permission:Delete": "Xóa", + "Permission:Create": "Tạo" + } +} diff --git a/samples/MicroserviceDemo/modules/product/src/ProductManagement.Domain.Shared/ProductManagement.Domain.Shared.csproj b/samples/MicroserviceDemo/modules/product/src/ProductManagement.Domain.Shared/ProductManagement.Domain.Shared.csproj index e694ad7425..18c95e3826 100644 --- a/samples/MicroserviceDemo/modules/product/src/ProductManagement.Domain.Shared/ProductManagement.Domain.Shared.csproj +++ b/samples/MicroserviceDemo/modules/product/src/ProductManagement.Domain.Shared/ProductManagement.Domain.Shared.csproj @@ -7,6 +7,7 @@ + diff --git a/samples/MicroserviceDemo/modules/product/src/ProductManagement.Domain/ProductManagement/ProductStockCountChangedEto.cs b/samples/MicroserviceDemo/modules/product/src/ProductManagement.Domain.Shared/ProductManagement/ProductStockCountChangedEto.cs similarity index 100% rename from samples/MicroserviceDemo/modules/product/src/ProductManagement.Domain/ProductManagement/ProductStockCountChangedEto.cs rename to samples/MicroserviceDemo/modules/product/src/ProductManagement.Domain.Shared/ProductManagement/ProductStockCountChangedEto.cs diff --git a/samples/MicroserviceDemo/modules/product/src/ProductManagement.Domain/ProductManagement.Domain.csproj b/samples/MicroserviceDemo/modules/product/src/ProductManagement.Domain/ProductManagement.Domain.csproj index 217120e629..e6f75956c5 100644 --- a/samples/MicroserviceDemo/modules/product/src/ProductManagement.Domain/ProductManagement.Domain.csproj +++ b/samples/MicroserviceDemo/modules/product/src/ProductManagement.Domain/ProductManagement.Domain.csproj @@ -6,7 +6,6 @@ - diff --git a/samples/MicroserviceDemo/modules/product/src/ProductManagement.Domain/ProductManagement/Localization/Domain/cs.json b/samples/MicroserviceDemo/modules/product/src/ProductManagement.Domain/ProductManagement/Localization/Domain/cs.json new file mode 100644 index 0000000000..6a060a54c1 --- /dev/null +++ b/samples/MicroserviceDemo/modules/product/src/ProductManagement.Domain/ProductManagement/Localization/Domain/cs.json @@ -0,0 +1,6 @@ +{ + "culture": "cs", + "texts": { + + } +} \ No newline at end of file diff --git a/samples/MicroserviceDemo/modules/product/src/ProductManagement.Domain/ProductManagement/Localization/Domain/pl.json b/samples/MicroserviceDemo/modules/product/src/ProductManagement.Domain/ProductManagement/Localization/Domain/pl.json new file mode 100644 index 0000000000..2ea227cbf3 --- /dev/null +++ b/samples/MicroserviceDemo/modules/product/src/ProductManagement.Domain/ProductManagement/Localization/Domain/pl.json @@ -0,0 +1,6 @@ +{ + "culture": "pl", + "texts": { + + } +} \ No newline at end of file diff --git a/samples/MicroserviceDemo/modules/product/src/ProductManagement.Domain/ProductManagement/Localization/Domain/vi b/samples/MicroserviceDemo/modules/product/src/ProductManagement.Domain/ProductManagement/Localization/Domain/vi new file mode 100644 index 0000000000..d8eb5f3c75 --- /dev/null +++ b/samples/MicroserviceDemo/modules/product/src/ProductManagement.Domain/ProductManagement/Localization/Domain/vi @@ -0,0 +1,6 @@ +{ + "culture": "vi", + "texts": { + + } +} diff --git a/samples/MicroserviceDemo/modules/product/src/ProductManagement.Domain/ProductManagement/Localization/Domain/vi.json b/samples/MicroserviceDemo/modules/product/src/ProductManagement.Domain/ProductManagement/Localization/Domain/vi.json new file mode 100644 index 0000000000..d8eb5f3c75 --- /dev/null +++ b/samples/MicroserviceDemo/modules/product/src/ProductManagement.Domain/ProductManagement/Localization/Domain/vi.json @@ -0,0 +1,6 @@ +{ + "culture": "vi", + "texts": { + + } +} diff --git a/samples/MicroserviceDemo/modules/product/src/ProductManagement.Web/Localization/Resources/ProductManagement/cs.json b/samples/MicroserviceDemo/modules/product/src/ProductManagement.Web/Localization/Resources/ProductManagement/cs.json new file mode 100644 index 0000000000..489699d9a6 --- /dev/null +++ b/samples/MicroserviceDemo/modules/product/src/ProductManagement.Web/Localization/Resources/ProductManagement/cs.json @@ -0,0 +1,16 @@ +{ + "culture": "cs", + "texts": { + "Menu:ProductManagement": "Správa produktů", + "Menu:Products": "Produkty", + "ProductManagement": "Správa produktů", + "CreateANewProduct": "Vytvořit nový produkt", + "Products": "Produkty", + "StockCount": "Skladem", + "Code": "Kód", + "Name": "Název", + "Price": "Cena", + "ImageName": "Název obrázku", + "ProductDeletionWarningMessage": "Opravdu chcete smazat tento produkt?" + } +} \ No newline at end of file diff --git a/samples/MicroserviceDemo/modules/product/src/ProductManagement.Web/Localization/Resources/ProductManagement/pl.json b/samples/MicroserviceDemo/modules/product/src/ProductManagement.Web/Localization/Resources/ProductManagement/pl.json new file mode 100644 index 0000000000..5828dd8942 --- /dev/null +++ b/samples/MicroserviceDemo/modules/product/src/ProductManagement.Web/Localization/Resources/ProductManagement/pl.json @@ -0,0 +1,16 @@ +{ + "culture": "pl", + "texts": { + "Menu:ProductManagement": "Zarządzanie produktami", + "Menu:Products": "Produkty", + "ProductManagement": "Zarządzanie produktami", + "CreateANewProduct": "Utwórz nowy produkt", + "Products": "Produkty", + "StockCount": "Ilość na magazynie", + "Code": "Kod", + "Name": "Nazwa", + "Price": "Cena", + "ImageName": "Nazwa obrazka", + "ProductDeletionWarningMessage": "Czy jesteś pewien, że chcesz usunąć ten produkt?" + } +} \ No newline at end of file diff --git a/samples/MicroserviceDemo/modules/product/src/ProductManagement.Web/Localization/Resources/ProductManagement/vi.json b/samples/MicroserviceDemo/modules/product/src/ProductManagement.Web/Localization/Resources/ProductManagement/vi.json new file mode 100644 index 0000000000..6b51506813 --- /dev/null +++ b/samples/MicroserviceDemo/modules/product/src/ProductManagement.Web/Localization/Resources/ProductManagement/vi.json @@ -0,0 +1,16 @@ +{ + "culture": "vi", + "texts": { + "Menu:ProductManagement": "Quản lý sản phẩm", + "Menu:Products": "Sản phẩm", + "ProductManagement": "Quản lý sản phẩm", + "CreateANewProduct": "Tạo một sản phẩm mới", + "Products": "Sản phẩm", + "StockCount": "Số chứng khoán", + "Code": "Mã", + "Name": "Tên", + "Price": "Giá", + "ImageName": "Tên ảnh", + "ProductDeletionWarningMessage": "Bạn có chắc chắn muốn xóa sản phẩm này?" + } +} diff --git a/templates/mvc-module/MyCompanyName.MyProjectName.sln b/templates/mvc-module/MyCompanyName.MyProjectName.sln index 9ca4ac6631..ea7d59fe2c 100644 --- a/templates/mvc-module/MyCompanyName.MyProjectName.sln +++ b/templates/mvc-module/MyCompanyName.MyProjectName.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.29001.49 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MyCompanyName.MyProjectName.Domain.Shared", "src\MyCompanyName.MyProjectName.Domain.Shared\MyCompanyName.MyProjectName.Domain.Shared.csproj", "{D64C1577-4929-4B60-939E-96DE1534891A}" EndProject @@ -13,7 +13,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MyCompanyName.MyProjectName EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{649A3FFA-182F-4E56-9717-E6A9A2BEC545}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{CCD2960C-23CC-4AB4-B84D-60C7AAA52F4D}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{CCD2960C-23CC-4AB4-B84D-60C7AAA52F4D}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "host", "host", "{E400416D-2895-4512-9D17-90681EEC7E0A}" EndProject diff --git a/templates/mvc-module/host/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj b/templates/mvc-module/host/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj index 9e51bd05cf..d6436852b6 100644 --- a/templates/mvc-module/host/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj +++ b/templates/mvc-module/host/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj @@ -14,7 +14,7 @@ - + diff --git a/templates/mvc-module/host/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs b/templates/mvc-module/host/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs index 97d3f7b847..2a330c49a8 100644 --- a/templates/mvc-module/host/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs +++ b/templates/mvc-module/host/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs @@ -71,6 +71,7 @@ namespace MyCompanyName.MyProjectName Configure(options => { + options.Languages.Add(new LanguageInfo("cs", "cs", "Čeština")); options.Languages.Add(new LanguageInfo("en", "en", "English")); options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português")); options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe")); diff --git a/templates/mvc-module/host/MyCompanyName.MyProjectName.IdentityServer/MyCompanyName.MyProjectName.IdentityServer.csproj b/templates/mvc-module/host/MyCompanyName.MyProjectName.IdentityServer/MyCompanyName.MyProjectName.IdentityServer.csproj index b1d532024c..cdf7bcb65e 100644 --- a/templates/mvc-module/host/MyCompanyName.MyProjectName.IdentityServer/MyCompanyName.MyProjectName.IdentityServer.csproj +++ b/templates/mvc-module/host/MyCompanyName.MyProjectName.IdentityServer/MyCompanyName.MyProjectName.IdentityServer.csproj @@ -12,7 +12,7 @@ - + diff --git a/templates/mvc-module/host/MyCompanyName.MyProjectName.IdentityServer/MyProjectNameIdentityServerModule.cs b/templates/mvc-module/host/MyCompanyName.MyProjectName.IdentityServer/MyProjectNameIdentityServerModule.cs index 9730db7df2..065f35e613 100644 --- a/templates/mvc-module/host/MyCompanyName.MyProjectName.IdentityServer/MyProjectNameIdentityServerModule.cs +++ b/templates/mvc-module/host/MyCompanyName.MyProjectName.IdentityServer/MyProjectNameIdentityServerModule.cs @@ -79,6 +79,7 @@ namespace MyCompanyName.MyProjectName Configure(options => { + options.Languages.Add(new LanguageInfo("cs", "cs", "Čeština")); options.Languages.Add(new LanguageInfo("en", "en", "English")); options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português")); options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe")); diff --git a/templates/mvc-module/host/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj b/templates/mvc-module/host/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj index 8a5fb3e236..dd7ba84dbd 100644 --- a/templates/mvc-module/host/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj +++ b/templates/mvc-module/host/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj @@ -14,7 +14,7 @@ - + diff --git a/templates/mvc-module/host/MyCompanyName.MyProjectName.Web.Host/MyProjectNameWebHostModule.cs b/templates/mvc-module/host/MyCompanyName.MyProjectName.Web.Host/MyProjectNameWebHostModule.cs index 57ea05c73e..ea15dd040b 100644 --- a/templates/mvc-module/host/MyCompanyName.MyProjectName.Web.Host/MyProjectNameWebHostModule.cs +++ b/templates/mvc-module/host/MyCompanyName.MyProjectName.Web.Host/MyProjectNameWebHostModule.cs @@ -10,6 +10,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.IdentityModel.Protocols.OpenIdConnect; using MyCompanyName.MyProjectName.Localization; using MyCompanyName.MyProjectName.MultiTenancy; +using MyCompanyName.MyProjectName.Web; using StackExchange.Redis; using Volo.Abp; using Volo.Abp.AspNetCore.Authentication.OAuth; @@ -149,8 +150,6 @@ namespace MyCompanyName.MyProjectName { Configure(options => { - options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}MyCompanyName.MyProjectName.Domain", Path.DirectorySeparatorChar))); - options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}MyCompanyName.MyProjectName.Application.Contracts", Path.DirectorySeparatorChar))); // options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}framework{0}src{0}Volo.Abp.UI", Path.DirectorySeparatorChar))); options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}framework{0}src{0}Volo.Abp.AspNetCore.Mvc.UI", Path.DirectorySeparatorChar))); @@ -160,6 +159,9 @@ namespace MyCompanyName.MyProjectName options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}modules{0}permission-management{0}src{0}Volo.Abp.PermissionManagement.Web", Path.DirectorySeparatorChar))); options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}modules{0}identity{0}src{0}Volo.Abp.Identity.Web", Path.DirectorySeparatorChar))); // + options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}MyCompanyName.MyProjectName.Domain", Path.DirectorySeparatorChar))); + options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}MyCompanyName.MyProjectName.Application.Contracts", Path.DirectorySeparatorChar))); + options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}MyCompanyName.MyProjectName.Web", Path.DirectorySeparatorChar))); }); } } diff --git a/templates/mvc-module/host/MyCompanyName.MyProjectName.Web.Unified/MyProjectNameWebUnifiedModule.cs b/templates/mvc-module/host/MyCompanyName.MyProjectName.Web.Unified/MyProjectNameWebUnifiedModule.cs index afe103d632..76ae5ef988 100644 --- a/templates/mvc-module/host/MyCompanyName.MyProjectName.Web.Unified/MyProjectNameWebUnifiedModule.cs +++ b/templates/mvc-module/host/MyCompanyName.MyProjectName.Web.Unified/MyProjectNameWebUnifiedModule.cs @@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.DependencyInjection; using MyCompanyName.MyProjectName.EntityFrameworkCore; using MyCompanyName.MyProjectName.MultiTenancy; +using MyCompanyName.MyProjectName.Web; using Swashbuckle.AspNetCore.Swagger; using Volo.Abp; using Volo.Abp.Account.Web; @@ -68,10 +69,10 @@ namespace MyCompanyName.MyProjectName { Configure(options => { - options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}MyCompanyName.MyProjectName.Domain", Path.DirectorySeparatorChar))); options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}MyCompanyName.MyProjectName.Domain.Shared", Path.DirectorySeparatorChar))); - options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}MyCompanyName.MyProjectName.Application", Path.DirectorySeparatorChar))); + options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}MyCompanyName.MyProjectName.Domain", Path.DirectorySeparatorChar))); options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}MyCompanyName.MyProjectName.Application.Contracts", Path.DirectorySeparatorChar))); + options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}MyCompanyName.MyProjectName.Application", Path.DirectorySeparatorChar))); options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}MyCompanyName.MyProjectName.Web", Path.DirectorySeparatorChar))); }); } @@ -86,8 +87,9 @@ namespace MyCompanyName.MyProjectName Configure(options => { + options.Languages.Add(new LanguageInfo("cs", "cs", "Čeština")); options.Languages.Add(new LanguageInfo("en", "en", "English")); - options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Portuguese (Brazilian)")); + options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português (Brasil)")); options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe")); options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "Chinese")); }); diff --git a/templates/mvc-module/src/MyCompanyName.MyProjectName.Application.Contracts/Localization/MyProjectName/ApplicationContracts/cs.json b/templates/mvc-module/src/MyCompanyName.MyProjectName.Application.Contracts/Localization/MyProjectName/ApplicationContracts/cs.json new file mode 100644 index 0000000000..a0373003c8 --- /dev/null +++ b/templates/mvc-module/src/MyCompanyName.MyProjectName.Application.Contracts/Localization/MyProjectName/ApplicationContracts/cs.json @@ -0,0 +1,6 @@ +{ + "culture": "cs", + "texts": { + "Permission:MyProjectName": "MyProjectName" + } +} \ No newline at end of file diff --git a/templates/mvc-module/src/MyCompanyName.MyProjectName.Application.Contracts/Localization/MyProjectName/ApplicationContracts/pl.json b/templates/mvc-module/src/MyCompanyName.MyProjectName.Application.Contracts/Localization/MyProjectName/ApplicationContracts/pl.json new file mode 100644 index 0000000000..3b93a2b580 --- /dev/null +++ b/templates/mvc-module/src/MyCompanyName.MyProjectName.Application.Contracts/Localization/MyProjectName/ApplicationContracts/pl.json @@ -0,0 +1,6 @@ +{ + "culture": "pl", + "texts": { + "Permission:MyProjectName": "MyProjectName" + } +} \ No newline at end of file diff --git a/templates/mvc-module/src/MyCompanyName.MyProjectName.Application.Contracts/Localization/MyProjectName/ApplicationContracts/pt-BR.json b/templates/mvc-module/src/MyCompanyName.MyProjectName.Application.Contracts/Localization/MyProjectName/ApplicationContracts/pt-BR.json new file mode 100644 index 0000000000..958055dcd5 --- /dev/null +++ b/templates/mvc-module/src/MyCompanyName.MyProjectName.Application.Contracts/Localization/MyProjectName/ApplicationContracts/pt-BR.json @@ -0,0 +1,6 @@ +{ + "culture": "pt-BR", + "texts": { + "Permission:MyProjectName": "MyProjectName" + } +} \ No newline at end of file diff --git a/templates/mvc-module/src/MyCompanyName.MyProjectName.Application.Contracts/Localization/MyProjectName/ApplicationContracts/vi.json b/templates/mvc-module/src/MyCompanyName.MyProjectName.Application.Contracts/Localization/MyProjectName/ApplicationContracts/vi.json new file mode 100644 index 0000000000..a60afc038e --- /dev/null +++ b/templates/mvc-module/src/MyCompanyName.MyProjectName.Application.Contracts/Localization/MyProjectName/ApplicationContracts/vi.json @@ -0,0 +1,6 @@ +{ + "culture": "vi", + "texts": { + "Permission:MyProjectName": "TenDuAnCuaBan" + } +} diff --git a/templates/mvc-module/src/MyCompanyName.MyProjectName.Application/MyProjectNameAppServiceBase.cs b/templates/mvc-module/src/MyCompanyName.MyProjectName.Application/MyProjectNameAppService.cs similarity index 65% rename from templates/mvc-module/src/MyCompanyName.MyProjectName.Application/MyProjectNameAppServiceBase.cs rename to templates/mvc-module/src/MyCompanyName.MyProjectName.Application/MyProjectNameAppService.cs index e54468cb79..31bfbeb0de 100644 --- a/templates/mvc-module/src/MyCompanyName.MyProjectName.Application/MyProjectNameAppServiceBase.cs +++ b/templates/mvc-module/src/MyCompanyName.MyProjectName.Application/MyProjectNameAppService.cs @@ -3,9 +3,9 @@ using Volo.Abp.Application.Services; namespace MyCompanyName.MyProjectName { - public abstract class MyProjectNameAppServiceBase : ApplicationService + public abstract class MyProjectNameAppService : ApplicationService { - protected MyProjectNameAppServiceBase() + protected MyProjectNameAppService() { LocalizationResource = typeof(MyProjectNameResource); } diff --git a/templates/mvc-module/src/MyCompanyName.MyProjectName.Application/Samples/SampleAppService.cs b/templates/mvc-module/src/MyCompanyName.MyProjectName.Application/Samples/SampleAppService.cs index d193c3f895..f34b7771bd 100644 --- a/templates/mvc-module/src/MyCompanyName.MyProjectName.Application/Samples/SampleAppService.cs +++ b/templates/mvc-module/src/MyCompanyName.MyProjectName.Application/Samples/SampleAppService.cs @@ -3,7 +3,7 @@ using Microsoft.AspNetCore.Authorization; namespace MyCompanyName.MyProjectName.Samples { - public class SampleAppService : MyProjectNameAppServiceBase, ISampleAppService + public class SampleAppService : MyProjectNameAppService, ISampleAppService { public Task GetAsync() { diff --git a/templates/mvc-module/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/DomainShared/cs.json b/templates/mvc-module/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/DomainShared/cs.json new file mode 100644 index 0000000000..6a060a54c1 --- /dev/null +++ b/templates/mvc-module/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/DomainShared/cs.json @@ -0,0 +1,6 @@ +{ + "culture": "cs", + "texts": { + + } +} \ No newline at end of file diff --git a/templates/mvc-module/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/DomainShared/pl.json b/templates/mvc-module/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/DomainShared/pl.json new file mode 100644 index 0000000000..2ea227cbf3 --- /dev/null +++ b/templates/mvc-module/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/DomainShared/pl.json @@ -0,0 +1,6 @@ +{ + "culture": "pl", + "texts": { + + } +} \ No newline at end of file diff --git a/templates/mvc-module/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/DomainShared/pt-BR.json b/templates/mvc-module/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/DomainShared/pt-BR.json new file mode 100644 index 0000000000..6d746df04c --- /dev/null +++ b/templates/mvc-module/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/DomainShared/pt-BR.json @@ -0,0 +1,6 @@ +{ + "culture": "pt-BR", + "texts": { + + } +} \ No newline at end of file diff --git a/templates/mvc-module/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/DomainShared/vi.json b/templates/mvc-module/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/DomainShared/vi.json new file mode 100644 index 0000000000..d8eb5f3c75 --- /dev/null +++ b/templates/mvc-module/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/DomainShared/vi.json @@ -0,0 +1,6 @@ +{ + "culture": "vi", + "texts": { + + } +} diff --git a/templates/mvc-module/src/MyCompanyName.MyProjectName.HttpApi/MyProjectNameControllerBase.cs b/templates/mvc-module/src/MyCompanyName.MyProjectName.HttpApi/MyProjectNameController.cs similarity index 66% rename from templates/mvc-module/src/MyCompanyName.MyProjectName.HttpApi/MyProjectNameControllerBase.cs rename to templates/mvc-module/src/MyCompanyName.MyProjectName.HttpApi/MyProjectNameController.cs index f447b65456..1dd9a6c8b2 100644 --- a/templates/mvc-module/src/MyCompanyName.MyProjectName.HttpApi/MyProjectNameControllerBase.cs +++ b/templates/mvc-module/src/MyCompanyName.MyProjectName.HttpApi/MyProjectNameController.cs @@ -3,9 +3,9 @@ using Volo.Abp.AspNetCore.Mvc; namespace MyCompanyName.MyProjectName { - public class MyProjectNameControllerBase : AbpController + public abstract class MyProjectNameController : AbpController { - public MyProjectNameControllerBase() + protected MyProjectNameController() { LocalizationResource = typeof(MyProjectNameResource); } diff --git a/templates/mvc-module/src/MyCompanyName.MyProjectName.HttpApi/Samples/SampleController.cs b/templates/mvc-module/src/MyCompanyName.MyProjectName.HttpApi/Samples/SampleController.cs index 7c4de3b65e..1bf34c32c4 100644 --- a/templates/mvc-module/src/MyCompanyName.MyProjectName.HttpApi/Samples/SampleController.cs +++ b/templates/mvc-module/src/MyCompanyName.MyProjectName.HttpApi/Samples/SampleController.cs @@ -7,7 +7,7 @@ namespace MyCompanyName.MyProjectName.Samples { [RemoteService] [Route("api/MyProjectName/sample")] - public class SampleController : MyProjectNameControllerBase, ISampleAppService + public class SampleController : MyProjectNameController, ISampleAppService { private readonly ISampleAppService _sampleAppService; diff --git a/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Localization/MyProjectName/Web/cs.json b/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Localization/MyProjectName/Web/cs.json new file mode 100644 index 0000000000..6a060a54c1 --- /dev/null +++ b/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Localization/MyProjectName/Web/cs.json @@ -0,0 +1,6 @@ +{ + "culture": "cs", + "texts": { + + } +} \ No newline at end of file diff --git a/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Localization/MyProjectName/Web/pl.json b/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Localization/MyProjectName/Web/pl.json new file mode 100644 index 0000000000..2ea227cbf3 --- /dev/null +++ b/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Localization/MyProjectName/Web/pl.json @@ -0,0 +1,6 @@ +{ + "culture": "pl", + "texts": { + + } +} \ No newline at end of file diff --git a/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Localization/MyProjectName/Web/pt-BR.json b/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Localization/MyProjectName/Web/pt-BR.json new file mode 100644 index 0000000000..6d746df04c --- /dev/null +++ b/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Localization/MyProjectName/Web/pt-BR.json @@ -0,0 +1,6 @@ +{ + "culture": "pt-BR", + "texts": { + + } +} \ No newline at end of file diff --git a/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Localization/MyProjectName/Web/vi.json b/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Localization/MyProjectName/Web/vi.json new file mode 100644 index 0000000000..d8eb5f3c75 --- /dev/null +++ b/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Localization/MyProjectName/Web/vi.json @@ -0,0 +1,6 @@ +{ + "culture": "vi", + "texts": { + + } +} diff --git a/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj b/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj index 384116e607..bf055b7d8b 100644 --- a/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj +++ b/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj @@ -7,7 +7,7 @@ $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; true Library - MyCompanyName.MyProjectName + MyCompanyName.MyProjectName.Web diff --git a/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/MyProjectNameMenuContributor.cs b/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/MyProjectNameMenuContributor.cs index b844d86ae2..3d63d39465 100644 --- a/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/MyProjectNameMenuContributor.cs +++ b/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/MyProjectNameMenuContributor.cs @@ -1,7 +1,7 @@ using System.Threading.Tasks; using Volo.Abp.UI.Navigation; -namespace MyCompanyName.MyProjectName +namespace MyCompanyName.MyProjectName.Web { public class MyProjectNameMenuContributor : IMenuContributor { diff --git a/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebAutoMapperProfile.cs b/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebAutoMapperProfile.cs index 2ff3773dc4..980df394b5 100644 --- a/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebAutoMapperProfile.cs +++ b/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebAutoMapperProfile.cs @@ -1,6 +1,6 @@ using AutoMapper; -namespace MyCompanyName.MyProjectName +namespace MyCompanyName.MyProjectName.Web { public class MyProjectNameWebAutoMapperProfile : Profile { diff --git a/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs b/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs index fb8e71f4ea..527dfa91b8 100644 --- a/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs +++ b/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs @@ -10,7 +10,7 @@ using Volo.Abp.Modularity; using Volo.Abp.UI.Navigation; using Volo.Abp.VirtualFileSystem; -namespace MyCompanyName.MyProjectName +namespace MyCompanyName.MyProjectName.Web { [DependsOn( typeof(MyProjectNameHttpApiModule), diff --git a/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectName/Index.cshtml b/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectName/Index.cshtml new file mode 100644 index 0000000000..0ef7562269 --- /dev/null +++ b/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectName/Index.cshtml @@ -0,0 +1,7 @@ +@page +@inherits MyCompanyName.MyProjectName.Web.Pages.MyProjectNamePage +@model MyCompanyName.MyProjectName.Web.Pages.MyProjectName.IndexModel +@{ +} +

    MyProjectName

    +

    A sample page for the MyProjectName module.

    \ No newline at end of file diff --git a/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectName/Index.cshtml.cs b/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectName/Index.cshtml.cs new file mode 100644 index 0000000000..a9c43a1c88 --- /dev/null +++ b/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectName/Index.cshtml.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; + +namespace MyCompanyName.MyProjectName.Web.Pages.MyProjectName +{ + public class IndexModel : PageModel + { + public void OnGet() + { + } + } +} \ No newline at end of file diff --git a/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectNamePage.cs b/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectNamePage.cs new file mode 100644 index 0000000000..5fe044221d --- /dev/null +++ b/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectNamePage.cs @@ -0,0 +1,16 @@ +using Microsoft.AspNetCore.Mvc.Localization; +using Microsoft.AspNetCore.Mvc.Razor.Internal; +using MyCompanyName.MyProjectName.Localization; +using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; + +namespace MyCompanyName.MyProjectName.Web.Pages +{ + /* Inherit your UI Pages from this class. To do that, add this line to your Pages (.cshtml files under the Page folder): + * @inherits MyCompanyName.MyProjectName.Web.Pages.MyProjectNamePage + */ + public abstract class MyProjectNamePage : AbpPage + { + [RazorInject] + public IHtmlLocalizer L { get; set; } + } +} diff --git a/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectNamePageModel.cs b/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectNamePageModel.cs new file mode 100644 index 0000000000..d0b9c04a45 --- /dev/null +++ b/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectNamePageModel.cs @@ -0,0 +1,15 @@ +using MyCompanyName.MyProjectName.Localization; +using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; + +namespace MyCompanyName.MyProjectName.Web.Pages +{ + /* Inherit your PageModel classes from this class. + */ + public abstract class MyProjectNamePageModel : AbpPageModel + { + protected MyProjectNamePageModel() + { + LocalizationResourceType = typeof(MyProjectNameResource); + } + } +} \ No newline at end of file diff --git a/templates/mvc-module/test/MyCompanyName.MyProjectName.Application.Tests/MyCompanyName.MyProjectName.Application.Tests.csproj b/templates/mvc-module/test/MyCompanyName.MyProjectName.Application.Tests/MyCompanyName.MyProjectName.Application.Tests.csproj index bfefdfcbfd..22898fcde0 100644 --- a/templates/mvc-module/test/MyCompanyName.MyProjectName.Application.Tests/MyCompanyName.MyProjectName.Application.Tests.csproj +++ b/templates/mvc-module/test/MyCompanyName.MyProjectName.Application.Tests/MyCompanyName.MyProjectName.Application.Tests.csproj @@ -13,7 +13,7 @@
    - + diff --git a/templates/mvc-module/test/MyCompanyName.MyProjectName.Domain.Tests/MyCompanyName.MyProjectName.Domain.Tests.csproj b/templates/mvc-module/test/MyCompanyName.MyProjectName.Domain.Tests/MyCompanyName.MyProjectName.Domain.Tests.csproj index 68328a77a1..2b2fd34bea 100644 --- a/templates/mvc-module/test/MyCompanyName.MyProjectName.Domain.Tests/MyCompanyName.MyProjectName.Domain.Tests.csproj +++ b/templates/mvc-module/test/MyCompanyName.MyProjectName.Domain.Tests/MyCompanyName.MyProjectName.Domain.Tests.csproj @@ -8,7 +8,7 @@ - + diff --git a/templates/mvc-module/test/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests.csproj b/templates/mvc-module/test/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests.csproj index 7a05b65e55..3b0c247ddf 100644 --- a/templates/mvc-module/test/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests.csproj +++ b/templates/mvc-module/test/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests.csproj @@ -8,7 +8,7 @@ - + diff --git a/templates/mvc-module/test/MyCompanyName.MyProjectName.MongoDB.Tests/MyCompanyName.MyProjectName.MongoDB.Tests.csproj b/templates/mvc-module/test/MyCompanyName.MyProjectName.MongoDB.Tests/MyCompanyName.MyProjectName.MongoDB.Tests.csproj index e71954d6a3..8ddb93bfdc 100644 --- a/templates/mvc-module/test/MyCompanyName.MyProjectName.MongoDB.Tests/MyCompanyName.MyProjectName.MongoDB.Tests.csproj +++ b/templates/mvc-module/test/MyCompanyName.MyProjectName.MongoDB.Tests/MyCompanyName.MyProjectName.MongoDB.Tests.csproj @@ -8,7 +8,7 @@ - + diff --git a/templates/mvc-module/test/MyCompanyName.MyProjectName.TestBase/MyCompanyName.MyProjectName.TestBase.csproj b/templates/mvc-module/test/MyCompanyName.MyProjectName.TestBase/MyCompanyName.MyProjectName.TestBase.csproj index 1481ea0ad4..4e2b8b1ed4 100644 --- a/templates/mvc-module/test/MyCompanyName.MyProjectName.TestBase/MyCompanyName.MyProjectName.TestBase.csproj +++ b/templates/mvc-module/test/MyCompanyName.MyProjectName.TestBase/MyCompanyName.MyProjectName.TestBase.csproj @@ -8,7 +8,7 @@ - + diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.Application/MyProjectNameAppService.cs b/templates/mvc/src/MyCompanyName.MyProjectName.Application/MyProjectNameAppService.cs new file mode 100644 index 0000000000..8cf7cca603 --- /dev/null +++ b/templates/mvc/src/MyCompanyName.MyProjectName.Application/MyProjectNameAppService.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Text; +using MyCompanyName.MyProjectName.Localization; +using Volo.Abp.Application.Services; + +namespace MyCompanyName.MyProjectName +{ + /* Inherit your application services from this class. + */ + public abstract class MyProjectNameAppService : ApplicationService + { + protected MyProjectNameAppService() + { + LocalizationResource = typeof(MyProjectNameResource); + } + } +} diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.DbMigrator/MyCompanyName.MyProjectName.DbMigrator.csproj b/templates/mvc/src/MyCompanyName.MyProjectName.DbMigrator/MyCompanyName.MyProjectName.DbMigrator.csproj index cde37075a3..81c032e17f 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.DbMigrator/MyCompanyName.MyProjectName.DbMigrator.csproj +++ b/templates/mvc/src/MyCompanyName.MyProjectName.DbMigrator/MyCompanyName.MyProjectName.DbMigrator.csproj @@ -19,6 +19,7 @@ + diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/cs.json b/templates/mvc/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/cs.json new file mode 100644 index 0000000000..619521939c --- /dev/null +++ b/templates/mvc/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/cs.json @@ -0,0 +1,8 @@ +{ + "culture": "cs", + "texts": { + "Menu:Home": "Úvod", + "Welcome": "Vítejte", + "LongWelcomeMessage": "Vítejte v aplikaci. Toto je startovací projekt založený na ABP frameworku. Pro více informací, navštivte abp.io." + } +} \ No newline at end of file diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/pl.json b/templates/mvc/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/pl.json new file mode 100644 index 0000000000..815bbcc83f --- /dev/null +++ b/templates/mvc/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/pl.json @@ -0,0 +1,8 @@ +{ + "culture": "pl", + "texts": { + "Menu:Home": "Home", + "Welcome": "Witaj", + "LongWelcomeMessage": "Witaj w aplikacji. To jest inicjalny projekt bazujący na ABP framework. Po więcej informacji odwiedź stronę abp.io." + } +} \ No newline at end of file diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/vi.json b/templates/mvc/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/vi.json new file mode 100644 index 0000000000..c115a35726 --- /dev/null +++ b/templates/mvc/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/vi.json @@ -0,0 +1,8 @@ +{ + "culture": "vi", + "texts": { + "Menu:Home": "Trang chủ", + "Welcome": "Chào mừng bạn", + "LongWelcomeMessage": "Chào mừng bạn đến ứng dụng. Đây là một dự án khởi nghiệp dựa trên khung ABP. Để biết thêm thông tin, hãy truy cập abp.io." + } +} diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj b/templates/mvc/src/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj index e719e8aeb5..d68c13bc6b 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj +++ b/templates/mvc/src/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj @@ -15,7 +15,7 @@ - + diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs b/templates/mvc/src/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs index ca5a3e6773..7cd698a711 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs +++ b/templates/mvc/src/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs @@ -89,6 +89,7 @@ namespace MyCompanyName.MyProjectName { Configure(options => { + options.Languages.Add(new LanguageInfo("cs", "cs", "Čeština")); options.Languages.Add(new LanguageInfo("en", "en", "English")); options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português")); options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe")); diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.HttpApi/Controllers/MyProjectNameController.cs b/templates/mvc/src/MyCompanyName.MyProjectName.HttpApi/Controllers/MyProjectNameController.cs index c80e008681..7fff0ecbc5 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.HttpApi/Controllers/MyProjectNameController.cs +++ b/templates/mvc/src/MyCompanyName.MyProjectName.HttpApi/Controllers/MyProjectNameController.cs @@ -3,6 +3,8 @@ using Volo.Abp.AspNetCore.Mvc; namespace MyCompanyName.MyProjectName.Controllers { + /* Inherit your controllers from this class. + */ public abstract class MyProjectNameController : AbpController { protected MyProjectNameController() diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.IdentityServer/MyCompanyName.MyProjectName.IdentityServer.csproj b/templates/mvc/src/MyCompanyName.MyProjectName.IdentityServer/MyCompanyName.MyProjectName.IdentityServer.csproj index 26947c4d19..8c18d8a43e 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.IdentityServer/MyCompanyName.MyProjectName.IdentityServer.csproj +++ b/templates/mvc/src/MyCompanyName.MyProjectName.IdentityServer/MyCompanyName.MyProjectName.IdentityServer.csproj @@ -5,6 +5,12 @@ netcoreapp2.2 MyCompanyName.MyProjectName + $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; + true + true + true + true + false @@ -14,18 +20,13 @@ - - - - - - + diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.IdentityServer/MyProjectNameIdentityServerModule.cs b/templates/mvc/src/MyCompanyName.MyProjectName.IdentityServer/MyProjectNameIdentityServerModule.cs index 588e62dba9..8b294109fc 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.IdentityServer/MyProjectNameIdentityServerModule.cs +++ b/templates/mvc/src/MyCompanyName.MyProjectName.IdentityServer/MyProjectNameIdentityServerModule.cs @@ -46,6 +46,7 @@ namespace MyCompanyName.MyProjectName typeof(AbpUiResource) ); + options.Languages.Add(new LanguageInfo("cs", "cs", "Čeština")); options.Languages.Add(new LanguageInfo("en", "en", "English")); options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português")); options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe")); diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/Menus/MyProjectNameMenuContributor.cs b/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/Menus/MyProjectNameMenuContributor.cs index 3c1f22206a..5f158525f3 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/Menus/MyProjectNameMenuContributor.cs +++ b/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/Menus/MyProjectNameMenuContributor.cs @@ -6,7 +6,7 @@ using MyCompanyName.MyProjectName.MultiTenancy; using Volo.Abp.TenantManagement.Web.Navigation; using Volo.Abp.UI.Navigation; -namespace MyCompanyName.MyProjectName.Menus +namespace MyCompanyName.MyProjectName.Web.Menus { public class MyProjectNameMenuContributor : IMenuContributor { diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj b/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj index b1fef7b208..4d9d970ace 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj +++ b/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj @@ -4,7 +4,13 @@ netcoreapp2.2 - MyCompanyName.MyProjectName + MyCompanyName.MyProjectName.Web + $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; + true + true + true + true + false @@ -14,7 +20,7 @@ - + diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/MyProjectNameBrandingProvider.cs b/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/MyProjectNameBrandingProvider.cs index aba2d3920e..ce09452496 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/MyProjectNameBrandingProvider.cs +++ b/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/MyProjectNameBrandingProvider.cs @@ -1,7 +1,7 @@ using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Components; using Volo.Abp.DependencyInjection; -namespace MyCompanyName.MyProjectName +namespace MyCompanyName.MyProjectName.Web { [Dependency(ReplaceServices = true)] public class MyProjectNameBrandingProvider : DefaultBrandingProvider diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/MyProjectNameWebAutoMapperProfile.cs b/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/MyProjectNameWebAutoMapperProfile.cs index b8069ae329..e728b8a6e7 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/MyProjectNameWebAutoMapperProfile.cs +++ b/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/MyProjectNameWebAutoMapperProfile.cs @@ -1,6 +1,6 @@ using AutoMapper; -namespace MyCompanyName.MyProjectName +namespace MyCompanyName.MyProjectName.Web { public class MyProjectNameWebAutoMapperProfile : Profile { diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/MyProjectNameWebModule.cs b/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/MyProjectNameWebModule.cs index 01353ad6ed..17df5f5df5 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/MyProjectNameWebModule.cs +++ b/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/MyProjectNameWebModule.cs @@ -1,17 +1,17 @@ using System; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.DependencyInjection; -using MyCompanyName.MyProjectName.Menus; -using Swashbuckle.AspNetCore.Swagger; using System.IO; using Microsoft.AspNetCore.Authentication.OAuth.Claims; +using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.DataProtection; +using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; using Microsoft.IdentityModel.Protocols.OpenIdConnect; using MyCompanyName.MyProjectName.Localization; using MyCompanyName.MyProjectName.MultiTenancy; +using MyCompanyName.MyProjectName.Web.Menus; using StackExchange.Redis; +using Swashbuckle.AspNetCore.Swagger; using Volo.Abp; using Volo.Abp.AspNetCore.Authentication.OAuth; using Volo.Abp.AspNetCore.Mvc.Client; @@ -34,7 +34,7 @@ using Volo.Abp.UI; using Volo.Abp.UI.Navigation; using Volo.Abp.VirtualFileSystem; -namespace MyCompanyName.MyProjectName +namespace MyCompanyName.MyProjectName.Web { [DependsOn( typeof(MyProjectNameHttpApiModule), @@ -145,8 +145,6 @@ namespace MyCompanyName.MyProjectName { Configure(options => { - options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}MyCompanyName.MyProjectName.Domain", Path.DirectorySeparatorChar))); - options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}MyCompanyName.MyProjectName.Application.Contracts", Path.DirectorySeparatorChar))); // options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}framework{0}src{0}Volo.Abp.UI", Path.DirectorySeparatorChar))); options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}framework{0}src{0}Volo.Abp.AspNetCore.Mvc.UI", Path.DirectorySeparatorChar))); @@ -156,6 +154,9 @@ namespace MyCompanyName.MyProjectName options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}modules{0}permission-management{0}src{0}Volo.Abp.PermissionManagement.Web", Path.DirectorySeparatorChar))); options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}modules{0}identity{0}src{0}Volo.Abp.Identity.Web", Path.DirectorySeparatorChar))); // + options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}MyCompanyName.MyProjectName.Domain", Path.DirectorySeparatorChar))); + options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}MyCompanyName.MyProjectName.Application.Contracts", Path.DirectorySeparatorChar))); + options.FileSets.ReplaceEmbeddedByPhysical(hostingEnvironment.ContentRootPath); }); } } diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/Pages/Index.cshtml b/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/Pages/Index.cshtml index c99ff43169..46a650e6b2 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/Pages/Index.cshtml +++ b/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/Pages/Index.cshtml @@ -1,7 +1,6 @@ @page -@using MyCompanyName.MyProjectName.Pages -@inherits MyProjectNamePageBase -@model IndexModel +@inherits MyCompanyName.MyProjectName.Web.Pages.MyProjectNamePageBase +@model MyCompanyName.MyProjectName.Web.Pages.IndexModel @section styles { diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/Pages/Index.cshtml.cs b/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/Pages/Index.cshtml.cs index 735570b82e..967ee7b353 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/Pages/Index.cshtml.cs +++ b/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/Pages/Index.cshtml.cs @@ -1,7 +1,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Authentication; -namespace MyCompanyName.MyProjectName.Pages +namespace MyCompanyName.MyProjectName.Web.Pages { public class IndexModel : MyProjectNamePageModelBase { diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/Pages/MyProjectNamePageBase.cs b/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/Pages/MyProjectNamePageBase.cs index fde2c858b9..217c70d491 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/Pages/MyProjectNamePageBase.cs +++ b/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/Pages/MyProjectNamePageBase.cs @@ -3,7 +3,7 @@ using Microsoft.AspNetCore.Mvc.Razor.Internal; using MyCompanyName.MyProjectName.Localization; using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; -namespace MyCompanyName.MyProjectName.Pages +namespace MyCompanyName.MyProjectName.Web.Pages { public abstract class MyProjectNamePageBase : AbpPage { diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/Pages/MyProjectNamePageModelBase.cs b/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/Pages/MyProjectNamePageModelBase.cs index 88795db56d..afd22b08c4 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/Pages/MyProjectNamePageModelBase.cs +++ b/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/Pages/MyProjectNamePageModelBase.cs @@ -1,7 +1,7 @@ using MyCompanyName.MyProjectName.Localization; using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; -namespace MyCompanyName.MyProjectName.Pages +namespace MyCompanyName.MyProjectName.Web.Pages { public abstract class MyProjectNamePageModelBase : AbpPageModel { diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/Program.cs b/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/Program.cs index 22b560f34f..ca7eeab845 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/Program.cs +++ b/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/Program.cs @@ -4,7 +4,7 @@ using Microsoft.AspNetCore.Hosting; using Serilog; using Serilog.Events; -namespace MyCompanyName.MyProjectName +namespace MyCompanyName.MyProjectName.Web { public class Program { diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/Startup.cs b/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/Startup.cs index 2e788dc051..db5c45e654 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/Startup.cs +++ b/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/Startup.cs @@ -4,7 +4,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Volo.Abp; -namespace MyCompanyName.MyProjectName +namespace MyCompanyName.MyProjectName.Web { public class Startup { diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.Web/Menus/MyProjectNameMenuContributor.cs b/templates/mvc/src/MyCompanyName.MyProjectName.Web/Menus/MyProjectNameMenuContributor.cs index 3c1f22206a..5f158525f3 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.Web/Menus/MyProjectNameMenuContributor.cs +++ b/templates/mvc/src/MyCompanyName.MyProjectName.Web/Menus/MyProjectNameMenuContributor.cs @@ -6,7 +6,7 @@ using MyCompanyName.MyProjectName.MultiTenancy; using Volo.Abp.TenantManagement.Web.Navigation; using Volo.Abp.UI.Navigation; -namespace MyCompanyName.MyProjectName.Menus +namespace MyCompanyName.MyProjectName.Web.Menus { public class MyProjectNameMenuContributor : IMenuContributor { diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj b/templates/mvc/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj index f0dfcbb41b..84ba69f73e 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj +++ b/templates/mvc/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj @@ -4,7 +4,13 @@ netcoreapp2.2 - MyCompanyName.MyProjectName + MyCompanyName.MyProjectName.Web + $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; + true + true + true + true + false diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.Web/MyProjectNameBrandingProvider.cs b/templates/mvc/src/MyCompanyName.MyProjectName.Web/MyProjectNameBrandingProvider.cs index aba2d3920e..ce09452496 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.Web/MyProjectNameBrandingProvider.cs +++ b/templates/mvc/src/MyCompanyName.MyProjectName.Web/MyProjectNameBrandingProvider.cs @@ -1,7 +1,7 @@ using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Components; using Volo.Abp.DependencyInjection; -namespace MyCompanyName.MyProjectName +namespace MyCompanyName.MyProjectName.Web { [Dependency(ReplaceServices = true)] public class MyProjectNameBrandingProvider : DefaultBrandingProvider diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebAutoMapperProfile.cs b/templates/mvc/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebAutoMapperProfile.cs index b8069ae329..e728b8a6e7 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebAutoMapperProfile.cs +++ b/templates/mvc/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebAutoMapperProfile.cs @@ -1,6 +1,6 @@ using AutoMapper; -namespace MyCompanyName.MyProjectName +namespace MyCompanyName.MyProjectName.Web { public class MyProjectNameWebAutoMapperProfile : Profile { diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs b/templates/mvc/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs index 1c33edf183..77da95f24a 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs +++ b/templates/mvc/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs @@ -1,14 +1,14 @@ -using Localization.Resources.AbpUi; +using System.IO; +using Localization.Resources.AbpUi; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using MyCompanyName.MyProjectName.EntityFrameworkCore; -using MyCompanyName.MyProjectName.Menus; -using Swashbuckle.AspNetCore.Swagger; -using System.IO; -using Microsoft.Extensions.Configuration; using MyCompanyName.MyProjectName.Localization; using MyCompanyName.MyProjectName.MultiTenancy; +using MyCompanyName.MyProjectName.Web.Menus; +using Swashbuckle.AspNetCore.Swagger; using Volo.Abp; using Volo.Abp.Account.Web; using Volo.Abp.AspNetCore.Authentication.JwtBearer; @@ -30,7 +30,7 @@ using Volo.Abp.UI; using Volo.Abp.UI.Navigation; using Volo.Abp.VirtualFileSystem; -namespace MyCompanyName.MyProjectName +namespace MyCompanyName.MyProjectName.Web { [DependsOn( typeof(MyProjectNameHttpApiModule), @@ -113,11 +113,6 @@ namespace MyCompanyName.MyProjectName { Configure(options => { - options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}MyCompanyName.MyProjectName.Domain.Shared", Path.DirectorySeparatorChar))); - options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}MyCompanyName.MyProjectName.Domain", Path.DirectorySeparatorChar))); - options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}MyCompanyName.MyProjectName.Application.Contracts", Path.DirectorySeparatorChar))); - options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}MyCompanyName.MyProjectName.Application", Path.DirectorySeparatorChar))); - options.FileSets.ReplaceEmbeddedByPhysical(hostingEnvironment.ContentRootPath); // options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}framework{0}src{0}Volo.Abp.UI", Path.DirectorySeparatorChar))); options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}framework{0}src{0}Volo.Abp.AspNetCore.Mvc.UI", Path.DirectorySeparatorChar))); @@ -128,6 +123,11 @@ namespace MyCompanyName.MyProjectName options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}modules{0}identity{0}src{0}Volo.Abp.Identity.Web", Path.DirectorySeparatorChar))); options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}modules{0}account{0}src{0}Volo.Abp.Account.Web", Path.DirectorySeparatorChar))); // + options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}MyCompanyName.MyProjectName.Domain.Shared", Path.DirectorySeparatorChar))); + options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}MyCompanyName.MyProjectName.Domain", Path.DirectorySeparatorChar))); + options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}MyCompanyName.MyProjectName.Application.Contracts", Path.DirectorySeparatorChar))); + options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}MyCompanyName.MyProjectName.Application", Path.DirectorySeparatorChar))); + options.FileSets.ReplaceEmbeddedByPhysical(hostingEnvironment.ContentRootPath); }); } } @@ -142,6 +142,7 @@ namespace MyCompanyName.MyProjectName typeof(AbpUiResource) ); + options.Languages.Add(new LanguageInfo("cs", "cs", "Čeština")); options.Languages.Add(new LanguageInfo("en", "en", "English")); options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português")); options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe")); diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.Web/Pages/Index.cshtml b/templates/mvc/src/MyCompanyName.MyProjectName.Web/Pages/Index.cshtml index 5efecf03a5..9324a9891a 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.Web/Pages/Index.cshtml +++ b/templates/mvc/src/MyCompanyName.MyProjectName.Web/Pages/Index.cshtml @@ -1,7 +1,6 @@ @page -@using MyCompanyName.MyProjectName.Pages -@inherits MyProjectNamePageBase -@model IndexModel +@inherits MyCompanyName.MyProjectName.Web.Pages.MyProjectNamePage +@model MyCompanyName.MyProjectName.Web.Pages.IndexModel @section styles { diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.Web/Pages/Index.cshtml.cs b/templates/mvc/src/MyCompanyName.MyProjectName.Web/Pages/Index.cshtml.cs index 024461326e..6a89e42f63 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.Web/Pages/Index.cshtml.cs +++ b/templates/mvc/src/MyCompanyName.MyProjectName.Web/Pages/Index.cshtml.cs @@ -1,6 +1,6 @@ -namespace MyCompanyName.MyProjectName.Pages +namespace MyCompanyName.MyProjectName.Web.Pages { - public class IndexModel : MyProjectNamePageModelBase + public class IndexModel : MyProjectNamePageModel { public void OnGet() { diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectNamePage.cs b/templates/mvc/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectNamePage.cs new file mode 100644 index 0000000000..5fe044221d --- /dev/null +++ b/templates/mvc/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectNamePage.cs @@ -0,0 +1,16 @@ +using Microsoft.AspNetCore.Mvc.Localization; +using Microsoft.AspNetCore.Mvc.Razor.Internal; +using MyCompanyName.MyProjectName.Localization; +using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; + +namespace MyCompanyName.MyProjectName.Web.Pages +{ + /* Inherit your UI Pages from this class. To do that, add this line to your Pages (.cshtml files under the Page folder): + * @inherits MyCompanyName.MyProjectName.Web.Pages.MyProjectNamePage + */ + public abstract class MyProjectNamePage : AbpPage + { + [RazorInject] + public IHtmlLocalizer L { get; set; } + } +} diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectNamePageBase.cs b/templates/mvc/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectNamePageBase.cs deleted file mode 100644 index fde2c858b9..0000000000 --- a/templates/mvc/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectNamePageBase.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Microsoft.AspNetCore.Mvc.Localization; -using Microsoft.AspNetCore.Mvc.Razor.Internal; -using MyCompanyName.MyProjectName.Localization; -using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; - -namespace MyCompanyName.MyProjectName.Pages -{ - public abstract class MyProjectNamePageBase : AbpPage - { - [RazorInject] - public IHtmlLocalizer L { get; set; } - } -} diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectNamePageModel.cs b/templates/mvc/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectNamePageModel.cs new file mode 100644 index 0000000000..d0b9c04a45 --- /dev/null +++ b/templates/mvc/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectNamePageModel.cs @@ -0,0 +1,15 @@ +using MyCompanyName.MyProjectName.Localization; +using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; + +namespace MyCompanyName.MyProjectName.Web.Pages +{ + /* Inherit your PageModel classes from this class. + */ + public abstract class MyProjectNamePageModel : AbpPageModel + { + protected MyProjectNamePageModel() + { + LocalizationResourceType = typeof(MyProjectNameResource); + } + } +} \ No newline at end of file diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectNamePageModelBase.cs b/templates/mvc/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectNamePageModelBase.cs deleted file mode 100644 index 88795db56d..0000000000 --- a/templates/mvc/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectNamePageModelBase.cs +++ /dev/null @@ -1,13 +0,0 @@ -using MyCompanyName.MyProjectName.Localization; -using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; - -namespace MyCompanyName.MyProjectName.Pages -{ - public abstract class MyProjectNamePageModelBase : AbpPageModel - { - protected MyProjectNamePageModelBase() - { - LocalizationResourceType = typeof(MyProjectNameResource); - } - } -} \ No newline at end of file diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.Web/Program.cs b/templates/mvc/src/MyCompanyName.MyProjectName.Web/Program.cs index 22b560f34f..ca7eeab845 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.Web/Program.cs +++ b/templates/mvc/src/MyCompanyName.MyProjectName.Web/Program.cs @@ -4,7 +4,7 @@ using Microsoft.AspNetCore.Hosting; using Serilog; using Serilog.Events; -namespace MyCompanyName.MyProjectName +namespace MyCompanyName.MyProjectName.Web { public class Program { diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.Web/Startup.cs b/templates/mvc/src/MyCompanyName.MyProjectName.Web/Startup.cs index 2e788dc051..db5c45e654 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.Web/Startup.cs +++ b/templates/mvc/src/MyCompanyName.MyProjectName.Web/Startup.cs @@ -4,7 +4,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Volo.Abp; -namespace MyCompanyName.MyProjectName +namespace MyCompanyName.MyProjectName.Web { public class Startup { diff --git a/templates/mvc/test/MyCompanyName.MyProjectName.Application.Tests/MyCompanyName.MyProjectName.Application.Tests.csproj b/templates/mvc/test/MyCompanyName.MyProjectName.Application.Tests/MyCompanyName.MyProjectName.Application.Tests.csproj index a6f18a84b2..a9845fe4b3 100644 --- a/templates/mvc/test/MyCompanyName.MyProjectName.Application.Tests/MyCompanyName.MyProjectName.Application.Tests.csproj +++ b/templates/mvc/test/MyCompanyName.MyProjectName.Application.Tests/MyCompanyName.MyProjectName.Application.Tests.csproj @@ -13,7 +13,7 @@ - + diff --git a/templates/mvc/test/MyCompanyName.MyProjectName.Domain.Tests/MyCompanyName.MyProjectName.Domain.Tests.csproj b/templates/mvc/test/MyCompanyName.MyProjectName.Domain.Tests/MyCompanyName.MyProjectName.Domain.Tests.csproj index 0cc541e353..24e65fa533 100644 --- a/templates/mvc/test/MyCompanyName.MyProjectName.Domain.Tests/MyCompanyName.MyProjectName.Domain.Tests.csproj +++ b/templates/mvc/test/MyCompanyName.MyProjectName.Domain.Tests/MyCompanyName.MyProjectName.Domain.Tests.csproj @@ -12,7 +12,7 @@ - + diff --git a/templates/mvc/test/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests.csproj b/templates/mvc/test/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests.csproj index 46e07869da..6b5a5e757c 100644 --- a/templates/mvc/test/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests.csproj +++ b/templates/mvc/test/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests.csproj @@ -13,7 +13,7 @@ - + diff --git a/templates/mvc/test/MyCompanyName.MyProjectName.MongoDB.Tests/MyCompanyName.MyProjectName.MongoDB.Tests.csproj b/templates/mvc/test/MyCompanyName.MyProjectName.MongoDB.Tests/MyCompanyName.MyProjectName.MongoDB.Tests.csproj index 0ae2555849..7fba41965c 100644 --- a/templates/mvc/test/MyCompanyName.MyProjectName.MongoDB.Tests/MyCompanyName.MyProjectName.MongoDB.Tests.csproj +++ b/templates/mvc/test/MyCompanyName.MyProjectName.MongoDB.Tests/MyCompanyName.MyProjectName.MongoDB.Tests.csproj @@ -13,8 +13,8 @@ - - + + diff --git a/templates/mvc/test/MyCompanyName.MyProjectName.TestBase/MyCompanyName.MyProjectName.TestBase.csproj b/templates/mvc/test/MyCompanyName.MyProjectName.TestBase/MyCompanyName.MyProjectName.TestBase.csproj index 37db2e4cbd..1b0f53db9c 100644 --- a/templates/mvc/test/MyCompanyName.MyProjectName.TestBase/MyCompanyName.MyProjectName.TestBase.csproj +++ b/templates/mvc/test/MyCompanyName.MyProjectName.TestBase/MyCompanyName.MyProjectName.TestBase.csproj @@ -15,8 +15,8 @@ - - + + diff --git a/templates/mvc/test/MyCompanyName.MyProjectName.TestBase/Security/FakeCurrentPrincipalAccessor.cs b/templates/mvc/test/MyCompanyName.MyProjectName.TestBase/Security/FakeCurrentPrincipalAccessor.cs new file mode 100644 index 0000000000..ef00c20a24 --- /dev/null +++ b/templates/mvc/test/MyCompanyName.MyProjectName.TestBase/Security/FakeCurrentPrincipalAccessor.cs @@ -0,0 +1,39 @@ +using System.Collections.Generic; +using System.Security.Claims; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Security.Claims; + +namespace MyCompanyName.MyProjectName.Security +{ + [Dependency(ReplaceServices = true)] + public class FakeCurrentPrincipalAccessor : ICurrentPrincipalAccessor, ISingletonDependency + { + public ClaimsPrincipal Principal => GetPrincipal(); + private ClaimsPrincipal _principal; + + private ClaimsPrincipal GetPrincipal() + { + if (_principal == null) + { + lock (this) + { + if (_principal == null) + { + _principal = new ClaimsPrincipal( + new ClaimsIdentity( + new List + { + new Claim(AbpClaimTypes.UserId,"2e701e62-0953-4dd3-910b-dc6cc93ccb0d"), + new Claim(AbpClaimTypes.UserName,"admin"), + new Claim(AbpClaimTypes.Email,"admin@abp.io") + } + ) + ); + } + } + } + + return _principal; + } + } +} \ No newline at end of file diff --git a/templates/mvc/test/MyCompanyName.MyProjectName.Web.Tests/MyCompanyName.MyProjectName.Web.Tests.csproj b/templates/mvc/test/MyCompanyName.MyProjectName.Web.Tests/MyCompanyName.MyProjectName.Web.Tests.csproj index 1f93e615d3..f3b0d21c93 100644 --- a/templates/mvc/test/MyCompanyName.MyProjectName.Web.Tests/MyCompanyName.MyProjectName.Web.Tests.csproj +++ b/templates/mvc/test/MyCompanyName.MyProjectName.Web.Tests/MyCompanyName.MyProjectName.Web.Tests.csproj @@ -14,7 +14,7 @@ - + diff --git a/templates/mvc/test/MyCompanyName.MyProjectName.Web.Tests/MyProjectNameWebTestModule.cs b/templates/mvc/test/MyCompanyName.MyProjectName.Web.Tests/MyProjectNameWebTestModule.cs index f99735b782..b39a72d70b 100644 --- a/templates/mvc/test/MyCompanyName.MyProjectName.Web.Tests/MyProjectNameWebTestModule.cs +++ b/templates/mvc/test/MyCompanyName.MyProjectName.Web.Tests/MyProjectNameWebTestModule.cs @@ -7,7 +7,8 @@ using Microsoft.AspNetCore.Mvc.ApplicationParts; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using MyCompanyName.MyProjectName.Localization; -using MyCompanyName.MyProjectName.Menus; +using MyCompanyName.MyProjectName.Web; +using MyCompanyName.MyProjectName.Web.Menus; using Volo.Abp; using Volo.Abp.AspNetCore.TestBase; using Volo.Abp.Localization;