diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000000..81cf37fc8a --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,28 @@ +name: "Main" +on: + pull_request: + paths: + - "framework/**" + - "modules/**" + - "templates/**" + push: + paths: + - "framework/**" + - "modules/**" + - "templates/**" +jobs: + build-test: + runs-on: windows-latest + steps: + - uses: actions/checkout@v1 + - uses: actions/setup-dotnet@master + with: + dotnet-version: "3.1.100" + + - name: Build All + run: .\build\build-all.ps1 + shell: pwsh + + - name: Test All + run: .\build\test-all.ps1 + shell: pwsh diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/ru.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/ru.json new file mode 100644 index 0000000000..a39240b02e --- /dev/null +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/ru.json @@ -0,0 +1,13 @@ +{ + "culture": "ru", + "texts": { + "Account": "Аккаунт", + "Welcome": "Добро пожаловать", + "UseOneOfTheFollowingLinksToContinue": "Для продолжения используйте одну из следующих ссылок", + "FrameworkHomePage": "Главная страница фреймворка", + "FrameworkDocumentation": "Документация фреймворка", + "OfficialBlog": "Официальный блог", + "CommercialHomePage": "Главная страница коммерческой версии", + "CommercialSupportWebSite": "Сайт коммерческой поддержки" + } +} diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/ru.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/ru.json new file mode 100644 index 0000000000..38b4e728f8 --- /dev/null +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/ru.json @@ -0,0 +1,90 @@ +{ + "culture": "ru", + "texts": { + "Permission:Organizations": "Организации", + "Permission:Manage": "Управление организациями", + "Permission:NpmPackages": "Пакеты NPM", + "Permission:NugetPackages": "Пакеты NuGet", + "Permission:Maintenance": "Обслуживание", + "Permission:Maintain": "Обслуживать", + "Permission:ClearCaches": "Очистить кэш", + "Permission:Modules": "Модули", + "Permission:Packages": "Пакеты", + "Permission:Edit": "Редактировать", + "Permission:Delete": "Удалить", + "Permission:Create": "Создать", + "Menu:Organizations": "Организации", + "Menu:Packages": "Пакеты", + "NpmPackageDeletionWarningMessage": "Этот пакет NPM будет удален. Вы подтверждаете это?", + "NugetPackageDeletionWarningMessage": "Этот пакет NuGet будет удален. Вы подтверждаете это?", + "ModuleDeletionWarningMessage": "Этот модуль будет удален. Вы подтверждаете это?", + "Name": "Имя", + "DisplayName": "Отображаемое имя", + "ShortDescription": "Краткое описание", + "NameFilter": "Имя", + "CreationTime": "Время создания", + "IsPro": "Is pro", + "EfCoreConfigureMethodName": "Настроить имя метода", + "IsProFilter": "Is pro", + "ApplicationType": "Тип приложения", + "Target": "Цель", + "TargetFilter": "Цель", + "ModuleClass": "Класс модуля", + "NugetPackageTarget.DomainShared": "Domain Shared", + "NugetPackageTarget.Domain": "Domain", + "NugetPackageTarget.Application": "Application", + "NugetPackageTarget.ApplicationContracts": "Application Contracts", + "NugetPackageTarget.HttpApi": "Http Api", + "NugetPackageTarget.HttpApiClient": "Http Api Client", + "NugetPackageTarget.Web": "Web", + "NugetPackageTarget.EntityFrameworkCore": "DeleteAllEntityFramework Core", + "NugetPackageTarget.MongoDB": "MongoDB", + "Edit": "Редактировать", + "Delete": "Удалить", + "Refresh": "Обновить", + "NpmPackages": "NPM пакеты", + "NugetPackages": "NuGet пакеты", + "NpmPackageCount": "Количество пакетов NPM", + "NugetPackageCount": "Количество пакетов NuGet", + "Module": "Модули", + "ModuleInfo": "Информация о модуле", + "CreateANpmPackage": "Создать пакет NPM", + "CreateAModule": "Создать модуль", + "CreateANugetPackage": "Создать пакет NuGet", + "AddNew": "Добавить новый", + "PackageAlreadyExist{0}": "\"{0}\" пакет уже существует.", + "ModuleAlreadyExist{0}": "\"{0}\" модуль уже добавлен.", + "ClearCache": "Очистить кэш", + "SuccessfullyCleared": "Успешно очищено", + "Menu:NpmPackages": "Пакеты NPM", + "Menu:Modules": "Модули", + "Menu:Maintenance": "Поддержка", + "Menu:NugetPackages": "Пакеты NuGet", + "CreateAnOrganization": "Создать организацию", + "Organizations": "Организации", + "LongName": "Полное название", + "LicenseType": "Тип лицензии", + "LicenseStartTime": "Время начала действия лицензии", + "LicenseEndTime": "Время окончания действия лицензии", + "AllowedDeveloperCount": "Разрешенное количество разработчиков", + "UserNameOrEmailAddress": "Имя пользователя или адрес электронной почты", + "AddOwner": "Добавить владельца", + "UserName": "Имя пользователя", + "Email": "Электронная почта", + "Developers": "Разработчики", + "AddDeveloper": "Добавить разработчика", + "Create": "Создать", + "UserNotFound": "Пользователь не обнаружен", + "{0}WillBeRemovedFromMembers": "{0} будет удален из членов", + "Computers": "Компьютеры", + "UniqueComputerId": "Уникальный id компьютера", + "LastSeenDate": "Дата последнего визита", + "{0}Computer{1}WillBeRemovedFromRecords": "Компьютер {0} ({1}) будет удален из записей", + "OrganizationDeletionWarningMessage": "Организация будет удалена", + "This{0}AlreadyExistInThisOrganization": "{0} уже существует в данной организации", + "AreYouSureYouWantToDeleteAllComputers": "Вы уверены, что хотите удалить все компьютеры?", + "DeleteAll": "Удалить все", + "DoYouWantToCreateNewUser": "Вы хотите создать нового пользователя?", + "MasterModules": "Мастер модулей" + } +} diff --git a/docs/en/Customizing-Application-Modules-Extending-Entities.md b/docs/en/Customizing-Application-Modules-Extending-Entities.md index dcfe30c019..a7c3f4e7cd 100644 --- a/docs/en/Customizing-Application-Modules-Extending-Entities.md +++ b/docs/en/Customizing-Application-Modules-Extending-Entities.md @@ -50,7 +50,7 @@ ObjectExtensionManager.Instance * You provide the `IdentityUser` as the entity name, `string` as the type of the new property, `SocialSecurityNumber` as the property name (also, the field name in the database table). * You also need to provide an action that defines the database mapping properties using the [EF Core Fluent API](https://docs.microsoft.com/en-us/ef/core/modeling/entity-properties). -> This code part must be executed before the related `DbContext` used. The [application startup template](Startup-Templates/Application.md) defines a static class named `YourProjectNameEntityExtensions`. You can define your extensions in this class to ensure that it is executed in the proper time. Otherwise, you should handle it yourself. +> This code part must be executed before the related `DbContext` used. The [application startup template](Startup-Templates/Application.md) defines a static class named `YourProjectNameEfCoreEntityExtensionMappings`. You can define your extensions in this class to ensure that it is executed in the proper time. Otherwise, you should handle it yourself. Once you define an entity extension, you then need to use the standard [Add-Migration](https://docs.microsoft.com/en-us/ef/core/miscellaneous/cli/powershell#add-migration) and [Update-Database](https://docs.microsoft.com/en-us/ef/core/miscellaneous/cli/powershell#update-database) commands of the EF Core to create a code first migration class and update your database. @@ -174,4 +174,4 @@ public class MyDistributedIdentityUserCreatedEventHandler : ## See Also * [Migration System for the EF Core](Entity-Framework-Core-Migrations.md) -* [Customizing the Existing Modules](Customizing-Application-Modules-Guide.md) \ No newline at end of file +* [Customizing the Existing Modules](Customizing-Application-Modules-Guide.md) diff --git a/docs/en/Exception-Handling.md b/docs/en/Exception-Handling.md index 6dc4ccbd9f..38a380dc64 100644 --- a/docs/en/Exception-Handling.md +++ b/docs/en/Exception-Handling.md @@ -315,8 +315,8 @@ The `context` object contains necessary information about the exception occurred Some exception types are automatically thrown by the framework: -- `AbpAuthorizationException` is thrown if the current user has no permission to perform the requested operation. See authorization document (TODO: link) for more. -- `AbpValidationException` is thrown if the input of the current request is not valid. See validation document (TODO: link) for more. +- `AbpAuthorizationException` is thrown if the current user has no permission to perform the requested operation. See [authorization](Authorization.md) for more. +- `AbpValidationException` is thrown if the input of the current request is not valid. See [validation] (Validation.md) for more. - `EntityNotFoundException` is thrown if the requested entity is not available. This is mostly thrown by [repositories](Repositories.md). You can also throw these type of exceptions in your code (although it's rarely needed). diff --git a/docs/en/Getting-Started-Angular-Template.md b/docs/en/Getting-Started-Angular-Template.md index 22d672d97a..9beb84bcef 100644 --- a/docs/en/Getting-Started-Angular-Template.md +++ b/docs/en/Getting-Started-Angular-Template.md @@ -1,126 +1,8 @@ -## Getting Started With the Angular Application Template +# Getting Started with the Startup Templates -This tutorial explains how to create a new Angular application using the startup template, configure and run it. +See the following tutorials to learn how to get started with the ABP Framework using the pre-built application startup templates: -### Creating a New Project +* [Getting Started With the ASP.NET Core MVC / Razor Pages UI](Getting-Started?UI=MVC&DB=EF&Tiered=No) +* [Getting Started with the Angular UI](Getting-Started?UI=NG&DB=EF&Tiered=No) -This tutorial uses **ABP CLI** to create a new project. See the [Get Started](https://abp.io/get-started) page for other options. - -Install the ABP CLI using a command line window, if you've not installed before: - -````bash -dotnet tool install -g Volo.Abp.Cli -```` - -Use `abp new` command in an empty folder to create your project: - -````bash -abp new Acme.BookStore -u angular -```` - -> You can use different level of namespaces; e.g. BookStore, Acme.BookStore or Acme.Retail.BookStore. - -`-u angular` option specifies the UI framework to be Angular. Default database provider is EF Core. See the [CLI documentation](CLI.md) for all available options. - -#### Pre Requirements - -The created solution requires; - -* [Visual Studio 2019 (v16.4+)](https://visualstudio.microsoft.com/vs/) -* [.NET Core 3.0+](https://www.microsoft.com/net/download/dotnet-core/) -* [Node v12+](https://nodejs.org) -* [Yarn v1.19+](https://classic.yarnpkg.com/) - -### The Solution Structure - -Open the solution in **Visual Studio**: - -![bookstore-visual-studio-solution](images/bookstore-visual-studio-solution-for-spa.png) - -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. - -> See the [Application Template Document](Startup-Templates/Application.md) to understand the solution structure in details. - -### Database Connection String - -Check the **connection string** in the `appsettings.json` file under the `.HttpApi.Host` project: - -````json -{ - "ConnectionStrings": { - "Default": "Server=localhost;Database=BookStore;Trusted_Connection=True" - } -} -```` - -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. - -#### 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 `.HttpApi.Host` project and select **Set as StartUp Project**: - -![set-as-startup-project](images/set-as-startup-project.png) - -Open the **Package Manager Console**, select `.EntityFrameworkCore.DbMigrations` project as the **Default Project** and run the `Update-Database` command: - -![pcm-update-database](images/pcm-update-database-v2.png) - -This will create a new database based on the configured connection string. - -> Using the `.DbMigrator` tool is the suggested way, because it also seeds the initial data to be able to properly run the web application. - -### Running the Application - -#### Run the API Host (Server Side) - -Ensure that the `.HttpApi.Host` project is the startup project and run the application which will open a Swagger UI: - -![bookstore-homepage](images/bookstore-swagger-ui-host.png) - -You can see the application APIs and test them here. Get [more info](https://swagger.io/tools/swagger-ui/) about the Swagger UI. - -##### Authorization for the Swagger UI - -Most of the application APIs require authentication & authorization. If you want to test authorized APIs, manually go to the `/Account/Login` page, enter `admin` as the username and `1q2w3E*` as the password to login to the application. Then you will be able to execute authorized APIs too. - -#### Run the Angular Application (Client Side) - -Go to the `angular` folder, open a command line terminal, type the `yarn` command (we suggest the [yarn](https://yarnpkg.com) package manager while `npm install` will also work in most cases) - -````bash -yarn -```` - -Once all node modules are loaded, execute `yarn start` or `npm start` command: - -````bash -yarn start -```` - -Open your favorite browser and go to `localhost:4200` URL. Initial username is `admin` and password is `1q2w3E*`. - -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**. - -> We recommend [Visual Studio Code](https://code.visualstudio.com/) as the editor for the Angular project, but you are free to use your favorite editor. - -### What's Next? - -* [Application development tutorial](Tutorials/Part-1) + \ 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 d074e8aaef..9beb84bcef 100644 --- a/docs/en/Getting-Started-AspNetCore-MVC-Template.md +++ b/docs/en/Getting-Started-AspNetCore-MVC-Template.md @@ -1,104 +1,8 @@ -## Getting Started With the ASP.NET Core MVC Template +# Getting Started with the Startup Templates -This tutorial explains how to create a new ASP.NET Core MVC web application using the startup template, configure and run it. +See the following tutorials to learn how to get started with the ABP Framework using the pre-built application startup templates: -### Creating a New Project +* [Getting Started With the ASP.NET Core MVC / Razor Pages UI](Getting-Started?UI=MVC&DB=EF&Tiered=No) +* [Getting Started with the Angular UI](Getting-Started?UI=NG&DB=EF&Tiered=No) -This tutorial uses **ABP CLI** to create a new project. See the [Get Started](https://abp.io/get-started) page for other options. - -Install the ABP CLI using a command line window, if you've not installed before: - -````bash -dotnet tool install -g Volo.Abp.Cli -```` - -Use `abp new` command in an empty folder to create your project: - -````bash -abp new Acme.BookStore -```` - -> You can use different level of namespaces; e.g. BookStore, Acme.BookStore or Acme.Retail.BookStore. - -`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. - -#### Pre Requirements - -The created solution requires; - -* [Visual Studio 2019 (v16.4+)](https://visualstudio.microsoft.com/vs/) -* [.NET Core 3.0+](https://www.microsoft.com/net/download/dotnet-core/) -* [Node v12+](https://nodejs.org) -* [Yarn v1.19+](https://classic.yarnpkg.com/) - -### The Solution Structure - -Open the solution in **Visual Studio**: - -![bookstore-visual-studio-solution](images/bookstore-visual-studio-solution-v3.png) - -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. - -> See [Application template document](Startup-Templates/Application.md) to understand the solution structure in details. - -### Database Connection String - -Check the **connection string** in the `appsettings.json` file under the `.Web` project: - -````json -{ - "ConnectionStrings": { - "Default": "Server=localhost;Database=BookStore;Trusted_Connection=True" - } -} -```` - -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. - -#### 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) - -Open the **Package Manager Console**, select `.EntityFrameworkCore.DbMigrations` project as the **Default Project** and run the `Update-Database` command: - -![pcm-update-database](images/pcm-update-database-v2.png) - -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 - -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** 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-v2.png) - -### What's Next? - -* [Application development tutorial](Tutorials/Part-1.md) + \ No newline at end of file diff --git a/docs/en/Getting-Started-With-Startup-Templates.md b/docs/en/Getting-Started-With-Startup-Templates.md index 19442ec81e..be2bb201b8 100644 --- a/docs/en/Getting-Started-With-Startup-Templates.md +++ b/docs/en/Getting-Started-With-Startup-Templates.md @@ -2,5 +2,7 @@ See the following tutorials to learn how to get started with the ABP Framework using the pre-built application startup templates: -* [Getting Started With the ASP.NET Core MVC / Razor Pages UI](Getting-Started-AspNetCore-MVC-Template.md) -* [Getting Started with the Angular UI](Getting-Started-Angular-Template.md) \ No newline at end of file +* [Getting Started With the ASP.NET Core MVC / Razor Pages UI](Getting-Started?UI=MVC&DB=EF&Tiered=No) +* [Getting Started with the Angular UI](Getting-Started?UI=NG&DB=EF&Tiered=No) + + \ No newline at end of file diff --git a/docs/en/Getting-Started.md b/docs/en/Getting-Started.md new file mode 100644 index 0000000000..07e55f553e --- /dev/null +++ b/docs/en/Getting-Started.md @@ -0,0 +1,407 @@ +# Getting started + +````json +//[doc-params] +{ + "UI": ["MVC","NG"], + "DB": ["EF", "Mongo"], + "Tiered": ["Yes", "No"] +} +```` + +This tutorial explains how to create a new {{if UI == "MVC"}} ASP.NET Core MVC web {{else if UI == "NG"}} Angular {{end}} application using the startup template, configure and run it. + + +## Setup your development environment + +First things first! Let's setup your development environment before creating the first project. + +### Pre-requirements + +The following tools should be installed on your development machine: + +* [Visual Studio 2019 (v16.4+)](https://visualstudio.microsoft.com/vs/) for Windows / [Visual Studio for Mac](https://visualstudio.microsoft.com/vs/mac/). +* [.NET Core 3.0+](https://www.microsoft.com/net/download/dotnet-core/) + +* [Node v12+](https://nodejs.org) +* [Yarn v1.19+](https://classic.yarnpkg.com/) + +> You can use another editor instead of Visual Studio as long as it supports .NET Core and ASP.NET Core. + +### Install the ABP CLI + +[ABP CLI](./CLI.md) is a command line interface that is used to authenticate and automate some tasks for ABP based applications. + +> ABP CLI is a free & open source tool for [the ABP framework](https://abp.io/). + +First, you need to install the ABP CLI using the following command: + +````shell +dotnet tool install -g Volo.Abp.Cli +```` + +If you've already installed, you can update it using the following command: + +````shell +dotnet tool update -g Volo.Abp.Cli +```` + +## Create a new project + +> This document assumes that you prefer to use **{{ UI_Value }}** as the UI framework and **{{ DB_Value }}** as the database provider. For other options, please change the preference on top of this document. + +### Using the ABP CLI to create a new project + +Use the `new` command of the ABP CLI to create a new project: + +````shell +abp new Acme.BookStore -t app{{if UI == "NG"}} -u angular {{end}}{{if DB == "Mongo"}} -d mongodb{{end}}{{if Tiered == "Yes" && UI != "NG"}} --tiered {{else if Tiered == "Yes" && UI == "NG"}}--separate-identity-server{{end}} +```` + +* `-t` argument specifies the [startup template](Startup-Templates/Application.md) name. `app` is the startup template that contains the essential [ABP Modules](Modules/Index.md) pre-installed and configured for you. + +{{ if UI == "NG" }} + +* `-u` argument specifies the UI framework, `angular` in this case. + +{{ if Tiered == "Yes" }} + +* `--separate-identity-server` argument is used to separate the identity server application from the API host application. If not specified, you will have a single endpoint. + +{{ end }} + +{{ end }} + +{{ if DB == "Mongo" }} + +* `-d` argument specifies the database provider, `mongodb` in this case. + +{{ end }} + +{{ if Tiered == "Yes" && UI != "NG" }} + +* `--tiered` argument is used to create N-tiered solution where authentication server, UI and API layers are physically separated. + +{{ end }} + +> You can use different level of namespaces; e.g. BookStore, Acme.BookStore or Acme.Retail.BookStore. + +#### ABP CLI commands & options + +[ABP CLI document](./CLI.md) covers all of the available commands and options for the ABP CLI. See the [ABP Startup Templates](Startup-Templates/Index.md) document for other templates. + +## The solution structure + +{{ if UI == "MVC" }} + +After creating your project, you will have the following solution folders & files: + +![](images/solution-files-mvc.png) + +You will see the following solution structure when you open the `.sln` file in the Visual Studio: + +{{if DB == "Mongo"}} + +![vs-default-app-solution-structure](images/vs-app-solution-structure-mongodb.png) + +{{else}} + +![vs-default-app-solution-structure](images/vs-app-solution-structure{{if Tiered == "Yes"}}-tiered{{end}}.png) + +{{end}} + +{{ else if UI == "NG" }} +There are three folders in the created solution: + +![](images/solution-files-non-mvc.png) + +* `angular` folder contains the Angular UI application. +* `aspnet-core` folder contains the backend solution. +* `react-native` folder contains the React Native UI application. + +Open the `.sln` (Visual Studio solution) file under the `aspnet-core` folder: + +![vs-angular-app-backend-solution-structure](images/vs-spa-app-backend-structure{{if DB == "Mongo"}}-mongodb{{end}}.png) + +{{ end }} + +> ###### About the projects in your solution +> +> Your solution may have slightly different structure based on your **UI**, **database** and other preferences. + +The solution has a layered structure (based on [Domain Driven Design](./Domain-Driven-Design.md)) and also contains unit & integration test projects. + +{{ if DB == "EF" }} + +Integration tests projects are properly configured to work with **EF Core** & **SQLite in-memory** database. + +{{ else if DB == "Mongo" }} + +Integration tests projects are properly configured to work with in-memory **MongoDB** database created per test (used [Mongo2Go](https://github.com/Mongo2Go/Mongo2Go) library). + +{{ end }} + +> See the [application template document](Startup-Templates/Application.md) to understand the solution structure in details. + +## Create the database + +### Database connection string + +Check the **connection string** in the `appsettings.json` file under the {{if UI == "MVC"}}{{if Tiered == "Yes"}}`.IdentityServer` and `.HttpApi.Host` projects{{else}}`.Web` project{{end}}{{else if UI == "NG" }}`.HttpApi.Host` project{{end}}: + +{{ if DB == "EF" }} + +````json +"ConnectionStrings": { + "Default": "Server=localhost;Database=BookStore;Trusted_Connection=True" +} +```` + +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 any supported DBMS. See [the Entity Framework integration document](https://docs.abp.io/en/abp/latest/Entity-Framework-Core) to learn how to switch to another DBMS. + +### Apply the migrations + +The solution uses the [Entity Framework Core Code First Migrations](https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/?tabs=dotnet-core-cli). So, you need to apply migrations to create the database. There are two ways of applying the database migrations. + +#### Apply migrations using the DbMigrator + +The solution comes with a `.DbMigrator` console application which applies migrations and also seed the 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: + + ![db-migrator-output](images/db-migrator-output.png) + +> Initial seed data creates the `admin` user in the database which is then used to login to the application. So, you need to use `.DbMigrator` at least once for a new database. + +#### Using EF Core Update-Database command + +Ef Core has `Update-Database` command which creates database if necessary and applies pending migrations. + +{{ if UI == "MVC" }} + +Right click to the {{if Tiered == "Yes"}}`.IdentityServer`{{else}}`.Web`{{end}} project and select **Set as StartUp project**: + +{{ else if UI != "MVC" }} + +Right click to the `.HttpApi.Host` project and select **Set as StartUp Project**: + +{{ end }} + +![set-as-startup-project](images/set-as-startup-project.png) + +Open the **Package Manager Console**, select `.EntityFrameworkCore.DbMigrations` project as the **Default Project** and run the `Update-Database` command: + +![package-manager-console-update-database](images/package-manager-console-update-database.png) + +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. + +{{ else if DB == "Mongo" }} + +````json +"ConnectionStrings": { + "Default": "mongodb://localhost:27017/BookStore" +} +```` + +The solution is configured to use **MongoDB** in your local computer, so you need to have a MongoDB server instance up and running or change the connection string to another MongoDB server. + +### Seed initial data + +The solution comes with a `.DbMigrator` console application which seeds the 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: + + ![db-migrator-output](images/db-migrator-output.png) + +> Initial seed data creates the `admin` user in the database which is then used to login to the application. So, you need to use `.DbMigrator` at least once for a new database. + +{{ end }} + +## Run the application + +{{ if UI == "MVC" }} + +{{ if Tiered == "Yes" }} + +Ensure that the `.IdentityServer` project is the startup project. Run the application which will open a **login** page in your browser. + +> Use Ctrl+F5 in Visual Studio (instead of F5) to run the application without debugging. If you don't have a debug purpose, this will be faster. + +You can login, but you cannot enter to the main application here. This is just the authentication server. + +Ensure that the `.HttpApi.Host` project is the startup project and run the application which will open a **Swagger UI** in your browser. + +![swagger-ui](images/swagger-ui.png) + +This is the API application that is used by the web application. + +Lastly, ensure that the `.Web` project is the startup project and run the application which will open a **welcome** page in your browser + +![mvc-tiered-app-home](images/bookstore-home.png) + +Click to the **login** button which will redirect you to the `Identity Server` to login to the application: + +![bookstore-login](images/bookstore-login.png) + +{{ else }} + +Ensure that the `.Web` project is the startup project. Run the application which will open the **login** page in your browser: + +> Use Ctrl+F5 in Visual Studio (instead of F5) to run the application without debugging. If you don't have a debug purpose, this will be faster. + +![bookstore-login](images/bookstore-login.png) + +{{ end }} + +{{ else if UI != "MVC" }} + +#### Running the HTTP API Host (server-side) + +{{ if Tiered == "Yes" }} + +Ensure that the `.IdentityServer` project is the startup project. Run the application which will open a **login** page in your browser. + +> Use Ctrl+F5 in Visual Studio (instead of F5) to run the application without debugging. If you don't have a debug purpose, this will be faster. + +You can login, but you cannot enter to the main application here. This is just the authentication server. + +{{ end }} + +Ensure that the `.HttpApi.Host` project is the startup project and run the application which will open a Swagger UI: + +{{ if Tiered == "No" }} + +> Use Ctrl+F5 in Visual Studio (instead of F5) to run the application without debugging. If you don't have a debug purpose, this will be faster. + +{{ end }} + +![swagger-ui](images/swagger-ui.png) + +You can see the application APIs and test them here. Get [more info](https://swagger.io/tools/swagger-ui/) about the Swagger UI. + +> ##### Authorization for the Swagger UI +> +> Most of the HTTP APIs require authentication & authorization. If you want to test authorized APIs, manually go to the `/Account/Login` page, enter `admin` as the username and `1q2w3E*` as the password to login to the application. Then you will be able to execute authorized APIs too. + +{{ end }} + +{{ if UI == "NG" }} +#### Running the Angular application (client-side) + +Go to the `angular` folder, open a command line terminal, type the `yarn` command (we suggest to the [yarn](https://yarnpkg.com/) package manager while `npm install` will also work in most cases) + +```bash +yarn +``` + +Once all node modules are loaded, execute `yarn start` (or `npm start`) command: + +```bash +yarn start +``` + +Wait `Angular CLI` to launch `Webpack` dev-server with `BrowserSync`. +This will take care of compiling your `TypeScript` code, and automatically reloading your browser. +After it finishes, `Angular Live Development Server` will be listening on localhost:4200, +open your web browser and navigate to [localhost:4200](http://localhost:4200/) + + + +![bookstore-login](images/bookstore-login.png) + +{{ end }} + +Enter **admin** as the username and **1q2w3E*** as the password to login to the application: + +![bookstore-home](images/bookstore-home.png) + +The application is up and running. You can start developing your application based on this startup template. + +#### Mobile Development + +ABP platform provide [React Native](https://reactnative.dev/) template to develop mobile applications. + +>The solution includes the React Native application in the `react-native` folder as default. If you don't plan to develop a mobile application with React Native, you can ignore this step and delete the `react-native` folder. + +The React Native application running on an Android emulator or a physical phone cannot connect to the backend on `localhost`. To fix this problem, it is necessary to run backend on the local IP. + +{{ if Tiered == "No"}} +![React Native host project local IP entry](images/rn-host-local-ip.png) + +* Open the `appsettings.json` in the `.HttpApi.Host` folder. Replace the `localhost` address on the `SelfUrl` and `Authority` properties with your local IP address. +* Open the `launchSettings.json` in the `.HttpApi.Host/Properties` folder. Replace the `localhost` address on the `applicationUrl` properties with your local IP address. + +{{ else if Tiered == "Yes" }} + +![React Native tiered project local IP entry](images/rn-tiered-local-ip.png) + +* Open the `appsettings.json` in the `.IdentityServer` folder. Replace the `localhost` address on the `SelfUrl` property with your local IP address. +* Open the `launchSettings.json` in the `.IdentityServer/Properties` folder. Replace the `localhost` address on the `applicationUrl` properties with your local IP address. +* Open the `appsettings.json` in the `.HttpApi.Host` folder. Replace the `localhost` address on the `Authority` property with your local IP address. +* Open the `launchSettings.json` in the `.HttpApi.Host/Properties` folder. Replace the `localhost` address on the `applicationUrl` properties with your local IP address. + +{{ end }} + +Run the backend as described in the [**Running the HTTP API Host (server-side)**](#running-the-http-api-host-server-side) section. + +> React Native application does not trust the auto-generated .NET HTTPS certificate, you should use the HTTP during development. + +Go to the `react-native` folder, open a command line terminal, type the `yarn` command (we suggest to the [yarn](https://yarnpkg.com/) package manager while `npm install` will also work in most cases): + +```bash +yarn +``` + +* Open the `Environment.js` in the `react-native` folder and replace the `localhost` address on the `apiUrl` and `issuer` properties with your local IP address as shown below: + +![react native environment local IP](images/rn-environment-local-ip.png) + +{{ if Tiered == "Yes" }} + +> Make sure that `issuer` matches the running address of the `.IdentityServer` project, `apiUrl` matches the running address of the `.HttpApi.Host` project. + +{{else}} + +> Make sure that `issuer` and `apiUrl` matches the running address of the `.HttpApi.Host` project. + +{{ end }} + +Once all node modules are loaded, execute `yarn start` (or `npm start`) command: + +```bash +yarn start +``` + +Wait Expo CLI to start. Expo CLI opens the management interface on the `http://localhost:19002/` address. + +![expo-interface](images/rn-expo-interface.png) + +In the above management interface, you can start the application with an Android emulator, an iOS simulator or a physical phone by the scan the QR code with the [Expo Client](https://expo.io/tools#client). + +> See the [Android Studio Emulator](https://docs.expo.io/versions/v36.0.0/workflow/android-studio-emulator/), [iOS Simulator](https://docs.expo.io/versions/v36.0.0/workflow/ios-simulator/) documents on expo.io. + +![React Native login screen on iPhone 11](images/rn-login-iphone.png) + +Enter **admin** as the username and **1q2w3E*** as the password to login to the application. + +The application is up and running. You can continue to develop your application based on this startup template. + +> The [application startup template](startup-templates/application/index.md) includes the TenantManagement and Identity modules. + +## What's next? + +[Application development tutorial](tutorials/book-store/part-1.md) diff --git a/docs/en/Tutorials/Angular/Part-I.md b/docs/en/Tutorials/Angular/Part-I.md index 65a7dc5714..2867a3159f 100644 --- a/docs/en/Tutorials/Angular/Part-I.md +++ b/docs/en/Tutorials/Angular/Part-I.md @@ -4,3 +4,5 @@ * [With ASP.NET Core MVC / Razor Pages UI](../Part-1?UI=MVC) * [With Angular UI](../Part-1?UI=NG) + + \ No newline at end of file diff --git a/docs/en/Tutorials/Angular/Part-II.md b/docs/en/Tutorials/Angular/Part-II.md index 65a7dc5714..2867a3159f 100644 --- a/docs/en/Tutorials/Angular/Part-II.md +++ b/docs/en/Tutorials/Angular/Part-II.md @@ -4,3 +4,5 @@ * [With ASP.NET Core MVC / Razor Pages UI](../Part-1?UI=MVC) * [With Angular UI](../Part-1?UI=NG) + + \ No newline at end of file diff --git a/docs/en/Tutorials/Angular/Part-III.md b/docs/en/Tutorials/Angular/Part-III.md index 65a7dc5714..2867a3159f 100644 --- a/docs/en/Tutorials/Angular/Part-III.md +++ b/docs/en/Tutorials/Angular/Part-III.md @@ -4,3 +4,5 @@ * [With ASP.NET Core MVC / Razor Pages UI](../Part-1?UI=MVC) * [With Angular UI](../Part-1?UI=NG) + + \ 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 65a7dc5714..2867a3159f 100644 --- a/docs/en/Tutorials/AspNetCore-Mvc/Part-I.md +++ b/docs/en/Tutorials/AspNetCore-Mvc/Part-I.md @@ -4,3 +4,5 @@ * [With ASP.NET Core MVC / Razor Pages UI](../Part-1?UI=MVC) * [With Angular UI](../Part-1?UI=NG) + + \ No newline at end of file diff --git a/docs/en/Tutorials/AspNetCore-Mvc/Part-II.md b/docs/en/Tutorials/AspNetCore-Mvc/Part-II.md index 65a7dc5714..2867a3159f 100644 --- a/docs/en/Tutorials/AspNetCore-Mvc/Part-II.md +++ b/docs/en/Tutorials/AspNetCore-Mvc/Part-II.md @@ -4,3 +4,5 @@ * [With ASP.NET Core MVC / Razor Pages UI](../Part-1?UI=MVC) * [With Angular UI](../Part-1?UI=NG) + + \ No newline at end of file diff --git a/docs/en/Tutorials/AspNetCore-Mvc/Part-III.md b/docs/en/Tutorials/AspNetCore-Mvc/Part-III.md index 65a7dc5714..2867a3159f 100644 --- a/docs/en/Tutorials/AspNetCore-Mvc/Part-III.md +++ b/docs/en/Tutorials/AspNetCore-Mvc/Part-III.md @@ -4,3 +4,5 @@ * [With ASP.NET Core MVC / Razor Pages UI](../Part-1?UI=MVC) * [With Angular UI](../Part-1?UI=NG) + + \ No newline at end of file diff --git a/docs/en/Tutorials/Part-1.md b/docs/en/Tutorials/Part-1.md index 85f5c47bac..9f8671d92a 100644 --- a/docs/en/Tutorials/Part-1.md +++ b/docs/en/Tutorials/Part-1.md @@ -34,14 +34,14 @@ The ASP.NET Core {{UI_Value}} tutorial series consists of 3 parts: ### Creating the project -Create a new project named `Acme.BookStore` where `Acme` is the company name and `BookStore` is the project name. You can check out [creating a new project](../Getting-Started-{{if UI == 'NG'}}Angular{{else}}AspNetCore-MVC{{end}}-Template#creating-a-new-project) document to see how you can create a new project. We will create the project with ABP CLI. But first of all, we need to login to the ABP Platform. +Create a new project named `Acme.BookStore` where `Acme` is the company name and `BookStore` is the project name. You can check out [creating a new project](../Getting-Started-{{if UI == 'NG'}}Angular{{else}}AspNetCore-MVC{{end}}-Template#creating-a-new-project) document to see how you can create a new project. We will create the project with ABP CLI. #### Create the project By running the below command, it creates a new ABP project with the database provider `{{DB_Text}}` and UI option `MVC`. To see the other CLI options, check out [ABP CLI](https://docs.abp.io/en/abp/latest/CLI) document. ```bash -abp new Acme.BookStore --template app --database-provider {{DB}} --ui {{UI_Text}} +abp new Acme.BookStore --template app --database-provider {{DB}} --ui {{UI_Text}} --mobile none ``` ![Creating project](./images/bookstore-create-project-{{UI_Text}}.png) diff --git a/docs/en/UI/AspNetCore/Tag-Helpers/Dynamic-Forms.md b/docs/en/UI/AspNetCore/Tag-Helpers/Dynamic-Forms.md index 6d700f030d..5b4b766a27 100644 --- a/docs/en/UI/AspNetCore/Tag-Helpers/Dynamic-Forms.md +++ b/docs/en/UI/AspNetCore/Tag-Helpers/Dynamic-Forms.md @@ -1,3 +1,277 @@ -## Dynamic Forms +# Dynamic Forms + +`Warning:` Before getting into this document, be sure that you have clearly understood [abp form elements](Form-elements.md) document. + +## Introduction + +`abp-dynamic-form` creates a bootstrap form for a given c# model. + +Basic usage: + +````xml + +```` +Model: +````csharp +public class DynamicFormsModel : PageModel + { + [BindProperty] + public DetailedModel MyDetailedModel { get; set; } + + public List CountryList { get; set; } = new List + { + new SelectListItem { Value = "CA", Text = "Canada"}, + new SelectListItem { Value = "US", Text = "USA"}, + new SelectListItem { Value = "UK", Text = "United Kingdom"}, + new SelectListItem { Value = "RU", Text = "Russia"} + }; + + public void OnGet() + { + MyDetailedModel = new DetailedModel + { + Name = "", + Description = "Lorem ipsum dolor sit amet.", + IsActive = true, + Age = 65, + Day = DateTime.Now, + MyCarType = CarType.Coupe, + YourCarType = CarType.Sedan, + Country = "RU", + NeighborCountries = new List() { "UK", "CA" } + }; + } + + public class DetailedModel + { + [Required] + [Placeholder("Enter your name...")] + [Display(Name = "Name")] + public string Name { get; set; } + + [TextArea(Rows = 4)] + [Display(Name = "Description")] + [InputInfoText("Describe Yourself")] + public string Description { get; set; } + + [Required] + [DataType(DataType.Password)] + [Display(Name = "Password")] + public string Password { get; set; } + + [Display(Name = "Is Active")] + public bool IsActive { get; set; } + + [Required] + [Display(Name = "Age")] + public int Age { get; set; } + + [Required] + [Display(Name = "My Car Type")] + public CarType MyCarType { get; set; } + + [Required] + [AbpRadioButton(Inline = true)] + [Display(Name = "Your Car Type")] + public CarType YourCarType { get; set; } + + [DataType(DataType.Date)] + [Display(Name = "Day")] + public DateTime Day { get; set; } + + [SelectItems(nameof(CountryList))] + [Display(Name = "Country")] + public string Country { get; set; } + + [SelectItems(nameof(CountryList))] + [Display(Name = "Neighbor Countries")] + public List NeighborCountries { get; set; } + } + + public enum CarType + { + Sedan, + Hatchback, + StationWagon, + Coupe + } + } +```` +## Demo + +See the [dynamic forms demo page](https://bootstrap-taghelpers.abp.io/Components/DynamicForms) to see it in action. + +## Attributes + +### abp-model + +Sets the c# model for dynamic form. Properties of this modal are turned into inputs in the form. + +### submit-button + +Can be `True` or `False`. + +If `True`, a submit button will be generated at the bottom of the form. + +Default value is `False`. + +### required-symbols + +Can be `True` or `False`. + +If `True`, required inputs will have a symbol (*) that indicates they are required. + +Default value is `True`. + +## Form Content Placement + +By default, `abp-dynamicform` clears the inner html and places the inputs into itself. If you want to add additional content to dynamic form or place the inputs to some specific area, you can use ` ` tag. This tag will be replaced by form content and rest of the inner html of `abp-dynamic-form` tag will be unchanged. + +Usage: + +````xml + +
+ Some content.... +
+
+ +
+
+ Some more content.... +
+
+```` + +## Input Order + +`abp-dynamic-form` orders the properties by their `DisplayOrder` attribute and then their property order in model class. + +Default `DisplayOrder` attribute number is 10000 for every property. + +See example below: + +````csharp + public class OrderExampleModel + { + [DisplayOrder(10004)] + public string Name{ get; set; } + + [DisplayOrder(10005)] + public string Surname{ get; set; } + + //Default 10000 + public string EmailAddress { get; set; } + + [DisplayOrder(10003)] + public string PhoneNumber { get; set; } + + [DisplayOrder(9999)] + public string City { get; set; } + } +```` + +In this example, input fields will be displayed with this order: `City` > `EmailAddress` > `PhoneNumber` > `Name` > `Surname`. + +## Ignoring a property + +By default, `abp-dynamic-form` generates input for every property in model class. If you want to ignore a property, use `DynamicFormIgnore` attribute. + +See example below: + +````csharp + public class MyModel + { + public string Name { get; set; } + + [DynamicFormIgnore] + public string Surname { get; set; } + } +```` + +In this example, no input will be generated for `Surname` property. + +## Indicating Text box, Radio Group and Combobox + +If you have read the [Form elements document](Form-elements.md), you noticed that `abp-radio` and `abp-select` tags are very similar on c# model. So we have to use `[AbpRadioButton()]` attribute to tell `abp-dynamic-form` which of your properties will be radio group and which will be combobox. See example below: + +````xml + +```` +Model: +````csharp +public class DynamicFormsModel : PageModel + { + [BindProperty] + public DetailedModel MyDetailedModel { get; set; } + + public List CountryList { get; set; } = new List + { + new SelectListItem { Value = "CA", Text = "Canada"}, + new SelectListItem { Value = "US", Text = "USA"}, + new SelectListItem { Value = "UK", Text = "United Kingdom"}, + new SelectListItem { Value = "RU", Text = "Russia"} + }; + + public void OnGet() + { + MyDetailedModel = new DetailedModel + { + ComboCarType = CarType.Coupe, + RadioCarType = CarType.Sedan, + ComboCountry = "RU", + RadioCountry = "UK" + }; + } + + public class DetailedModel + { + public CarType ComboCarType { get; set; } + + [AbpRadioButton(Inline = true)] + public CarType RadioCarType { get; set; } + + [SelectItems(nameof(CountryList))] + public string ComboCountry { get; set; } + + [AbpRadioButton()] + [SelectItems(nameof(CountryList))] + public string RadioCountry { get; set; } + } + + public enum CarType + { + Sedan, + Hatchback, + StationWagon, + Coupe + } + } +```` + +As you see in example above: + +* If `[AbpRadioButton()]` are used on a **Enum** property, it will be a radio group. Otherwise, combobox. +* If `[SelectItems()]` and `[AbpRadioButton()]` are used on a property, it will be a radio group. +* If just `[SelectItems()]` is used on a property, it will be a combobox. +* If none of these attributes are used on a property, it will be a text box. + +## Localization + +`abp-dynamic-form` handles localization as well. + +By default, it will try to find "DisplayName:{PropertyName}" or "{PropertyName}" localization keys and set the localization value as input label. + +You can set it yourself by using `[Display()]` attribute of Asp.Net Core. You can use a localization key in this attribute. See example below: + +````csharp + [Display(Name = "Name")] + public string Name { get; set; } +```` + + + + + + -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/UI/AspNetCore/Tag-Helpers/Form-elements.md b/docs/en/UI/AspNetCore/Tag-Helpers/Form-elements.md new file mode 100644 index 0000000000..df23fd649c --- /dev/null +++ b/docs/en/UI/AspNetCore/Tag-Helpers/Form-elements.md @@ -0,0 +1,261 @@ +# Form Elements + +## Introduction + +Abp provides form input tag helpers to make building forms easier. + +## Demo + +See the [form elements demo page](https://bootstrap-taghelpers.abp.io/Components/FormElements) to see it in action. + +## abp-input + +`abp-input` tag creates a Bootstrap form input for a given c# property. It uses [Asp.Net Core Input Tag Helper](https://docs.microsoft.com/tr-tr/aspnet/core/mvc/views/working-with-forms?view=aspnetcore-3.1#the-input-tag-helper) in background, so every data annotation attribute of `input` tag helper of Asp.Net Core is also valid for `abp-input`. + +Usage: + +````xml + + + + +```` + +Model: + +````csharp + public class FormElementsModel : PageModel + { + public SampleModel MyModel { get; set; } + + public void OnGet() + { + MyModel = new SampleModel(); + } + + public class SampleModel + { + [Required] + [Placeholder("Enter your name...")] + [InputInfoText("What is your name?")] + public string Name { get; set; } + + [Required] + [FormControlSize(AbpFormControlSize.Large)] + public string SurName { get; set; } + + [TextArea(Rows = 4)] + public string Description { get; set; } + + [Required] + [DataType(DataType.Password)] + public string Password { get; set; } + + public bool IsActive { get; set; } + } + } +```` + +### Attributes + +You can set some of the attributes on your c# property, or directly on html tag. If you are going to use this property in a [abp-dynamic-form](Dynamic-forms.md), then you can only set these properties via property attributes. + +#### Property Attributes + +- `[TextArea()]`: Converts the input into a text area. + +* `[Placeholder()]`: Sets placeholder for input. You can use a localization key directly. +* `[InputInfoText()]`: Sets a small info text for input. You can use a localization key directly. +* `[FormControlSize()]`: Sets size of form-control wrapper element. Available values are + - `AbpFormControlSize.Default` + - `AbpFormControlSize.Small` + - `AbpFormControlSize.Medium` + - `AbpFormControlSize.Large` +* `[DisabledInput]` : Input is disabled. +* `[ReadOnlyInput]`: Input is read-only. + +#### Tag Attributes + +* `info`: Sets a small info text for input. You can use a localization key directly. +* `auto-focus`: If true, browser auto focuses on the element. +* `size`: Sets size of form-control wrapper element. Available values are + - `AbpFormControlSize.Default` + - `AbpFormControlSize.Small` + - `AbpFormControlSize.Medium` + - `AbpFormControlSize.Large` +* `disabled`: Input is disabled. +* `readonly`: Input is read-only. +* `label`: Sets the label for input. +* `display-required-symbol`: Adds the required symbol (*) to label if input is required. Default `True`. + +### Label & Localization + +You can set label of your input in different ways: + +- You can use `Label` attribute and directly set the label. But it doesn't auto localize your localization key. So use it as `label="@L["{LocalizationKey}"].Value"`. +- You can set it using `[Display(name="{LocalizationKey}")]` attribute of Asp.Net Core. +- You can just let **abp** find the localization key for the property. It will try to find "DisplayName:{PropertyName}" or "{PropertyName}" localization keys, if `label` or `[DisplayName]` attributes are not set. + +## abp-select + +`abp-select` tag creates a Bootstrap form select for a given c# property. It uses [Asp.Net Core Select Tag Helper](https://docs.microsoft.com/tr-tr/aspnet/core/mvc/views/working-with-forms?view=aspnetcore-3.1#the-select-tag-helper) in background, so every data annotation attribute of `select` tag helper of Asp.Net Core is also valid for `abp-select`. + +`abp-select` tag needs a list of `Microsoft.AspNetCore.Mvc.Rendering.SelectListItem ` to work. It can be provided by `asp-items` attriube on the tag or `[SelectItems()]` attribute on c# property. (if you are using [abp-dynamic-form](Dynamic-forms.md), c# attribute is the only way.) + +`abp-select` supports multiple selection. + +`abp-select` auto-creates a select list for **Enum** properties. No extra data is needed. If property is nullable, an empty key and value is added to top of the auto-generated list. + +Usage: + +````xml + + + + + + + + + +```` + +Model: + +````csharp + public class FormElementsModel : PageModel + { + public SampleModel MyModel { get; set; } + + public List CityList { get; set; } + + public void OnGet() + { + MyModel = new SampleModel(); + + CityList = new List + { + new SelectListItem { Value = "NY", Text = "New York"}, + new SelectListItem { Value = "LDN", Text = "London"}, + new SelectListItem { Value = "IST", Text = "Istanbul"}, + new SelectListItem { Value = "MOS", Text = "Moscow"} + }; + } + + public class SampleModel + { + public string City { get; set; } + + [SelectItems(nameof(CityList))] + public string AnotherCity { get; set; } + + public List MultipleCities { get; set; } + + public CarType MyCarType { get; set; } + + public CarType? MyNullableCarType { get; set; } + } + + public enum CarType + { + Sedan, + Hatchback, + StationWagon, + Coupe + } + } +```` + +### Attributes + +You can set some of the attributes on your c# property, or directly on html tag. If you are going to use this property in a [abp-dynamic-form](Dynamic-forms.md), then you can only set these properties via property attributes. + +#### Property Attributes + +* `[SelectItems()]`: Sets the select data. Parameter should be the name of the data list. (see example above) + +- `[InputInfoText()]`: Sets a small info text for input. You can use a localization key directly. +- `[FormControlSize()]`: Sets size of form-control wrapper element. Available values are + - `AbpFormControlSize.Default` + - `AbpFormControlSize.Small` + - `AbpFormControlSize.Medium` + - `AbpFormControlSize.Large` + +#### Tag Attributes + +- `asp-items`: Sets the select data. This Should be a list of SelectListItem. +- `info`: Sets a small info text for input. You can use a localization key directly. +- `size`: Sets size of form-control wrapper element. Available values are + - `AbpFormControlSize.Default` + - `AbpFormControlSize.Small` + - `AbpFormControlSize.Medium` + - `AbpFormControlSize.Large` +- `label`: Sets the label for input. +- `display-required-symbol`: Adds the required symbol (*) to label if input is required. Default `True`. + +### Label & Localization + +You can set label of your input in different ways: + +- You can use `Label` attribute and directly set the label. But it doesn't auto localize your localization key. So use it as `label="@L["{LocalizationKey}"].Value".` +- You can set it using `[Display(name="{LocalizationKey}")]` attribute of Asp.Net Core. +- You can just let **abp** find the localization key for the property. It will try to find "DisplayName:{PropertyName}" or "{PropertyName}" localization keys. + +Localizations of combobox values are set by `abp-select` for **Enum** property. It searches for "{EnumTypeName}.{EnumPropertyName}" or "{EnumPropertyName}" localization keys. For instance, in the example above, it will use "CarType.StationWagon" or "StationWagon" keys for localization when it localizes combobox values. + +## abp-radio + +`abp-radio` tag creates a Bootstrap form radio group for a given c# property. Usage is very similar to `abp-select` tag. + +Usage: + +````xml + + + +```` + +Model: + +````csharp + public class FormElementsModel : PageModel + { + public SampleModel MyModel { get; set; } + + public List CityList { get; set; } = new List + { + new SelectListItem { Value = "NY", Text = "New York"}, + new SelectListItem { Value = "LDN", Text = "London"}, + new SelectListItem { Value = "IST", Text = "Istanbul"}, + new SelectListItem { Value = "MOS", Text = "Moscow"} + }; + + public void OnGet() + { + MyModel = new SampleModel(); + MyModel.CityRadio = "IST"; + MyModel.CityRadio2 = "MOS"; + } + + public class SampleModel + { + public string CityRadio { get; set; } + + [SelectItems(nameof(CityList))] + public string CityRadio2 { get; set; } + } + } +```` + +### Attributes + +You can set some of the attributes on your c# property, or directly on html tag. If you are going to use this property in a [abp-dynamic-form](Dynamic-forms.md), then you can only set these properties via property attributes. + +#### Property Attributes + +- `[SelectItems()]`: Sets the select data. Parameter should be the name of the data list. (see example above) + +#### Tag Attributes + +- `asp-items`: Sets the select data. This Should be a list of SelectListItem. +- `Inline`: If true, radio buttons will be in single line, next to each other. If false, they will be under each other. \ No newline at end of file diff --git a/docs/en/UI/AspNetCore/Tag-Helpers/Index.md b/docs/en/UI/AspNetCore/Tag-Helpers/Index.md index a7aa0b65d2..aefbb88e01 100644 --- a/docs/en/UI/AspNetCore/Tag-Helpers/Index.md +++ b/docs/en/UI/AspNetCore/Tag-Helpers/Index.md @@ -31,8 +31,8 @@ Here, the list of components those are wrapped by the ABP Framework: ## Form Elements -See [demo](https://bootstrap-taghelpers.abp.io/Components/FormElements). +**Abp Tag Helpers** add new features to standard **Asp.Net Core MVC input & select Tag Helpers** and wrap them with **Bootstrap** form controls. See [Form Elements documentation](Form-elements.md) . -## Dynamic Inputs +## Dynamic Forms -See [demo](https://bootstrap-taghelpers.abp.io/Components/DynamicForms). \ No newline at end of file +**Abp Tag helpers** offer an easy way to build complete **Bootstrap forms**. See [Dynamic Forms documentation](Dynamic-Forms.md). \ No newline at end of file diff --git a/docs/en/docs-nav.json b/docs/en/docs-nav.json index 346c33a118..8b5d41aa59 100644 --- a/docs/en/docs-nav.json +++ b/docs/en/docs-nav.json @@ -5,17 +5,7 @@ "items": [ { "text": "From Startup Templates", - "path": "Getting-Started-With-Startup-Templates.md", - "items": [ - { - "text": "Application with MVC (Razor Pages) UI", - "path": "Getting-Started-AspNetCore-MVC-Template.md" - }, - { - "text": "Application with Angular UI", - "path": "Getting-Started-Angular-Template.md" - } - ] + "path": "Getting-Started.md" }, { "text": "From Empty Projects", @@ -302,7 +292,17 @@ }, { "text": "Tag Helpers", - "path": "UI/AspNetCore/Tag-Helpers/Index.md" + "path": "UI/AspNetCore/Tag-Helpers/Index.md", + "items": [ + { + "text": "Form Elements", + "path": "UI/AspNetCore/Tag-Helpers/Form-elements.md" + }, + { + "text": "Dynamic Forms", + "path": "UI/AspNetCore/Tag-Helpers/Dynamic-Forms.md" + } + ] }, { "text": "Widgets", diff --git a/docs/en/images/bookstore-home.png b/docs/en/images/bookstore-home.png new file mode 100644 index 0000000000..5e5b512220 Binary files /dev/null and b/docs/en/images/bookstore-home.png differ diff --git a/docs/en/images/bookstore-login.png b/docs/en/images/bookstore-login.png new file mode 100644 index 0000000000..cd8bfa9bf9 Binary files /dev/null and b/docs/en/images/bookstore-login.png differ diff --git a/docs/en/images/db-migrator-output.png b/docs/en/images/db-migrator-output.png new file mode 100644 index 0000000000..ace6abb226 Binary files /dev/null and b/docs/en/images/db-migrator-output.png differ diff --git a/docs/en/images/package-manager-console-update-database.png b/docs/en/images/package-manager-console-update-database.png new file mode 100644 index 0000000000..d5bb9c2975 Binary files /dev/null and b/docs/en/images/package-manager-console-update-database.png differ diff --git a/docs/en/images/rn-environment-local-ip.png b/docs/en/images/rn-environment-local-ip.png new file mode 100644 index 0000000000..7e60efff2f Binary files /dev/null and b/docs/en/images/rn-environment-local-ip.png differ diff --git a/docs/en/images/rn-expo-interface.png b/docs/en/images/rn-expo-interface.png new file mode 100644 index 0000000000..f1f405ebf4 Binary files /dev/null and b/docs/en/images/rn-expo-interface.png differ diff --git a/docs/en/images/rn-host-local-ip.png b/docs/en/images/rn-host-local-ip.png new file mode 100644 index 0000000000..8691d749e5 Binary files /dev/null and b/docs/en/images/rn-host-local-ip.png differ diff --git a/docs/en/images/rn-login-iphone.png b/docs/en/images/rn-login-iphone.png new file mode 100644 index 0000000000..2da1d24601 Binary files /dev/null and b/docs/en/images/rn-login-iphone.png differ diff --git a/docs/en/images/rn-tiered-local-ip.png b/docs/en/images/rn-tiered-local-ip.png new file mode 100644 index 0000000000..35168455ab Binary files /dev/null and b/docs/en/images/rn-tiered-local-ip.png differ diff --git a/docs/en/images/solution-files-mvc.png b/docs/en/images/solution-files-mvc.png new file mode 100644 index 0000000000..08bbfb9595 Binary files /dev/null and b/docs/en/images/solution-files-mvc.png differ diff --git a/docs/en/images/solution-files-non-mvc.png b/docs/en/images/solution-files-non-mvc.png new file mode 100644 index 0000000000..880cf20d46 Binary files /dev/null and b/docs/en/images/solution-files-non-mvc.png differ diff --git a/docs/en/images/swagger-ui.png b/docs/en/images/swagger-ui.png new file mode 100644 index 0000000000..7f52269474 Binary files /dev/null and b/docs/en/images/swagger-ui.png differ diff --git a/docs/en/images/vs-app-solution-structure-mongodb.png b/docs/en/images/vs-app-solution-structure-mongodb.png new file mode 100644 index 0000000000..8e0e6ba565 Binary files /dev/null and b/docs/en/images/vs-app-solution-structure-mongodb.png differ diff --git a/docs/en/images/vs-app-solution-structure-tiered.png b/docs/en/images/vs-app-solution-structure-tiered.png new file mode 100644 index 0000000000..fd41ef4b0a Binary files /dev/null and b/docs/en/images/vs-app-solution-structure-tiered.png differ diff --git a/docs/en/images/vs-app-solution-structure.png b/docs/en/images/vs-app-solution-structure.png new file mode 100644 index 0000000000..00d92164e7 Binary files /dev/null and b/docs/en/images/vs-app-solution-structure.png differ diff --git a/docs/en/images/vs-spa-app-backend-structure-mongodb.png b/docs/en/images/vs-spa-app-backend-structure-mongodb.png new file mode 100644 index 0000000000..8f0427c14b Binary files /dev/null and b/docs/en/images/vs-spa-app-backend-structure-mongodb.png differ diff --git a/docs/en/images/vs-spa-app-backend-structure.png b/docs/en/images/vs-spa-app-backend-structure.png new file mode 100644 index 0000000000..2cd394c8eb Binary files /dev/null and b/docs/en/images/vs-spa-app-backend-structure.png differ diff --git a/docs/zh-Hans/Entities.md b/docs/zh-Hans/Entities.md index 96d75895d2..1a059e477f 100644 --- a/docs/zh-Hans/Entities.md +++ b/docs/zh-Hans/Entities.md @@ -379,10 +379,10 @@ public static class IdentityUserExtensions * 这些属性**不容易[自动映射](Object-To-Object-Mapping.md)到其他对象**. * 它**不会**为EF Core在数据库表中**创建字段**,因此在数据库中针对这个字段创建索引或搜索/排序并不容易. -### 额外属性背后的实体 +### 额外属性背后的实体 `IHasExtraProperties` 不限于与实体一起使用. 你可以为任何类型的类实现这个接口,使用 `GetProperty`,`SetProperty` 和其他相关方法. ## 另请参阅 -* [实体设计最佳实践指南](Best-Practices/Entities.md) \ No newline at end of file +* [实体设计最佳实践指南](Best-Practices/Entities.md) diff --git a/docs/zh-Hans/Modules/Index.md b/docs/zh-Hans/Modules/Index.md index 9b44967c53..fb07b5b001 100644 --- a/docs/zh-Hans/Modules/Index.md +++ b/docs/zh-Hans/Modules/Index.md @@ -16,6 +16,7 @@ ABP是一个 **模块化的应用程序框架** 由十多个 **nuget packages** * **Background Jobs**: 用于在使用默认后台作业管理器时保存后台作业. * **Blogging**: 用于创建精美的博客. ABP的[博客](https://blog.abp.io/) 就使用了此模块. * [**Docs**](Docs.md): 用于创建技术文档页面. ABP的[文档](https://abp.io/documents/) 就使用了此模块. +* **Feature Management**: 用于保存和管理功能. * **Identity**: 基于Microsoft Identity管理角色,用户和他们的权限. * **Identity Server**: 集成了IdentityServer4. * **Permission Management**: 用于保存权限. @@ -27,4 +28,4 @@ ABP是一个 **模块化的应用程序框架** 由十多个 **nuget packages** ## 商业应用模块 -[ABP商业](https://commercial.abp.io/)许可证在ABP框架上提供了额外的预构建应用程序模块. 参见ABP商业版提供的[模块列表](https://commercial.abp.io/module). \ No newline at end of file +[ABP商业](https://commercial.abp.io/)许可证在ABP框架上提供了额外的预构建应用程序模块. 参见ABP商业版提供的[模块列表](https://commercial.abp.io/module). diff --git a/docs/zh-Hans/Startup-Templates/Application.md b/docs/zh-Hans/Startup-Templates/Application.md index 78d43759db..ecf57a19cd 100644 --- a/docs/zh-Hans/Startup-Templates/Application.md +++ b/docs/zh-Hans/Startup-Templates/Application.md @@ -139,7 +139,7 @@ ABP是一个模块化的框架,理想的设计是让每个模块都有自己的 初始化种子数据很重要,ABP具有模块化的种子数据基础设施. 种子数据的更多信息,请参阅[文档](../Data-Seeding.md). -虽然创建数据库和应用迁移似乎只对关系数据库有用,但即使您选择NoSQL数据库提供程序(如MongoDB),也会生成此项目. 这时,它会为应用程序提供必要的初始数据. +虽然创建数据库和应用迁移似乎只对关系数据库有用,但即使你选择NoSQL数据库提供程序(如MongoDB),也会生成此项目. 这时,它会为应用程序提供必要的初始数据. * 它依赖 `.EntityFrameworkCore.DbMigrations` 项目 (针对EF Core),因为它需要访问迁移文件. * 它依赖 `.Application.Contracts` 项目,因为它需要访问权限定义在初始化种子数据时为管理员用户赋予所有权限. @@ -270,6 +270,159 @@ ABP使用开源的[IdentityServer4](https://identityserver.io/)框架做应用 `angular/src/environments` 文件夹下的文件含有应用程序的基础配置. +#### AppModule(应用程序模块) + +`AppModule` 是应用程序的根模块. 一些ABP模块和一些基本模块导入到 `AppModule` 中. + +ABP 配置模块也已经导入到 `AppModule` 中, 以满足可延迟加载 ABP 模块的初始需求. + +#### AppRoutingModule(应用程序路由模块) + +在 `AppRoutingModule` 中有可延迟加载的 ABP 模块作为路由. + +> 不应更改ABP模块的路径. + +你应该在 `data` 对象中添加 `routes` 属性, 以便在菜单中添加一个链接来重定向到自定义页面. + +```js +{ + path: 'dashboard', + loadChildren: () => import('./dashboard/dashboard.module').then(m => m.DashboardModule), + canActivate: [AuthGuard, PermissionGuard], + data: { + routes: { + name: 'ProjectName::Menu:Dashboard', + order: 2, + iconClass: 'fa fa-dashboard', + requiredPolicy: 'ProjectName.Dashboard.Host' + } as ABP.Route + } +} +``` +在上面的例子中; +* 如果用户没有登录, AuthGuard 会阻塞访问并重定向到登录页面. +* PermissionGuard 使用 `rotues` 对象的 `requiredPolicy` 属性检查用户的权限. 如果用户未被授权访问该页, 则显示403页. +* `routes` 的 `name` 属性是菜单链接标签. 可以定义本地化 key. +* `routes` 对象的 `iconClass` 属性是菜单链接图标类. +* `routes` 对象的 `requiredPolicy` 属性是访问页面所需的策略 key. + +在上述 `routes` 定义之后, 如果用户被授权, 仪表盘链接将出现在菜单上. + +#### Shared Module(共享模块) + +所有模块可能需要的模块已导入到 `SharedModule`. 你应该将 `SharedModule` 导入所有模块. + +参见 [Sharing Modules(共享模块)](https://angular.io/guide/sharing-ngmodules) 文档. + +#### Environments(环境) + +`src/environments` 文件夹下的文件包含应用程序的基本配置. + +#### Home Module + +Home模块是一个可延迟加载的模块, 它加载应用程序的根地址. + +#### Styles(样式) + +在 `angular.json` 中向 `styles` 数组添加所需的样式文件. `AppComponent` 在主包加载后通过 `LazyLoadService` 加载一些样式文件, 以缩短第一次绘制的时间. + +#### Testing(测试) + +你应该在与要测试的文件相同的文件夹中创建测试. + +参见[测试文档](https://angular.io/guide/testing/). + +#### Depended Packages(依赖包) + +* [NG Bootstrap](https://ng-bootstrap.github.io/) 被用作UI组件库. +* [NGXS](https://www.ngxs.io/) 被用作状态管理库. +* [angular-oauth2-oidc](https://github.com/manfredsteyer/angular-oauth2-oidc) 用于支持OAuth 2和OpenId Connect (OIDC). +* [Chart.js](https://www.chartjs.org/) 用于创建小部件. +* [ngx-validate](https://github.com/ng-turkey/ngx-validate) 用于对交互表单进行动态验证. + +### React Native + +解决方案将[React Native](https://reactnative.dev/)应用程序作为默认值包含在 `react-native` 文件夹中. + +服务器端类似于上面描述的解决方案. `*.HttpApi.Host` 的项目提供 API, 所以 React 本机应用程序使用它. + +React 本机应用程序是用 [Expo](https://expo.io/)生成的. Expo 是一套基于 React Native 构建的工具, 帮助你快速启动一个应用程序, 尽管它有很多功能. + +React Native 应用文件夹结构, 如下图所示: + +![react-native-folder-structure](../images/react-native-folder-structure.png) + +* `App.js` 是应用程序的引导组件. +* `Environment.js` f文件有应用程序的基本配置. 在这个文件中定义了 `prod` and `dev` 配置. +* [Contexts](https://reactjs.org/docs/context.html) 是在 `src/contexts` 文件夹中创建的. +* [Higher order components](https://reactjs.org/docs/higher-order-components.html) 是在 `src/hocs` 文件夹中创建的. +* [Custom hooks](https://reactjs.org/docs/hooks-custom.html#extracting-a-custom-hook) 是在 `src/hooks` 中创建的. +* [Axios interceptors](https://github.com/axios/axios#interceptors) 是在 `src/interceptors` 文件夹中创建. +* 工具函数从 `src/utils` 文件夹导出. + +#### Components(组件) + +可以在所有屏幕上使用的组件是在 `src/components` 文件夹中创建的. 所有组件都是作为一个能够使用 [hooks](https://reactjs.org/docs/hooks-intro.html) 的函数创建的. + +#### Screens(屏幕) + +![react-native-navigation-structure](../images/react-native-navigation-structure.png) + +Screens 是通过在 `src/screens` 文件夹中创建将名称分开的文件夹来创建的. 某些 screens 的某些部分可以拆分为组件. + +每个 screen 都在 `src/navigators` 文件夹中的导航器中使用. + +#### Navigation(导航) + +[React Navigation](https://reactnavigation.org/) 被用作导航库. 导航器是在 `src/navigators` 中创建的. 一个 [drawer](https://reactnavigation.org/docs/drawer-based-navigation/) 导航器和几个 [stack](https://reactnavigation.org/docs/hello-react-navigation/#installing-the-stack-navigator-library) 导航器在此文件夹中创建. 查看 [上图](#screens) 中的导航结构. + +#### State Management(状态管理) + +[Redux](https://redux.js.org/) 被用作状态管理库. [Redux Toolkit](https://redux-toolkit.js.org/) 库被用作高效Redux开发的工具集. + +在 `src/store` 文件夹中创建 Actions, reducers, sagas, selectors. 存储文件夹如下: + +![react-native-store-folder](../images/react-native-store-folder.png) + +* [**Store**](https://redux.js.org/basics/store) 在 `src/store/index.js` 文件中定义. +* [**Actions**](https://redux.js.org/basics/actions/) 是将数据从应用程序发送到存储的有效信息负载. +* [**Reducers**](https://redux.js.org/basics/reducers) 指定应用程序的状态如何更改以响应发送到存储的操作. +* [**Redux-Saga**](https://redux-saga.js.org/) 是一个库, 旨在使应用程序的副作用(即异步的事情, 如数据获取和不纯的事情, 如访问浏览器缓存)更容易管理. Sagas 是在 `src/store/sagas` 文件夹中创建的. +* [**Reselect**](https://github.com/reduxjs/reselect) 库用于创建缓存的选择器. 选择器是在 `src/store/selectors` 文件夹中创建的. + +#### APIs + +[Axios](https://github.com/axios/axios) 用作HTTP客户端库. Axios 实例从 `src/api/API.js` 导出 . 使用相同的配置进行HTTP调用. `src/api` 文件夹中还有为 API 调用创建的 API 文件. + +#### Theming(主题) + +[Native Base](https://nativebase.io/) 被用作UI组件库. 本地基本组件可以很容易地进行自定义。参见 [Native Base customize](https://docs.nativebase.io/Customize.html#Customize) 文档。我们沿着同样的路走。 + +* Native Base 主题变量在 `src/theme/variables` 文件夹中。 +* Native Base 组件样式在 `src/theme/components` 文件夹中。这些文件是用 Native Base's `ejectTheme` 脚本生成的。 +* 组件样式用 `src/theme/overrides` 文件夹下的文件覆盖。 + +#### Testing(单元测试) + +将创建单元测试。 + +参见[测试概述](https://reactjs.org/docs/testing.html)文档。 + +#### Depended Libraries(依赖库) + +* [Native Base](https://nativebase.io/) 用作UI组件库。 +* [React Navigation](https://reactnavigation.org/) 用作导航库。 +* [Axios](https://github.com/axios/axios) 用作HTTP客户端库。 +* [Redux](https://redux.js.org/) 用作状态管理库。 +* [Redux Toolkit](https://redux-toolkit.js.org/) 库被用作高效Redux开发的工具集。 +* [Redux-Saga](https://redux-saga.js.org/) 用于管理异步进程。 +* [Redux Persist](https://github.com/rt2zz/redux-persist) 被用作状态持久化。 +* [Reselect](https://github.com/reduxjs/reselect) 用于创建缓存的选择器。 +* [i18n-js](https://github.com/fnando/i18n-js) 作为国际化库使用。 +* [expo-font](https://docs.expo.io/versions/latest/sdk/font/) 库可以轻松加载字体。 +* [Formik](https://github.com/jaredpalmer/formik) 用于构建表单。 +* [Yup](https://github.com/jquense/yup) 用于表单验证。 + ## 下一步是什么? * 参阅[ASP.NET Core MVC 模板入门](../Getting-Started-AspNetCore-MVC-Template.md)创建此模板的新解决方案并运行它. diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/ru.json b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/ru.json new file mode 100644 index 0000000000..04b2e5cf85 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/ru.json @@ -0,0 +1,12 @@ +{ + "culture": "ru", + "texts": { + "GivenTenantIsNotAvailable": "Данный арендатор недоступен: {0}", + "Tenant": "Арендатор", + "Switch": "переключиться", + "Name": "Имя", + "SwitchTenantHint": "Оставьте поле Имя пустым, чтобы переключиться на администратора.", + "SwitchTenant": "Сменить арендатора", + "NotSelected": "Не выбрано" + } +} diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Module/ModuleTemplateBase.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Module/ModuleTemplateBase.cs index 3faf920ab0..c9976712c9 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Module/ModuleTemplateBase.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Module/ModuleTemplateBase.cs @@ -18,6 +18,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Templates.Module DeleteUnrelatedProjects(context, steps); RandomizeSslPorts(context, steps); + UpdateNuGetConfig(context, steps); CleanupFolderHierarchy(context, steps); return steps; @@ -58,6 +59,11 @@ namespace Volo.Abp.Cli.ProjectBuilding.Templates.Module })); } + private static void UpdateNuGetConfig(ProjectBuildContext context, List steps) + { + steps.Add(new UpdateNuGetConfigStep("/aspnet-core/NuGet.Config")); + } + private void CleanupFolderHierarchy(ProjectBuildContext context, List steps) { steps.Add(new MoveFolderStep("/aspnet-core/", "/")); diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/UpdateNuGetConfigStep.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/UpdateNuGetConfigStep.cs similarity index 95% rename from framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/UpdateNuGetConfigStep.cs rename to framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/UpdateNuGetConfigStep.cs index 1a40eff341..deeb297047 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/UpdateNuGetConfigStep.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/UpdateNuGetConfigStep.cs @@ -4,7 +4,7 @@ using System.Linq; using Volo.Abp.Cli.ProjectBuilding.Building; using Volo.Abp.Cli.ProjectBuilding.Files; -namespace Volo.Abp.Cli.ProjectBuilding.Templates.App +namespace Volo.Abp.Cli.ProjectBuilding.Templates { public class UpdateNuGetConfigStep : ProjectBuildPipelineStep { diff --git a/framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Localization/Resources/AbpDdd/ru.json b/framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Localization/Resources/AbpDdd/ru.json new file mode 100644 index 0000000000..b84f77f8b3 --- /dev/null +++ b/framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Localization/Resources/AbpDdd/ru.json @@ -0,0 +1,6 @@ +{ + "culture": "ru", + "texts": { + "MaxResultCountExceededExceptionMessage": "{0} не может быть больше {1}! Увеличьте {2}.{3} на стороне сервера, чтобы получить больше результатов." + } +} diff --git a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Localization/ru.json b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Localization/ru.json new file mode 100644 index 0000000000..249baa61b2 --- /dev/null +++ b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Localization/ru.json @@ -0,0 +1,23 @@ +{ + "culture": "ru", + "texts": { + "DisplayName:Abp.Mailing.DefaultFromAddress": "Адрес отправления по умолчанию", + "DisplayName:Abp.Mailing.DefaultFromDisplayName": "Имя отправителя по умолчанию", + "DisplayName:Abp.Mailing.Smtp.Host": "Сервер", + "DisplayName:Abp.Mailing.Smtp.Port": "Порт", + "DisplayName:Abp.Mailing.Smtp.UserName": "Имя пользователя", + "DisplayName:Abp.Mailing.Smtp.Password": "Пароль", + "DisplayName:Abp.Mailing.Smtp.Domain": "Домен", + "DisplayName:Abp.Mailing.Smtp.EnableSsl": "Включить SSL", + "DisplayName:Abp.Mailing.Smtp.UseDefaultCredentials": "Использовать учетные данные по умолчанию", + "Description:Abp.Mailing.DefaultFromAddress": "Отправление по умолчанию от адреса.", + "Description:Abp.Mailing.DefaultFromDisplayName": "Имя отправителя по умолчанию.", + "Description:Abp.Mailing.Smtp.Host": "Имя или IP- адрес сервера, используемого для отправки по протоколу SMTP.", + "Description:Abp.Mailing.Smtp.Port": "Порт, используемый для отправки по протоколу SMTP.", + "Description:Abp.Mailing.Smtp.UserName": "Имя пользователя для SMTP-сервера.", + "Description:Abp.Mailing.Smtp.Password": "Пароль для SMTP-сервера.", + "Description:Abp.Mailing.Smtp.Domain": "Домен или имя компьютера, от которого производится SMTP-запрос.", + "Description:Abp.Mailing.Smtp.EnableSsl": "Использовать SSL для подключения к SMTP-серверу.", + "Description:Abp.Mailing.Smtp.UseDefaultCredentials": "Использовать учетные данные для SMTP по умолчанию." + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs index 3ba7092395..b1bb2df421 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs @@ -155,7 +155,6 @@ namespace Volo.Abp.EntityFrameworkCore } ChangeTracker.CascadeDeleteTiming = CascadeTiming.OnSaveChanges; - ChangeTracker.DeleteOrphansTiming = CascadeTiming.OnSaveChanges; ChangeTracker.Tracked += ChangeTracker_Tracked; } diff --git a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs index d5d90ed182..031ea7d99b 100644 --- a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs +++ b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Globalization; using System.Linq; @@ -106,18 +106,10 @@ namespace Volo.Abp.Http.Client.DynamicProxying private async Task MakeRequestAndGetResultAsync(IAbpMethodInvocation invocation) { var responseAsString = await MakeRequestAsync(invocation); - - //TODO: Think on that - if (TypeHelper.IsPrimitiveExtended(typeof(T), true)) + + if (typeof(T) == typeof(string)) { - if (typeof(DateTime).IsAssignableFrom(typeof(T))) - { - return (T)(object)DateTime.Parse(responseAsString.Trim('\"'), CultureInfo.InvariantCulture); - } - else - { - return (T)Convert.ChangeType(responseAsString, typeof(T)); - } + return (T)Convert.ChangeType(responseAsString, typeof(T)); } return JsonSerializer.Deserialize(responseAsString); diff --git a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/UrlBuilder.cs b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/UrlBuilder.cs index dae7853e08..162da88f16 100644 --- a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/UrlBuilder.cs +++ b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/UrlBuilder.cs @@ -6,6 +6,7 @@ using System.Text; using JetBrains.Annotations; using Volo.Abp.Http.Modeling; using Volo.Abp.Http.ProxyScripting.Generators; +using Volo.Abp.Localization; using Volo.Abp.Reflection; namespace Volo.Abp.Http.Client.DynamicProxying @@ -104,12 +105,15 @@ namespace Volo.Abp.Http.Client.DynamicProxying private static string ConvertValueToString([NotNull] object value) { - if (value is DateTime dateTimeValue) + using (CultureHelper.Use(CultureInfo.InvariantCulture)) { - return dateTimeValue.ToUniversalTime().ToString("u"); - } + if (value is DateTime dateTimeValue) + { + return dateTimeValue.ToUniversalTime().ToString("u"); + } - return value.ToString(); + return value.ToString(); + } } } } diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpLocalization/ru.json b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpLocalization/ru.json new file mode 100644 index 0000000000..3f00c8994b --- /dev/null +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpLocalization/ru.json @@ -0,0 +1,7 @@ +{ + "culture": "ru", + "texts": { + "DisplayName:Abp.Localization.DefaultLanguage": "Язык по умолчанию", + "Description:Abp.Localization.DefaultLanguage": "Язык приложения по умолчанию." + } +} diff --git a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/ru.json b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/ru.json new file mode 100644 index 0000000000..2a76578396 --- /dev/null +++ b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/ru.json @@ -0,0 +1,6 @@ +{ + "culture": "ru", + "texts": { + "Menu:Administration": "Администрирование" + } +} diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ru.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ru.json new file mode 100644 index 0000000000..7b48db1a3a --- /dev/null +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ru.json @@ -0,0 +1,62 @@ +{ + "culture": "ru", + "texts": { + "InternalServerErrorMessage": "Во время запроса произошла внутренняя ошибка!", + "ValidationErrorMessage": "Ваш запрос недействителен!", + "ValidationNarrativeErrorMessageTitle": "При проверке были обнаружены следующие ошибки.", + "DefaultErrorMessage": "Произошла ошибка!", + "DefaultErrorMessageDetail": "Сведения об ошибке не были предоставлены сервером.", + "DefaultErrorMessage401": "Вы не авторизированы!", + "DefaultErrorMessage401Detail": "Вы должны Войти, чтобы выполнить эту операцию.", + "DefaultErrorMessage403": "Вы не авторизованы!", + "DefaultErrorMessage403Detail": "У вас нет доступа к выполнению этой операции!", + "DefaultErrorMessage404": "Ресурс не найден!", + "DefaultErrorMessage404Detail": "Запрошенный ресурс не удалось найти на сервере!", + "EntityNotFoundErrorMessage": "Нет объекта {0} с id = {1}!", + "Languages": "Языки", + "Error": "Ошибка", + "AreYouSure": "Вы уверены?", + "Cancel": "Отмена", + "Yes": "Да", + "No": "Нет", + "Ok": "ОК", + "Close": "Закрыть", + "Save": "Сохранить", + "SavingWithThreeDot": "Сохранение...", + "Actions": "Действия", + "Delete": "Удалить", + "Edit": "Редактировать", + "Refresh": "Обновить", + "Language": "Язык", + "LoadMore": "Загрузить еще", + "ProcessingWithThreeDot": "Обработка...", + "LoadingWithThreeDot": "Загрузка...", + "Welcome": "Добро пожаловать", + "Login": "Войти", + "Register": "Зарегистрироваться", + "Logout": "Выйти", + "Submit": "Подтвердить", + "Back": "Назад", + "PagerSearch": "Поиск", + "PagerNext": "Следующее", + "PagerPrevious": "Предыдущее", + "PagerFirst": "Первая", + "PagerLast": "Последняя", + "PagerInfo": "Записи с _START_ до _END_ из _TOTAL_ записей", + "PagerInfoEmpty": "Записи с 0 до 0 из 0 записей.", + "PagerInfoFiltered": "(отфильтровано из _MAX_ записей)", + "NoDataAvailableInDatatable": "Данные в таблице отсутствуют", + "PagerShowMenuEntries": "Показать _MENU_ записей", + "DatatableActionDropdownDefaultText": "Действия", + "ChangePassword": "Изменить пароль", + "PersonalInfo": "Мой профиль", + "AreYouSureYouWantToCancelEditingWarningMessage": "У вас есть несохраненные изменения.", + "UnhandledException": "Непредвиденная ошибка!", + "401Message": "Неавторизованный", + "403Message": "В доступе отказано", + "404Message": "Страница не найдена", + "500Message": "Внутренняя ошибка сервера", + "GoHomePage": "Вернуться на главную страницу", + "GoBack": "Вернуться назад" + } +} diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/Localization/ru.json b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/Localization/ru.json new file mode 100644 index 0000000000..6272fdf534 --- /dev/null +++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/Localization/ru.json @@ -0,0 +1,34 @@ +{ + "culture": "ru", + "texts": { + "'{0}' and '{1}' do not match.": "'{0}' и '{1}' не совпадают.", + "The {0} field is not a valid credit card number.": "Поле {0} не содержит действительный номер кредитной карты.", + "{0} is not valid.": "Значение {0} недействительно.", + "The {0} field is not a valid e-mail address.": "Поле {0} не содержит действительный адрес электронной почты.", + "The {0} field only accepts files with the following extensions: {1}": "В поле {0} вы можете загрузить файлы следующих форматов: {1}", + "The field {0} must be a string or array type with a maximum length of '{1}'.": "Поле {0} должно иметь тип строки или массива с максимальной длиной '{1}'.", + "The field {0} must be a string or array type with a minimum length of '{1}'.": "Поле {0} должно иметь тип строки или массива с минимальной длиной '{1}'.", + "The {0} field is not a valid phone number.": "Поле {0} не содержит действительный номер телефона.", + "The field {0} must be between {1} and {2}.": "Поле {0} должно находиться между {1} и {2}.", + "The field {0} must match the regular expression '{1}'.": "Поле {0} должно соответствовать регулярному выражению '{1}'.", + "The {0} field is required.": "Поле {0} необходимо заполнить.", + "The field {0} must be a string with a maximum length of {1}.": "Поле {0} должно быть строкой с максимальной длиной {1}.", + "The field {0} must be a string with a minimum length of {2} and a maximum length of {1}.": "Поле {0} должно быть строкой с минимальной длиной {2} и максимальной длиной {1}.", + "The {0} field is not a valid fully-qualified http, https, or ftp URL.": "Поле {0} не является действительным полным http, https или ftp адресом.", + "The field {0} is invalid.": "Значение в поле {0} недопустимо.", + "ThisFieldIsNotAValidCreditCardNumber.": "Это поле не содержит действительный номер кредитной карты.", + "ThisFieldIsNotValid.": "Значение в этом поле недействительно.", + "ThisFieldIsNotAValidEmailAddress.": "Это поле не содержит действительный адрес электронной почты.", + "ThisFieldOnlyAcceptsFilesWithTheFollowingExtensions:{0}": "Вы можете загрузить файлы только следующих форматов: {0}", + "ThisFieldMustBeAStringOrArrayTypeWithAMaximumLengthoOf{0}": "Это поле должно иметь тип строки или массива с максимальной длиной '{0}'.", + "ThisFieldMustBeAStringOrArrayTypeWithAMinimumLengthOf{0}": "Это поле должно иметь тип строки или массива с минимальной длиной '{0}'.", + "ThisFieldIsNotAValidPhoneNumber.": "Это поле не содержит действительный номер телефона.", + "ThisFieldMustBeBetween{0}And{1}": "Это поле должно быть между {0} и {1}.", + "ThisFieldMustMatchTheRegularExpression{0}": "Это поле должно соответствовать регулярному выражению '{0}'.", + "ThisFieldIsRequired.": "Это обязательное поле.", + "ThisFieldMustBeAStringWithAMaximumLengthOf{0}": "Это поле должно быть строкой с максимальной длиной {0}.", + "ThisFieldMustBeAStringWithAMinimumLengthOf{1}AndAMaximumLengthOf{0}": "Это поле должно быть строкой с минимальной длиной {1} и максимальной длиной {0}.", + "ThisFieldIsNotAValidFullyQualifiedHttpHttpsOrFtpUrl": "Значение в поле не является действительным полным http, https или ftp адресом.", + "ThisFieldIsInvalid.": "Значение в этом поле недопустимо." + } +} diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreTestModule.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreTestModule.cs index e19d939cba..240211d74d 100644 --- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreTestModule.cs +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreTestModule.cs @@ -1,4 +1,4 @@ -using System; +using System; using Microsoft.Data.Sqlite; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; @@ -38,6 +38,11 @@ namespace Volo.Abp.EntityFrameworkCore { opt.DefaultWithDetailsFunc = q => q.Include(p => p.Phones); }); + + options.Entity(opt => + { + opt.DefaultWithDetailsFunc = q => q.Include(p => p.Books); + }); }); var sqliteConnection = CreateDatabaseAndGetConnection(); diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/DataFiltering/SoftDelete_Tests.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/DataFiltering/SoftDelete_Tests.cs index 7d92ed3a87..1a85cb291f 100644 --- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/DataFiltering/SoftDelete_Tests.cs +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/DataFiltering/SoftDelete_Tests.cs @@ -1,9 +1,49 @@ -using Volo.Abp.TestApp.Testing; +using System; +using System.Linq; +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.Domain.Repositories; +using Volo.Abp.TestApp; +using Volo.Abp.TestApp.Domain; +using Volo.Abp.TestApp.Testing; +using Volo.Abp.Uow; +using Xunit; namespace Volo.Abp.EntityFrameworkCore.DataFiltering { + /// + /// This is just to test the cascade delete behavior of EF Core's navigation properties. + /// Soft delete is usually only used in the aggregate root entity instead . + /// public class SoftDelete_Tests : SoftDelete_Tests { - + [Fact] + public async Task Navigation_Properties_Cascade_Delete_Test() + { + var authorRepository = GetRequiredService>(); + var authorId = Guid.NewGuid(); + + var author = new Author(authorId, "tom"); + author.Books.Add(new Book(authorId, Guid.NewGuid(), "asp net core")); + author.Books.Add(new Book(authorId, Guid.NewGuid(),"c#")); + await authorRepository.InsertAsync(author); + + await WithUnitOfWorkAsync(async () => + { + var author = await authorRepository.GetAsync(authorId); + author.Books.ShouldNotBeEmpty(); + author.Books.Count.ShouldBe(2); + + author.Books.Clear(); + await authorRepository.UpdateAsync(author); + }); + + using (DataFilter.Disable()) + { + author = await authorRepository.GetAsync(authorId); + author.Books.ShouldNotBeEmpty(); + author.Books.ShouldAllBe(x => x.IsDeleted); + } + } } } diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/TestMigrationsDbContext.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/TestMigrationsDbContext.cs index da66392a18..23137f0f0c 100644 --- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/TestMigrationsDbContext.cs +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/TestMigrationsDbContext.cs @@ -1,4 +1,4 @@ -using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore.TestApp.SecondContext; using Volo.Abp.EntityFrameworkCore.TestApp.ThirdDbContext; using Volo.Abp.TestApp.Domain; @@ -16,7 +16,9 @@ namespace Volo.Abp.EntityFrameworkCore public DbSet Books { get; set; } public DbSet EntityWithIntPks { get; set; } - + + public DbSet Author { get; set; } + public TestMigrationsDbContext(DbContextOptions options) : base(options) { diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/Domain/Author.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/Domain/Author.cs new file mode 100644 index 0000000000..a1bb46470b --- /dev/null +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/Domain/Author.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using Volo.Abp.Domain.Entities; + +namespace Volo.Abp.TestApp.Domain +{ + public class Author : AggregateRoot + { + public string Name { get; set; } + + public ICollection Books { get; set; } + + private Author() + { + + } + + public Author(Guid id, string name) + : base(id) + { + Name = name; + Books = new List(); + } + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/Domain/Book.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/Domain/Book.cs new file mode 100644 index 0000000000..c8323f79d9 --- /dev/null +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/Domain/Book.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using Volo.Abp.Domain.Entities; + +namespace Volo.Abp.TestApp.Domain +{ + public class Book : Entity, ISoftDelete + { + public Guid AuthorId { get; set; } + + public string Title { get; set; } + + private Book() + { + + } + + public Book(Guid authorId, Guid id, string title) + { + Id = id; + AuthorId = authorId; + Title = title; + } + + public bool IsDeleted { get; set; } + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/TestAppDbContext.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/TestAppDbContext.cs index 289364411d..da8bbc8a6c 100644 --- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/TestAppDbContext.cs +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/TestAppDbContext.cs @@ -17,6 +17,8 @@ namespace Volo.Abp.TestApp.EntityFrameworkCore public DbSet EntityWithIntPks { get; set; } + public DbSet Author { get; set; } + public TestAppDbContext(DbContextOptions options) : base(options) { diff --git a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/ExtraProperties_Tests.cs b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/ExtraProperties_Tests.cs index 47f4c6a4cd..c624bb7a94 100644 --- a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/ExtraProperties_Tests.cs +++ b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/ExtraProperties_Tests.cs @@ -1,8 +1,10 @@ -using System.Threading.Tasks; +using System; +using System.Threading.Tasks; using Shouldly; using Volo.Abp.Data; using Volo.Abp.Modularity; using Volo.Abp.TestApp.Domain; +using Volo.Abp.Timing; using Xunit; namespace Volo.Abp.TestApp.Testing @@ -50,5 +52,45 @@ namespace Volo.Abp.TestApp.Testing london2.HasProperty("Population").ShouldBeTrue(); london2.GetProperty("Population").ShouldBe(11_000_042); } + + [Fact] + public async Task Testing_With_Different_Primitive_Types() + { + var clock = GetRequiredService(); + + var london = await CityRepository.FindByNameAsync("London"); + + london.SetProperty("IntProp", 42); + london.SetProperty("DateTimeProp", + DateTime.SpecifyKind(new DateTime( + 2020, + 04, + 16, + 22, + 05, + 41, + 999 + ), + DateTimeKind.Utc + ) + ); + + await CityRepository.UpdateAsync(london); + + var london2 = await CityRepository.FindByNameAsync("London"); + + london2.HasProperty("IntProp").ShouldBeTrue(); + london2.GetProperty("IntProp").ShouldBe(42); + + london2.HasProperty("DateTimeProp").ShouldBeTrue(); + var dateTimeProp = london2.GetProperty("DateTimeProp"); + dateTimeProp.Year.ShouldBe(2020); + dateTimeProp.Month.ShouldBe(04); + dateTimeProp.Day.ShouldBe(16); + dateTimeProp.Hour.ShouldBe(22); + dateTimeProp.Minute.ShouldBe(05); + dateTimeProp.Second.ShouldBe(41); + dateTimeProp.Millisecond.ShouldBe(999); + } } } diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/ru.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/ru.json new file mode 100644 index 0000000000..7f366bd782 --- /dev/null +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/ru.json @@ -0,0 +1,45 @@ +{ + "culture": "ru", + "texts": { + "UserName": "Имя пользователя", + "EmailAddress": "Адрес электронной почты", + "UserNameOrEmailAddress": "Имя пользователя или адрес электронной почты", + "Password": "Пароль", + "RememberMe": "Запомнить меня", + "UseAnotherServiceToLogin": "Использовать сторонний сервис для входа", + "UserLockedOutMessage": "Пользователь заблокирован из-за большого количества попыток входа. Пожалуйста, попробуйте позднее.", + "InvalidUserNameOrPassword": "Неправильные имя пользователя и/или пароль!", + "LoginIsNotAllowed": "Вы не можете войти. Вам необходимо подтвердить электронную почту или телефон.", + "SelfRegistrationDisabledMessage": "Самостоятельная регистрация не предусмотрена. Пожалуйста, свяжитесь с администраром для получения доступа.", + "LocalLoginDisabledMessage": "Локальный вход отключен.", + "Login": "Войти", + "Cancel": "Отмена", + "Register": "Регистрация", + "AreYouANewUser": "Новый пользователь?", + "AlreadyRegistered": "Уже зарегистрированы?", + "InvalidLoginRequest": "Неправильный запрос", + "ThereAreNoLoginSchemesConfiguredForThisClient": "Не найдено схемы для входа с текущим клиентским приложением.", + "LogInUsingYourProviderAccount": "Войти использую свой {0} аккаунт", + "DisplayName:CurrentPassword": "Текущий пароль", + "DisplayName:NewPassword": "Новый пароль", + "DisplayName:NewPasswordConfirm": "Повторите новый пароль", + "PasswordChangedMessage": "Ваш пароль успешно изменен.", + "DisplayName:UserName": "Имя пользователя", + "DisplayName:Email": "Email", + "DisplayName:Name": "Имя", + "DisplayName:Surname": "Фамилия", + "DisplayName:Password": "Пароль", + "DisplayName:EmailAddress": "Электронная почта", + "DisplayName:PhoneNumber": "Номер телефона", + "PersonalSettings": "Персональные настройки", + "PersonalSettingsSaved": "Персональные настройки сохранены", + "PasswordChanged": "Пароль изменен", + "NewPasswordConfirmFailed": "Пожалуйста подтвердите новый пароль.", + "Manage": "Управление учетной записью", + "ManageYourProfile": "Настройки", + "DisplayName:Abp.Account.IsSelfRegistrationEnabled": "Самостоятельная регистрация включена", + "Description:Abp.Account.IsSelfRegistrationEnabled": "Позволяет новым пользователям регистрироваться самостоятельно.", + "DisplayName:Abp.Account.EnableLocalLogin": "Вход с помощью локальной учетной записи приложения", + "Description:Abp.Account.EnableLocalLogin": "Указывает на то, разрешено ли пользователям входить с помощью локальной учетной записи приложения." + } +} diff --git a/modules/account/src/Volo.Abp.Account.Web.IdentityServer/Pages/Consent.cshtml.cs b/modules/account/src/Volo.Abp.Account.Web.IdentityServer/Pages/Consent.cshtml.cs index 261408d623..a0f0543765 100644 --- a/modules/account/src/Volo.Abp.Account.Web.IdentityServer/Pages/Consent.cshtml.cs +++ b/modules/account/src/Volo.Abp.Account.Web.IdentityServer/Pages/Consent.cshtml.cs @@ -42,7 +42,7 @@ namespace Volo.Abp.Account.Web.Pages _resourceStore = resourceStore; } - public virtual async Task OnGet() + public virtual async Task OnGet() { var request = await _interaction.GetAuthorizationContextAsync(ReturnUrl); if (request == null) @@ -74,6 +74,8 @@ namespace Volo.Abp.Account.Web.Pages { ConsentInput.ApiScopes.Add(GetOfflineAccessScope(true)); } + + return Page(); } public virtual async Task OnPost(string userDecision) diff --git a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Logout.cshtml.cs b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Logout.cshtml.cs index de62eb370d..8cb2c2bc1e 100644 --- a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Logout.cshtml.cs +++ b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Logout.cshtml.cs @@ -24,9 +24,9 @@ namespace Volo.Abp.Account.Web.Pages.Account return RedirectToPage("/Account/Login"); } - public virtual Task OnPostAsync() + public virtual Task OnPostAsync() { - return Task.CompletedTask; + return Task.FromResult(Page()); } } } diff --git a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Manage.cshtml.cs b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Manage.cshtml.cs index 58614de744..deed56b736 100644 --- a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Manage.cshtml.cs +++ b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Manage.cshtml.cs @@ -1,6 +1,7 @@ using System.ComponentModel.DataAnnotations; using System.Threading.Tasks; using Volo.Abp.Identity; +using Microsoft.AspNetCore.Mvc; namespace Volo.Abp.Account.Web.Pages.Account { @@ -17,16 +18,18 @@ namespace Volo.Abp.Account.Web.Pages.Account ProfileAppService = profileAppService; } - public virtual async Task OnGetAsync() + public virtual async Task OnGetAsync() { var user = await ProfileAppService.GetAsync(); PersonalSettingsInfoModel = ObjectMapper.Map(user); + + return Page(); } - public virtual Task OnPostAsync() + public virtual Task OnPostAsync() { - return Task.CompletedTask; + return Task.FromResult(Page()); } } diff --git a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Register.cshtml.cs b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Register.cshtml.cs index db085d6587..3b5a5b2cd1 100644 --- a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Register.cshtml.cs +++ b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Register.cshtml.cs @@ -31,9 +31,11 @@ namespace Volo.Abp.Account.Web.Pages.Account AccountAppService = accountAppService; } - public virtual async Task OnGetAsync() + public virtual async Task OnGetAsync() { await CheckSelfRegistrationAsync(); + + return Page(); } public virtual async Task OnPostAsync() diff --git a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/SendSecurityCode.cshtml.cs b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/SendSecurityCode.cshtml.cs index 94a52cd0bd..56f2e44b85 100644 --- a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/SendSecurityCode.cshtml.cs +++ b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/SendSecurityCode.cshtml.cs @@ -41,9 +41,9 @@ namespace Volo.Abp.Account.Web.Pages.Account //); } - public virtual Task OnPostAsync() + public virtual Task OnPostAsync() { - return Task.CompletedTask; + return Task.FromResult(Page()); } } } \ No newline at end of file diff --git a/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Localization/Resources/ru.json b/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Localization/Resources/ru.json new file mode 100644 index 0000000000..898d363cef --- /dev/null +++ b/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Localization/Resources/ru.json @@ -0,0 +1,47 @@ +{ + "culture": "ru", + "texts": { + "Menu:Blogs": "Блоги", + "Menu:BlogManagement": "Управление блогом", + "Title": "Заголовок", + "Delete": "Удалить", + "Reply": "Ответить", + "ReplyTo": "Ответить {0}", + "ContinueReading": "Продолжить чтение", + "DaysAgo": "{0} дней назад", + "YearsAgo": "{0} лет назад", + "MonthsAgo": "{0} месяцев назад", + "WeeksAgo": "{0} недель назад", + "MinutesAgo": "{0} минут назад", + "SecondsAgo": "{0} секунд назад", + "HoursAgo": "{0} часов назад", + "Now": "сейчас", + "Content": "Содержание", + "SeeAll": "Увидеть все", + "PopularTags": "Популярные тэги", + "WiewsWithCount": "{0} просмотров", + "LastPosts": "Последние записи", + "LeaveComment": "Оставить комментарий", + "TagsInThisArticle": "Теги в этой статье", + "Posts": "Записи", + "Edit": "Редактировать", + "BLOG": "БЛОГ", + "CommentDeletionWarningMessage": "Комментарий будет удален.", + "PostDeletionWarningMessage": "Запись будет удалена.", + "BlogDeletionWarningMessage": "Блог будет удален.", + "AreYouSure": "Вы уверены?", + "CommentWithCount": "{0} комментариев", + "Comment": "Комментарий", + "ShareOnTwitter": "Поделиться в Twitter", + "CoverImage": "Обложка", + "CreateANewPost": "Создать новый пост", + "CreateANewBlog": "Создать новый блог", + "WhatIsNew": "Что нового?", + "Name": "Имя", + "ShortName": "Фамилия", + "CreationTime": "Время создания", + "Description": "Описание", + "Blogs": "Блоги", + "Tags": "Теги" + } +} diff --git a/modules/blogging/src/Volo.Blogging.Web/Pages/Admin/Blogs/Create.cshtml.cs b/modules/blogging/src/Volo.Blogging.Web/Pages/Admin/Blogs/Create.cshtml.cs index c23661a0a2..f8c40a1b01 100644 --- a/modules/blogging/src/Volo.Blogging.Web/Pages/Admin/Blogs/Create.cshtml.cs +++ b/modules/blogging/src/Volo.Blogging.Web/Pages/Admin/Blogs/Create.cshtml.cs @@ -24,7 +24,7 @@ namespace Volo.Blogging.Pages.Admin.Blogs _authorization = authorization; } - public async Task OnGetAsync() + public virtual async Task OnGetAsync() { if (!await _authorization.IsGrantedAsync(BloggingPermissions.Blogs.Create)) { @@ -34,7 +34,7 @@ namespace Volo.Blogging.Pages.Admin.Blogs return Page(); } - public async Task OnPostAsync() + public virtual async Task OnPostAsync() { var blogDto = ObjectMapper.Map(Blog); diff --git a/modules/blogging/src/Volo.Blogging.Web/Pages/Admin/Blogs/Edit.cshtml.cs b/modules/blogging/src/Volo.Blogging.Web/Pages/Admin/Blogs/Edit.cshtml.cs index 9a15efd829..9c40720261 100644 --- a/modules/blogging/src/Volo.Blogging.Web/Pages/Admin/Blogs/Edit.cshtml.cs +++ b/modules/blogging/src/Volo.Blogging.Web/Pages/Admin/Blogs/Edit.cshtml.cs @@ -29,7 +29,7 @@ namespace Volo.Blogging.Pages.Admin.Blogs _authorization = authorization; } - public async Task OnGetAsync() + public virtual async Task OnGetAsync() { if (!await _authorization.IsGrantedAsync(BloggingPermissions.Blogs.Update)) { @@ -43,7 +43,7 @@ namespace Volo.Blogging.Pages.Admin.Blogs return Page(); } - public async Task OnPostAsync() + public virtual async Task OnPostAsync() { await _blogAppService.Update(Blog.Id, new UpdateBlogDto() { @@ -51,6 +51,8 @@ namespace Volo.Blogging.Pages.Admin.Blogs ShortName = Blog.ShortName, Description = Blog.Description }); + + return Page(); } public class BlogEditViewModel diff --git a/modules/blogging/src/Volo.Blogging.Web/Pages/Admin/Blogs/Index.cshtml.cs b/modules/blogging/src/Volo.Blogging.Web/Pages/Admin/Blogs/Index.cshtml.cs index 367f19d60c..038f2e63f3 100644 --- a/modules/blogging/src/Volo.Blogging.Web/Pages/Admin/Blogs/Index.cshtml.cs +++ b/modules/blogging/src/Volo.Blogging.Web/Pages/Admin/Blogs/Index.cshtml.cs @@ -15,7 +15,7 @@ namespace Volo.Blogging.Pages.Admin.Blogs _authorization = authorization; } - public async Task OnGetAsync() + public virtual async Task OnGetAsync() { if (!await _authorization.IsGrantedAsync(BloggingPermissions.Blogs.Management)) { diff --git a/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Index.cshtml.cs b/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Index.cshtml.cs index cf16556c66..2835b05dc5 100644 --- a/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Index.cshtml.cs +++ b/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Index.cshtml.cs @@ -19,7 +19,7 @@ namespace Volo.Blogging.Pages.Blog _blogAppService = blogAppService; } - public async Task OnGetAsync() + public virtual async Task OnGetAsync() { var result = await _blogAppService.GetListAsync(); diff --git a/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Detail.cshtml.cs b/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Detail.cshtml.cs index f6e86a2218..c2e9eb8ec8 100644 --- a/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Detail.cshtml.cs +++ b/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Detail.cshtml.cs @@ -46,12 +46,14 @@ namespace Volo.Blogging.Pages.Blog.Posts _commentAppService = commentAppService; } - public async Task OnGetAsync() + public virtual async Task OnGetAsync() { await GetData(); + + return Page(); } - public async Task OnPostAsync() + public virtual async Task OnPostAsync() { var comment = await _commentAppService.CreateAsync(new CreateCommentDto() { @@ -63,6 +65,8 @@ namespace Volo.Blogging.Pages.Blog.Posts FocusCommentId = comment.Id; await GetData(); + + return Page(); } private async Task GetData() diff --git a/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Edit.cshtml.cs b/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Edit.cshtml.cs index 2203aacbea..90e9209645 100644 --- a/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Edit.cshtml.cs +++ b/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Edit.cshtml.cs @@ -33,7 +33,7 @@ namespace Volo.Blogging.Pages.Blog.Posts _authorization = authorization; } - public async Task OnGetAsync() + public virtual async Task OnGetAsync() { if (!await _authorization.IsGrantedAsync(BloggingPermissions.Posts.Update)) { @@ -47,7 +47,7 @@ namespace Volo.Blogging.Pages.Blog.Posts return Page(); } - public async Task OnPostAsync() + public virtual async Task OnPostAsync() { var post = new UpdatePostDto { diff --git a/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Index.cshtml.cs b/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Index.cshtml.cs index f27d4e8f05..0b0597c60f 100644 --- a/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Index.cshtml.cs +++ b/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Index.cshtml.cs @@ -35,11 +35,13 @@ namespace Volo.Blogging.Pages.Blog.Posts _tagAppService = tagAppService; } - public async Task OnGetAsync() + public virtual async Task OnGetAsync() { Blog = await _blogAppService.GetByShortNameAsync(BlogShortName); Posts = (await _postAppService.GetListByBlogIdAndTagName(Blog.Id, TagName)).Items; PopularTags = (await _tagAppService.GetPopularTags(Blog.Id, new GetPopularTagsInput {ResultCount = 10, MinimumPostCount = 2})); + + return Page(); } } } \ No newline at end of file diff --git a/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/New.cshtml.cs b/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/New.cshtml.cs index 353e469590..11c853b30c 100644 --- a/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/New.cshtml.cs +++ b/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/New.cshtml.cs @@ -35,7 +35,7 @@ namespace Volo.Blogging.Pages.Blog.Posts _blogOptions = blogOptions.Value; } - public async Task OnGetAsync() + public virtual async Task OnGetAsync() { if (!await _authorization.IsGrantedAsync(BloggingPermissions.Posts.Create)) { @@ -51,7 +51,7 @@ namespace Volo.Blogging.Pages.Blog.Posts return Page(); } - public async Task OnPost() + public virtual async Task OnPost() { var blog = await _blogAppService.GetAsync(Post.BlogId); diff --git a/modules/client-simulation/src/Volo.ClientSimulation.Web/Pages/ClientSimulation/Index.cshtml.cs b/modules/client-simulation/src/Volo.ClientSimulation.Web/Pages/ClientSimulation/Index.cshtml.cs index 8636bf2567..823be7aa53 100644 --- a/modules/client-simulation/src/Volo.ClientSimulation.Web/Pages/ClientSimulation/Index.cshtml.cs +++ b/modules/client-simulation/src/Volo.ClientSimulation.Web/Pages/ClientSimulation/Index.cshtml.cs @@ -1,13 +1,14 @@ using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; namespace Volo.ClientSimulation.Pages.ClientSimulation { public class IndexModel : PageModel { - public async Task OnGetAsync() + public virtual Task OnGetAsync() { - + return Task.FromResult(Page()); } } } \ No newline at end of file diff --git a/modules/client-simulation/src/Volo.ClientSimulation.Web/Pages/ClientSimulation/SimulationArea.cshtml.cs b/modules/client-simulation/src/Volo.ClientSimulation.Web/Pages/ClientSimulation/SimulationArea.cshtml.cs index e55f504f10..094e8358e2 100644 --- a/modules/client-simulation/src/Volo.ClientSimulation.Web/Pages/ClientSimulation/SimulationArea.cshtml.cs +++ b/modules/client-simulation/src/Volo.ClientSimulation.Web/Pages/ClientSimulation/SimulationArea.cshtml.cs @@ -16,19 +16,19 @@ namespace Volo.ClientSimulation.Pages.ClientSimulation Simulation = simulation; } - public Task OnGetAsync() + public virtual Task OnGetAsync() { Snapshot = Simulation.CreateSnapshot(); - return Task.CompletedTask; + return Task.FromResult(Page()); } - public async Task OnPostStartAsync() + public virtual async Task OnPostStartAsync() { Simulation.Start(); return new NoContentResult(); } - public async Task OnPostStopAsync() + public virtual async Task OnPostStopAsync() { Simulation.Stop(); return new NoContentResult(); diff --git a/modules/docs/app/VoloDocs.Web/Localization/Resources/VoloDocs/Web/ru.json b/modules/docs/app/VoloDocs.Web/Localization/Resources/VoloDocs/Web/ru.json new file mode 100644 index 0000000000..e0e5094cc1 --- /dev/null +++ b/modules/docs/app/VoloDocs.Web/Localization/Resources/VoloDocs/Web/ru.json @@ -0,0 +1,10 @@ +{ + "culture": "ru", + "texts": { + "DocsTitle": "VoloDocs", + "WelcomeVoloDocs": "Добро пожаловать в VoloDocs!", + "NoProjectWarning": "Отсутствует определение проекта!", + "CreateYourFirstProject": "Нажмите здесь, чтобы добавить свой первый проект", + "NoProject": "Нет проекта!" + } +} diff --git a/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml.cs b/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml.cs index 537d650f83..8e4a26db44 100644 --- a/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml.cs +++ b/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml.cs @@ -24,7 +24,7 @@ namespace VoloDocs.Web.Pages _urlUiOptions = urlOptions.Value; } - public async Task OnGetAsync() + public virtual async Task OnGetAsync() { var projects = await _projectAppService.GetListAsync(); diff --git a/modules/docs/app/VoloDocs.Web/wwwroot/libs/abp/utils/abp-utils.umd.js b/modules/docs/app/VoloDocs.Web/wwwroot/libs/abp/utils/abp-utils.umd.js new file mode 100644 index 0000000000..7d35c09db1 --- /dev/null +++ b/modules/docs/app/VoloDocs.Web/wwwroot/libs/abp/utils/abp-utils.umd.js @@ -0,0 +1,600 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('just-compare')) : + typeof define === 'function' && define.amd ? define('@abp/utils', ['exports', 'just-compare'], factory) : + (global = global || self, factory((global.abp = global.abp || {}, global.abp.utils = global.abp.utils || {}, global.abp.utils.common = {}), global.compare)); +}(this, (function (exports, compare) { 'use strict'; + + compare = compare && Object.prototype.hasOwnProperty.call(compare, 'default') ? compare['default'] : compare; + + /*! ***************************************************************************** + Copyright (c) Microsoft Corporation. All rights reserved. + Licensed under the Apache License, Version 2.0 (the "License"); you may not use + this file except in compliance with the License. You may obtain a copy of the + License at http://www.apache.org/licenses/LICENSE-2.0 + + THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED + WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, + MERCHANTABLITY OR NON-INFRINGEMENT. + + See the Apache Version 2.0 License for specific language governing permissions + and limitations under the License. + ***************************************************************************** */ + /* global Reflect, Promise */ + + var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + + function __extends(d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + } + + var __assign = function() { + __assign = Object.assign || function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); + }; + + function __rest(s, e) { + var t = {}; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) + t[p] = s[p]; + if (s != null && typeof Object.getOwnPropertySymbols === "function") + for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { + if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) + t[p[i]] = s[p[i]]; + } + return t; + } + + function __decorate(decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; + } + + function __param(paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } + } + + function __metadata(metadataKey, metadataValue) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue); + } + + function __awaiter(thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); + } + + function __generator(thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } + } + + function __exportStar(m, exports) { + for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; + } + + function __values(o) { + var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; + if (m) return m.call(o); + if (o && typeof o.length === "number") return { + next: function () { + if (o && i >= o.length) o = void 0; + return { value: o && o[i++], done: !o }; + } + }; + throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); + } + + function __read(o, n) { + var m = typeof Symbol === "function" && o[Symbol.iterator]; + if (!m) return o; + var i = m.call(o), r, ar = [], e; + try { + while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); + } + catch (error) { e = { error: error }; } + finally { + try { + if (r && !r.done && (m = i["return"])) m.call(i); + } + finally { if (e) throw e.error; } + } + return ar; + } + + function __spread() { + for (var ar = [], i = 0; i < arguments.length; i++) + ar = ar.concat(__read(arguments[i])); + return ar; + } + + function __spreadArrays() { + for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; + for (var r = Array(s), k = 0, i = 0; i < il; i++) + for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) + r[k] = a[j]; + return r; + }; + + function __await(v) { + return this instanceof __await ? (this.v = v, this) : new __await(v); + } + + function __asyncGenerator(thisArg, _arguments, generator) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var g = generator.apply(thisArg, _arguments || []), i, q = []; + return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; + function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } + function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function fulfill(value) { resume("next", value); } + function reject(value) { resume("throw", value); } + function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } + } + + function __asyncDelegator(o) { + var i, p; + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; } : f; } + } + + function __asyncValues(o) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var m = o[Symbol.asyncIterator], i; + return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); + function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } + function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } + } + + function __makeTemplateObject(cooked, raw) { + if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; } + return cooked; + }; + + function __importStar(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; + result.default = mod; + return result; + } + + function __importDefault(mod) { + return (mod && mod.__esModule) ? mod : { default: mod }; + } + + function __classPrivateFieldGet(receiver, privateMap) { + if (!privateMap.has(receiver)) { + throw new TypeError("attempted to get private field on non-instance"); + } + return privateMap.get(receiver); + } + + function __classPrivateFieldSet(receiver, privateMap, value) { + if (!privateMap.has(receiver)) { + throw new TypeError("attempted to set private field on non-instance"); + } + privateMap.set(receiver, value); + return value; + } + + /* tslint:disable:no-non-null-assertion */ + var ListNode = /** @class */ (function () { + function ListNode(value) { + this.value = value; + } + return ListNode; + }()); + var LinkedList = /** @class */ (function () { + function LinkedList() { + this.size = 0; + } + Object.defineProperty(LinkedList.prototype, "head", { + get: function () { + return this.first; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(LinkedList.prototype, "tail", { + get: function () { + return this.last; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(LinkedList.prototype, "length", { + get: function () { + return this.size; + }, + enumerable: true, + configurable: true + }); + LinkedList.prototype.attach = function (value, previousNode, nextNode) { + if (!previousNode) + return this.addHead(value); + if (!nextNode) + return this.addTail(value); + var node = new ListNode(value); + node.previous = previousNode; + previousNode.next = node; + node.next = nextNode; + nextNode.previous = node; + this.size++; + return node; + }; + LinkedList.prototype.attachMany = function (values, previousNode, nextNode) { + if (!values.length) + return []; + if (!previousNode) + return this.addManyHead(values); + if (!nextNode) + return this.addManyTail(values); + var list = new LinkedList(); + list.addManyTail(values); + list.first.previous = previousNode; + previousNode.next = list.first; + list.last.next = nextNode; + nextNode.previous = list.last; + this.size += values.length; + return list.toNodeArray(); + }; + LinkedList.prototype.detach = function (node) { + if (!node.previous) + return this.dropHead(); + if (!node.next) + return this.dropTail(); + node.previous.next = node.next; + node.next.previous = node.previous; + this.size--; + return node; + }; + LinkedList.prototype.add = function (value) { + var _this = this; + return { + after: function () { + var _a; + var params = []; + for (var _i = 0; _i < arguments.length; _i++) { + params[_i] = arguments[_i]; + } + return (_a = _this.addAfter).call.apply(_a, __spread([_this, value], params)); + }, + before: function () { + var _a; + var params = []; + for (var _i = 0; _i < arguments.length; _i++) { + params[_i] = arguments[_i]; + } + return (_a = _this.addBefore).call.apply(_a, __spread([_this, value], params)); + }, + byIndex: function (position) { return _this.addByIndex(value, position); }, + head: function () { return _this.addHead(value); }, + tail: function () { return _this.addTail(value); }, + }; + }; + LinkedList.prototype.addMany = function (values) { + var _this = this; + return { + after: function () { + var _a; + var params = []; + for (var _i = 0; _i < arguments.length; _i++) { + params[_i] = arguments[_i]; + } + return (_a = _this.addManyAfter).call.apply(_a, __spread([_this, values], params)); + }, + before: function () { + var _a; + var params = []; + for (var _i = 0; _i < arguments.length; _i++) { + params[_i] = arguments[_i]; + } + return (_a = _this.addManyBefore).call.apply(_a, __spread([_this, values], params)); + }, + byIndex: function (position) { return _this.addManyByIndex(values, position); }, + head: function () { return _this.addManyHead(values); }, + tail: function () { return _this.addManyTail(values); }, + }; + }; + LinkedList.prototype.addAfter = function (value, previousValue, compareFn) { + if (compareFn === void 0) { compareFn = compare; } + var previous = this.find(function (node) { return compareFn(node.value, previousValue); }); + return previous ? this.attach(value, previous, previous.next) : this.addTail(value); + }; + LinkedList.prototype.addBefore = function (value, nextValue, compareFn) { + if (compareFn === void 0) { compareFn = compare; } + var next = this.find(function (node) { return compareFn(node.value, nextValue); }); + return next ? this.attach(value, next.previous, next) : this.addHead(value); + }; + LinkedList.prototype.addByIndex = function (value, position) { + if (position < 0) + position += this.size; + else if (position >= this.size) + return this.addTail(value); + if (position <= 0) + return this.addHead(value); + var next = this.get(position); + return this.attach(value, next.previous, next); + }; + LinkedList.prototype.addHead = function (value) { + var node = new ListNode(value); + node.next = this.first; + if (this.first) + this.first.previous = node; + else + this.last = node; + this.first = node; + this.size++; + return node; + }; + LinkedList.prototype.addTail = function (value) { + var node = new ListNode(value); + if (this.first) { + node.previous = this.last; + this.last.next = node; + this.last = node; + } + else { + this.first = node; + this.last = node; + } + this.size++; + return node; + }; + LinkedList.prototype.addManyAfter = function (values, previousValue, compareFn) { + if (compareFn === void 0) { compareFn = compare; } + var previous = this.find(function (node) { return compareFn(node.value, previousValue); }); + return previous ? this.attachMany(values, previous, previous.next) : this.addManyTail(values); + }; + LinkedList.prototype.addManyBefore = function (values, nextValue, compareFn) { + if (compareFn === void 0) { compareFn = compare; } + var next = this.find(function (node) { return compareFn(node.value, nextValue); }); + return next ? this.attachMany(values, next.previous, next) : this.addManyHead(values); + }; + LinkedList.prototype.addManyByIndex = function (values, position) { + if (position < 0) + position += this.size; + if (position <= 0) + return this.addManyHead(values); + if (position >= this.size) + return this.addManyTail(values); + var next = this.get(position); + return this.attachMany(values, next.previous, next); + }; + LinkedList.prototype.addManyHead = function (values) { + var _this = this; + return values.reduceRight(function (nodes, value) { + nodes.unshift(_this.addHead(value)); + return nodes; + }, []); + }; + LinkedList.prototype.addManyTail = function (values) { + var _this = this; + return values.map(function (value) { return _this.addTail(value); }); + }; + LinkedList.prototype.drop = function () { + var _this = this; + return { + byIndex: function (position) { return _this.dropByIndex(position); }, + byValue: function () { + var params = []; + for (var _i = 0; _i < arguments.length; _i++) { + params[_i] = arguments[_i]; + } + return _this.dropByValue.apply(_this, params); + }, + byValueAll: function () { + var params = []; + for (var _i = 0; _i < arguments.length; _i++) { + params[_i] = arguments[_i]; + } + return _this.dropByValueAll.apply(_this, params); + }, + head: function () { return _this.dropHead(); }, + tail: function () { return _this.dropTail(); }, + }; + }; + LinkedList.prototype.dropMany = function (count) { + var _this = this; + return { + byIndex: function (position) { return _this.dropManyByIndex(count, position); }, + head: function () { return _this.dropManyHead(count); }, + tail: function () { return _this.dropManyTail(count); }, + }; + }; + LinkedList.prototype.dropByIndex = function (position) { + if (position < 0) + position += this.size; + var current = this.get(position); + return current ? this.detach(current) : undefined; + }; + LinkedList.prototype.dropByValue = function (value, compareFn) { + if (compareFn === void 0) { compareFn = compare; } + var position = this.findIndex(function (node) { return compareFn(node.value, value); }); + return position < 0 ? undefined : this.dropByIndex(position); + }; + LinkedList.prototype.dropByValueAll = function (value, compareFn) { + if (compareFn === void 0) { compareFn = compare; } + var dropped = []; + for (var current = this.first, position = 0; current; position++, current = current.next) { + if (compareFn(current.value, value)) { + dropped.push(this.dropByIndex(position - dropped.length)); + } + } + return dropped; + }; + LinkedList.prototype.dropHead = function () { + var head = this.first; + if (head) { + this.first = head.next; + if (this.first) + this.first.previous = undefined; + else + this.last = undefined; + this.size--; + return head; + } + return undefined; + }; + LinkedList.prototype.dropTail = function () { + var tail = this.last; + if (tail) { + this.last = tail.previous; + if (this.last) + this.last.next = undefined; + else + this.first = undefined; + this.size--; + return tail; + } + return undefined; + }; + LinkedList.prototype.dropManyByIndex = function (count, position) { + if (count <= 0) + return []; + if (position < 0) + position = Math.max(position + this.size, 0); + else if (position >= this.size) + return []; + count = Math.min(count, this.size - position); + var dropped = []; + while (count--) { + var current = this.get(position); + dropped.push(this.detach(current)); + } + return dropped; + }; + LinkedList.prototype.dropManyHead = function (count) { + if (count <= 0) + return []; + count = Math.min(count, this.size); + var dropped = []; + while (count--) + dropped.unshift(this.dropHead()); + return dropped; + }; + LinkedList.prototype.dropManyTail = function (count) { + if (count <= 0) + return []; + count = Math.min(count, this.size); + var dropped = []; + while (count--) + dropped.push(this.dropTail()); + return dropped; + }; + LinkedList.prototype.find = function (predicate) { + for (var current = this.first, position = 0; current; position++, current = current.next) { + if (predicate(current, position, this)) + return current; + } + return undefined; + }; + LinkedList.prototype.findIndex = function (predicate) { + for (var current = this.first, position = 0; current; position++, current = current.next) { + if (predicate(current, position, this)) + return position; + } + return -1; + }; + LinkedList.prototype.forEach = function (callback) { + for (var node = this.first, position = 0; node; position++, node = node.next) { + callback(node, position, this); + } + }; + LinkedList.prototype.get = function (position) { + return this.find(function (_, index) { return position === index; }); + }; + LinkedList.prototype.indexOf = function (value, compareFn) { + if (compareFn === void 0) { compareFn = compare; } + return this.findIndex(function (node) { return compareFn(node.value, value); }); + }; + LinkedList.prototype.toArray = function () { + var array = new Array(this.size); + this.forEach(function (node, index) { return (array[index] = node.value); }); + return array; + }; + LinkedList.prototype.toNodeArray = function () { + var array = new Array(this.size); + this.forEach(function (node, index) { return (array[index] = node); }); + return array; + }; + LinkedList.prototype.toString = function (mapperFn) { + if (mapperFn === void 0) { mapperFn = JSON.stringify; } + return this.toArray() + .map(function (value) { return mapperFn(value); }) + .join(' <-> '); + }; + // Cannot use Generator type because of ng-packagr + LinkedList.prototype[Symbol.iterator] = function () { + var node, position; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + node = this.first, position = 0; + _a.label = 1; + case 1: + if (!node) return [3 /*break*/, 4]; + return [4 /*yield*/, node.value]; + case 2: + _a.sent(); + _a.label = 3; + case 3: + position++, node = node.next; + return [3 /*break*/, 1]; + case 4: return [2 /*return*/]; + } + }); + }; + return LinkedList; + }()); + + exports.LinkedList = LinkedList; + exports.ListNode = ListNode; + + Object.defineProperty(exports, '__esModule', { value: true }); + +}))); +//# sourceMappingURL=abp-utils.umd.js.map diff --git a/modules/docs/app/VoloDocs.Web/wwwroot/libs/abp/utils/abp-utils.umd.js.map b/modules/docs/app/VoloDocs.Web/wwwroot/libs/abp/utils/abp-utils.umd.js.map new file mode 100644 index 0000000000..19639413d4 --- /dev/null +++ b/modules/docs/app/VoloDocs.Web/wwwroot/libs/abp/utils/abp-utils.umd.js.map @@ -0,0 +1 @@ +{"version":3,"file":"abp-utils.umd.js","sources":["../../node_modules/tslib/tslib.es6.js","ng://@abp/utils/lib/linked-list.ts"],"sourcesContent":["/*! *****************************************************************************\r\nCopyright (c) Microsoft Corporation. All rights reserved.\r\nLicensed under the Apache License, Version 2.0 (the \"License\"); you may not use\r\nthis file except in compliance with the License. You may obtain a copy of the\r\nLicense at http://www.apache.org/licenses/LICENSE-2.0\r\n\r\nTHIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\r\nKIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\r\nWARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\r\nMERCHANTABLITY OR NON-INFRINGEMENT.\r\n\r\nSee the Apache Version 2.0 License for specific language governing permissions\r\nand limitations under the License.\r\n***************************************************************************** */\r\n/* global Reflect, Promise */\r\n\r\nvar extendStatics = function(d, b) {\r\n extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\r\n return extendStatics(d, b);\r\n};\r\n\r\nexport function __extends(d, b) {\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n}\r\n\r\nexport var __assign = function() {\r\n __assign = Object.assign || function __assign(t) {\r\n for (var s, i = 1, n = arguments.length; i < n; i++) {\r\n s = arguments[i];\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\r\n }\r\n return t;\r\n }\r\n return __assign.apply(this, arguments);\r\n}\r\n\r\nexport function __rest(s, e) {\r\n var t = {};\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\r\n t[p] = s[p];\r\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\r\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\r\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\r\n t[p[i]] = s[p[i]];\r\n }\r\n return t;\r\n}\r\n\r\nexport function __decorate(decorators, target, key, desc) {\r\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\r\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\r\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\r\n return c > 3 && r && Object.defineProperty(target, key, r), r;\r\n}\r\n\r\nexport function __param(paramIndex, decorator) {\r\n return function (target, key) { decorator(target, key, paramIndex); }\r\n}\r\n\r\nexport function __metadata(metadataKey, metadataValue) {\r\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\r\n}\r\n\r\nexport function __awaiter(thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n}\r\n\r\nexport function __generator(thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (_) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n}\r\n\r\nexport function __exportStar(m, exports) {\r\n for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];\r\n}\r\n\r\nexport function __values(o) {\r\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\r\n if (m) return m.call(o);\r\n if (o && typeof o.length === \"number\") return {\r\n next: function () {\r\n if (o && i >= o.length) o = void 0;\r\n return { value: o && o[i++], done: !o };\r\n }\r\n };\r\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\r\n}\r\n\r\nexport function __read(o, n) {\r\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\r\n if (!m) return o;\r\n var i = m.call(o), r, ar = [], e;\r\n try {\r\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\r\n }\r\n catch (error) { e = { error: error }; }\r\n finally {\r\n try {\r\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\r\n }\r\n finally { if (e) throw e.error; }\r\n }\r\n return ar;\r\n}\r\n\r\nexport function __spread() {\r\n for (var ar = [], i = 0; i < arguments.length; i++)\r\n ar = ar.concat(__read(arguments[i]));\r\n return ar;\r\n}\r\n\r\nexport function __spreadArrays() {\r\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\r\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\r\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\r\n r[k] = a[j];\r\n return r;\r\n};\r\n\r\nexport function __await(v) {\r\n return this instanceof __await ? (this.v = v, this) : new __await(v);\r\n}\r\n\r\nexport function __asyncGenerator(thisArg, _arguments, generator) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\r\n return i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i;\r\n function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }\r\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\r\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\r\n function fulfill(value) { resume(\"next\", value); }\r\n function reject(value) { resume(\"throw\", value); }\r\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\r\n}\r\n\r\nexport function __asyncDelegator(o) {\r\n var i, p;\r\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\r\n function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === \"return\" } : f ? f(v) : v; } : f; }\r\n}\r\n\r\nexport function __asyncValues(o) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var m = o[Symbol.asyncIterator], i;\r\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\r\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\r\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\r\n}\r\n\r\nexport function __makeTemplateObject(cooked, raw) {\r\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\r\n return cooked;\r\n};\r\n\r\nexport function __importStar(mod) {\r\n if (mod && mod.__esModule) return mod;\r\n var result = {};\r\n if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];\r\n result.default = mod;\r\n return result;\r\n}\r\n\r\nexport function __importDefault(mod) {\r\n return (mod && mod.__esModule) ? mod : { default: mod };\r\n}\r\n\r\nexport function __classPrivateFieldGet(receiver, privateMap) {\r\n if (!privateMap.has(receiver)) {\r\n throw new TypeError(\"attempted to get private field on non-instance\");\r\n }\r\n return privateMap.get(receiver);\r\n}\r\n\r\nexport function __classPrivateFieldSet(receiver, privateMap, value) {\r\n if (!privateMap.has(receiver)) {\r\n throw new TypeError(\"attempted to set private field on non-instance\");\r\n }\r\n privateMap.set(receiver, value);\r\n return value;\r\n}\r\n","/* tslint:disable:no-non-null-assertion */\r\n\r\nimport compare from 'just-compare';\r\n\r\nexport class ListNode {\r\n readonly value: T;\r\n next: ListNode | undefined;\r\n previous: ListNode | undefined;\r\n\r\n constructor(value: T) {\r\n this.value = value;\r\n }\r\n}\r\n\r\nexport class LinkedList {\r\n private first: ListNode | undefined;\r\n private last: ListNode | undefined;\r\n private size = 0;\r\n\r\n get head(): ListNode | undefined {\r\n return this.first;\r\n }\r\n get tail(): ListNode | undefined {\r\n return this.last;\r\n }\r\n get length(): number {\r\n return this.size;\r\n }\r\n\r\n private attach(\r\n value: T,\r\n previousNode: ListNode | undefined,\r\n nextNode: ListNode | undefined,\r\n ): ListNode {\r\n if (!previousNode) return this.addHead(value);\r\n\r\n if (!nextNode) return this.addTail(value);\r\n\r\n const node = new ListNode(value);\r\n node.previous = previousNode;\r\n previousNode.next = node;\r\n node.next = nextNode;\r\n nextNode.previous = node;\r\n\r\n this.size++;\r\n\r\n return node;\r\n }\r\n\r\n private attachMany(\r\n values: T[],\r\n previousNode: ListNode | undefined,\r\n nextNode: ListNode | undefined,\r\n ): ListNode[] {\r\n if (!values.length) return [];\r\n\r\n if (!previousNode) return this.addManyHead(values);\r\n\r\n if (!nextNode) return this.addManyTail(values);\r\n\r\n const list = new LinkedList();\r\n list.addManyTail(values);\r\n list.first!.previous = previousNode;\r\n previousNode.next = list.first;\r\n list.last!.next = nextNode;\r\n nextNode.previous = list.last;\r\n\r\n this.size += values.length;\r\n\r\n return list.toNodeArray();\r\n }\r\n\r\n private detach(node: ListNode) {\r\n if (!node.previous) return this.dropHead();\r\n\r\n if (!node.next) return this.dropTail();\r\n\r\n node.previous.next = node.next;\r\n node.next.previous = node.previous;\r\n\r\n this.size--;\r\n\r\n return node;\r\n }\r\n\r\n add(value: T) {\r\n return {\r\n after: (...params: [T] | [any, ListComparisonFn]) =>\r\n this.addAfter.call(this, value, ...params),\r\n before: (...params: [T] | [any, ListComparisonFn]) =>\r\n this.addBefore.call(this, value, ...params),\r\n byIndex: (position: number) => this.addByIndex(value, position),\r\n head: () => this.addHead(value),\r\n tail: () => this.addTail(value),\r\n };\r\n }\r\n\r\n addMany(values: T[]) {\r\n return {\r\n after: (...params: [T] | [any, ListComparisonFn]) =>\r\n this.addManyAfter.call(this, values, ...params),\r\n before: (...params: [T] | [any, ListComparisonFn]) =>\r\n this.addManyBefore.call(this, values, ...params),\r\n byIndex: (position: number) => this.addManyByIndex(values, position),\r\n head: () => this.addManyHead(values),\r\n tail: () => this.addManyTail(values),\r\n };\r\n }\r\n\r\n addAfter(value: T, nextValue: T): ListNode;\r\n addAfter(value: T, previousValue: any, compareFn: ListComparisonFn): ListNode;\r\n addAfter(value: T, previousValue: any, compareFn: ListComparisonFn = compare): ListNode {\r\n const previous = this.find(node => compareFn(node.value, previousValue));\r\n\r\n return previous ? this.attach(value, previous, previous.next) : this.addTail(value);\r\n }\r\n\r\n addBefore(value: T, nextValue: T): ListNode;\r\n addBefore(value: T, nextValue: any, compareFn: ListComparisonFn): ListNode;\r\n addBefore(value: T, nextValue: any, compareFn: ListComparisonFn = compare): ListNode {\r\n const next = this.find(node => compareFn(node.value, nextValue));\r\n\r\n return next ? this.attach(value, next.previous, next) : this.addHead(value);\r\n }\r\n\r\n addByIndex(value: T, position: number): ListNode {\r\n if (position < 0) position += this.size;\r\n else if (position >= this.size) return this.addTail(value);\r\n\r\n if (position <= 0) return this.addHead(value);\r\n\r\n const next = this.get(position)!;\r\n\r\n return this.attach(value, next.previous, next);\r\n }\r\n\r\n addHead(value: T): ListNode {\r\n const node = new ListNode(value);\r\n\r\n node.next = this.first;\r\n\r\n if (this.first) this.first.previous = node;\r\n else this.last = node;\r\n\r\n this.first = node;\r\n this.size++;\r\n\r\n return node;\r\n }\r\n\r\n addTail(value: T): ListNode {\r\n const node = new ListNode(value);\r\n\r\n if (this.first) {\r\n node.previous = this.last;\r\n this.last!.next = node;\r\n this.last = node;\r\n } else {\r\n this.first = node;\r\n this.last = node;\r\n }\r\n\r\n this.size++;\r\n\r\n return node;\r\n }\r\n\r\n addManyAfter(values: T[], previousValue: T): ListNode[];\r\n addManyAfter(values: T[], previousValue: any, compareFn: ListComparisonFn): ListNode[];\r\n addManyAfter(\r\n values: T[],\r\n previousValue: any,\r\n compareFn: ListComparisonFn = compare,\r\n ): ListNode[] {\r\n const previous = this.find(node => compareFn(node.value, previousValue));\r\n\r\n return previous ? this.attachMany(values, previous, previous.next) : this.addManyTail(values);\r\n }\r\n\r\n addManyBefore(values: T[], previousValue: T): ListNode[];\r\n addManyBefore(values: T[], nextValue: any, compareFn: ListComparisonFn): ListNode[];\r\n addManyBefore(\r\n values: T[],\r\n nextValue: any,\r\n compareFn: ListComparisonFn = compare,\r\n ): ListNode[] {\r\n const next = this.find(node => compareFn(node.value, nextValue));\r\n\r\n return next ? this.attachMany(values, next.previous, next) : this.addManyHead(values);\r\n }\r\n\r\n addManyByIndex(values: T[], position: number): ListNode[] {\r\n if (position < 0) position += this.size;\r\n\r\n if (position <= 0) return this.addManyHead(values);\r\n\r\n if (position >= this.size) return this.addManyTail(values);\r\n\r\n const next = this.get(position)!;\r\n\r\n return this.attachMany(values, next.previous, next);\r\n }\r\n\r\n addManyHead(values: T[]): ListNode[] {\r\n return values.reduceRight[]>((nodes, value) => {\r\n nodes.unshift(this.addHead(value));\r\n return nodes;\r\n }, []);\r\n }\r\n\r\n addManyTail(values: T[]): ListNode[] {\r\n return values.map(value => this.addTail(value));\r\n }\r\n\r\n drop() {\r\n return {\r\n byIndex: (position: number) => this.dropByIndex(position),\r\n byValue: (...params: [T] | [any, ListComparisonFn]) =>\r\n this.dropByValue.apply(this, params),\r\n byValueAll: (...params: [T] | [any, ListComparisonFn]) =>\r\n this.dropByValueAll.apply(this, params),\r\n head: () => this.dropHead(),\r\n tail: () => this.dropTail(),\r\n };\r\n }\r\n\r\n dropMany(count: number) {\r\n return {\r\n byIndex: (position: number) => this.dropManyByIndex(count, position),\r\n head: () => this.dropManyHead(count),\r\n tail: () => this.dropManyTail(count),\r\n };\r\n }\r\n\r\n dropByIndex(position: number): ListNode | undefined {\r\n if (position < 0) position += this.size;\r\n\r\n const current = this.get(position);\r\n\r\n return current ? this.detach(current) : undefined;\r\n }\r\n\r\n dropByValue(value: T): ListNode | undefined;\r\n dropByValue(value: any, compareFn: ListComparisonFn): ListNode | undefined;\r\n dropByValue(value: any, compareFn: ListComparisonFn = compare): ListNode | undefined {\r\n const position = this.findIndex(node => compareFn(node.value, value));\r\n\r\n return position < 0 ? undefined : this.dropByIndex(position);\r\n }\r\n\r\n dropByValueAll(value: T): ListNode[];\r\n dropByValueAll(value: any, compareFn: ListComparisonFn): ListNode[];\r\n dropByValueAll(value: any, compareFn: ListComparisonFn = compare): ListNode[] {\r\n const dropped: ListNode[] = [];\r\n\r\n for (let current = this.first, position = 0; current; position++, current = current.next) {\r\n if (compareFn(current.value, value)) {\r\n dropped.push(this.dropByIndex(position - dropped.length)!);\r\n }\r\n }\r\n\r\n return dropped;\r\n }\r\n\r\n dropHead(): ListNode | undefined {\r\n const head = this.first;\r\n\r\n if (head) {\r\n this.first = head.next;\r\n\r\n if (this.first) this.first.previous = undefined;\r\n else this.last = undefined;\r\n\r\n this.size--;\r\n\r\n return head;\r\n }\r\n\r\n return undefined;\r\n }\r\n\r\n dropTail(): ListNode | undefined {\r\n const tail = this.last;\r\n\r\n if (tail) {\r\n this.last = tail.previous;\r\n\r\n if (this.last) this.last.next = undefined;\r\n else this.first = undefined;\r\n\r\n this.size--;\r\n\r\n return tail;\r\n }\r\n\r\n return undefined;\r\n }\r\n\r\n dropManyByIndex(count: number, position: number): ListNode[] {\r\n if (count <= 0) return [];\r\n\r\n if (position < 0) position = Math.max(position + this.size, 0);\r\n else if (position >= this.size) return [];\r\n\r\n count = Math.min(count, this.size - position);\r\n\r\n const dropped: ListNode[] = [];\r\n\r\n while (count--) {\r\n const current = this.get(position);\r\n dropped.push(this.detach(current!)!);\r\n }\r\n\r\n return dropped;\r\n }\r\n\r\n dropManyHead(count: Exclude): ListNode[] {\r\n if (count <= 0) return [];\r\n\r\n count = Math.min(count, this.size);\r\n\r\n const dropped: ListNode[] = [];\r\n\r\n while (count--) dropped.unshift(this.dropHead()!);\r\n\r\n return dropped;\r\n }\r\n\r\n dropManyTail(count: Exclude): ListNode[] {\r\n if (count <= 0) return [];\r\n\r\n count = Math.min(count, this.size);\r\n\r\n const dropped: ListNode[] = [];\r\n\r\n while (count--) dropped.push(this.dropTail()!);\r\n\r\n return dropped;\r\n }\r\n\r\n find(predicate: ListIteratorFn): ListNode | undefined {\r\n for (let current = this.first, position = 0; current; position++, current = current.next) {\r\n if (predicate(current, position, this)) return current;\r\n }\r\n\r\n return undefined;\r\n }\r\n\r\n findIndex(predicate: ListIteratorFn): number {\r\n for (let current = this.first, position = 0; current; position++, current = current.next) {\r\n if (predicate(current, position, this)) return position;\r\n }\r\n\r\n return -1;\r\n }\r\n\r\n forEach(callback: ListIteratorFn) {\r\n for (let node = this.first, position = 0; node; position++, node = node.next) {\r\n callback(node, position, this);\r\n }\r\n }\r\n\r\n get(position: number): ListNode | undefined {\r\n return this.find((_, index) => position === index);\r\n }\r\n\r\n indexOf(value: T): number;\r\n indexOf(value: any, compareFn: ListComparisonFn): number;\r\n indexOf(value: any, compareFn: ListComparisonFn = compare): number {\r\n return this.findIndex(node => compareFn(node.value, value));\r\n }\r\n\r\n toArray(): T[] {\r\n const array = new Array(this.size);\r\n\r\n this.forEach((node, index) => (array[index!] = node.value));\r\n\r\n return array;\r\n }\r\n\r\n toNodeArray(): ListNode[] {\r\n const array = new Array(this.size);\r\n\r\n this.forEach((node, index) => (array[index!] = node));\r\n\r\n return array;\r\n }\r\n\r\n toString(mapperFn: ListMapperFn = JSON.stringify): string {\r\n return this.toArray()\r\n .map(value => mapperFn(value))\r\n .join(' <-> ');\r\n }\r\n\r\n // Cannot use Generator type because of ng-packagr\r\n *[Symbol.iterator](): any {\r\n for (let node = this.first, position = 0; node; position++, node = node.next) {\r\n yield node.value;\r\n }\r\n }\r\n}\r\n\r\nexport type ListMapperFn = (value: T) => any;\r\n\r\nexport type ListComparisonFn = (value1: T, value2: any) => boolean;\r\n\r\nexport type ListIteratorFn = (\r\n node: ListNode,\r\n index?: number,\r\n list?: LinkedList,\r\n) => R;\r\n"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/modules/docs/app/VoloDocs.Web/wwwroot/libs/abp/utils/abp-utils.umd.min.js b/modules/docs/app/VoloDocs.Web/wwwroot/libs/abp/utils/abp-utils.umd.min.js new file mode 100644 index 0000000000..b65fa8f40f --- /dev/null +++ b/modules/docs/app/VoloDocs.Web/wwwroot/libs/abp/utils/abp-utils.umd.min.js @@ -0,0 +1,2 @@ +!function(t,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports,require("just-compare")):"function"==typeof define&&define.amd?define("@abp/utils",["exports","just-compare"],r):r(((t=t||self).abp=t.abp||{},t.abp.utils=t.abp.utils||{},t.abp.utils.common={}),t.compare)}(this,(function(t,r){"use strict";r=r&&Object.prototype.hasOwnProperty.call(r,"default")?r.default:r;function e(t,r){var e,n,i,o,a={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:u(0),throw:u(1),return:u(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function u(o){return function(u){return function(o){if(e)throw new TypeError("Generator is already executing.");for(;a;)try{if(e=1,n&&(i=2&o[0]?n.return:o[0]?n.throw||((i=n.return)&&i.call(n),0):n.next)&&!(i=i.call(n,o[1])).done)return i;switch(n=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return a.label++,{value:o[1],done:!1};case 5:a.label++,n=o[1],o=[0];continue;case 7:o=a.ops.pop(),a.trys.pop();continue;default:if(!(i=a.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){a=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]0)&&!(n=o.next()).done;)a.push(n.value)}catch(t){i={error:t}}finally{try{n&&!n.done&&(e=o.return)&&e.call(o)}finally{if(i)throw i.error}}return a}function i(){for(var t=[],r=0;r=this.size)return this.addTail(t);if(r<=0)return this.addHead(t);var e=this.get(r);return this.attach(t,e.previous,e)},t.prototype.addHead=function(t){var r=new o(t);return r.next=this.first,this.first?this.first.previous=r:this.last=r,this.first=r,this.size++,r},t.prototype.addTail=function(t){var r=new o(t);return this.first?(r.previous=this.last,this.last.next=r,this.last=r):(this.first=r,this.last=r),this.size++,r},t.prototype.addManyAfter=function(t,e,n){void 0===n&&(n=r);var i=this.find((function(t){return n(t.value,e)}));return i?this.attachMany(t,i,i.next):this.addManyTail(t)},t.prototype.addManyBefore=function(t,e,n){void 0===n&&(n=r);var i=this.find((function(t){return n(t.value,e)}));return i?this.attachMany(t,i.previous,i):this.addManyHead(t)},t.prototype.addManyByIndex=function(t,r){if(r<0&&(r+=this.size),r<=0)return this.addManyHead(t);if(r>=this.size)return this.addManyTail(t);var e=this.get(r);return this.attachMany(t,e.previous,e)},t.prototype.addManyHead=function(t){var r=this;return t.reduceRight((function(t,e){return t.unshift(r.addHead(e)),t}),[])},t.prototype.addManyTail=function(t){var r=this;return t.map((function(t){return r.addTail(t)}))},t.prototype.drop=function(){var t=this;return{byIndex:function(r){return t.dropByIndex(r)},byValue:function(){for(var r=[],e=0;e=this.size)return[];t=Math.min(t,this.size-r);for(var e=[];t--;){var n=this.get(r);e.push(this.detach(n))}return e},t.prototype.dropManyHead=function(t){if(t<=0)return[];t=Math.min(t,this.size);for(var r=[];t--;)r.unshift(this.dropHead());return r},t.prototype.dropManyTail=function(t){if(t<=0)return[];t=Math.min(t,this.size);for(var r=[];t--;)r.push(this.dropTail());return r},t.prototype.find=function(t){for(var r=this.first,e=0;r;e++,r=r.next)if(t(r,e,this))return r},t.prototype.findIndex=function(t){for(var r=this.first,e=0;r;e++,r=r.next)if(t(r,e,this))return e;return-1},t.prototype.forEach=function(t){for(var r=this.first,e=0;r;e++,r=r.next)t(r,e,this)},t.prototype.get=function(t){return this.find((function(r,e){return t===e}))},t.prototype.indexOf=function(t,e){return void 0===e&&(e=r),this.findIndex((function(r){return e(r.value,t)}))},t.prototype.toArray=function(){var t=new Array(this.size);return this.forEach((function(r,e){return t[e]=r.value})),t},t.prototype.toNodeArray=function(){var t=new Array(this.size);return this.forEach((function(r,e){return t[e]=r})),t},t.prototype.toString=function(t){return void 0===t&&(t=JSON.stringify),this.toArray().map((function(r){return t(r)})).join(" <-> ")},t.prototype[Symbol.iterator]=function(){var t;return e(this,(function(r){switch(r.label){case 0:t=this.first,0,r.label=1;case 1:return t?[4,t.value]:[3,4];case 2:r.sent(),r.label=3;case 3:return t=t.next,[3,1];case 4:return[2]}}))},t}();t.LinkedList=a,t.ListNode=o,Object.defineProperty(t,"__esModule",{value:!0})})); +//# sourceMappingURL=abp-utils.umd.min.js.map \ No newline at end of file diff --git a/modules/docs/app/VoloDocs.Web/wwwroot/libs/abp/utils/abp-utils.umd.min.js.map b/modules/docs/app/VoloDocs.Web/wwwroot/libs/abp/utils/abp-utils.umd.min.js.map new file mode 100644 index 0000000000..817cd863b6 --- /dev/null +++ b/modules/docs/app/VoloDocs.Web/wwwroot/libs/abp/utils/abp-utils.umd.min.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../node_modules/tslib/tslib.es6.js","ng://@abp/utils/lib/linked-list.ts"],"names":["__generator","thisArg","body","f","y","t","g","_","label","sent","trys","ops","next","verb","throw","return","Symbol","iterator","this","n","v","op","TypeError","call","done","value","pop","length","push","e","step","__read","o","m","r","i","ar","error","__spread","arguments","concat","LinkedList","size","Object","defineProperty","prototype","first","last","attach","previousNode","nextNode","addHead","addTail","node","ListNode","previous","attachMany","values","addManyHead","addManyTail","list","toNodeArray","detach","dropTail","dropHead","add","_this","after","params","_i","_a","addAfter","apply","before","addBefore","byIndex","position","addByIndex","head","tail","addMany","addManyAfter","addManyBefore","addManyByIndex","previousValue","compareFn","compare","find","nextValue","get","reduceRight","nodes","unshift","map","drop","dropByIndex","byValue","dropByValue","byValueAll","dropByValueAll","dropMany","count","dropManyByIndex","dropManyHead","dropManyTail","current","undefined","findIndex","dropped","Math","max","min","predicate","forEach","callback","index","indexOf","toArray","array","Array","toString","mapperFn","JSON","stringify","join"],"mappings":"+XA6EO,SAASA,EAAYC,EAASC,GACjC,IAAsGC,EAAGC,EAAGC,EAAGC,EAA3GC,EAAI,CAAEC,MAAO,EAAGC,KAAM,WAAa,GAAW,EAAPJ,EAAE,GAAQ,MAAMA,EAAE,GAAI,OAAOA,EAAE,IAAOK,KAAM,GAAIC,IAAK,IAChG,OAAOL,EAAI,CAAEM,KAAMC,EAAK,GAAIC,MAASD,EAAK,GAAIE,OAAUF,EAAK,IAAwB,mBAAXG,SAA0BV,EAAEU,OAAOC,UAAY,WAAa,OAAOC,OAAUZ,EACvJ,SAASO,EAAKM,GAAK,OAAO,SAAUC,GAAK,OACzC,SAAcC,GACV,GAAIlB,EAAG,MAAM,IAAImB,UAAU,mCAC3B,KAAOf,GAAG,IACN,GAAIJ,EAAI,EAAGC,IAAMC,EAAY,EAARgB,EAAG,GAASjB,EAAU,OAAIiB,EAAG,GAAKjB,EAAS,SAAOC,EAAID,EAAU,SAAMC,EAAEkB,KAAKnB,GAAI,GAAKA,EAAEQ,SAAWP,EAAIA,EAAEkB,KAAKnB,EAAGiB,EAAG,KAAKG,KAAM,OAAOnB,EAE3J,OADID,EAAI,EAAGC,IAAGgB,EAAK,CAAS,EAARA,EAAG,GAAQhB,EAAEoB,QACzBJ,EAAG,IACP,KAAK,EAAG,KAAK,EAAGhB,EAAIgB,EAAI,MACxB,KAAK,EAAc,OAAXd,EAAEC,QAAgB,CAAEiB,MAAOJ,EAAG,GAAIG,MAAM,GAChD,KAAK,EAAGjB,EAAEC,QAASJ,EAAIiB,EAAG,GAAIA,EAAK,CAAC,GAAI,SACxC,KAAK,EAAGA,EAAKd,EAAEI,IAAIe,MAAOnB,EAAEG,KAAKgB,MAAO,SACxC,QACI,KAAMrB,EAAIE,EAAEG,MAAML,EAAIA,EAAEsB,OAAS,GAAKtB,EAAEA,EAAEsB,OAAS,KAAkB,IAAVN,EAAG,IAAsB,IAAVA,EAAG,IAAW,CAAEd,EAAI,EAAG,SACjG,GAAc,IAAVc,EAAG,MAAchB,GAAMgB,EAAG,GAAKhB,EAAE,IAAMgB,EAAG,GAAKhB,EAAE,IAAM,CAAEE,EAAEC,MAAQa,EAAG,GAAI,MAC9E,GAAc,IAAVA,EAAG,IAAYd,EAAEC,MAAQH,EAAE,GAAI,CAAEE,EAAEC,MAAQH,EAAE,GAAIA,EAAIgB,EAAI,MAC7D,GAAIhB,GAAKE,EAAEC,MAAQH,EAAE,GAAI,CAAEE,EAAEC,MAAQH,EAAE,GAAIE,EAAEI,IAAIiB,KAAKP,GAAK,MACvDhB,EAAE,IAAIE,EAAEI,IAAIe,MAChBnB,EAAEG,KAAKgB,MAAO,SAEtBL,EAAKnB,EAAKqB,KAAKtB,EAASM,GAC1B,MAAOsB,GAAKR,EAAK,CAAC,EAAGQ,GAAIzB,EAAI,EAAI,QAAWD,EAAIE,EAAI,EACtD,GAAY,EAARgB,EAAG,GAAQ,MAAMA,EAAG,GAAI,MAAO,CAAEI,MAAOJ,EAAG,GAAKA,EAAG,QAAK,EAAQG,MAAM,GArB9BM,CAAK,CAACX,EAAGC,MAyCtD,SAASW,EAAOC,EAAGb,GACtB,IAAIc,EAAsB,mBAAXjB,QAAyBgB,EAAEhB,OAAOC,UACjD,IAAKgB,EAAG,OAAOD,EACf,IAAmBE,EAAYL,EAA3BM,EAAIF,EAAEV,KAAKS,GAAOI,EAAK,GAC3B,IACI,WAAc,IAANjB,GAAgBA,KAAM,MAAQe,EAAIC,EAAEvB,QAAQY,MAAMY,EAAGR,KAAKM,EAAET,OAExE,MAAOY,GAASR,EAAI,CAAEQ,MAAOA,GACjC,QACQ,IACQH,IAAMA,EAAEV,OAASS,EAAIE,EAAU,SAAIF,EAAEV,KAAKY,GAE1D,QAAkB,GAAIN,EAAG,MAAMA,EAAEQ,OAE7B,OAAOD,EAGJ,SAASE,IACZ,IAAK,IAAIF,EAAK,GAAID,EAAI,EAAGA,EAAII,UAAUZ,OAAQQ,IAC3CC,EAAKA,EAAGI,OAAOT,EAAOQ,UAAUJ,KACpC,OAAOC,QCpIT,SAAYX,GACVP,KAAKO,MAAQA,gBAIjB,SAAAgB,IAGUvB,KAAAwB,KAAO,EA+XjB,OA7XEC,OAAAC,eAAIH,EAAAI,UAAA,OAAI,KAAR,WACE,OAAO3B,KAAK4B,uCAEdH,OAAAC,eAAIH,EAAAI,UAAA,OAAI,KAAR,WACE,OAAO3B,KAAK6B,sCAEdJ,OAAAC,eAAIH,EAAAI,UAAA,SAAM,KAAV,WACE,OAAO3B,KAAKwB,sCAGND,EAAAI,UAAAG,OAAR,SACEvB,EACAwB,EACAC,GAEA,IAAKD,EAAc,OAAO/B,KAAKiC,QAAQ1B,GAEvC,IAAKyB,EAAU,OAAOhC,KAAKkC,QAAQ3B,GAEnC,IAAM4B,EAAO,IAAIC,EAAS7B,GAQ1B,OAPA4B,EAAKE,SAAWN,EAChBA,EAAarC,KAAOyC,EACpBA,EAAKzC,KAAOsC,EACZA,EAASK,SAAWF,EAEpBnC,KAAKwB,OAEEW,GAGDZ,EAAAI,UAAAW,WAAR,SACEC,EACAR,EACAC,GAEA,IAAKO,EAAO9B,OAAQ,MAAO,GAE3B,IAAKsB,EAAc,OAAO/B,KAAKwC,YAAYD,GAE3C,IAAKP,EAAU,OAAOhC,KAAKyC,YAAYF,GAEvC,IAAMG,EAAO,IAAInB,EASjB,OARAmB,EAAKD,YAAYF,GACjBG,EAAKd,MAAOS,SAAWN,EACvBA,EAAarC,KAAOgD,EAAKd,MACzBc,EAAKb,KAAMnC,KAAOsC,EAClBA,EAASK,SAAWK,EAAKb,KAEzB7B,KAAKwB,MAAQe,EAAO9B,OAEbiC,EAAKC,eAGNpB,EAAAI,UAAAiB,OAAR,SAAeT,GACb,OAAKA,EAAKE,SAELF,EAAKzC,MAEVyC,EAAKE,SAAS3C,KAAOyC,EAAKzC,KAC1ByC,EAAKzC,KAAK2C,SAAWF,EAAKE,SAE1BrC,KAAKwB,OAEEW,GAPgBnC,KAAK6C,WAFD7C,KAAK8C,YAYlCvB,EAAAI,UAAAoB,IAAA,SAAIxC,GAAJ,IAAAyC,EAAAhD,KACE,MAAO,CACLiD,MAAO,qBAACC,EAAA,GAAAC,EAAA,EAAAA,EAAA9B,UAAAZ,OAAA0C,IAAAD,EAAAC,GAAA9B,UAAA8B,GACN,OAAAC,EAAAJ,EAAKK,UAAShD,KAAIiD,MAAAF,EAAAhC,EAAA,CAAC4B,EAAMzC,GAAU2C,KACrCK,OAAQ,qBAACL,EAAA,GAAAC,EAAA,EAAAA,EAAA9B,UAAAZ,OAAA0C,IAAAD,EAAAC,GAAA9B,UAAA8B,GACP,OAAAC,EAAAJ,EAAKQ,WAAUnD,KAAIiD,MAAAF,EAAAhC,EAAA,CAAC4B,EAAMzC,GAAU2C,KACtCO,QAAS,SAACC,GAAqB,OAAAV,EAAKW,WAAWpD,EAAOmD,IACtDE,KAAM,WAAM,OAAAZ,EAAKf,QAAQ1B,IACzBsD,KAAM,WAAM,OAAAb,EAAKd,QAAQ3B,MAI7BgB,EAAAI,UAAAmC,QAAA,SAAQvB,GAAR,IAAAS,EAAAhD,KACE,MAAO,CACLiD,MAAO,qBAACC,EAAA,GAAAC,EAAA,EAAAA,EAAA9B,UAAAZ,OAAA0C,IAAAD,EAAAC,GAAA9B,UAAA8B,GACN,OAAAC,EAAAJ,EAAKe,cAAa1D,KAAIiD,MAAAF,EAAAhC,EAAA,CAAC4B,EAAMT,GAAWW,KAC1CK,OAAQ,qBAACL,EAAA,GAAAC,EAAA,EAAAA,EAAA9B,UAAAZ,OAAA0C,IAAAD,EAAAC,GAAA9B,UAAA8B,GACP,OAAAC,EAAAJ,EAAKgB,eAAc3D,KAAIiD,MAAAF,EAAAhC,EAAA,CAAC4B,EAAMT,GAAWW,KAC3CO,QAAS,SAACC,GAAqB,OAAAV,EAAKiB,eAAe1B,EAAQmB,IAC3DE,KAAM,WAAM,OAAAZ,EAAKR,YAAYD,IAC7BsB,KAAM,WAAM,OAAAb,EAAKP,YAAYF,MAMjChB,EAAAI,UAAA0B,SAAA,SAAS9C,EAAU2D,EAAoBC,QAAA,IAAAA,IAAAA,EAAAC,GACrC,IAAM/B,EAAWrC,KAAKqE,MAAK,SAAAlC,GAAQ,OAAAgC,EAAUhC,EAAK5B,MAAO2D,MAEzD,OAAO7B,EAAWrC,KAAK8B,OAAOvB,EAAO8B,EAAUA,EAAS3C,MAAQM,KAAKkC,QAAQ3B,IAK/EgB,EAAAI,UAAA6B,UAAA,SAAUjD,EAAU+D,EAAgBH,QAAA,IAAAA,IAAAA,EAAAC,GAClC,IAAM1E,EAAOM,KAAKqE,MAAK,SAAAlC,GAAQ,OAAAgC,EAAUhC,EAAK5B,MAAO+D,MAErD,OAAO5E,EAAOM,KAAK8B,OAAOvB,EAAOb,EAAK2C,SAAU3C,GAAQM,KAAKiC,QAAQ1B,IAGvEgB,EAAAI,UAAAgC,WAAA,SAAWpD,EAAUmD,GACnB,GAAIA,EAAW,EAAGA,GAAY1D,KAAKwB,UAC9B,GAAIkC,GAAY1D,KAAKwB,KAAM,OAAOxB,KAAKkC,QAAQ3B,GAEpD,GAAImD,GAAY,EAAG,OAAO1D,KAAKiC,QAAQ1B,GAEvC,IAAMb,EAAOM,KAAKuE,IAAIb,GAEtB,OAAO1D,KAAK8B,OAAOvB,EAAOb,EAAK2C,SAAU3C,IAG3C6B,EAAAI,UAAAM,QAAA,SAAQ1B,GACN,IAAM4B,EAAO,IAAIC,EAAS7B,GAU1B,OARA4B,EAAKzC,KAAOM,KAAK4B,MAEb5B,KAAK4B,MAAO5B,KAAK4B,MAAMS,SAAWF,EACjCnC,KAAK6B,KAAOM,EAEjBnC,KAAK4B,MAAQO,EACbnC,KAAKwB,OAEEW,GAGTZ,EAAAI,UAAAO,QAAA,SAAQ3B,GACN,IAAM4B,EAAO,IAAIC,EAAS7B,GAa1B,OAXIP,KAAK4B,OACPO,EAAKE,SAAWrC,KAAK6B,KACrB7B,KAAK6B,KAAMnC,KAAOyC,EAClBnC,KAAK6B,KAAOM,IAEZnC,KAAK4B,MAAQO,EACbnC,KAAK6B,KAAOM,GAGdnC,KAAKwB,OAEEW,GAKTZ,EAAAI,UAAAoC,aAAA,SACExB,EACA2B,EACAC,QAAA,IAAAA,IAAAA,EAAAC,GAEA,IAAM/B,EAAWrC,KAAKqE,MAAK,SAAAlC,GAAQ,OAAAgC,EAAUhC,EAAK5B,MAAO2D,MAEzD,OAAO7B,EAAWrC,KAAKsC,WAAWC,EAAQF,EAAUA,EAAS3C,MAAQM,KAAKyC,YAAYF,IAKxFhB,EAAAI,UAAAqC,cAAA,SACEzB,EACA+B,EACAH,QAAA,IAAAA,IAAAA,EAAAC,GAEA,IAAM1E,EAAOM,KAAKqE,MAAK,SAAAlC,GAAQ,OAAAgC,EAAUhC,EAAK5B,MAAO+D,MAErD,OAAO5E,EAAOM,KAAKsC,WAAWC,EAAQ7C,EAAK2C,SAAU3C,GAAQM,KAAKwC,YAAYD,IAGhFhB,EAAAI,UAAAsC,eAAA,SAAe1B,EAAamB,GAG1B,GAFIA,EAAW,IAAGA,GAAY1D,KAAKwB,MAE/BkC,GAAY,EAAG,OAAO1D,KAAKwC,YAAYD,GAE3C,GAAImB,GAAY1D,KAAKwB,KAAM,OAAOxB,KAAKyC,YAAYF,GAEnD,IAAM7C,EAAOM,KAAKuE,IAAIb,GAEtB,OAAO1D,KAAKsC,WAAWC,EAAQ7C,EAAK2C,SAAU3C,IAGhD6B,EAAAI,UAAAa,YAAA,SAAYD,GAAZ,IAAAS,EAAAhD,KACE,OAAOuC,EAAOiC,aAA2B,SAACC,EAAOlE,GAE/C,OADAkE,EAAMC,QAAQ1B,EAAKf,QAAQ1B,IACpBkE,IACN,KAGLlD,EAAAI,UAAAc,YAAA,SAAYF,GAAZ,IAAAS,EAAAhD,KACE,OAAOuC,EAAOoC,KAAI,SAAApE,GAAS,OAAAyC,EAAKd,QAAQ3B,OAG1CgB,EAAAI,UAAAiD,KAAA,WAAA,IAAA5B,EAAAhD,KACE,MAAO,CACLyD,QAAS,SAACC,GAAqB,OAAAV,EAAK6B,YAAYnB,IAChDoB,QAAS,eAAC,IAAA5B,EAAA,GAAAC,EAAA,EAAAA,EAAA9B,UAAAZ,OAAA0C,IAAAD,EAAAC,GAAA9B,UAAA8B,GACR,OAAAH,EAAK+B,YAAYzB,MAAMN,EAAME,IAC/B8B,WAAY,eAAC,IAAA9B,EAAA,GAAAC,EAAA,EAAAA,EAAA9B,UAAAZ,OAAA0C,IAAAD,EAAAC,GAAA9B,UAAA8B,GACX,OAAAH,EAAKiC,eAAe3B,MAAMN,EAAME,IAClCU,KAAM,WAAM,OAAAZ,EAAKF,YACjBe,KAAM,WAAM,OAAAb,EAAKH,cAIrBtB,EAAAI,UAAAuD,SAAA,SAASC,GAAT,IAAAnC,EAAAhD,KACE,MAAO,CACLyD,QAAS,SAACC,GAAqB,OAAAV,EAAKoC,gBAAgBD,EAAOzB,IAC3DE,KAAM,WAAM,OAAAZ,EAAKqC,aAAaF,IAC9BtB,KAAM,WAAM,OAAAb,EAAKsC,aAAaH,MAIlC5D,EAAAI,UAAAkD,YAAA,SAAYnB,GACNA,EAAW,IAAGA,GAAY1D,KAAKwB,MAEnC,IAAM+D,EAAUvF,KAAKuE,IAAIb,GAEzB,OAAO6B,EAAUvF,KAAK4C,OAAO2C,QAAWC,GAK1CjE,EAAAI,UAAAoD,YAAA,SAAYxE,EAAY4D,QAAA,IAAAA,IAAAA,EAAAC,GACtB,IAAMV,EAAW1D,KAAKyF,WAAU,SAAAtD,GAAQ,OAAAgC,EAAUhC,EAAK5B,MAAOA,MAE9D,OAAOmD,EAAW,OAAI8B,EAAYxF,KAAK6E,YAAYnB,IAKrDnC,EAAAI,UAAAsD,eAAA,SAAe1E,EAAY4D,QAAA,IAAAA,IAAAA,EAAAC,GAGzB,IAFA,IAAMsB,EAAyB,GAEtBH,EAAUvF,KAAK4B,MAAO8B,EAAW,EAAG6B,EAAS7B,IAAY6B,EAAUA,EAAQ7F,KAC9EyE,EAAUoB,EAAQhF,MAAOA,IAC3BmF,EAAQhF,KAAKV,KAAK6E,YAAYnB,EAAWgC,EAAQjF,SAIrD,OAAOiF,GAGTnE,EAAAI,UAAAmB,SAAA,WACE,IAAMc,EAAO5D,KAAK4B,MAElB,GAAIgC,EAQF,OAPA5D,KAAK4B,MAAQgC,EAAKlE,KAEdM,KAAK4B,MAAO5B,KAAK4B,MAAMS,cAAWmD,EACjCxF,KAAK6B,UAAO2D,EAEjBxF,KAAKwB,OAEEoC,GAMXrC,EAAAI,UAAAkB,SAAA,WACE,IAAMgB,EAAO7D,KAAK6B,KAElB,GAAIgC,EAQF,OAPA7D,KAAK6B,KAAOgC,EAAKxB,SAEbrC,KAAK6B,KAAM7B,KAAK6B,KAAKnC,UAAO8F,EAC3BxF,KAAK4B,WAAQ4D,EAElBxF,KAAKwB,OAEEqC,GAMXtC,EAAAI,UAAAyD,gBAAA,SAAgBD,EAAezB,GAC7B,GAAIyB,GAAS,EAAG,MAAO,GAEvB,GAAIzB,EAAW,EAAGA,EAAWiC,KAAKC,IAAIlC,EAAW1D,KAAKwB,KAAM,QACvD,GAAIkC,GAAY1D,KAAKwB,KAAM,MAAO,GAEvC2D,EAAQQ,KAAKE,IAAIV,EAAOnF,KAAKwB,KAAOkC,GAIpC,IAFA,IAAMgC,EAAyB,GAExBP,KAAS,CACd,IAAMI,EAAUvF,KAAKuE,IAAIb,GACzBgC,EAAQhF,KAAKV,KAAK4C,OAAO2C,IAG3B,OAAOG,GAGTnE,EAAAI,UAAA0D,aAAA,SAAaF,GACX,GAAIA,GAAS,EAAG,MAAO,GAEvBA,EAAQQ,KAAKE,IAAIV,EAAOnF,KAAKwB,MAI7B,IAFA,IAAMkE,EAAyB,GAExBP,KAASO,EAAQhB,QAAQ1E,KAAK8C,YAErC,OAAO4C,GAGTnE,EAAAI,UAAA2D,aAAA,SAAaH,GACX,GAAIA,GAAS,EAAG,MAAO,GAEvBA,EAAQQ,KAAKE,IAAIV,EAAOnF,KAAKwB,MAI7B,IAFA,IAAMkE,EAAyB,GAExBP,KAASO,EAAQhF,KAAKV,KAAK6C,YAElC,OAAO6C,GAGTnE,EAAAI,UAAA0C,KAAA,SAAKyB,GACH,IAAK,IAAIP,EAAUvF,KAAK4B,MAAO8B,EAAW,EAAG6B,EAAS7B,IAAY6B,EAAUA,EAAQ7F,KAClF,GAAIoG,EAAUP,EAAS7B,EAAU1D,MAAO,OAAOuF,GAMnDhE,EAAAI,UAAA8D,UAAA,SAAUK,GACR,IAAK,IAAIP,EAAUvF,KAAK4B,MAAO8B,EAAW,EAAG6B,EAAS7B,IAAY6B,EAAUA,EAAQ7F,KAClF,GAAIoG,EAAUP,EAAS7B,EAAU1D,MAAO,OAAO0D,EAGjD,OAAQ,GAGVnC,EAAAI,UAAAoE,QAAA,SAAqBC,GACnB,IAAK,IAAI7D,EAAOnC,KAAK4B,MAAO8B,EAAW,EAAGvB,EAAMuB,IAAYvB,EAAOA,EAAKzC,KACtEsG,EAAS7D,EAAMuB,EAAU1D,OAI7BuB,EAAAI,UAAA4C,IAAA,SAAIb,GACF,OAAO1D,KAAKqE,MAAK,SAAChF,EAAG4G,GAAU,OAAAvC,IAAauC,MAK9C1E,EAAAI,UAAAuE,QAAA,SAAQ3F,EAAY4D,GAClB,YADkB,IAAAA,IAAAA,EAAAC,GACXpE,KAAKyF,WAAU,SAAAtD,GAAQ,OAAAgC,EAAUhC,EAAK5B,MAAOA,OAGtDgB,EAAAI,UAAAwE,QAAA,WACE,IAAMC,EAAQ,IAAIC,MAAMrG,KAAKwB,MAI7B,OAFAxB,KAAK+F,SAAQ,SAAC5D,EAAM8D,GAAU,OAACG,EAAMH,GAAU9D,EAAK5B,SAE7C6F,GAGT7E,EAAAI,UAAAgB,YAAA,WACE,IAAMyD,EAAQ,IAAIC,MAAMrG,KAAKwB,MAI7B,OAFAxB,KAAK+F,SAAQ,SAAC5D,EAAM8D,GAAU,OAACG,EAAMH,GAAU9D,KAExCiE,GAGT7E,EAAAI,UAAA2E,SAAA,SAASC,GACP,YADO,IAAAA,IAAAA,EAA4BC,KAAKC,WACjCzG,KAAKmG,UACTxB,KAAI,SAAApE,GAAS,OAAAgG,EAAShG,MACtBmG,KAAK,UAITnF,EAAAI,UAAC7B,OAAOC,UAAT,mEACWoC,EAAOnC,KAAK4B,MAAkB,0BAAGO,EACxC,CAAA,EAAMA,EAAK5B,OADiC,CAAA,EAAA,UAC5C6C,EAAA7D,+BAD0D4C,EAAOA,EAAKzC,iCAI5E6B","sourcesContent":["/*! *****************************************************************************\r\nCopyright (c) Microsoft Corporation. All rights reserved.\r\nLicensed under the Apache License, Version 2.0 (the \"License\"); you may not use\r\nthis file except in compliance with the License. You may obtain a copy of the\r\nLicense at http://www.apache.org/licenses/LICENSE-2.0\r\n\r\nTHIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\r\nKIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\r\nWARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\r\nMERCHANTABLITY OR NON-INFRINGEMENT.\r\n\r\nSee the Apache Version 2.0 License for specific language governing permissions\r\nand limitations under the License.\r\n***************************************************************************** */\r\n/* global Reflect, Promise */\r\n\r\nvar extendStatics = function(d, b) {\r\n extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\r\n return extendStatics(d, b);\r\n};\r\n\r\nexport function __extends(d, b) {\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n}\r\n\r\nexport var __assign = function() {\r\n __assign = Object.assign || function __assign(t) {\r\n for (var s, i = 1, n = arguments.length; i < n; i++) {\r\n s = arguments[i];\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\r\n }\r\n return t;\r\n }\r\n return __assign.apply(this, arguments);\r\n}\r\n\r\nexport function __rest(s, e) {\r\n var t = {};\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\r\n t[p] = s[p];\r\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\r\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\r\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\r\n t[p[i]] = s[p[i]];\r\n }\r\n return t;\r\n}\r\n\r\nexport function __decorate(decorators, target, key, desc) {\r\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\r\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\r\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\r\n return c > 3 && r && Object.defineProperty(target, key, r), r;\r\n}\r\n\r\nexport function __param(paramIndex, decorator) {\r\n return function (target, key) { decorator(target, key, paramIndex); }\r\n}\r\n\r\nexport function __metadata(metadataKey, metadataValue) {\r\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\r\n}\r\n\r\nexport function __awaiter(thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n}\r\n\r\nexport function __generator(thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (_) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n}\r\n\r\nexport function __exportStar(m, exports) {\r\n for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];\r\n}\r\n\r\nexport function __values(o) {\r\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\r\n if (m) return m.call(o);\r\n if (o && typeof o.length === \"number\") return {\r\n next: function () {\r\n if (o && i >= o.length) o = void 0;\r\n return { value: o && o[i++], done: !o };\r\n }\r\n };\r\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\r\n}\r\n\r\nexport function __read(o, n) {\r\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\r\n if (!m) return o;\r\n var i = m.call(o), r, ar = [], e;\r\n try {\r\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\r\n }\r\n catch (error) { e = { error: error }; }\r\n finally {\r\n try {\r\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\r\n }\r\n finally { if (e) throw e.error; }\r\n }\r\n return ar;\r\n}\r\n\r\nexport function __spread() {\r\n for (var ar = [], i = 0; i < arguments.length; i++)\r\n ar = ar.concat(__read(arguments[i]));\r\n return ar;\r\n}\r\n\r\nexport function __spreadArrays() {\r\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\r\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\r\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\r\n r[k] = a[j];\r\n return r;\r\n};\r\n\r\nexport function __await(v) {\r\n return this instanceof __await ? (this.v = v, this) : new __await(v);\r\n}\r\n\r\nexport function __asyncGenerator(thisArg, _arguments, generator) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\r\n return i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i;\r\n function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }\r\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\r\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\r\n function fulfill(value) { resume(\"next\", value); }\r\n function reject(value) { resume(\"throw\", value); }\r\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\r\n}\r\n\r\nexport function __asyncDelegator(o) {\r\n var i, p;\r\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\r\n function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === \"return\" } : f ? f(v) : v; } : f; }\r\n}\r\n\r\nexport function __asyncValues(o) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var m = o[Symbol.asyncIterator], i;\r\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\r\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\r\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\r\n}\r\n\r\nexport function __makeTemplateObject(cooked, raw) {\r\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\r\n return cooked;\r\n};\r\n\r\nexport function __importStar(mod) {\r\n if (mod && mod.__esModule) return mod;\r\n var result = {};\r\n if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];\r\n result.default = mod;\r\n return result;\r\n}\r\n\r\nexport function __importDefault(mod) {\r\n return (mod && mod.__esModule) ? mod : { default: mod };\r\n}\r\n\r\nexport function __classPrivateFieldGet(receiver, privateMap) {\r\n if (!privateMap.has(receiver)) {\r\n throw new TypeError(\"attempted to get private field on non-instance\");\r\n }\r\n return privateMap.get(receiver);\r\n}\r\n\r\nexport function __classPrivateFieldSet(receiver, privateMap, value) {\r\n if (!privateMap.has(receiver)) {\r\n throw new TypeError(\"attempted to set private field on non-instance\");\r\n }\r\n privateMap.set(receiver, value);\r\n return value;\r\n}\r\n","/* tslint:disable:no-non-null-assertion */\r\n\r\nimport compare from 'just-compare';\r\n\r\nexport class ListNode {\r\n readonly value: T;\r\n next: ListNode | undefined;\r\n previous: ListNode | undefined;\r\n\r\n constructor(value: T) {\r\n this.value = value;\r\n }\r\n}\r\n\r\nexport class LinkedList {\r\n private first: ListNode | undefined;\r\n private last: ListNode | undefined;\r\n private size = 0;\r\n\r\n get head(): ListNode | undefined {\r\n return this.first;\r\n }\r\n get tail(): ListNode | undefined {\r\n return this.last;\r\n }\r\n get length(): number {\r\n return this.size;\r\n }\r\n\r\n private attach(\r\n value: T,\r\n previousNode: ListNode | undefined,\r\n nextNode: ListNode | undefined,\r\n ): ListNode {\r\n if (!previousNode) return this.addHead(value);\r\n\r\n if (!nextNode) return this.addTail(value);\r\n\r\n const node = new ListNode(value);\r\n node.previous = previousNode;\r\n previousNode.next = node;\r\n node.next = nextNode;\r\n nextNode.previous = node;\r\n\r\n this.size++;\r\n\r\n return node;\r\n }\r\n\r\n private attachMany(\r\n values: T[],\r\n previousNode: ListNode | undefined,\r\n nextNode: ListNode | undefined,\r\n ): ListNode[] {\r\n if (!values.length) return [];\r\n\r\n if (!previousNode) return this.addManyHead(values);\r\n\r\n if (!nextNode) return this.addManyTail(values);\r\n\r\n const list = new LinkedList();\r\n list.addManyTail(values);\r\n list.first!.previous = previousNode;\r\n previousNode.next = list.first;\r\n list.last!.next = nextNode;\r\n nextNode.previous = list.last;\r\n\r\n this.size += values.length;\r\n\r\n return list.toNodeArray();\r\n }\r\n\r\n private detach(node: ListNode) {\r\n if (!node.previous) return this.dropHead();\r\n\r\n if (!node.next) return this.dropTail();\r\n\r\n node.previous.next = node.next;\r\n node.next.previous = node.previous;\r\n\r\n this.size--;\r\n\r\n return node;\r\n }\r\n\r\n add(value: T) {\r\n return {\r\n after: (...params: [T] | [any, ListComparisonFn]) =>\r\n this.addAfter.call(this, value, ...params),\r\n before: (...params: [T] | [any, ListComparisonFn]) =>\r\n this.addBefore.call(this, value, ...params),\r\n byIndex: (position: number) => this.addByIndex(value, position),\r\n head: () => this.addHead(value),\r\n tail: () => this.addTail(value),\r\n };\r\n }\r\n\r\n addMany(values: T[]) {\r\n return {\r\n after: (...params: [T] | [any, ListComparisonFn]) =>\r\n this.addManyAfter.call(this, values, ...params),\r\n before: (...params: [T] | [any, ListComparisonFn]) =>\r\n this.addManyBefore.call(this, values, ...params),\r\n byIndex: (position: number) => this.addManyByIndex(values, position),\r\n head: () => this.addManyHead(values),\r\n tail: () => this.addManyTail(values),\r\n };\r\n }\r\n\r\n addAfter(value: T, nextValue: T): ListNode;\r\n addAfter(value: T, previousValue: any, compareFn: ListComparisonFn): ListNode;\r\n addAfter(value: T, previousValue: any, compareFn: ListComparisonFn = compare): ListNode {\r\n const previous = this.find(node => compareFn(node.value, previousValue));\r\n\r\n return previous ? this.attach(value, previous, previous.next) : this.addTail(value);\r\n }\r\n\r\n addBefore(value: T, nextValue: T): ListNode;\r\n addBefore(value: T, nextValue: any, compareFn: ListComparisonFn): ListNode;\r\n addBefore(value: T, nextValue: any, compareFn: ListComparisonFn = compare): ListNode {\r\n const next = this.find(node => compareFn(node.value, nextValue));\r\n\r\n return next ? this.attach(value, next.previous, next) : this.addHead(value);\r\n }\r\n\r\n addByIndex(value: T, position: number): ListNode {\r\n if (position < 0) position += this.size;\r\n else if (position >= this.size) return this.addTail(value);\r\n\r\n if (position <= 0) return this.addHead(value);\r\n\r\n const next = this.get(position)!;\r\n\r\n return this.attach(value, next.previous, next);\r\n }\r\n\r\n addHead(value: T): ListNode {\r\n const node = new ListNode(value);\r\n\r\n node.next = this.first;\r\n\r\n if (this.first) this.first.previous = node;\r\n else this.last = node;\r\n\r\n this.first = node;\r\n this.size++;\r\n\r\n return node;\r\n }\r\n\r\n addTail(value: T): ListNode {\r\n const node = new ListNode(value);\r\n\r\n if (this.first) {\r\n node.previous = this.last;\r\n this.last!.next = node;\r\n this.last = node;\r\n } else {\r\n this.first = node;\r\n this.last = node;\r\n }\r\n\r\n this.size++;\r\n\r\n return node;\r\n }\r\n\r\n addManyAfter(values: T[], previousValue: T): ListNode[];\r\n addManyAfter(values: T[], previousValue: any, compareFn: ListComparisonFn): ListNode[];\r\n addManyAfter(\r\n values: T[],\r\n previousValue: any,\r\n compareFn: ListComparisonFn = compare,\r\n ): ListNode[] {\r\n const previous = this.find(node => compareFn(node.value, previousValue));\r\n\r\n return previous ? this.attachMany(values, previous, previous.next) : this.addManyTail(values);\r\n }\r\n\r\n addManyBefore(values: T[], previousValue: T): ListNode[];\r\n addManyBefore(values: T[], nextValue: any, compareFn: ListComparisonFn): ListNode[];\r\n addManyBefore(\r\n values: T[],\r\n nextValue: any,\r\n compareFn: ListComparisonFn = compare,\r\n ): ListNode[] {\r\n const next = this.find(node => compareFn(node.value, nextValue));\r\n\r\n return next ? this.attachMany(values, next.previous, next) : this.addManyHead(values);\r\n }\r\n\r\n addManyByIndex(values: T[], position: number): ListNode[] {\r\n if (position < 0) position += this.size;\r\n\r\n if (position <= 0) return this.addManyHead(values);\r\n\r\n if (position >= this.size) return this.addManyTail(values);\r\n\r\n const next = this.get(position)!;\r\n\r\n return this.attachMany(values, next.previous, next);\r\n }\r\n\r\n addManyHead(values: T[]): ListNode[] {\r\n return values.reduceRight[]>((nodes, value) => {\r\n nodes.unshift(this.addHead(value));\r\n return nodes;\r\n }, []);\r\n }\r\n\r\n addManyTail(values: T[]): ListNode[] {\r\n return values.map(value => this.addTail(value));\r\n }\r\n\r\n drop() {\r\n return {\r\n byIndex: (position: number) => this.dropByIndex(position),\r\n byValue: (...params: [T] | [any, ListComparisonFn]) =>\r\n this.dropByValue.apply(this, params),\r\n byValueAll: (...params: [T] | [any, ListComparisonFn]) =>\r\n this.dropByValueAll.apply(this, params),\r\n head: () => this.dropHead(),\r\n tail: () => this.dropTail(),\r\n };\r\n }\r\n\r\n dropMany(count: number) {\r\n return {\r\n byIndex: (position: number) => this.dropManyByIndex(count, position),\r\n head: () => this.dropManyHead(count),\r\n tail: () => this.dropManyTail(count),\r\n };\r\n }\r\n\r\n dropByIndex(position: number): ListNode | undefined {\r\n if (position < 0) position += this.size;\r\n\r\n const current = this.get(position);\r\n\r\n return current ? this.detach(current) : undefined;\r\n }\r\n\r\n dropByValue(value: T): ListNode | undefined;\r\n dropByValue(value: any, compareFn: ListComparisonFn): ListNode | undefined;\r\n dropByValue(value: any, compareFn: ListComparisonFn = compare): ListNode | undefined {\r\n const position = this.findIndex(node => compareFn(node.value, value));\r\n\r\n return position < 0 ? undefined : this.dropByIndex(position);\r\n }\r\n\r\n dropByValueAll(value: T): ListNode[];\r\n dropByValueAll(value: any, compareFn: ListComparisonFn): ListNode[];\r\n dropByValueAll(value: any, compareFn: ListComparisonFn = compare): ListNode[] {\r\n const dropped: ListNode[] = [];\r\n\r\n for (let current = this.first, position = 0; current; position++, current = current.next) {\r\n if (compareFn(current.value, value)) {\r\n dropped.push(this.dropByIndex(position - dropped.length)!);\r\n }\r\n }\r\n\r\n return dropped;\r\n }\r\n\r\n dropHead(): ListNode | undefined {\r\n const head = this.first;\r\n\r\n if (head) {\r\n this.first = head.next;\r\n\r\n if (this.first) this.first.previous = undefined;\r\n else this.last = undefined;\r\n\r\n this.size--;\r\n\r\n return head;\r\n }\r\n\r\n return undefined;\r\n }\r\n\r\n dropTail(): ListNode | undefined {\r\n const tail = this.last;\r\n\r\n if (tail) {\r\n this.last = tail.previous;\r\n\r\n if (this.last) this.last.next = undefined;\r\n else this.first = undefined;\r\n\r\n this.size--;\r\n\r\n return tail;\r\n }\r\n\r\n return undefined;\r\n }\r\n\r\n dropManyByIndex(count: number, position: number): ListNode[] {\r\n if (count <= 0) return [];\r\n\r\n if (position < 0) position = Math.max(position + this.size, 0);\r\n else if (position >= this.size) return [];\r\n\r\n count = Math.min(count, this.size - position);\r\n\r\n const dropped: ListNode[] = [];\r\n\r\n while (count--) {\r\n const current = this.get(position);\r\n dropped.push(this.detach(current!)!);\r\n }\r\n\r\n return dropped;\r\n }\r\n\r\n dropManyHead(count: Exclude): ListNode[] {\r\n if (count <= 0) return [];\r\n\r\n count = Math.min(count, this.size);\r\n\r\n const dropped: ListNode[] = [];\r\n\r\n while (count--) dropped.unshift(this.dropHead()!);\r\n\r\n return dropped;\r\n }\r\n\r\n dropManyTail(count: Exclude): ListNode[] {\r\n if (count <= 0) return [];\r\n\r\n count = Math.min(count, this.size);\r\n\r\n const dropped: ListNode[] = [];\r\n\r\n while (count--) dropped.push(this.dropTail()!);\r\n\r\n return dropped;\r\n }\r\n\r\n find(predicate: ListIteratorFn): ListNode | undefined {\r\n for (let current = this.first, position = 0; current; position++, current = current.next) {\r\n if (predicate(current, position, this)) return current;\r\n }\r\n\r\n return undefined;\r\n }\r\n\r\n findIndex(predicate: ListIteratorFn): number {\r\n for (let current = this.first, position = 0; current; position++, current = current.next) {\r\n if (predicate(current, position, this)) return position;\r\n }\r\n\r\n return -1;\r\n }\r\n\r\n forEach(callback: ListIteratorFn) {\r\n for (let node = this.first, position = 0; node; position++, node = node.next) {\r\n callback(node, position, this);\r\n }\r\n }\r\n\r\n get(position: number): ListNode | undefined {\r\n return this.find((_, index) => position === index);\r\n }\r\n\r\n indexOf(value: T): number;\r\n indexOf(value: any, compareFn: ListComparisonFn): number;\r\n indexOf(value: any, compareFn: ListComparisonFn = compare): number {\r\n return this.findIndex(node => compareFn(node.value, value));\r\n }\r\n\r\n toArray(): T[] {\r\n const array = new Array(this.size);\r\n\r\n this.forEach((node, index) => (array[index!] = node.value));\r\n\r\n return array;\r\n }\r\n\r\n toNodeArray(): ListNode[] {\r\n const array = new Array(this.size);\r\n\r\n this.forEach((node, index) => (array[index!] = node));\r\n\r\n return array;\r\n }\r\n\r\n toString(mapperFn: ListMapperFn = JSON.stringify): string {\r\n return this.toArray()\r\n .map(value => mapperFn(value))\r\n .join(' <-> ');\r\n }\r\n\r\n // Cannot use Generator type because of ng-packagr\r\n *[Symbol.iterator](): any {\r\n for (let node = this.first, position = 0; node; position++, node = node.next) {\r\n yield node.value;\r\n }\r\n }\r\n}\r\n\r\nexport type ListMapperFn = (value: T) => any;\r\n\r\nexport type ListComparisonFn = (value1: T, value2: any) => boolean;\r\n\r\nexport type ListIteratorFn = (\r\n node: ListNode,\r\n index?: number,\r\n list?: LinkedList,\r\n) => R;\r\n"]} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/ru.json b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/ru.json new file mode 100644 index 0000000000..ba2680892c --- /dev/null +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/ru.json @@ -0,0 +1,37 @@ +{ + "culture": "ru", + "texts": { + "Permission:DocumentManagement": "Управление документацией", + "Permission:Projects": "Проекты", + "Permission:Edit": "Редактировать", + "Permission:Delete": "Удалить", + "Permission:Create": "Создать", + "Permission:Documents": "Документы", + "Menu:DocumentManagement": "Документы", + "Menu:ProjectManagement": "Проекты", + "CreateANewProject": "Создать проекты", + "Edit": "Редактировать", + "Create": "Создать", + "Pull": "Получить", + "Projects": "Проекты", + "Name": "Название", + "ShortName": "Сокращенное название", + "DocumentStoreType": "Тип системы хранения", + "Format": "Формат", + "ShortNameInfoText": "Будет использоваться для уникального URL.", + "DisplayName:Name": "Название", + "DisplayName:ShortName": "Сокращенное название", + "DisplayName:Format": "Формат", + "DisplayName:DefaultDocumentName": "Имя документа по умолчанию", + "DisplayName:NavigationDocumentName": "Имя документа для навигации", + "DisplayName:MinimumVersion": "Минимальная версия", + "DisplayName:MainWebsiteUrl": "URL основного веб-сайта", + "DisplayName:LatestVersionBranchName": "Название ветки последней версии", + "DisplayName:GitHubRootUrl": "Корневой URL-адрес GitHub", + "DisplayName:GitHubAccessToken": "Маркер доступа для GitHub", + "DisplayName:GitHubUserAgent": "Заголовок User-Agent для GitHub", + "DisplayName:All": "Получить все", + "DisplayName:LanguageCode": "Код языка", + "DisplayName:Version": "Версия" + } +} diff --git a/modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Projects/Create.cshtml.cs b/modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Projects/Create.cshtml.cs index dc4af5e94c..e6de68a3b1 100644 --- a/modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Projects/Create.cshtml.cs +++ b/modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Projects/Create.cshtml.cs @@ -29,7 +29,7 @@ namespace Volo.Docs.Admin.Pages.Docs.Admin.Projects _projectAppService = projectAppService; } - public async Task OnGetAsync(string source) + public virtual async Task OnGetAsync(string source) { if (source != null && source.ToLowerInvariant() == "github") { @@ -42,7 +42,7 @@ namespace Volo.Docs.Admin.Pages.Docs.Admin.Projects } } - public async Task OnPostAsync() + public virtual async Task OnPostAsync() { if (GithubProject != null) { diff --git a/modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Projects/Edit.cshtml.cs b/modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Projects/Edit.cshtml.cs index 49b569d18c..3b9aba5303 100644 --- a/modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Projects/Edit.cshtml.cs +++ b/modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Projects/Edit.cshtml.cs @@ -29,7 +29,7 @@ namespace Volo.Docs.Admin.Pages.Docs.Admin.Projects _projectAppService = projectAppService; } - public async Task OnGetAsync(Guid id) + public virtual async Task OnGetAsync(Guid id) { var project = await _projectAppService.GetAsync(id); @@ -42,7 +42,7 @@ namespace Volo.Docs.Admin.Pages.Docs.Admin.Projects throw new BusinessException("UnknowDocumentSourceExceptionMessage"); } - public async Task OnPostAsync() + public virtual async Task OnPostAsync() { if (GithubProject != null) { diff --git a/modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Projects/Index.cshtml.cs b/modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Projects/Index.cshtml.cs index de530d36b8..bfac3a2220 100644 --- a/modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Projects/Index.cshtml.cs +++ b/modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Projects/Index.cshtml.cs @@ -1,4 +1,6 @@ +using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; namespace Volo.Docs.Admin.Pages.Docs.Admin.Projects @@ -6,8 +8,9 @@ namespace Volo.Docs.Admin.Pages.Docs.Admin.Projects [Authorize(DocsAdminPermissions.Projects.Default)] public class IndexModel : DocsAdminPageModel { - public void OnGet() + public virtual Task OnGet() { + return Task.FromResult(Page()); } } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Projects/Pull.cshtml.cs b/modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Projects/Pull.cshtml.cs index dd1b5c2ac9..195337a22e 100644 --- a/modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Projects/Pull.cshtml.cs +++ b/modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Projects/Pull.cshtml.cs @@ -23,7 +23,7 @@ namespace Volo.Docs.Admin.Pages.Docs.Admin.Projects _documentAppService = documentAppService; } - public async Task OnGetAsync(Guid id) + public virtual async Task OnGetAsync(Guid id) { var project = await _projectAppService.GetAsync(id); @@ -36,7 +36,7 @@ namespace Volo.Docs.Admin.Pages.Docs.Admin.Projects return Page(); } - public async Task OnPostAsync() + public virtual async Task OnPostAsync() { if (PullDocument.All) { 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 50db79cb43..74fa74090d 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 @@ -25,7 +25,7 @@ namespace Volo.Docs.Pages.Documents _uiOptions = urlOptions.Value; } - public async Task OnGetAsync() + public virtual async Task OnGetAsync() { DocumentsUrlPrefix = _uiOptions.RoutePrefix; 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 56f9dac913..04f8614f56 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 @@ -92,7 +92,7 @@ namespace Volo.Docs.Pages.Documents.Project _uiOptions = options.Value; } - public async Task OnGetAsync() + public virtual async Task OnGetAsync() { try { @@ -597,6 +597,11 @@ namespace Volo.Docs.Pages.Documents.Project public string GetDescription() { + if (Document == null || Document.Content.IsNullOrWhiteSpace()) + { + return null; + } + var firstParagraph = new Regex(@"

(.*?)

", RegexOptions.IgnoreCase); var match = firstParagraph.Match(Document.Content); if (!match.Success) diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Search.cshtml.cs b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Search.cshtml.cs index 7be8271b0f..702141bc1e 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Search.cshtml.cs +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Search.cshtml.cs @@ -39,7 +39,7 @@ namespace Volo.Docs.Pages.Documents public List SearchOutputs { get; set; } = new List(); - public async Task OnGetAsync(string keyword) + public virtual async Task OnGetAsync(string keyword) { if (!await _documentAppService.FullSearchEnabledAsync()) { diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/ru.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/ru.json new file mode 100644 index 0000000000..3945762269 --- /dev/null +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/ru.json @@ -0,0 +1,7 @@ +{ + "culture": "ru", + "texts": { + "Features": "Функциональные возможности", + "NoFeatureFoundMessage": "Нет доступных функциональных возможностей." + } +} diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/ru.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/ru.json new file mode 100644 index 0000000000..1df7b63bfe --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/ru.json @@ -0,0 +1,102 @@ +{ + "culture": "ru", + "texts": { + "Menu:IdentityManagement": "Управление идентификацией", + "Users": "Пользователи", + "NewUser": "Новый пользователь", + "UserName": "Имя пользователя", + "EmailAddress": "Адрес электронной почты", + "PhoneNumber": "Номер телефона", + "UserInformations": "Информация о пользователе", + "DisplayName:IsDefault": "По умолчанию", + "DisplayName:IsStatic": "Статичная", + "DisplayName:IsPublic": "Доступно", + "Roles": "Роли", + "Password": "Пароль", + "PersonalInfo": "Мой профиль", + "PersonalSettings": "Персональные настройки", + "UserDeletionConfirmationMessage": "Пользователь '{0}' будет удален. Вы подтверждаете это?", + "RoleDeletionConfirmationMessage": "Роль '{0}' будет удалена. Вы подтверждаете это?", + "DisplayName:RoleName": "Название роли", + "DisplayName:UserName": "Имя пользователя", + "DisplayName:Name": "Имя", + "DisplayName:Surname": "Фамилия", + "DisplayName:Password": "Пароль", + "DisplayName:Email": "Адрес электронной почты", + "DisplayName:PhoneNumber": "Номер телефона", + "DisplayName:TwoFactorEnabled": "Двухфакторная проверка подлинности", + "DisplayName:LockoutEnabled": "Заблокировать учетную запись после неудачных попыток входа", + "NewRole": "Новая роль", + "RoleName": "Имя роли", + "CreationTime": "Время создания", + "Permissions": "Разрешения", + "DisplayName:CurrentPassword": "Текущий пароль", + "DisplayName:NewPassword": "Новый пароль", + "DisplayName:NewPasswordConfirm": "Подтверждение нового пароля", + "PasswordChangedMessage": "Ваш пароль был успешно изменен.", + "PersonalSettingsSavedMessage": "Ваши персональные настройки были успешно сохранены.", + "Identity.DefaultError": "Возникла непредвиденная ошибка.", + "Identity.ConcurrencyFailure": "Ошибка оптимального управления многопоточностью, объект был изменен.", + "Identity.DuplicateEmail": "Электронная почта '{0}' уже зарегистрирована.", + "Identity.DuplicateRoleName": "Имя роли '{0}' уже занято.", + "Identity.DuplicateUserName": "Имя пользователя '{0}' уже занято.", + "Identity.InvalidEmail": "Адрес электронной почты '{0}' недействителен.", + "Identity.InvalidPasswordHasherCompatibilityMode": "Предоставленный PasswordHasherCompatibilityMode недействителен.", + "Identity.InvalidPasswordHasherIterationCount": "Число итераций должно быть положительным целым числом.", + "Identity.InvalidRoleName": "Имя роли '{0}' недопустимо.", + "Identity.InvalidToken": "Недопустимый маркер.", + "Identity.InvalidUserName": "Имя пользователя '{0}' недопустимо и может содержать только буквы или цифры.", + "Identity.LoginAlreadyAssociated": "Пользователь с таким логином уже существует.", + "Identity.PasswordMismatch": "Неверный пароль.", + "Identity.PasswordRequiresDigit": "Пароль должен содержать по крайней мере одну цифру.", + "Identity.PasswordRequiresLower": "Пароль должен содержать хотя бы одну строчную букву.", + "Identity.PasswordRequiresNonAlphanumeric": "Пароль должен иметь по крайней мере один не буквенно-цифровой символ.", + "Identity.PasswordRequiresUpper": "Пароль должен иметь хотя бы одну букву верхнего регистра.", + "Identity.PasswordTooShort": "Пароль должен содержать не менее {0} символов.", + "Identity.RoleNotFound": "Роль {0} не существует.", + "Identity.UserAlreadyHasPassword": "У пользователя уже установлен пароль.", + "Identity.UserAlreadyInRole": "Пользователь уже имеет роль '{0}'.", + "Identity.UserLockedOut": "Пользователь временно заблокирован.", + "Identity.UserLockoutNotEnabled": "Блокировка не активирована для этого пользователя.", + "Identity.UserNameNotFound": "Пользователь {0} не существует.", + "Identity.UserNotInRole": "Пользователь не имеет роль '{0}'.", + "Identity.PasswordConfirmationFailed": "Пароли не совпадают.", + "Identity.StaticRoleRenamingErrorMessage": "Статические роли не могут быть переименованы.", + "Identity.StaticRoleDeletionErrorMessage": "Статические роли не могут быть удалены.", + "Volo.Abp.Identity:010001": "Вы не можете удалить свой собственный аккаунт!", + "Permission:IdentityManagement": "Управление идентификацией", + "Permission:RoleManagement": "Управление ролями", + "Permission:Create": "Создать", + "Permission:Edit": "Редактировать", + "Permission:Delete": "Удалить", + "Permission:ChangePermissions": "Изменить разрешения", + "Permission:UserManagement": "Управление пользователями", + "Permission:UserLookup": "Поиск пользователя", + "DisplayName:Abp.Identity.Password.RequiredLength": "Требуемая длина", + "DisplayName:Abp.Identity.Password.RequiredUniqueChars": "Обязательное количество уникальных символов", + "DisplayName:Abp.Identity.Password.RequireNonAlphanumeric": "Обязательный не буквенно-цифровой символ", + "DisplayName:Abp.Identity.Password.RequireLowercase": "Обязательный символ нижнего регистра", + "DisplayName:Abp.Identity.Password.RequireUppercase": "Обязательный символ верхнего регистра", + "DisplayName:Abp.Identity.Password.RequireDigit": "Требуемая цифра", + "DisplayName:Abp.Identity.Lockout.AllowedForNewUsers": "Включено для новых пользователей", + "DisplayName:Abp.Identity.Lockout.LockoutDuration": "Длительность блокировки (секунды)", + "DisplayName:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Максимальное количество неудачных попыток доступа", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Требуется подтверждение электронной почты", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Требуется подтверждение номера телефона", + "DisplayName:Abp.Identity.User.IsUserNameUpdateEnabled": "Пользователь может изменять имя", + "DisplayName:Abp.Identity.User.IsEmailUpdateEnabled": "Электронная почта может быть изменена", + "Description:Abp.Identity.Password.RequiredLength": "Минимальная длина пароля.", + "Description:Abp.Identity.Password.RequiredUniqueChars": "Минимальное количество уникальных символов, которые должен содержать пароль.", + "Description:Abp.Identity.Password.RequireNonAlphanumeric": "Если пароли должны содержать не буквенно- цифровой символ.", + "Description:Abp.Identity.Password.RequireLowercase": "Если пароли должны содержать строчные символы ASCII.", + "Description:Abp.Identity.Password.RequireUppercase": "Если пароли должны содержать символ ASCII в верхнем регистре.", + "Description:Abp.Identity.Password.RequireDigit": "Если пароли должны содержать цифру.", + "Description:Abp.Identity.Lockout.AllowedForNewUsers": "Может ли новый пользователь быть заблокирован.", + "Description:Abp.Identity.Lockout.LockoutDuration": "Длительность блокировки пользователя.", + "Description:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Число неудачных попыток доступа, после которых пользователь будет заблокирован.", + "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Требуется ли для входа подтвержденный адрес электронной почты.", + "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Требуется ли для входа в систему подтвержденный номер телефона.", + "Description:Abp.Identity.User.IsUserNameUpdateEnabled": "Может ли пользователь обновить имя пользователя.", + "Description:Abp.Identity.User.IsEmailUpdateEnabled": "Может ли электронная почта быть обновлена пользователем." + } +} diff --git a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Roles/CreateModal.cshtml.cs b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Roles/CreateModal.cshtml.cs index 6d022c7048..e7244c80f1 100644 --- a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Roles/CreateModal.cshtml.cs +++ b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Roles/CreateModal.cshtml.cs @@ -16,9 +16,9 @@ namespace Volo.Abp.Identity.Web.Pages.Identity.Roles IdentityRoleAppService = identityRoleAppService; } - public virtual Task OnGetAsync() + public virtual Task OnGetAsync() { - return Task.CompletedTask; + return Task.FromResult(Page()); } public virtual async Task OnPostAsync() diff --git a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Roles/Index.cshtml.cs b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Roles/Index.cshtml.cs index 0fab86d195..254c1785bc 100644 --- a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Roles/Index.cshtml.cs +++ b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Roles/Index.cshtml.cs @@ -1,17 +1,18 @@ using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; namespace Volo.Abp.Identity.Web.Pages.Identity.Roles { public class IndexModel : IdentityPageModel { - public virtual Task OnGetAsync() + public virtual Task OnGetAsync() { - return Task.CompletedTask; + return Task.FromResult(Page()); } - public virtual Task OnPostAsync() + public virtual Task OnPostAsync() { - return Task.CompletedTask; + return Task.FromResult(Page()); } } } \ No newline at end of file diff --git a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/CreateModal.cshtml.cs b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/CreateModal.cshtml.cs index f480ee925f..9622d87de2 100644 --- a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/CreateModal.cshtml.cs +++ b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/CreateModal.cshtml.cs @@ -25,7 +25,7 @@ namespace Volo.Abp.Identity.Web.Pages.Identity.Users IdentityRoleAppService = identityRoleAppService; } - public virtual async Task OnGetAsync() + public virtual async Task OnGetAsync() { UserInfo = new UserInfoViewModel(); @@ -37,6 +37,8 @@ namespace Volo.Abp.Identity.Web.Pages.Identity.Users { role.IsAssigned = role.IsDefault; } + + return Page(); } public virtual async Task OnPostAsync() diff --git a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/EditModal.cshtml.cs b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/EditModal.cshtml.cs index df676ecaf4..7ffb58ccab 100644 --- a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/EditModal.cshtml.cs +++ b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/EditModal.cshtml.cs @@ -27,7 +27,7 @@ namespace Volo.Abp.Identity.Web.Pages.Identity.Users IdentityRoleAppService = identityRoleAppService; } - public virtual async Task OnGetAsync(Guid id) + public virtual async Task OnGetAsync(Guid id) { UserInfo = ObjectMapper.Map(await IdentityUserAppService.GetAsync(id)); @@ -41,6 +41,8 @@ namespace Volo.Abp.Identity.Web.Pages.Identity.Users role.IsAssigned = true; } } + + return Page(); } public virtual async Task OnPostAsync() diff --git a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/Index.cshtml.cs b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/Index.cshtml.cs index d1382c59b6..b6ff2c0e94 100644 --- a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/Index.cshtml.cs +++ b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/Index.cshtml.cs @@ -1,17 +1,18 @@ using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; namespace Volo.Abp.Identity.Web.Pages.Identity.Users { public class IndexModel : IdentityPageModel { - public virtual Task OnGetAsync() + public virtual Task OnGetAsync() { - return Task.CompletedTask; + return Task.FromResult(Page()); } - public virtual Task OnPostAsync() + public virtual Task OnPostAsync() { - return Task.CompletedTask; + return Task.FromResult(Page()); } } } diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/ru.json b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/ru.json new file mode 100644 index 0000000000..808962d8e5 --- /dev/null +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/ru.json @@ -0,0 +1,12 @@ +{ + "culture": "ru", + "texts": { + "Volo.IdentityServer:DuplicateIdentityResourceName": "Имя ресурса идентификации уже существует: {Name}", + "Volo.IdentityServer:DuplicateApiResourceName": "Имя ресурса API уже существует: {Name}", + "Volo.IdentityServer:DuplicateClientId": "Параметр ClientID уже существует: {ClientId}", + "UserLockedOut": "Учетная запись пользователя была заблокирована из-за неудачных попыток входа в систему. Пожалуйста, попробуйте позже.", + "InvalidUserNameOrPassword": "Неверное имя пользователя или пароль!", + "LoginIsNotAllowed": "У вас нет разрешения на вход в систему. Необходимо подтвердить свой адрес электронной почты/номер телефона.", + "InvalidUsername": "Неверное имя пользователя или пароль!" + } +} diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/ru.json b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/ru.json new file mode 100644 index 0000000000..33291e66a0 --- /dev/null +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/ru.json @@ -0,0 +1,10 @@ +{ + "culture": "ru", + "texts": { + "Permissions": "Разрешения", + "OnlyProviderPermissons": "Только этот провайдер", + "All": "Все", + "SelectAllInAllTabs": "Предоставить все разрешения", + "SelectAllInThisTab": "Выбрать все" + } +} diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/PermissionManagementModal.cshtml.cs b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/PermissionManagementModal.cshtml.cs index 02f5a8af17..041121b8cb 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/PermissionManagementModal.cshtml.cs +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/PermissionManagementModal.cshtml.cs @@ -38,7 +38,7 @@ namespace Volo.Abp.PermissionManagement.Web.Pages.AbpPermissionManagement PermissionAppService = permissionAppService; } - public virtual async Task OnGetAsync() + public virtual async Task OnGetAsync() { ValidateModel(); @@ -62,6 +62,8 @@ namespace Volo.Abp.PermissionManagement.Web.Pages.AbpPermissionManagement } SelectAllInAllTabs = Groups.All(g => g.IsAllPermissionsGranted); + + return Page(); } public virtual async Task OnPostAsync() diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/ru.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/ru.json new file mode 100644 index 0000000000..3b23b1d04a --- /dev/null +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/ru.json @@ -0,0 +1,7 @@ +{ + "culture": "ru", + "texts": { + "Settings": "Настройки", + "SuccessfullySaved": "Успешно сохранено" + } +} diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Index.cshtml.cs b/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Index.cshtml.cs index 31602957cf..7f9c332e13 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Index.cshtml.cs +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Index.cshtml.cs @@ -1,6 +1,7 @@ using System; using System.Threading.Tasks; using Microsoft.Extensions.Options; +using Microsoft.AspNetCore.Mvc; using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; namespace Volo.Abp.SettingManagement.Web.Pages.SettingManagement @@ -16,7 +17,7 @@ namespace Volo.Abp.SettingManagement.Web.Pages.SettingManagement Options = options.Value; } - public virtual async Task OnGetAsync() + public virtual async Task OnGetAsync() { SettingPageCreationContext = new SettingPageCreationContext(ServiceProvider); @@ -24,11 +25,13 @@ namespace Volo.Abp.SettingManagement.Web.Pages.SettingManagement { await contributor.ConfigureAsync(SettingPageCreationContext); } + + return Page(); } - public virtual Task OnPostAsync() + public virtual Task OnPostAsync() { - return Task.CompletedTask; + return Task.FromResult(Page()); } } } \ No newline at end of file diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/ru.json b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/ru.json new file mode 100644 index 0000000000..dd8f0c3847 --- /dev/null +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/ru.json @@ -0,0 +1,20 @@ +{ + "culture": "ru", + "texts": { + "Menu:TenantManagement": "Управление арендаторами", + "Tenants": "Арендаторы", + "NewTenant": "Новый арендатор", + "TenantName": "Имя арендатора", + "DisplayName:TenantName": "Имя арендатора", + "TenantDeletionConfirmationMessage": "Арендатор '{0}' будет удален. Вы подтверждаете это?", + "ConnectionStrings": "Строки подключения", + "DisplayName:DefaultConnectionString": "Строка подключения по умолчанию", + "DisplayName:UseSharedDatabase": "Использование общей базы данных", + "Permission:TenantManagement": "Управление арендаторами", + "Permission:Create": "Создать", + "Permission:Edit": "Редактировать", + "Permission:Delete": "Удалить", + "Permission:ManageConnectionStrings": "Управление строками подключения", + "Permission:ManageFeatures": "Управление функциями" + } +} diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Pages/TenantManagement/Tenants/ConnectionStringsModal.cshtml.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Pages/TenantManagement/Tenants/ConnectionStringsModal.cshtml.cs index 5456e512ec..9093437f98 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Pages/TenantManagement/Tenants/ConnectionStringsModal.cshtml.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Pages/TenantManagement/Tenants/ConnectionStringsModal.cshtml.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.ComponentModel.DataAnnotations; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; @@ -17,7 +17,7 @@ namespace Volo.Abp.TenantManagement.Web.Pages.TenantManagement.Tenants TenantAppService = tenantAppService; } - public virtual async Task OnGetAsync(Guid id) + public virtual async Task OnGetAsync(Guid id) { var defaultConnectionString = await TenantAppService.GetDefaultConnectionStringAsync(id); Tenant = new TenantInfoModel @@ -26,6 +26,8 @@ namespace Volo.Abp.TenantManagement.Web.Pages.TenantManagement.Tenants DefaultConnectionString = defaultConnectionString, UseSharedDatabase = defaultConnectionString.IsNullOrWhiteSpace() }; + + return Page(); } public virtual async Task OnPostAsync() diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Pages/TenantManagement/Tenants/CreateModal.cshtml.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Pages/TenantManagement/Tenants/CreateModal.cshtml.cs index 86569149f8..fa517594ee 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Pages/TenantManagement/Tenants/CreateModal.cshtml.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Pages/TenantManagement/Tenants/CreateModal.cshtml.cs @@ -1,4 +1,4 @@ -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; @@ -16,9 +16,9 @@ namespace Volo.Abp.TenantManagement.Web.Pages.TenantManagement.Tenants TenantAppService = tenantAppService; } - public virtual Task OnGetAsync() + public virtual Task OnGetAsync() { - return Task.CompletedTask; + return Task.FromResult(Page()); } public virtual async Task OnPostAsync() diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Pages/TenantManagement/Tenants/EditModal.cshtml.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Pages/TenantManagement/Tenants/EditModal.cshtml.cs index 1ae5709d57..74ac176b02 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Pages/TenantManagement/Tenants/EditModal.cshtml.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Pages/TenantManagement/Tenants/EditModal.cshtml.cs @@ -17,11 +17,13 @@ namespace Volo.Abp.TenantManagement.Web.Pages.TenantManagement.Tenants TenantAppService = tenantAppService; } - public virtual async Task OnGetAsync(Guid id) + public virtual async Task OnGetAsync(Guid id) { Tenant = ObjectMapper.Map( await TenantAppService.GetAsync(id) ); + + return Page(); } public virtual async Task OnPostAsync() diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Pages/TenantManagement/Tenants/Index.cshtml.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Pages/TenantManagement/Tenants/Index.cshtml.cs index 93bc14a62b..11395d870f 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Pages/TenantManagement/Tenants/Index.cshtml.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Pages/TenantManagement/Tenants/Index.cshtml.cs @@ -1,18 +1,19 @@ using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; namespace Volo.Abp.TenantManagement.Web.Pages.TenantManagement.Tenants { public class IndexModel : TenantManagementPageModel { - public virtual Task OnGetAsync() + public virtual Task OnGetAsync() { - return Task.CompletedTask; + return Task.FromResult(Page()); } - public virtual Task OnPostAsync() + public virtual Task OnPostAsync() { - return Task.CompletedTask; + return Task.FromResult(Page()); } } } \ No newline at end of file diff --git a/npm/ng-packs/apps/dev-app/src/app/app.module.ts b/npm/ng-packs/apps/dev-app/src/app/app.module.ts index 64f8150f01..2416eb881d 100644 --- a/npm/ng-packs/apps/dev-app/src/app/app.module.ts +++ b/npm/ng-packs/apps/dev-app/src/app/app.module.ts @@ -1,5 +1,4 @@ import { CoreModule } from '@abp/ng.core'; -import { LAYOUTS } from '@abp/ng.theme.basic'; import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; @@ -19,6 +18,9 @@ const LOGGERS = [NgxsLoggerPluginModule.forRoot({ disabled: false })]; @NgModule({ imports: [ + BrowserModule, + BrowserAnimationsModule, + AppRoutingModule, CoreModule.forRoot({ environment, }), @@ -28,9 +30,6 @@ const LOGGERS = [NgxsLoggerPluginModule.forRoot({ disabled: false })]; TenantManagementConfigModule, SettingManagementConfigModule, NgxsModule.forRoot(), - BrowserModule, - BrowserAnimationsModule, - AppRoutingModule, SharedModule, ...(environment.production ? [] : LOGGERS), ], diff --git a/npm/ng-packs/packages/core/src/lib/models/common.ts b/npm/ng-packs/packages/core/src/lib/models/common.ts index 8a413b1077..d1041bcf09 100644 --- a/npm/ng-packs/packages/core/src/lib/models/common.ts +++ b/npm/ng-packs/packages/core/src/lib/models/common.ts @@ -1,7 +1,7 @@ -import { eLayoutType } from '../enums/common'; -import { Config } from './config'; import { EventEmitter } from '@angular/core'; import { Subject } from 'rxjs'; +import { eLayoutType } from '../enums/common'; +import { Config } from './config'; export namespace ABP { export interface Root { @@ -51,6 +51,11 @@ export namespace ABP { name: string; } + export interface Option { + key: Extract; + value: T[Extract]; + } + export interface Dictionary { [key: string]: T; } diff --git a/npm/ng-packs/packages/core/src/lib/plugins/config.plugin.ts b/npm/ng-packs/packages/core/src/lib/plugins/config.plugin.ts index a638e32204..f9c8f45423 100644 --- a/npm/ng-packs/packages/core/src/lib/plugins/config.plugin.ts +++ b/npm/ng-packs/packages/core/src/lib/plugins/config.plugin.ts @@ -28,7 +28,7 @@ export class ConfigPlugin implements NgxsPlugin { const matches = actionMatcher(event); const isInitAction = matches(InitState) || matches(UpdateState); - if (isInitAction && !this.initialized && getAbpRoutes().length) { + if (isInitAction && !this.initialized) { const transformedRoutes = transformRoutes(this.router.config); let { routes } = transformedRoutes; const { wrappers } = transformedRoutes; diff --git a/npm/ng-packs/packages/core/src/lib/tests/form-utils.spec.ts b/npm/ng-packs/packages/core/src/lib/tests/form-utils.spec.ts new file mode 100644 index 0000000000..02e20a5c04 --- /dev/null +++ b/npm/ng-packs/packages/core/src/lib/tests/form-utils.spec.ts @@ -0,0 +1,30 @@ +import { mapEnumToOptions } from '../utils/form-utils'; + +enum SomeEnum { + NotApplicable = 'N/A', + Foo = 0, + Bar, +} + +describe('Form Utils', () => { + describe('#mapEnumToOptions', () => { + it('should return options from enum', () => { + const options = mapEnumToOptions(SomeEnum); + + expect(options).toEqual([ + { + key: 'NotApplicable', + value: SomeEnum.NotApplicable, + }, + { + key: 'Foo', + value: SomeEnum.Foo, + }, + { + key: 'Bar', + value: SomeEnum.Bar, + }, + ]); + }); + }); +}); diff --git a/npm/ng-packs/packages/core/src/lib/tests/number-utils.spec.ts b/npm/ng-packs/packages/core/src/lib/tests/number-utils.spec.ts new file mode 100644 index 0000000000..659225fb62 --- /dev/null +++ b/npm/ng-packs/packages/core/src/lib/tests/number-utils.spec.ts @@ -0,0 +1,17 @@ +import { isNumber } from '../utils/number-utils'; + +describe('Number Utils', () => { + describe('#isNumber', () => { + it('should return true if input is a numeric expression', () => { + expect(isNumber(0)).toBe(true); + expect(isNumber(0.15)).toBe(true); + expect(isNumber(2e8)).toBe(true); + expect(isNumber(Infinity)).toBe(true); + + expect(isNumber('0')).toBe(true); + expect(isNumber('0.15')).toBe(true); + expect(isNumber('2e8')).toBe(true); + expect(isNumber('Infinity')).toBe(true); + }); + }); +}); diff --git a/npm/ng-packs/packages/core/src/lib/utils/form-utils.ts b/npm/ng-packs/packages/core/src/lib/utils/form-utils.ts new file mode 100644 index 0000000000..414b259ab9 --- /dev/null +++ b/npm/ng-packs/packages/core/src/lib/utils/form-utils.ts @@ -0,0 +1,15 @@ +import { ABP } from '../models/common'; +import { isNumber } from './number-utils'; + +export function mapEnumToOptions(_enum: T): ABP.Option[] { + const options: ABP.Option[] = []; + + for (const member in _enum) + if (!isNumber(member)) + options.push({ + key: member, + value: _enum[member], + }); + + return options; +} diff --git a/npm/ng-packs/packages/core/src/lib/utils/index.ts b/npm/ng-packs/packages/core/src/lib/utils/index.ts index a0404f7568..6f6b0585d9 100644 --- a/npm/ng-packs/packages/core/src/lib/utils/index.ts +++ b/npm/ng-packs/packages/core/src/lib/utils/index.ts @@ -1,6 +1,8 @@ export * from './common-utils'; +export * from './form-utils'; export * from './generator-utils'; export * from './initial-utils'; export * from './lazy-load-utils'; +export * from './number-utils'; export * from './route-utils'; export * from './rxjs-utils'; diff --git a/npm/ng-packs/packages/core/src/lib/utils/number-utils.ts b/npm/ng-packs/packages/core/src/lib/utils/number-utils.ts new file mode 100644 index 0000000000..ebd44b67c6 --- /dev/null +++ b/npm/ng-packs/packages/core/src/lib/utils/number-utils.ts @@ -0,0 +1,4 @@ +export function isNumber(value: string | number): boolean { + /* tslint:disable-next-line:triple-equals */ + return value == Number(value); +} diff --git a/npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts b/npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts index 93d3080cc0..ae19f7df5e 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts @@ -19,6 +19,7 @@ import { HttpErrorWrapperComponent } from '../components/http-error-wrapper/http import { HttpErrorConfig, ErrorScreenErrorCodes } from '../models/common'; import { Confirmation } from '../models/confirmation'; import { ConfirmationService } from '../services/confirmation.service'; +import { filter, tap } from 'rxjs/operators'; export const DEFAULT_ERROR_MESSAGES = { defaultError: { @@ -57,108 +58,122 @@ export class ErrorHandler { private injector: Injector, @Inject('HTTP_ERROR_CONFIG') private httpErrorConfig: HttpErrorConfig, ) { + this.httpErrorConfig.skipHandledErrorCodes = this.httpErrorConfig.skipHandledErrorCodes || []; + this.listenToRestError(); + this.listenToRouterError(); + this.listenToRouterDataResolved(); + } + + private listenToRouterError() { this.actions - .pipe(ofActionSuccessful(RestOccurError, RouterError, RouterDataResolved)) - .subscribe(res => { - if (res instanceof RestOccurError) { - const { payload: err = {} as HttpErrorResponse | any } = res; - const body = snq( - () => (err as HttpErrorResponse).error.error, - DEFAULT_ERROR_MESSAGES.defaultError.title, - ); + .pipe(ofActionSuccessful(RouterError), filter(this.filterRouteErrors), tap(console.warn)) + .subscribe(() => this.show404Page()); + } - if (err instanceof HttpErrorResponse && err.headers.get('_AbpErrorFormat')) { - const confirmation$ = this.showError(null, null, body); + private listenToRouterDataResolved() { + this.actions + .pipe( + ofActionSuccessful(RouterDataResolved), + filter(() => !!this.componentRef), + ) + .subscribe(() => { + this.componentRef.destroy(); + this.componentRef = null; + }); + } - if (err.status === 401) { - confirmation$.subscribe(() => { - this.navigateToLogin(); + private listenToRestError() { + this.actions + .pipe(ofActionSuccessful(RestOccurError), filter(this.filterRestErrors)) + .subscribe(({ payload: { err = {} as HttpErrorResponse } }) => { + const body = snq( + () => (err as HttpErrorResponse).error.error, + DEFAULT_ERROR_MESSAGES.defaultError.title, + ); + + if (err instanceof HttpErrorResponse && err.headers.get('_AbpErrorFormat')) { + const confirmation$ = this.showError(null, null, body); + + if (err.status === 401) { + confirmation$.subscribe(() => { + this.navigateToLogin(); + }); + } + } else { + switch ((err as HttpErrorResponse).status) { + case 401: + this.canCreateCustomError(401) + ? this.show401Page() + : this.showError( + { + key: 'AbpAccount::DefaultErrorMessage401', + defaultValue: DEFAULT_ERROR_MESSAGES.defaultError401.title, + }, + { + key: 'AbpAccount::DefaultErrorMessage401Detail', + defaultValue: DEFAULT_ERROR_MESSAGES.defaultError401.details, + }, + ).subscribe(() => this.navigateToLogin()); + break; + case 403: + this.createErrorComponent({ + title: { + key: 'AbpAccount::DefaultErrorMessage403', + defaultValue: DEFAULT_ERROR_MESSAGES.defaultError403.title, + }, + details: { + key: 'AbpAccount::DefaultErrorMessage403Detail', + defaultValue: DEFAULT_ERROR_MESSAGES.defaultError403.details, + }, + status: 403, }); - } - } else { - switch ((err as HttpErrorResponse).status) { - case 401: - this.canCreateCustomError(401) - ? this.show401Page() - : this.showError( - { - key: 'AbpAccount::DefaultErrorMessage401', - defaultValue: DEFAULT_ERROR_MESSAGES.defaultError401.title, - }, - { - key: 'AbpAccount::DefaultErrorMessage401Detail', - defaultValue: DEFAULT_ERROR_MESSAGES.defaultError401.details, - }, - ).subscribe(() => this.navigateToLogin()); - break; - case 403: - this.createErrorComponent({ - title: { - key: 'AbpAccount::DefaultErrorMessage403', - defaultValue: DEFAULT_ERROR_MESSAGES.defaultError403.title, - }, - details: { - key: 'AbpAccount::DefaultErrorMessage403Detail', - defaultValue: DEFAULT_ERROR_MESSAGES.defaultError403.details, - }, - status: 403, - }); - break; - case 404: - this.canCreateCustomError(404) - ? this.show404Page() - : this.showError( - { - key: 'AbpAccount::DefaultErrorMessage404', - defaultValue: DEFAULT_ERROR_MESSAGES.defaultError404.details, - }, - { - key: 'AbpAccount::DefaultErrorMessage404Detail', - defaultValue: DEFAULT_ERROR_MESSAGES.defaultError404.title, - }, - ); - break; - case 500: + break; + case 404: + this.canCreateCustomError(404) + ? this.show404Page() + : this.showError( + { + key: 'AbpAccount::DefaultErrorMessage404', + defaultValue: DEFAULT_ERROR_MESSAGES.defaultError404.details, + }, + { + key: 'AbpAccount::DefaultErrorMessage404Detail', + defaultValue: DEFAULT_ERROR_MESSAGES.defaultError404.title, + }, + ); + break; + case 500: + this.createErrorComponent({ + title: { + key: 'AbpAccount::500Message', + defaultValue: DEFAULT_ERROR_MESSAGES.defaultError500.title, + }, + details: { + key: 'AbpAccount::InternalServerErrorMessage', + defaultValue: DEFAULT_ERROR_MESSAGES.defaultError500.details, + }, + status: 500, + }); + break; + case 0: + if ((err as HttpErrorResponse).statusText === 'Unknown Error') { this.createErrorComponent({ title: { - key: 'AbpAccount::500Message', - defaultValue: DEFAULT_ERROR_MESSAGES.defaultError500.title, + key: 'AbpAccount::DefaultErrorMessage', + defaultValue: DEFAULT_ERROR_MESSAGES.defaultError.title, }, - details: { - key: 'AbpAccount::InternalServerErrorMessage', - defaultValue: DEFAULT_ERROR_MESSAGES.defaultError500.details, - }, - status: 500, + details: err.message, + isHomeShow: false, }); - break; - case 0: - if ((err as HttpErrorResponse).statusText === 'Unknown Error') { - this.createErrorComponent({ - title: { - key: 'AbpAccount::DefaultErrorMessage', - defaultValue: DEFAULT_ERROR_MESSAGES.defaultError.title, - }, - details: err.message, - isHomeShow: false, - }); - } - break; - default: - this.showError( - DEFAULT_ERROR_MESSAGES.defaultError.details, - DEFAULT_ERROR_MESSAGES.defaultError.title, - ); - break; - } + } + break; + default: + this.showError( + DEFAULT_ERROR_MESSAGES.defaultError.details, + DEFAULT_ERROR_MESSAGES.defaultError.title, + ); + break; } - } else if ( - res instanceof RouterError && - snq(() => res.event.error.indexOf('Cannot match') > -1, false) - ) { - this.show404Page(); - } else if (res instanceof RouterDataResolved && this.componentRef) { - this.componentRef.destroy(); - this.componentRef = null; } }); } @@ -254,4 +269,20 @@ export class ErrorHandler { this.httpErrorConfig.errorScreen.forWhichErrors.indexOf(status) > -1, ); } + + private filterRestErrors = (instance: RestOccurError): boolean => { + const { + payload: { err: { status } = {} as HttpErrorResponse }, + } = instance; + if (!status) return false; + + return this.httpErrorConfig.skipHandledErrorCodes.findIndex(code => code === status) < 0; + }; + + private filterRouteErrors = (instance: RouterError): boolean => { + return ( + snq(() => instance.event.error.indexOf('Cannot match') > -1) && + this.httpErrorConfig.skipHandledErrorCodes.findIndex(code => code === 404) < 0 + ); + }; } diff --git a/npm/ng-packs/packages/theme-shared/src/lib/models/common.ts b/npm/ng-packs/packages/theme-shared/src/lib/models/common.ts index 2bca410f5e..d75c854476 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/models/common.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/models/common.ts @@ -7,13 +7,10 @@ export interface RootParams { export type ErrorScreenErrorCodes = 401 | 403 | 404 | 500; export interface HttpErrorConfig { + skipHandledErrorCodes?: ErrorScreenErrorCodes[] | number[]; errorScreen?: { component: Type; - forWhichErrors?: - | [ErrorScreenErrorCodes] - | [ErrorScreenErrorCodes, ErrorScreenErrorCodes] - | [ErrorScreenErrorCodes, ErrorScreenErrorCodes, ErrorScreenErrorCodes] - | [ErrorScreenErrorCodes, ErrorScreenErrorCodes, ErrorScreenErrorCodes, ErrorScreenErrorCodes]; + forWhichErrors?: ErrorScreenErrorCodes[]; hideCloseIcon?: boolean; }; } diff --git a/npm/ng-packs/packages/theme-shared/src/lib/tokens/http-error.token.ts b/npm/ng-packs/packages/theme-shared/src/lib/tokens/http-error.token.ts index 3df2b3fe2d..62f2d2d593 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/tokens/http-error.token.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/tokens/http-error.token.ts @@ -7,6 +7,7 @@ export function httpErrorConfigFactory(config = {} as HttpErrorConfig) { } return { + skipHandledErrorCodes: [], errorScreen: {}, ...config, } as HttpErrorConfig; diff --git a/npm/ng-packs/yarn.lock b/npm/ng-packs/yarn.lock index 207685a176..72c5990945 100644 --- a/npm/ng-packs/yarn.lock +++ b/npm/ng-packs/yarn.lock @@ -4698,7 +4698,7 @@ debug@3.1.0, debug@~3.1.0: dependencies: ms "2.0.0" -debug@^3.0.0, debug@^3.1.0, debug@^3.1.1, debug@^3.2.5, debug@^3.2.6: +debug@^3.0.0, debug@^3.1.0, debug@^3.1.1, debug@^3.2.5: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== @@ -4890,11 +4890,6 @@ detect-indent@^5.0.0: resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d" integrity sha1-OHHMCmoALow+Wzz38zYmRnXwa50= -detect-libc@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= - detect-newline@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2" @@ -6349,7 +6344,7 @@ humanize-ms@^1.2.1: dependencies: ms "^2.0.0" -iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13: +iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@~0.4.13: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -8521,15 +8516,6 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= -needle@^2.2.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/needle/-/needle-2.4.1.tgz#14af48732463d7475696f937626b1b993247a56a" - integrity sha512-x/gi6ijr4B7fwl6WYL9FwlCvRQKGlUNvnceho8wxkwXqN8jvVmmmATTmZPRRG7b/yC1eode26C2HO9jl78Du9g== - dependencies: - debug "^3.2.6" - iconv-lite "^0.4.4" - sax "^1.2.4" - negotiator@0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" @@ -8683,22 +8669,6 @@ node-notifier@^5.4.2: shellwords "^0.1.1" which "^1.3.0" -node-pre-gyp@*: - version "0.14.0" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.14.0.tgz#9a0596533b877289bcad4e143982ca3d904ddc83" - integrity sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA== - dependencies: - detect-libc "^1.0.2" - mkdirp "^0.5.1" - needle "^2.2.1" - nopt "^4.0.1" - npm-packlist "^1.1.6" - npmlog "^4.0.2" - rc "^1.2.7" - rimraf "^2.6.1" - semver "^5.3.0" - tar "^4.4.2" - node-releases@^1.1.52, node-releases@^1.1.53: version "1.1.53" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.53.tgz#2d821bfa499ed7c5dffc5e2f28c88e78a08ee3f4" @@ -8812,7 +8782,7 @@ npm-package-arg@6.1.0: semver "^5.6.0" validate-npm-package-name "^3.0.0" -npm-packlist@^1.1.12, npm-packlist@^1.1.6, npm-packlist@^1.4.4: +npm-packlist@^1.1.12, npm-packlist@^1.4.4: version "1.4.8" resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.8.tgz#56ee6cc135b9f98ad3d51c1c95da22bbb9b2ef3e" integrity sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A== @@ -8885,7 +8855,7 @@ npm-run-path@^4.0.0: dependencies: path-key "^3.0.0" -"npmlog@2 || ^3.1.0 || ^4.0.0", npmlog@^4.0.2, npmlog@^4.1.2: +"npmlog@2 || ^3.1.0 || ^4.0.0", npmlog@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== @@ -9920,7 +9890,7 @@ raw-loader@3.1.0: loader-utils "^1.1.0" schema-utils "^2.0.1" -rc@^1.2.7, rc@^1.2.8: +rc@^1.2.8: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== @@ -10406,7 +10376,7 @@ rimraf@3.0.0: dependencies: glob "^7.1.3" -rimraf@^2.2.8, rimraf@^2.5.2, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3: +rimraf@^2.2.8, rimraf@^2.5.2, rimraf@^2.5.4, rimraf@^2.6.2, rimraf@^2.6.3: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== @@ -11484,7 +11454,7 @@ tapable@^1.0.0, tapable@^1.1.3: resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== -tar@^4.4.10, tar@^4.4.12, tar@^4.4.2, tar@^4.4.8: +tar@^4.4.10, tar@^4.4.12, tar@^4.4.8: version "4.4.13" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525" integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA== diff --git a/templates/app/angular/src/app/app.module.ts b/templates/app/angular/src/app/app.module.ts index 928dff5172..bda69544fb 100644 --- a/templates/app/angular/src/app/app.module.ts +++ b/templates/app/angular/src/app/app.module.ts @@ -18,8 +18,11 @@ const LOGGERS = [NgxsLoggerPluginModule.forRoot({ disabled: false })]; @NgModule({ imports: [ + BrowserModule, + BrowserAnimationsModule, + AppRoutingModule, CoreModule.forRoot({ - environment + environment, }), ThemeSharedModule.forRoot(), AccountConfigModule.forRoot({ redirectUrl: '/' }), @@ -27,13 +30,10 @@ const LOGGERS = [NgxsLoggerPluginModule.forRoot({ disabled: false })]; TenantManagementConfigModule, SettingManagementConfigModule, NgxsModule.forRoot(), - BrowserModule, - BrowserAnimationsModule, - AppRoutingModule, SharedModule, - ...(environment.production ? [] : LOGGERS) + ...(environment.production ? [] : LOGGERS), ], declarations: [AppComponent], - bootstrap: [AppComponent] + bootstrap: [AppComponent], }) export class AppModule {} diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/ru.json b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/ru.json new file mode 100644 index 0000000000..8464e44344 --- /dev/null +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/ru.json @@ -0,0 +1,8 @@ +{ + "culture": "ru", + "texts": { + "Menu:Home": "Главная", + "Welcome": "Добро пожаловать", + "LongWelcomeMessage": "Добро пожаловать в приложение. Этот запущенный проект основан на фреймворке ABP. Для получения дополнительной информации посетите сайт abp.io." + } +} diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs index 6cdc617690..edbece71e0 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs @@ -111,6 +111,7 @@ namespace MyCompanyName.MyProjectName 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("ru", "ru", "Русский")); options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe")); options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); options.Languages.Add(new LanguageInfo("zh-Hant", "zh-Hant", "繁體中文")); diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/MyProjectNameHttpApiHostModule.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/MyProjectNameHttpApiHostModule.cs index 80aa44c647..27a5485c05 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/MyProjectNameHttpApiHostModule.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/MyProjectNameHttpApiHostModule.cs @@ -120,6 +120,7 @@ namespace MyCompanyName.MyProjectName 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("ru", "ru", "Русский")); options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe")); options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); options.Languages.Add(new LanguageInfo("zh-Hant", "zh-Hant", "繁體中文")); diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.IdentityServer/MyProjectNameIdentityServerModule.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.IdentityServer/MyProjectNameIdentityServerModule.cs index c20e77adf1..9a17f5e3ba 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.IdentityServer/MyProjectNameIdentityServerModule.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.IdentityServer/MyProjectNameIdentityServerModule.cs @@ -59,6 +59,7 @@ namespace MyCompanyName.MyProjectName 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("ru", "ru", "Русский")); options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe")); options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); options.Languages.Add(new LanguageInfo("zh-Hant", "zh-Hant", "繁體中文")); diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs index 89cf3c1358..4a588d4945 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs @@ -152,6 +152,7 @@ namespace MyCompanyName.MyProjectName.Web 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("ru", "ru", "Русский")); options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe")); options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); options.Languages.Add(new LanguageInfo("zh-Hant", "zh-Hant", "繁體中文")); diff --git a/templates/module/angular/src/app/app.module.ts b/templates/module/angular/src/app/app.module.ts index 93e09321ec..3145dfd66a 100644 --- a/templates/module/angular/src/app/app.module.ts +++ b/templates/module/angular/src/app/app.module.ts @@ -21,6 +21,9 @@ const LOGGERS = [NgxsLoggerPluginModule.forRoot({ disabled: false })]; @NgModule({ declarations: [AppComponent], imports: [ + BrowserModule, + BrowserAnimationsModule, + AppRoutingModule, ThemeSharedModule.forRoot(), CoreModule.forRoot({ environment, @@ -32,9 +35,6 @@ const LOGGERS = [NgxsLoggerPluginModule.forRoot({ disabled: false })]; TenantManagementConfigModule, SettingManagementConfigModule, MyProjectNameConfigModule, - BrowserModule, - BrowserAnimationsModule, - AppRoutingModule, SharedModule, ...(environment.production ? [] : LOGGERS), diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs index 3bfa9a36bf..bb63eed520 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs @@ -86,6 +86,7 @@ namespace MyCompanyName.MyProjectName 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("ru", "ru", "Русский")); options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe")); options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); options.Languages.Add(new LanguageInfo("zh-Hant", "zh-Hant", "繁體中文")); diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/MyProjectNameIdentityServerModule.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/MyProjectNameIdentityServerModule.cs index b92fe455b5..1085d796f5 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/MyProjectNameIdentityServerModule.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/MyProjectNameIdentityServerModule.cs @@ -97,6 +97,7 @@ namespace MyCompanyName.MyProjectName 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("ru", "ru", "Русский")); options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe")); options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); options.Languages.Add(new LanguageInfo("zh-Hant", "zh-Hant", "繁體中文")); diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/MyProjectNameWebUnifiedModule.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/MyProjectNameWebUnifiedModule.cs index cdd5de9398..c7daebdc7b 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/MyProjectNameWebUnifiedModule.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/MyProjectNameWebUnifiedModule.cs @@ -97,6 +97,7 @@ namespace MyCompanyName.MyProjectName 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 (Brasil)")); + options.Languages.Add(new LanguageInfo("ru", "ru", "Русский")); options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe")); options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); options.Languages.Add(new LanguageInfo("zh-Hant", "zh-Hant", "繁體中文"));