diff --git a/Directory.Packages.props b/Directory.Packages.props
index 5d9885ddbd..afcb39eb77 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -128,11 +128,11 @@
-
-
-
-
-
+
+
+
+
+
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json
index 40a2e878d6..082f607eb0 100644
--- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json
@@ -1892,6 +1892,8 @@
"SEOTitle": "SEO URL",
"InvalidYouTubeUrl": "The URL you entered is not a valid YouTube video link. Please make sure it points to a specific video and try again.",
"SelectAnOption": "Select an option",
- "MostPopular": "Most Popular"
+ "MostPopular": "Most Popular",
+ "AnnouncmentsPageTitle": "ABP Community Announcements | Stay Updated with the Latest News",
+ "AnnouncmentsPageDescription": "Get the latest news, feature updates, release notes, and important announcements about the ABP framework and .NET ecosystem. Stay ahead with timely information directly from the ABP team."
}
}
diff --git a/docs/en/Community-Articles/2025-07-17-summar-campaign/post.md b/docs/en/Community-Articles/2025-07-17-summar-campaign/post.md
new file mode 100644
index 0000000000..d1ac596c29
--- /dev/null
+++ b/docs/en/Community-Articles/2025-07-17-summar-campaign/post.md
@@ -0,0 +1,28 @@
+**It is going to get hotter with ABP’s Summer Campaign!**
+
+Since it’s summer time, we wanted to make it even hotter by announcing a summer campaign! From July 21 to 31 we are offering a 20% discount on all ABP licenses. Now is the best time to invest in ABP and start developing asp net applications faster without wasting your time with repetitive tasks.
+
+## Summer Campaign Terms
+
+Please review the following terms and conditions carefully.
+
+* This offer is available for extensions and new purchases.
+* Developer seat purchases are also included to the campaign.
+* Campaign is available from July 21st to July 31st.
+* Discounts are valid on selected licenses only.
+* This offer cannot be combined with other promotions or discounts.
+
+**Why Choose ABP?**
+
+ABP offers a powerful infrastructure, simplifying modern ASP.NET core development. It helps develop modern ASP.NET applications, including ASP.NET core MVC web applications, blazor front-end projects, and angular .NET Core solutions.
+
+-The core framework and pre-built modules are designed with microservice architecture in mind.
+-ABP provides a module system that allows you to develop reusable application modules.
+-Helps implement a DDD based layered architecture and build a maintainable code base.
+-Easily manage SaaS applications with integrated multi-tenancy, from database to UI.
+
+**This Offer Ends July 31, So Hurry Up!**
+
+This summer campaign is running from July 21 to July 31, so don’t miss your chance. Now is the perfect opportunity to enhance your asp net web development with ABP and benefit from our exclusive features.
+
+Get Your Discount Now: [https://abp.io/pricing?utm_source=abpwebsite&utm_medium=referral&utm_campaign=summer25_blog](https://abp.io/pricing?utm_source=abpwebsite&utm_medium=referral&utm_campaign=summer25_blog)
diff --git a/docs/en/docs-nav.json b/docs/en/docs-nav.json
index 4b5e2908a6..33f4315bf7 100644
--- a/docs/en/docs-nav.json
+++ b/docs/en/docs-nav.json
@@ -2127,11 +2127,11 @@
{
"text": "Microservice Solution",
"isLazyExpandable": true,
- "path": "solution-templates/microservice",
+ "path": "solution-templates/microservice/index.md",
"items":[
{
"text": "Overview",
- "path": "solution-templates/microservice"
+ "path": "solution-templates/microservice/overview.md"
},
{
"text": "Solution Structure",
@@ -2187,7 +2187,7 @@
},
{
"text": "Swagger integration",
- "path": "solution-templates/microservice/swagger.md"
+ "path": "solution-templates/microservice/swagger-integration.md"
},
{
"text": "Permission management",
diff --git a/docs/en/framework/architecture/modularity/installer-projects.md b/docs/en/framework/architecture/modularity/installer-projects.md
new file mode 100644
index 0000000000..81c75ab015
--- /dev/null
+++ b/docs/en/framework/architecture/modularity/installer-projects.md
@@ -0,0 +1,221 @@
+# Module Installer Projects
+
+Each ABP module includes an `.Installer` project (e.g., `Volo.Abp.Account.Installer`) that serves as a **Virtual File System container** for module installation and resource management. These projects are essential for the ABP CLI to understand and install modules properly.
+
+## Purpose of Installer Projects
+
+Installer projects have three main purposes:
+
+1. **Virtual File System Integration**: Register the module's embedded resources with ABP's Virtual File System
+2. **Resource Packaging**: Package module metadata files (`.abpmdl` and `.abppkg`) as embedded resources
+3. **CLI Integration**: Enable the ABP CLI to understand module structure and install modules automatically
+
+## Structure of Installer Projects
+
+### Project Files
+
+- **`{ModuleName}.Installer.csproj`**: References `Volo.Abp.VirtualFileSystem` and embeds module metadata files
+- **`InstallationNotes.md`**: Documentation for the module
+- **`Volo/Abp/{ModuleName}/Abp{ModuleName}InstallerModule.cs`**: The core module class that registers embedded resources
+
+### Example Installer Module
+
+```csharp
+using Volo.Abp.Modularity;
+using Volo.Abp.VirtualFileSystem;
+
+namespace Volo.Abp.Account;
+
+[DependsOn(typeof(AbpVirtualFileSystemModule))]
+public class AbpAccountInstallerModule : AbpModule
+{
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ Configure(options =>
+ {
+ options.FileSets.AddEmbedded();
+ });
+ }
+}
+```
+
+### Project Configuration
+
+The `.csproj` file embeds module metadata as content:
+
+```xml
+
+
+ net9.0
+ true
+
+
+
+
+
+
+
+
+
+
+ true
+ content\
+
+
+
+
+ true
+ content\
+
+
+
+```
+
+## Module Metadata Files
+
+### `.abpmdl` (Module Definition)
+
+The module definition file describes the module's structure and packages:
+
+```json
+{
+ "folders": {
+ "items": {
+ "src": {},
+ "test": {}
+ }
+ },
+ "packages": {
+ "Volo.Abp.Account.Web": {
+ "path": "src/Volo.Abp.Account.Web/Volo.Abp.Account.Web.abppkg",
+ "folder": "src"
+ },
+ "Volo.Abp.Account.Application": {
+ "path": "src/Volo.Abp.Account.Application/Volo.Abp.Account.Application.abppkg",
+ "folder": "src"
+ }
+ }
+}
+```
+
+### `.abppkg` (Package Definition)
+
+Each package has a definition file that specifies its role:
+
+```json
+{
+ "role": "lib.application"
+}
+```
+
+Common roles:
+- `lib.application`: Application layer package
+- `lib.mvc`: MVC/Web layer package
+- `lib.domain`: Domain layer package
+- `lib.domain-shared`: Shared domain layer package
+- `lib.efcore`: Entity Framework Core package
+
+## How Installer Projects Work
+
+### 1. CLI Installation Process
+
+When you run `abp add-module Volo.Abp.Account`:
+
+1. **Download Installer Package**: CLI downloads `Volo.Abp.Account.Installer` from NuGet
+2. **Read Module Definition**: CLI reads the embedded `.abpmdl` file to understand module structure
+3. **Read Package Definitions**: CLI reads `.abppkg` files to understand package roles
+4. **Install Packages**: CLI installs appropriate packages to correct project types based on roles
+5. **Add Dependencies**: CLI adds module dependencies to project module classes
+
+### 2. Virtual File System Integration
+
+The `InstallerModule` registers itself with the Virtual File System:
+
+```csharp
+options.FileSets.AddEmbedded();
+```
+
+This makes embedded resources available at runtime and enables:
+- Access to module metadata
+- Resource file management
+- Module configuration
+
+## Creating Installer Projects for New Modules
+
+### Required Files
+
+1. **Project File**: `{ModuleName}.Installer.csproj`
+2. **Module Class**: `Abp{ModuleName}InstallerModule.cs`
+3. **Documentation**: `InstallationNotes.md`
+4. **Module Definition**: `{ModuleName}.abpmdl` (in module root)
+5. **Package Definitions**: `{PackageName}.abppkg` (in each package)
+
+### Template Structure
+
+```
+modules/your-module/
+├── src/
+│ ├── Volo.Abp.YourModule.Installer/
+│ │ ├── Volo.Abp.YourModule.Installer.csproj
+│ │ ├── InstallationNotes.md
+│ │ └── Volo/
+│ │ └── Abp/
+│ │ └── YourModule/
+│ │ └── AbpYourModuleInstallerModule.cs
+│ └── [other packages]/
+├── Volo.Abp.YourModule.abpmdl
+└── [other module files]
+```
+
+### Package Definition Examples
+
+For different package types:
+
+```json
+// Application package
+{ "role": "lib.application" }
+
+// MVC package
+{ "role": "lib.mvc" }
+
+// Domain package
+{ "role": "lib.domain" }
+
+// EF Core package
+{ "role": "lib.efcore" }
+```
+
+## Why Installer Projects Appear "Empty"
+
+Installer projects appear minimal because their primary function is infrastructure, not business logic:
+
+- **No Business Logic**: Business logic belongs in the actual module packages
+- **Pure Infrastructure**: They only handle module installation and resource management
+- **CLI Integration**: They enable automated module installation through the ABP CLI
+- **Resource Management**: They package and distribute module metadata
+
+## Best Practices
+
+1. **Follow Naming Convention**: Use `{ModuleName}.Installer` for the project name
+2. **Include Documentation**: Always provide `InstallationNotes.md` with module information
+3. **Proper Dependencies**: Only depend on `Volo.Abp.VirtualFileSystem`
+4. **Embed All Metadata**: Include both `.abpmdl` and `.abppkg` files
+5. **Test Installation**: Verify your installer works with `abp add-module` command
+
+## Troubleshooting
+
+### Common Issues
+
+1. **Missing .abpmdl file**: Ensure the module definition file exists in the module root
+2. **Missing .abppkg files**: Each package needs a definition file
+3. **Incorrect roles**: Use appropriate roles for each package type
+4. **CLI not finding module**: Verify the installer package is published to NuGet
+
+### Verification Steps
+
+1. Build the installer project: `dotnet build`
+2. Check embedded resources: Verify `.abpmdl` and `.abppkg` files are embedded
+3. Test CLI installation: `abp add-module YourModule`
+4. Verify dependencies: Check that module dependencies are added correctly
+
+This installer system enables ABP's sophisticated module architecture, allowing for automated installation with proper dependency resolution and project type matching.
\ No newline at end of file
diff --git a/docs/en/framework/infrastructure/json.md b/docs/en/framework/infrastructure/json.md
index 67126edceb..6146436818 100644
--- a/docs/en/framework/infrastructure/json.md
+++ b/docs/en/framework/infrastructure/json.md
@@ -69,6 +69,19 @@ Add [Volo.Abp.Json.Newtonsoft](https://www.nuget.org/packages/Volo.Abp.Json.Newt
## Configuring JSON options in ASP.NET Core
-You can change the JSON behavior in ASP.NET Core by configuring [JsonOptions](https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.jsonoptions) or
-[MvcNewtonsoftJsonOptions](https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.mvcnewtonsoftjsonoptions)(if you use `Newtonsoft.Json`)
+Configuring JSON options in ABP does not affect ASP.NET Core's JSON settings. To modify ASP.NET Core JSON behavior, configure [JsonOptions](https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.jsonoptions) or [MvcNewtonsoftJsonOptions](https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.mvcnewtonsoftjsonoptions) (if you're using `Newtonsoft.Json`) separately.
+Example:
+
+```csharp
+Configure(options =>
+{
+ //options.SerializerOptions
+});
+
+// If you use Newtonsoft.Json
+Configure(options =>
+{
+ //options.SerializerSettings
+});
+```
diff --git a/docs/en/framework/ui/maui/index.md b/docs/en/framework/ui/maui/index.md
index 28f74aa6a3..94d9357fed 100644
--- a/docs/en/framework/ui/maui/index.md
+++ b/docs/en/framework/ui/maui/index.md
@@ -13,6 +13,8 @@ ABP Commercial platform provides a basic [MAUI](https://docs.microsoft.com/en-us
Run the backend application described in the [getting started document](../../../get-started/index.md).
+## Run the Mobile Application
+
Open the `appsettings.json` in the `MAUI` project:
{{ if Tiered == "Yes" }}
@@ -25,6 +27,12 @@ Open the `appsettings.json` in the `MAUI` project:
{{ end }}
+After ensuring the backend application is running and the `appsettings.json` is properly configured in the mobile application, you can proceed to run the mobile application. You can run the application either by using the `dotnet build` command (e.g. `dotnet build -t:Run -f net9.0-android` for Android or `dotnet build -t:Run -f net9.0-ios` for iOS) or by running it through Visual Studio or any other IDE that supports MAUI.
+
+> For more information about running the mobile application, please refer to the [Microsoft's documentation](https://learn.microsoft.com/en-us/dotnet/maui/?view=net-maui-9.0).
+
+You can examine the [Users Page](#users-page) or any other pre-defined page to see how to use CSharp Client Proxy to request backend API and consume the backend API in the same way in your application. Also, if you encounter any errors on specific platforms, you can refer to the following sections for each platform to find common issues and their solutions.
+
### Android
If you get the following error when connecting to the emulator or a physical phone, you need to set up port mapping.
@@ -65,10 +73,11 @@ If you run the MAUI on a Mac agent, the remote iOS Simulator can't access the ba
## User Interface
The MAUI template consists of four pages:
-* **Homepage**: This is the welcome page of the application.
-* **Users**: Management page for your application users. You can search, add, update, or delete users of your application.
-* **Tenants**: Management page for your tenants.
-* **Settings**: Management page for your application settings. On this page, you can change **the current language**, **the profile picture**, **the current password**, or/and **the current theme**.
+
+- **Homepage**: This is the welcome page of the application.
+- **Users**: Management page for your application users. You can search, add, update, or delete users of your application.
+- **Tenants**: Management page for your tenants.
+- **Settings**: Management page for your application settings. On this page, you can change **the current language**, **the profile picture**, **the current password**, or/and **the current theme**.
### Homepage
@@ -86,12 +95,6 @@ The MAUI template consists of four pages:

-## Run the Mobile Application
-
-You can run the MAUI application through Visual Studio or any other IDE that supports MAUI. After the application is up and running, you can continue to develop your application based on this startup template.
-
-You can examine the [Users Page](#users-page) or any other pre-defined page to see how to use CSharp Client Proxy to request backend API and consume the backend API in the same way in your application.
-
### Advanced
#### Validation
diff --git a/docs/en/get-started/images/abp-studio-new-solution-dialog-solution-structure-tiered.png b/docs/en/get-started/images/abp-studio-new-solution-dialog-solution-structure-tiered.png
new file mode 100644
index 0000000000..0264df8da8
Binary files /dev/null and b/docs/en/get-started/images/abp-studio-new-solution-dialog-solution-structure-tiered.png differ
diff --git a/docs/en/get-started/images/abp-studio-new-solution-dialog-solution-structure.png b/docs/en/get-started/images/abp-studio-new-solution-dialog-solution-structure.png
index 310488c1bc..b3ea308fa8 100644
Binary files a/docs/en/get-started/images/abp-studio-new-solution-dialog-solution-structure.png and b/docs/en/get-started/images/abp-studio-new-solution-dialog-solution-structure.png differ
diff --git a/docs/en/get-started/layered-web-application.md b/docs/en/get-started/layered-web-application.md
index 9e2a2ad6f2..e314f6a5b0 100644
--- a/docs/en/get-started/layered-web-application.md
+++ b/docs/en/get-started/layered-web-application.md
@@ -75,8 +75,16 @@ Installing a module after creating the solution may require manual steps. So, it
Once you select the desired modules, click the *Next* button for the *Solution Structure* screen:
+{{ if Tiered == "Yes" }}
+
+
+
+{{ else }}
+

+{{ end }}
+
It creates a separate host application that only serves the HTTP (REST) APIs. The web application then performs remote HTTP calls to that application for every operation. If the *Tiered* option is not selected, then the web and HTTP APIs are hosted in a single application, and the calls from the UI layer to the API layer are performed in-process.
The tiered architecture allows you to host the web (UI) application in a server that can not access to your database server. However, it brings a slight loss of performance (because of the HTTP calls between UI and HTTP API applications) and makes your architecture, development, and deployment more complex. If you don't understand the tiered structure, just skip it.
diff --git a/docs/en/solution-templates/microservice/index.md b/docs/en/solution-templates/microservice/index.md
index 7650ccb46d..542f9e6021 100644
--- a/docs/en/solution-templates/microservice/index.md
+++ b/docs/en/solution-templates/microservice/index.md
@@ -1,5 +1,15 @@
# ABP Studio: Microservice Solution Template
+````json
+//[doc-nav]
+{
+ "Next": {
+ "Name": "Microservice Solution: Overview",
+ "Path": "solution-templates/microservice/overview"
+ }
+}
+````
+
> You must have an ABP Business or a higher license to use this startup template.
ABP Studio provides pre-architected and production-ready templates to jump start a new solution. One of them is the Microservice solution template. You can use it to build distributed systems with common microservice patterns. It includes multiple services, API gateways and applications that are well integrated to each other and ready to be a great base solution for your microservice system.
diff --git a/docs/en/solution-templates/microservice/main-components.md b/docs/en/solution-templates/microservice/main-components.md
index a83dc9cd29..e2a0f1aaa9 100644
--- a/docs/en/solution-templates/microservice/main-components.md
+++ b/docs/en/solution-templates/microservice/main-components.md
@@ -1,5 +1,15 @@
# Microservice Solution: Main Components
+```json
+//[doc-nav]
+{
+ "Next": {
+ "Name": "Microservices",
+ "Path": "solution-templates/microservice/microservices"
+ }
+}
+```
+
> You must have an ABP Business or a higher license to be able to create a microservice solution.
The solution consists of various applications, API gateways and services. The following documents explains these components in details:
diff --git a/docs/en/tutorials/book-store/part-05.md b/docs/en/tutorials/book-store/part-05.md
index 0acc5cac9f..0f84a945d3 100644
--- a/docs/en/tutorials/book-store/part-05.md
+++ b/docs/en/tutorials/book-store/part-05.md
@@ -72,7 +72,12 @@ public class BookStorePermissionDefinitionProvider : PermissionDefinitionProvide
public override void Define(IPermissionDefinitionContext context)
{
var bookStoreGroup = context.AddGroup(BookStorePermissions.GroupName, L("Permission:BookStore"));
+
+ //Dashboard permissions
+ bookStoreGroup.AddPermission(BookStorePermissions.Dashboard.Host, L("Permission:Dashboard"), MultiTenancySides.Host);
+ bookStoreGroup.AddPermission(BookStorePermissions.Dashboard.Tenant, L("Permission:Dashboard"), MultiTenancySides.Tenant);
+ //Books permissions
var booksPermission = bookStoreGroup.AddPermission(BookStorePermissions.Books.Default, L("Permission:Books"));
booksPermission.AddChild(BookStorePermissions.Books.Create, L("Permission:Books.Create"));
booksPermission.AddChild(BookStorePermissions.Books.Edit, L("Permission:Books.Edit"));
diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/EntityActions.razor.cs b/framework/src/Volo.Abp.BlazoriseUI/Components/EntityActions.razor.cs
index ec1428e8aa..10506545dd 100644
--- a/framework/src/Volo.Abp.BlazoriseUI/Components/EntityActions.razor.cs
+++ b/framework/src/Volo.Abp.BlazoriseUI/Components/EntityActions.razor.cs
@@ -42,10 +42,10 @@ public partial class EntityActions : ComponentBase
{
Actions.Add(action);
}
-
- private bool DisabledOrNoActions()
+
+ protected virtual bool DisabledOrNoActions()
{
- return Disabled || !Actions.Any(t => t is { Visible: true, HasPermission: true });
+ return Disabled || (Actions.Any() && Actions.All(t => !t.Visible || !t.HasPermission));
}
protected override void OnInitialized()
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Auth/AuthService.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Auth/AuthService.cs
index 333ae59e3f..4b8d71214b 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Auth/AuthService.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Auth/AuthService.cs
@@ -47,7 +47,7 @@ public class AuthService : IAuthService, ITransientDependency
return null;
}
- var url = $"{CliUrls.WwwAbpIo}api/license/login-info";
+ var url = $"{CliUrls.AccountAbpIo}api/license/login-info";
var client = CliHttpClientFactory.CreateClient();
@@ -130,7 +130,7 @@ public class AuthService : IAuthService, ITransientDependency
public async Task CheckMultipleOrganizationsAsync(string username)
{
- var url = $"{CliUrls.WwwAbpIo}api/license/check-multiple-organizations?username={username}";
+ var url = $"{CliUrls.AccountAbpIo}api/license/check-multiple-organizations?username={username}";
var client = CliHttpClientFactory.CreateClient();
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliConsts.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliConsts.cs
index d968ae6b12..78a36fe329 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliConsts.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliConsts.cs
@@ -12,7 +12,7 @@ public static class CliConsts
public static string GithubHttpClientName = "GithubHttpClient";
- public static string LogoutUrl = CliUrls.WwwAbpIo + "api/license/logout";
+ public static string LogoutUrl = CliUrls.AccountAbpIo + "api/license/logout";
public static string LicenseCodePlaceHolder = @" ";
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Licensing/AbpIoApiKeyService.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Licensing/AbpIoApiKeyService.cs
index ffd0dfdde2..4cade89493 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Licensing/AbpIoApiKeyService.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Licensing/AbpIoApiKeyService.cs
@@ -51,7 +51,7 @@ public class AbpIoApiKeyService : IApiKeyService, ITransientDependency
return _apiKeyResult;
}
- var url = $"{CliUrls.WwwAbpIo}api/license/api-key";
+ var url = $"{CliUrls.AccountAbpIo}api/license/api-key";
var client = _cliHttpClientFactory.CreateClient();
using (var response = await client.GetHttpResponseMessageWithRetryAsync(url, CancellationTokenProvider.Token, _logger))
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateInfoProvider.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateInfoProvider.cs
index f59c373984..7094604049 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateInfoProvider.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateInfoProvider.cs
@@ -88,7 +88,7 @@ public class TemplateInfoProvider : ITemplateInfoProvider, ITransientDependency
try
{
- var url = $"{CliUrls.WwwAbpIo}api/license/check-user";
+ var url = $"{CliUrls.AccountAbpIo}api/license/check-user";
var client = _cliHttpClientFactory.CreateClient();
using (var response = await client.GetHttpResponseMessageWithRetryAsync(url, CancellationTokenProvider.Token, Logger))
diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ChangeTrackers/AbpEfCoreNavigationHelper.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ChangeTrackers/AbpEfCoreNavigationHelper.cs
index 3d7b12f86e..39835569cb 100644
--- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ChangeTrackers/AbpEfCoreNavigationHelper.cs
+++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ChangeTrackers/AbpEfCoreNavigationHelper.cs
@@ -60,7 +60,7 @@ public class AbpEfCoreNavigationHelper : ITransientDependency
return;
}
- var foreignKeys = entityEntry.Metadata.GetForeignKeys().ToList();
+ var foreignKeys = entityEntry.Metadata.GetForeignKeys();
foreach (var foreignKey in foreignKeys)
{
var principal = stateManager.FindPrincipal(internalEntityEntityEntry, foreignKey);
@@ -75,15 +75,20 @@ public class AbpEfCoreNavigationHelper : ITransientDependency
continue;
}
- abpEntityEntry.UpdateNavigationEntries();
+ var navigationEntry = abpEntityEntry.NavigationEntries.FirstOrDefault(x => x.NavigationEntry.Metadata is INavigation navigationMetadata && navigationMetadata.ForeignKey == foreignKey) ??
+ abpEntityEntry.NavigationEntries.FirstOrDefault(x => x.NavigationEntry.Metadata is ISkipNavigation skipNavigationMetadata && skipNavigationMetadata.ForeignKey == foreignKey);
+
+ if (navigationEntry != null && checkEntityEntryState && entityEntry.State == EntityState.Unchanged)
+ {
+ abpEntityEntry.UpdateNavigation(entityEntry, navigationEntry);
+ }
+
if (!abpEntityEntry.IsModified && (!checkEntityEntryState || IsEntityEntryChanged(entityEntry)))
{
abpEntityEntry.IsModified = true;
DetectChanges(abpEntityEntry.EntityEntry, false);
}
- var navigationEntry = abpEntityEntry.NavigationEntries.FirstOrDefault(x => x.NavigationEntry.Metadata is INavigation navigationMetadata && navigationMetadata.ForeignKey == foreignKey) ??
- abpEntityEntry.NavigationEntries.FirstOrDefault(x => x.NavigationEntry.Metadata is ISkipNavigation skipNavigationMetadata && skipNavigationMetadata.ForeignKey == foreignKey);
if (navigationEntry != null && IsEntityEntryChanged(entityEntry))
{
navigationEntry.IsModified = true;
@@ -115,15 +120,20 @@ public class AbpEfCoreNavigationHelper : ITransientDependency
continue;
}
- abpEntityEntry.UpdateNavigationEntries();
+ var navigationEntry = abpEntityEntry.NavigationEntries.FirstOrDefault(x => x.NavigationEntry.Metadata is INavigation navigationMetadata && navigationMetadata.ForeignKey == inverseForeignKey) ??
+ abpEntityEntry.NavigationEntries.FirstOrDefault(x => x.NavigationEntry.Metadata is ISkipNavigation skipNavigationMetadata && skipNavigationMetadata.ForeignKey == inverseForeignKey);
+
+ if (navigationEntry != null && checkEntityEntryState && entityEntry.State == EntityState.Unchanged)
+ {
+ abpEntityEntry.UpdateNavigation(entityEntry, navigationEntry);
+ }
+
if (!abpEntityEntry.IsModified && (!checkEntityEntryState || IsEntityEntryChanged(entityEntry)))
{
abpEntityEntry.IsModified = true;
DetectChanges(abpEntityEntry.EntityEntry, false);
}
- var navigationEntry = abpEntityEntry.NavigationEntries.FirstOrDefault(x => x.NavigationEntry.Metadata is INavigation navigationMetadata && navigationMetadata.ForeignKey == inverseForeignKey) ??
- abpEntityEntry.NavigationEntries.FirstOrDefault(x => x.NavigationEntry.Metadata is ISkipNavigation skipNavigationMetadata && skipNavigationMetadata.ForeignKey == inverseForeignKey);
if (navigationEntry != null && (!checkEntityEntryState || IsEntityEntryChanged(entityEntry)))
{
navigationEntry.IsModified = true;
diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ChangeTrackers/AbpEntityEntry.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ChangeTrackers/AbpEntityEntry.cs
index 4b8a531db1..194132d001 100644
--- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ChangeTrackers/AbpEntityEntry.cs
+++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ChangeTrackers/AbpEntityEntry.cs
@@ -1,4 +1,4 @@
-using System.Collections;
+using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.EntityFrameworkCore;
@@ -21,10 +21,7 @@ public class AbpEntityEntry
{
return _isModified || EntityEntry.State == EntityState.Modified || NavigationEntries.Any(n => n.IsModified);
}
- set
- {
- _isModified = value;
- }
+ set => _isModified = value;
}
public AbpEntityEntry(string id, EntityEntry entityEntry)
@@ -34,46 +31,29 @@ public class AbpEntityEntry
NavigationEntries = EntityEntry.Navigations.Select(x => new AbpNavigationEntry(x, x.Metadata.Name)).ToList();
}
- public void UpdateNavigationEntries()
+ public void UpdateNavigation(EntityEntry entityEntry, AbpNavigationEntry navigationEntry)
{
- foreach (var navigationEntry in NavigationEntries)
+ if (IsModified ||
+ EntityEntry.State == EntityState.Modified ||
+ navigationEntry.IsModified)
{
- if (IsModified ||
- EntityEntry.State == EntityState.Modified ||
- navigationEntry.IsModified ||
- navigationEntry.NavigationEntry.IsModified)
- {
- continue;
- }
-
- var navigation = EntityEntry.Navigations.FirstOrDefault(n => n.Metadata.Name == navigationEntry.Name);
-
- var currentValue = AbpNavigationEntry.GetOriginalValue(navigation?.CurrentValue);
- if (currentValue == null)
- {
- continue;
- }
+ return;
+ }
- switch (navigationEntry.OriginalValue)
- {
- case null:
- navigationEntry.OriginalValue = currentValue;
- break;
- case IEnumerable originalValueCollection when currentValue is IEnumerable currentValueCollection:
- {
- var existingList = originalValueCollection.Cast().ToList();
- var newList = currentValueCollection.Cast().ToList();
- if (newList.Count > existingList.Count)
- {
- navigationEntry.OriginalValue = currentValue;
- }
+ var currentValue = navigationEntry.NavigationEntry.CurrentValue;
+ if (currentValue == null)
+ {
+ return;
+ }
- break;
- }
- default:
- navigationEntry.OriginalValue = currentValue;
- break;
- }
+ if (navigationEntry.NavigationEntry is CollectionEntry)
+ {
+ navigationEntry.OriginalValue ??= new List();
+ navigationEntry.OriginalValue.As>().Add(entityEntry.Entity);
+ }
+ else
+ {
+ navigationEntry.OriginalValue = currentValue;
}
}
}
@@ -86,7 +66,7 @@ public class AbpNavigationEntry
public bool IsModified { get; set; }
- public List? OriginalValue { get; set; }
+ public object? OriginalValue { get; set; }
public object? CurrentValue => NavigationEntry.CurrentValue;
@@ -94,21 +74,9 @@ public class AbpNavigationEntry
{
NavigationEntry = navigationEntry;
Name = name;
- OriginalValue = GetOriginalValue(navigationEntry.CurrentValue);
- }
-
- public static List? GetOriginalValue(object? currentValue)
- {
- if (currentValue is null)
+ if (navigationEntry.CurrentValue != null )
{
- return null;
+ OriginalValue = navigationEntry is CollectionEntry ? new List() : navigationEntry.CurrentValue;
}
-
- if (currentValue is IEnumerable enumerable)
- {
- return enumerable.Cast().ToList();
- }
-
- return new List { currentValue };
}
}
diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/AbpEfCoreNavigationHelper_Tests.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/AbpEfCoreNavigationHelper_Tests.cs
new file mode 100644
index 0000000000..9d10af9705
--- /dev/null
+++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/AbpEfCoreNavigationHelper_Tests.cs
@@ -0,0 +1,92 @@
+using System;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading.Tasks;
+using Shouldly;
+using Volo.Abp.Domain.Repositories;
+using Volo.Abp.TestApp.Domain;
+using Xunit;
+
+namespace Volo.Abp.EntityFrameworkCore;
+
+public class AbpEfCoreNavigationHelper_Tests : EntityFrameworkCoreTestBase
+{
+ private readonly IRepository _blogRepository;
+
+ public AbpEfCoreNavigationHelper_Tests()
+ {
+ _blogRepository = GetRequiredService>();
+ }
+
+ [Fact]
+ public async Task Performance_Test()
+ {
+ //These time taken varies on different machines.
+ //I used relatively large values, but it can also check for performance problem.
+ var batchUpdateTime = TimeSpan.FromSeconds(30);
+ var queryTime = TimeSpan.FromSeconds(10);
+
+ if (!Environment.GetEnvironmentVariable("GITHUB_ACTIONS").IsNullOrWhiteSpace())
+ {
+ batchUpdateTime = batchUpdateTime * 6;
+ queryTime = queryTime * 6;
+ }
+
+
+ var stopWatch = Stopwatch.StartNew();
+ await WithUnitOfWorkAsync(async () =>
+ {
+ for (var i = 0; i < 5 * 1000; i++)
+ {
+ await _blogRepository.InsertAsync(
+ new Blog(Guid.NewGuid())
+ {
+ Name = "Blog" + i,
+ BlogPosts =
+ [
+ new BlogPost(Guid.NewGuid())
+ {
+ Title = "Post" + i
+ }
+ ]
+ });
+ }
+ });
+ stopWatch.Stop();
+ stopWatch.Elapsed.ShouldBeLessThan(batchUpdateTime);
+
+
+ stopWatch.Restart();
+ var blogs = await _blogRepository.GetListAsync(includeDetails: true);
+ blogs.Count.ShouldBe(5 * 1000);
+ blogs.SelectMany(x => x.BlogPosts).Count().ShouldBe(5 * 1000);
+ stopWatch.Stop();
+ stopWatch.Elapsed.ShouldBeLessThan(queryTime);
+
+
+ var blogId = blogs.First().Id;
+ stopWatch.Restart();
+ await WithUnitOfWorkAsync(async () =>
+ {
+ var blog = await _blogRepository.GetAsync(blogId);
+ blog.ShouldNotBeNull();
+ for (var i = 0; i < 5 * 1000; i++)
+ {
+ blog.BlogPosts.Add(
+ new BlogPost(Guid.NewGuid())
+ {
+ Title = "NewPost" + i
+ });
+ }
+ await _blogRepository.UpdateAsync(blog);
+ });
+ stopWatch.Stop();
+ stopWatch.Elapsed.ShouldBeLessThan(batchUpdateTime);
+
+ stopWatch.Restart();
+ var blog = await _blogRepository.GetAsync(blogId);
+ blog.BlogPosts.Count.ShouldBe(5 * 1000 + 1);
+ stopWatch.Stop();
+ stopWatch.Elapsed.ShouldBeLessThan(queryTime);
+ }
+}
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 e75af9a556..22c0b92477 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
@@ -53,6 +53,11 @@ public class AbpEntityFrameworkCoreTestModule : AbpModule
{
opt.DefaultWithDetailsFunc = q => q.Include(p => p.OneToOne).ThenInclude(x => x.OneToOne).Include(p => p.OneToMany).ThenInclude(x => x.OneToMany).Include(p => p.ManyToMany);
});
+
+ options.Entity(opt =>
+ {
+ opt.DefaultWithDetailsFunc = q => q.Include(p => p.BlogPosts);
+ });
});
context.Services.AddAbpDbContext(options =>
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 6841f8d504..d05e367ff7 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
@@ -30,6 +30,9 @@ public class TestMigrationsDbContext : AbpDbContext
public DbSet AppEntityWithNavigationsForeign { get; set; }
+ public DbSet Blogs { get; set; }
+ public DbSet BlogPosts { get; set; }
+
public TestMigrationsDbContext(DbContextOptions options)
: base(options)
{
@@ -97,5 +100,18 @@ public class TestMigrationsDbContext : AbpDbContext
{
b.ConfigureByConvention();
});
+
+ modelBuilder.Entity(b =>
+ {
+ b.ConfigureByConvention();
+ b.HasMany(bp => bp.BlogPosts)
+ .WithOne(bp => bp.Blog)
+ .HasForeignKey(bp => bp.BlogId);
+ });
+
+ modelBuilder.Entity(b =>
+ {
+ b.ConfigureByConvention();
+ });
}
}
diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/Domain/BlogPost.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/Domain/BlogPost.cs
new file mode 100644
index 0000000000..9ef826176b
--- /dev/null
+++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/Domain/BlogPost.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using Volo.Abp.Domain.Entities;
+using Volo.Abp.Domain.Entities.Auditing;
+
+namespace Volo.Abp.TestApp.Domain;
+
+public class Blog : FullAuditedAggregateRoot
+{
+ public Blog(Guid id)
+ : base(id)
+ {
+ }
+
+ public string Name { get; set; }
+
+ public List BlogPosts { get; set; }
+}
+
+public class BlogPost : Entity
+{
+ public BlogPost(Guid id)
+ : base(id)
+ {
+ }
+
+ public Guid BlogId { get; set; }
+ public Blog Blog { get; set; }
+
+ public string Title { get; set; }
+}
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 fbbac40844..242809bf7c 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
@@ -1,6 +1,7 @@
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.Extensions.Logging;
using Volo.Abp.DependencyInjection;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore.Modeling;
@@ -36,6 +37,9 @@ public class TestAppDbContext : AbpDbContext, IThirdDbContext,
public DbSet AppEntityWithNavigationsForeign { get; set; }
+ public DbSet Blogs { get; set; }
+ public DbSet BlogPosts { get; set; }
+
public TestAppDbContext(DbContextOptions options)
: base(options)
{
@@ -123,6 +127,19 @@ public class TestAppDbContext : AbpDbContext, IThirdDbContext,
b.ConfigureByConvention();
});
+ modelBuilder.Entity(b =>
+ {
+ b.ConfigureByConvention();
+ b.HasMany(bp => bp.BlogPosts)
+ .WithOne(bp => bp.Blog)
+ .HasForeignKey(bp => bp.BlogId);
+ });
+
+ modelBuilder.Entity(b =>
+ {
+ b.ConfigureByConvention();
+ });
+
modelBuilder.TryConfigureObjectExtensions();
}
}
diff --git a/latest-versions.json b/latest-versions.json
index 21fbe41bf4..1d49e265f6 100644
--- a/latest-versions.json
+++ b/latest-versions.json
@@ -1,4 +1,13 @@
[
+ {
+ "version": "9.2.2",
+ "releaseDate": "",
+ "type": "stable",
+ "message": "",
+ "leptonx": {
+ "version": "4.2.2"
+ }
+ },
{
"version": "9.2.1",
"releaseDate": "",
diff --git a/modules/README.md b/modules/README.md
index 670d60c1cc..4eea191640 100644
--- a/modules/README.md
+++ b/modules/README.md
@@ -1,3 +1,5 @@
## ABP Free Modules
-These modules are free & open source.
\ No newline at end of file
+These modules are free & open source.
+
+For detailed information about module architecture and installer projects, see the [Module Installer Projects documentation](../docs/en/framework/architecture/modularity/installer-projects.md).
\ No newline at end of file
diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogFeature.cs b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogFeature.cs
index 5571e776b1..2ef2e6a4e5 100644
--- a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogFeature.cs
+++ b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogFeature.cs
@@ -7,11 +7,11 @@ namespace Volo.CmsKit.Blogs;
public class BlogFeature : FullAuditedAggregateRoot
{
- public Guid BlogId { get; protected set; }
+ public virtual Guid BlogId { get; protected set; }
- public string FeatureName { get; protected set; }
+ public virtual string FeatureName { get; protected set; }
- public bool IsEnabled { get; protected internal set; }
+ public virtual bool IsEnabled { get; protected internal set; }
protected BlogFeature()
{
diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/MarkedItems/UserMarkedItem.cs b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/MarkedItems/UserMarkedItem.cs
index 24fddd1382..5fcdca4008 100644
--- a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/MarkedItems/UserMarkedItem.cs
+++ b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/MarkedItems/UserMarkedItem.cs
@@ -15,8 +15,8 @@ public class UserMarkedItem : BasicAggregateRoot, IHasCreationTime, IMustH
public virtual DateTime CreationTime { get; set; }
- public string EntityId { get; protected set; }
- public string EntityType { get; protected set; }
+ public virtual string EntityId { get; protected set; }
+ public virtual string EntityType { get; protected set; }
protected UserMarkedItem() { }
diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/MediaDescriptors/MediaDescriptor.cs b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/MediaDescriptors/MediaDescriptor.cs
index 6bbbdff675..d52a0b9355 100644
--- a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/MediaDescriptors/MediaDescriptor.cs
+++ b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/MediaDescriptors/MediaDescriptor.cs
@@ -7,15 +7,15 @@ namespace Volo.CmsKit.MediaDescriptors;
public class MediaDescriptor : FullAuditedAggregateRoot, IMultiTenant
{
- public Guid? TenantId { get; protected set; }
+ public virtual Guid? TenantId { get; protected set; }
- public string EntityType { get; protected set; }
+ public virtual string EntityType { get; protected set; }
- public string Name { get; protected set; }
+ public virtual string Name { get; protected set; }
- public string MimeType { get; protected set; }
+ public virtual string MimeType { get; protected set; }
- public long Size { get; protected set; }
+ public virtual long Size { get; protected set; }
protected MediaDescriptor()
{
diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Menus/MenuItem.cs b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Menus/MenuItem.cs
index 418bb19408..57faabbdec 100644
--- a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Menus/MenuItem.cs
+++ b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Menus/MenuItem.cs
@@ -17,31 +17,31 @@ public class MenuItem : AuditedAggregateRoot, IMultiTenant
/// Presents another Id.
/// If it's , then it's a root menu item.
///
- public Guid? ParentId { get; set; }
+ public virtual Guid? ParentId { get; set; }
[NotNull]
- public string DisplayName { get; protected set; }
+ public virtual string DisplayName { get; protected set; }
- public bool IsActive { get; set; }
+ public virtual bool IsActive { get; set; }
[NotNull]
- public string Url { get; protected set; }
+ public virtual string Url { get; protected set; }
- public string Icon { get; set; }
+ public virtual string Icon { get; set; }
- public int Order { get; set; }
+ public virtual int Order { get; set; }
- public string Target { get; set; }
+ public virtual string Target { get; set; }
- public string ElementId { get; set; }
+ public virtual string ElementId { get; set; }
- public string CssClass { get; set; }
+ public virtual string CssClass { get; set; }
- public Guid? PageId { get; protected set; }
+ public virtual Guid? PageId { get; protected set; }
- public Guid? TenantId { get; protected set; }
-
- public string RequiredPermissionName { get; set; }
+ public virtual Guid? TenantId { get; protected set; }
+
+ public virtual string RequiredPermissionName { get; set; }
protected MenuItem()
{
diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/DocumentContributor.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/DocumentContributor.cs
index 876686b5ff..2fb555fb50 100644
--- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/DocumentContributor.cs
+++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/DocumentContributor.cs
@@ -5,15 +5,15 @@ namespace Volo.Docs.Documents
{
public class DocumentContributor : Entity
{
- public Guid DocumentId { get; set; }
+ public virtual Guid DocumentId { get; set; }
- public string Username { get; set; }
+ public virtual string Username { get; set; }
- public int CommitCount { get; set; }
+ public virtual int CommitCount { get; set; }
- public string UserProfileUrl { get; set; }
+ public virtual string UserProfileUrl { get; set; }
- public string AvatarUrl { get; set; }
+ public virtual string AvatarUrl { get; set; }
protected DocumentContributor()
{
diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureDefinitionRecord.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureDefinitionRecord.cs
index 20ba414b08..8a2fff0846 100644
--- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureDefinitionRecord.cs
+++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureDefinitionRecord.cs
@@ -7,31 +7,31 @@ namespace Volo.Abp.FeatureManagement;
public class FeatureDefinitionRecord : BasicAggregateRoot, IHasExtraProperties
{
- public string GroupName { get; set; }
+ public virtual string GroupName { get; set; }
- public string Name { get; set; }
+ public virtual string Name { get; set; }
- public string ParentName { get; set; }
+ public virtual string ParentName { get; set; }
- public string DisplayName { get; set; }
+ public virtual string DisplayName { get; set; }
- public string Description { get; set; }
+ public virtual string Description { get; set; }
- public string DefaultValue { get; set; }
+ public virtual string DefaultValue { get; set; }
- public bool IsVisibleToClients { get; set; }
+ public virtual bool IsVisibleToClients { get; set; }
- public bool IsAvailableToHost { get; set; }
+ public virtual bool IsAvailableToHost { get; set; }
///
/// Comma separated list of provider names.
///
- public string AllowedProviders { get; set; }
+ public virtual string AllowedProviders { get; set; }
///
/// Serialized string to store info about the ValueType.
///
- public string ValueType { get; set; } // ToggleStringValueType
+ public virtual string ValueType { get; set; } // ToggleStringValueType
public ExtraPropertyDictionary ExtraProperties { get; protected set; }
diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureGroupDefinitionRecord.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureGroupDefinitionRecord.cs
index 61c7e60473..e50bd5e66d 100644
--- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureGroupDefinitionRecord.cs
+++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureGroupDefinitionRecord.cs
@@ -6,11 +6,11 @@ namespace Volo.Abp.FeatureManagement;
public class FeatureGroupDefinitionRecord : BasicAggregateRoot, IHasExtraProperties
{
- public string Name { get; set; }
+ public virtual string Name { get; set; }
- public string DisplayName { get; set; }
+ public virtual string DisplayName { get; set; }
- public ExtraPropertyDictionary ExtraProperties { get; protected set; }
+ public virtual ExtraPropertyDictionary ExtraProperties { get; protected set; }
public FeatureGroupDefinitionRecord()
{
diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentitySecurityLog.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentitySecurityLog.cs
index c801c263e6..5c0c08fae9 100644
--- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentitySecurityLog.cs
+++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentitySecurityLog.cs
@@ -8,29 +8,29 @@ namespace Volo.Abp.Identity;
public class IdentitySecurityLog : AggregateRoot, IMultiTenant
{
- public Guid? TenantId { get; protected set; }
+ public virtual Guid? TenantId { get; protected set; }
- public string ApplicationName { get; protected set; }
+ public virtual string ApplicationName { get; protected set; }
- public string Identity { get; protected set; }
+ public virtual string Identity { get; protected set; }
- public string Action { get; protected set; }
+ public virtual string Action { get; protected set; }
- public Guid? UserId { get; protected set; }
+ public virtual Guid? UserId { get; protected set; }
- public string UserName { get; protected set; }
+ public virtual string UserName { get; protected set; }
- public string TenantName { get; protected set; }
+ public virtual string TenantName { get; protected set; }
- public string ClientId { get; protected set; }
+ public virtual string ClientId { get; protected set; }
- public string CorrelationId { get; protected set; }
+ public virtual string CorrelationId { get; protected set; }
- public string ClientIpAddress { get; protected set; }
+ public virtual string ClientIpAddress { get; protected set; }
- public string BrowserInfo { get; protected set; }
+ public virtual string BrowserInfo { get; protected set; }
- public DateTime CreationTime { get; protected set; }
+ public virtual DateTime CreationTime { get; protected set; }
protected IdentitySecurityLog()
{
diff --git a/modules/openiddict/app/OpenIddict.Demo.Client.Console/Program.cs b/modules/openiddict/app/OpenIddict.Demo.Client.Console/Program.cs
index 2e55cc24b1..87948a4cdc 100644
--- a/modules/openiddict/app/OpenIddict.Demo.Client.Console/Program.cs
+++ b/modules/openiddict/app/OpenIddict.Demo.Client.Console/Program.cs
@@ -75,6 +75,41 @@ Console.WriteLine("UserInfo: {0}", JsonSerializer.Serialize(JsonDocument.Parse(u
}));
Console.WriteLine();
+var tokenExchangeResponse = await client.RequestTokenExchangeTokenAsync(new TokenExchangeTokenRequest()
+{
+ Address = configuration.TokenEndpoint,
+ ClientId = clientId,
+ ClientSecret = clientSecret,
+ SubjectToken = refreshTokenResponse.AccessToken!,
+ SubjectTokenType = "urn:ietf:params:oauth:token-type:access_token",
+ Scope = "AbpAPI profile roles email phone offline_access",
+});
+
+if (tokenExchangeResponse.IsError)
+{
+ throw new Exception(tokenExchangeResponse.Error);
+}
+
+Console.WriteLine("Token Exchange token: {0}", tokenExchangeResponse.AccessToken);
+Console.WriteLine();
+Console.WriteLine("Token Exchange token: {0}", tokenExchangeResponse.RefreshToken);
+Console.WriteLine();
+
+userinfo = await client.GetUserInfoAsync(new UserInfoRequest()
+{
+ Address = configuration.UserInfoEndpoint,
+ Token = tokenExchangeResponse.AccessToken
+});
+if (userinfo.IsError)
+{
+ throw new Exception(userinfo.Error);
+}
+
+Console.WriteLine("Token Exchange UserInfo: {0}", JsonSerializer.Serialize(JsonDocument.Parse(userinfo.Raw), new JsonSerializerOptions
+{
+ WriteIndented = true
+}));
+Console.WriteLine();
var introspectionResponse = await client.IntrospectTokenAsync(new TokenIntrospectionRequest()
{
diff --git a/modules/openiddict/app/OpenIddict.Demo.Server/EntityFrameworkCore/ServerDataSeedContributor.cs b/modules/openiddict/app/OpenIddict.Demo.Server/EntityFrameworkCore/ServerDataSeedContributor.cs
index c67b2977ef..e1fd97136b 100644
--- a/modules/openiddict/app/OpenIddict.Demo.Server/EntityFrameworkCore/ServerDataSeedContributor.cs
+++ b/modules/openiddict/app/OpenIddict.Demo.Server/EntityFrameworkCore/ServerDataSeedContributor.cs
@@ -79,6 +79,7 @@ public class ServerDataSeedContributor : IDataSeedContributor, ITransientDepende
OpenIddictConstants.Permissions.GrantTypes.RefreshToken,
OpenIddictConstants.Permissions.GrantTypes.DeviceCode,
OpenIddictConstants.Permissions.GrantTypes.ClientCredentials,
+ OpenIddictConstants.Permissions.GrantTypes.TokenExchange,
OpenIddictConstants.Permissions.Prefixes.GrantType + MyTokenExtensionGrant.ExtensionGrantName,
OpenIddictConstants.Permissions.ResponseTypes.Code,
diff --git a/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20250630055813_Initial.Designer.cs b/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20250710090114_Initial.Designer.cs
similarity index 99%
rename from modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20250630055813_Initial.Designer.cs
rename to modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20250710090114_Initial.Designer.cs
index 5c4b03ed99..1ba6189674 100644
--- a/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20250630055813_Initial.Designer.cs
+++ b/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20250710090114_Initial.Designer.cs
@@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
namespace OpenIddict.Demo.Server.Migrations
{
[DbContext(typeof(ServerDbContext))]
- [Migration("20250630055813_Initial")]
+ [Migration("20250710090114_Initial")]
partial class Initial
{
///
@@ -1164,8 +1164,8 @@ namespace OpenIddict.Demo.Server.Migrations
.HasColumnType("nvarchar(400)");
b.Property("Type")
- .HasMaxLength(50)
- .HasColumnType("nvarchar(50)");
+ .HasMaxLength(150)
+ .HasColumnType("nvarchar(150)");
b.HasKey("Id");
diff --git a/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20250630055813_Initial.cs b/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20250710090114_Initial.cs
similarity index 99%
rename from modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20250630055813_Initial.cs
rename to modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20250710090114_Initial.cs
index 77775a3324..a992bf78c2 100644
--- a/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20250630055813_Initial.cs
+++ b/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20250710090114_Initial.cs
@@ -645,7 +645,7 @@ namespace OpenIddict.Demo.Server.Migrations
ReferenceId = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true),
Status = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: true),
Subject = table.Column(type: "nvarchar(400)", maxLength: 400, nullable: true),
- Type = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: true),
+ Type = table.Column(type: "nvarchar(150)", maxLength: 150, nullable: true),
ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false),
ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false)
},
diff --git a/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/ServerDbContextModelSnapshot.cs b/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/ServerDbContextModelSnapshot.cs
index ff0eaf970c..b1caafb242 100644
--- a/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/ServerDbContextModelSnapshot.cs
+++ b/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/ServerDbContextModelSnapshot.cs
@@ -1161,8 +1161,8 @@ namespace OpenIddict.Demo.Server.Migrations
.HasColumnType("nvarchar(400)");
b.Property("Type")
- .HasMaxLength(50)
- .HasColumnType("nvarchar(50)");
+ .HasMaxLength(150)
+ .HasColumnType("nvarchar(150)");
b.HasKey("Id");
diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/AbpOpenIddictAspNetCoreModule.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/AbpOpenIddictAspNetCoreModule.cs
index dddc89d515..3a9c8109fc 100644
--- a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/AbpOpenIddictAspNetCoreModule.cs
+++ b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/AbpOpenIddictAspNetCoreModule.cs
@@ -79,7 +79,8 @@ public class AbpOpenIddictAspNetCoreModule : AbpModule
.AllowClientCredentialsFlow()
.AllowRefreshTokenFlow()
.AllowDeviceAuthorizationFlow()
- .AllowNoneFlow();
+ .AllowNoneFlow()
+ .AllowTokenExchangeFlow();
builder.RegisterScopes(new[]
{
diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/AbpOpenIddictErrors.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/AbpOpenIddictErrors.cs
new file mode 100644
index 0000000000..45422ad210
--- /dev/null
+++ b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/AbpOpenIddictErrors.cs
@@ -0,0 +1,8 @@
+namespace Volo.Abp.OpenIddict;
+
+public static class AbpOpenIddictErrors
+{
+ public const string AccountLocked = "account_locked";
+
+ public const string AccountInactive = "account_inactive";
+}
diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/AuthorizeController.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/AuthorizeController.cs
index a8350e22e5..6216571168 100644
--- a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/AuthorizeController.cs
+++ b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/AuthorizeController.cs
@@ -44,7 +44,7 @@ public class AuthorizeController : AbpOpenIdDictControllerBase
var result = await HttpContext.AuthenticateAsync(IdentityConstants.ApplicationScheme);
if (result is not { Succeeded: true } ||
((request.HasPromptValue(OpenIddictConstants.PromptValues.Login) || request.MaxAge is 0 ||
- (request.MaxAge != null && result.Properties?.IssuedUtc != null &&
+ (request.MaxAge is not null && result.Properties?.IssuedUtc is not null &&
TimeProvider.System.GetUtcNow() - result.Properties.IssuedUtc > TimeSpan.FromSeconds(request.MaxAge.Value))) &&
TempData["IgnoreAuthenticationChallenge"] is null or false))
{
diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.Password.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.Password.cs
index 33a1a37845..5059c7c5ca 100644
--- a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.Password.cs
+++ b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.Password.cs
@@ -107,10 +107,13 @@ public partial class TokenController
ClientId = request.ClientId
});
+ var errorCode = OpenIddictConstants.Errors.InvalidGrant;
string errorDescription;
+
if (result.IsLockedOut)
{
Logger.LogInformation("Authentication failed for username: {username}, reason: locked out", request.Username);
+ errorCode = AbpOpenIddictErrors.AccountLocked;
errorDescription = "The user account has been locked out due to invalid login attempts. Please wait a while and try again.";
}
else if (result.IsNotAllowed)
@@ -139,7 +142,8 @@ public partial class TokenController
return await HandleConfirmUserAsync(request, user);
}
- errorDescription = "You are not allowed to login! Your account is inactive.";
+ errorCode = AbpOpenIddictErrors.AccountInactive;
+ errorDescription = "You are not allowed to login! Your account is inactive or needs to confirm your email/phone number.";
}
}
else
@@ -150,7 +154,7 @@ public partial class TokenController
var properties = new AuthenticationProperties(new Dictionary
{
- [OpenIddictServerAspNetCoreConstants.Properties.Error] = OpenIddictConstants.Errors.InvalidGrant,
+ [OpenIddictServerAspNetCoreConstants.Properties.Error] = errorCode,
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = errorDescription
});
diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.TokenExchange.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.TokenExchange.cs
new file mode 100644
index 0000000000..8f17a34be0
--- /dev/null
+++ b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.TokenExchange.cs
@@ -0,0 +1,92 @@
+using System;
+using System.Collections.Generic;
+using System.Security.Claims;
+using System.Text.Json.Nodes;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Authentication;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.IdentityModel.Tokens;
+using OpenIddict.Abstractions;
+using OpenIddict.Server.AspNetCore;
+
+namespace Volo.Abp.OpenIddict.Controllers;
+
+public partial class TokenController
+{
+ protected virtual async Task HandleTokenExchangeGrantTypeAsync(OpenIddictRequest request)
+ {
+ // Retrieve the claims principal stored in the subject token.
+ //
+ // Note: the principal may not represent a user (e.g if the token was issued during a client credentials token
+ // request and represents a client application): developers are strongly encouraged to ensure that the user
+ // and client identifiers are randomly generated so that a malicious client cannot impersonate a legit user.
+ //
+ // See https://datatracker.ietf.org/doc/html/rfc9068#SecurityConsiderations for more information.
+ var result = await HttpContext.AuthenticateAsync(OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);
+
+ // If available, retrieve the claims principal stored in the actor token.
+ var actor = result.Properties?.GetParameter(OpenIddictServerAspNetCoreConstants.Properties.ActorTokenPrincipal);
+
+ // Retrieve the user profile corresponding to the subject token.
+ var user = await UserManager.FindByIdAsync(result.Principal!.GetClaim(OpenIddictConstants.Claims.Subject)!);
+ if (user is null)
+ {
+ return Forbid(
+ authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
+ properties: new AuthenticationProperties(new Dictionary
+ {
+ [OpenIddictServerAspNetCoreConstants.Properties.Error] = OpenIddictConstants.Errors.InvalidGrant,
+ [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = "The token is no longer valid."
+ }));
+ }
+
+ // Ensure the user is still allowed to sign in.
+ if (!await PreSignInCheckAsync(user))
+ {
+ return Forbid(
+ authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
+ properties: new AuthenticationProperties(new Dictionary
+ {
+ [OpenIddictServerAspNetCoreConstants.Properties.Error] = OpenIddictConstants.Errors.InvalidGrant,
+ [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = "The user is no longer allowed to sign in."
+ }));
+ }
+
+ // Note: whether the identity represents a delegated or impersonated access (or any other
+ // model) is entirely up to the implementer: to support all scenarios, OpenIddict doesn't
+ // enforce any specific constraint on the identity used for the sign-in operation and only
+ // requires that the standard "act" and "may_act" claims be valid JSON objects if present.
+
+ // Clear the dynamic claims cache.
+ await IdentityDynamicClaimsPrincipalContributorCache.ClearAsync(user.Id, user.TenantId);
+
+ // Create a new ClaimsPrincipal containing the claims that
+ // will be used to create an id_token, a token or a code.
+ var principal = await SignInManager.CreateUserPrincipalAsync(user);
+
+ // Note: IdentityModel doesn't support serializing ClaimsIdentity.Actor to the
+ // standard "act" claim yet, which requires adding the "act" claim manually.
+ //
+ // For more information, see
+ // https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/pull/3219.
+ if (!string.IsNullOrEmpty(actor?.GetClaim(OpenIddictConstants.Claims.Subject)) &&
+ !string.Equals(principal.GetClaim(OpenIddictConstants.Claims.Subject), actor.GetClaim(OpenIddictConstants.Claims.Subject), StringComparison.Ordinal))
+ {
+ principal.SetClaim(OpenIddictConstants.Claims.Actor, new JsonObject
+ {
+ [OpenIddictConstants.Claims.Subject] = actor.GetClaim(OpenIddictConstants.Claims.Subject)
+ });
+ }
+
+ // Note: in this sample, the granted scopes match the requested scope
+ // but you may want to allow the user to uncheck specific scopes.
+ // For that, simply restrict the list of scopes before calling SetScopes.
+ principal.SetScopes(request.GetScopes());
+ principal.SetResources(await GetResourcesAsync(request.GetScopes()));
+
+ await OpenIddictClaimsPrincipalManager.HandleAsync(request, principal);
+
+ // Returning a SignInResult will ask OpenIddict to issue the appropriate access/identity tokens.
+ return SignIn(principal, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);
+ }
+}
diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.cs
index e3b3d10c39..e348ffe007 100644
--- a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.cs
+++ b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.cs
@@ -42,6 +42,11 @@ public partial class TokenController : AbpOpenIdDictControllerBase
return await HandleClientCredentialsAsync(request);
}
+ if (request.IsTokenExchangeGrantType())
+ {
+ return await HandleTokenExchangeGrantTypeAsync(request);
+ }
+
var extensionGrantsOptions = HttpContext.RequestServices.GetRequiredService>();
var extensionTokenGrant = extensionGrantsOptions.Value.Find(request.GrantType);
if (extensionTokenGrant != null)
diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain.Shared/Volo/Abp/OpenIddict/Tokens/OpenIddictTokenConsts.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain.Shared/Volo/Abp/OpenIddict/Tokens/OpenIddictTokenConsts.cs
index c0e2674911..847cf0ef7a 100644
--- a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain.Shared/Volo/Abp/OpenIddict/Tokens/OpenIddictTokenConsts.cs
+++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain.Shared/Volo/Abp/OpenIddict/Tokens/OpenIddictTokenConsts.cs
@@ -8,5 +8,5 @@ public class OpenIddictTokenConsts
public static int SubjectMaxLength { get; set; } = 400;
- public static int TypeMaxLength { get; set; } = 50;
+ public static int TypeMaxLength { get; set; } = 150;
}
diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/AbpOpenIddictDomainModule.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/AbpOpenIddictDomainModule.cs
index 1312ad5d8c..fd20f71012 100644
--- a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/AbpOpenIddictDomainModule.cs
+++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/AbpOpenIddictDomainModule.cs
@@ -3,6 +3,7 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
using OpenIddict.Abstractions;
+using OpenIddict.Core;
using Volo.Abp.BackgroundWorkers;
using Volo.Abp.Caching;
using Volo.Abp.DistributedLocking;
@@ -65,15 +66,15 @@ public class AbpOpenIddictDomainModule : AbpModule
.SetDefaultTokenEntity();
builder
- .AddApplicationStore()
- .AddAuthorizationStore()
- .AddScopeStore()
- .AddTokenStore();
-
- builder.ReplaceApplicationManager(typeof(AbpApplicationManager));
- builder.ReplaceAuthorizationManager(typeof(AbpAuthorizationManager));
- builder.ReplaceScopeManager(typeof(AbpScopeManager));
- builder.ReplaceTokenManager(typeof(AbpTokenManager));
+ .ReplaceApplicationStore()
+ .ReplaceAuthorizationStore()
+ .ReplaceScopeStore()
+ .ReplaceTokenStore();
+
+ builder.ReplaceApplicationManager();
+ builder.ReplaceAuthorizationManager();
+ builder.ReplaceScopeManager();
+ builder.ReplaceTokenManager();
builder.Services.TryAddScoped(provider => (IAbpApplicationManager)provider.GetRequiredService());
diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Applications/AbpApplicationManager.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Applications/AbpApplicationManager.cs
index 99b44e4293..ea2283ea25 100644
--- a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Applications/AbpApplicationManager.cs
+++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Applications/AbpApplicationManager.cs
@@ -17,7 +17,7 @@ public class AbpApplicationManager : OpenIddictApplicationManager cache,
[NotNull] ILogger logger,
[NotNull] IOptionsMonitor options,
- [NotNull] IOpenIddictApplicationStoreResolver resolver,
+ [NotNull] IOpenIddictApplicationStore resolver,
AbpOpenIddictIdentifierConverter identifierConverter)
: base(cache, logger, options, resolver)
{
diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Authorizations/AbpAuthorizationManager.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Authorizations/AbpAuthorizationManager.cs
index d190192058..50ec2866ec 100644
--- a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Authorizations/AbpAuthorizationManager.cs
+++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Authorizations/AbpAuthorizationManager.cs
@@ -16,7 +16,7 @@ public class AbpAuthorizationManager : OpenIddictAuthorizationManager cache,
[NotNull] [ItemNotNull] ILogger> logger,
[NotNull] [ItemNotNull] IOptionsMonitor options,
- [NotNull] IOpenIddictAuthorizationStoreResolver resolver,
+ [NotNull] IOpenIddictAuthorizationStore resolver,
AbpOpenIddictIdentifierConverter identifierConverter)
: base(cache, logger, options, resolver)
{
diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Scopes/AbpScopeManager.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Scopes/AbpScopeManager.cs
index 76596c159b..0f89463733 100644
--- a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Scopes/AbpScopeManager.cs
+++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Scopes/AbpScopeManager.cs
@@ -16,7 +16,7 @@ public class AbpScopeManager : OpenIddictScopeManager
[NotNull] [ItemNotNull] IOpenIddictScopeCache cache,
[NotNull] [ItemNotNull] ILogger> logger,
[NotNull] [ItemNotNull] IOptionsMonitor options,
- [NotNull] IOpenIddictScopeStoreResolver resolver,
+ [NotNull] IOpenIddictScopeStore resolver,
AbpOpenIddictIdentifierConverter identifierConverter)
: base(cache, logger, options, resolver)
{
diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Tokens/AbpTokenManager.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Tokens/AbpTokenManager.cs
index 7f4f967124..879d5b3f4f 100644
--- a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Tokens/AbpTokenManager.cs
+++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Tokens/AbpTokenManager.cs
@@ -16,7 +16,7 @@ public class AbpTokenManager : OpenIddictTokenManager
[NotNull] [ItemNotNull] IOpenIddictTokenCache cache,
[NotNull] [ItemNotNull] ILogger> logger,
[NotNull] [ItemNotNull] IOptionsMonitor options,
- [NotNull] IOpenIddictTokenStoreResolver resolver,
+ [NotNull] IOpenIddictTokenStore resolver,
AbpOpenIddictIdentifierConverter identifierConverter)
: base(cache, logger, options, resolver)
{
diff --git a/npm/ng-packs/packages/account-core/proxy/src/lib/proxy/account/account.service.ts b/npm/ng-packs/packages/account-core/proxy/src/lib/proxy/account/account.service.ts
index adeb2ee5c9..ad584495c6 100644
--- a/npm/ng-packs/packages/account-core/proxy/src/lib/proxy/account/account.service.ts
+++ b/npm/ng-packs/packages/account-core/proxy/src/lib/proxy/account/account.service.ts
@@ -1,12 +1,14 @@
import type { RegisterDto, ResetPasswordDto, SendPasswordResetCodeDto } from './models';
import { RestService } from '@abp/ng.core';
-import { Injectable } from '@angular/core';
+import { Injectable, inject } from '@angular/core';
import type { IdentityUserDto } from '../identity/models';
@Injectable({
providedIn: 'root',
})
export class AccountService {
+ private restService = inject(RestService);
+
apiName = 'AbpAccount';
register = (input: RegisterDto) =>
@@ -32,6 +34,4 @@ export class AccountService {
body: input,
},
{ apiName: this.apiName });
-
- constructor(private restService: RestService) {}
}
diff --git a/npm/ng-packs/packages/account-core/proxy/src/lib/proxy/account/profile.service.ts b/npm/ng-packs/packages/account-core/proxy/src/lib/proxy/account/profile.service.ts
index 0cea6b8cfb..a14c6cedfd 100644
--- a/npm/ng-packs/packages/account-core/proxy/src/lib/proxy/account/profile.service.ts
+++ b/npm/ng-packs/packages/account-core/proxy/src/lib/proxy/account/profile.service.ts
@@ -1,11 +1,13 @@
import type { ChangePasswordInput, ProfileDto, UpdateProfileDto } from './models';
import { RestService } from '@abp/ng.core';
-import { Injectable } from '@angular/core';
+import { Injectable, inject } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class ProfileService {
+ private restService = inject(RestService);
+
apiName = 'AbpAccount';
changePassword = (input: ChangePasswordInput) =>
@@ -30,6 +32,4 @@ export class ProfileService {
body: input,
},
{ apiName: this.apiName });
-
- constructor(private restService: RestService) {}
}
diff --git a/npm/ng-packs/packages/account-core/proxy/src/lib/proxy/account/web/areas/account/controllers/account.service.ts b/npm/ng-packs/packages/account-core/proxy/src/lib/proxy/account/web/areas/account/controllers/account.service.ts
index 8adf5385b0..52c779655b 100644
--- a/npm/ng-packs/packages/account-core/proxy/src/lib/proxy/account/web/areas/account/controllers/account.service.ts
+++ b/npm/ng-packs/packages/account-core/proxy/src/lib/proxy/account/web/areas/account/controllers/account.service.ts
@@ -1,11 +1,13 @@
import type { AbpLoginResult, UserLoginInfo } from './models/models';
import { RestService } from '@abp/ng.core';
-import { Injectable } from '@angular/core';
+import { Injectable, inject } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class AccountService {
+ private restService = inject(RestService);
+
apiName = 'AbpAccount';
checkPasswordByLogin = (login: UserLoginInfo) =>
@@ -30,6 +32,4 @@ export class AccountService {
url: '/api/account/logout',
},
{ apiName: this.apiName });
-
- constructor(private restService: RestService) {}
}
diff --git a/npm/ng-packs/packages/account-core/src/lib/auth-wrapper.service.ts b/npm/ng-packs/packages/account-core/src/lib/auth-wrapper.service.ts
index 7bad8ef96a..10ca25380b 100644
--- a/npm/ng-packs/packages/account-core/src/lib/auth-wrapper.service.ts
+++ b/npm/ng-packs/packages/account-core/src/lib/auth-wrapper.service.ts
@@ -1,4 +1,4 @@
-import { Injectable, Injector } from '@angular/core';
+import { Injectable, Injector, inject } from '@angular/core';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { ActivatedRoute } from '@angular/router';
@@ -6,6 +6,9 @@ import { ConfigStateService, MultiTenancyService } from '@abp/ng.core';
@Injectable()
export class AuthWrapperService {
+ readonly multiTenancy = inject(MultiTenancyService);
+ private configState = inject(ConfigStateService);
+
isMultiTenancyEnabled$ = this.configState.getDeep$('multiTenancy.isEnabled');
get enableLocalLogin$(): Observable {
@@ -25,11 +28,9 @@ export class AuthWrapperService {
return this.isTenantBoxVisibleForCurrentRoute && this.multiTenancy.isTenantBoxVisible;
}
- constructor(
- public readonly multiTenancy: MultiTenancyService,
- private configState: ConfigStateService,
- injector: Injector,
- ) {
+ constructor() {
+ const injector = inject(Injector);
+
this.route = injector.get(ActivatedRoute);
}
diff --git a/npm/ng-packs/packages/account-core/src/lib/tenant-box.service.ts b/npm/ng-packs/packages/account-core/src/lib/tenant-box.service.ts
index bcb37c3d48..2890d90776 100644
--- a/npm/ng-packs/packages/account-core/src/lib/tenant-box.service.ts
+++ b/npm/ng-packs/packages/account-core/src/lib/tenant-box.service.ts
@@ -5,11 +5,16 @@ import {
SessionStateService,
} from '@abp/ng.core';
import { ToasterService } from '@abp/ng.theme.shared';
-import { Injectable } from '@angular/core';
+import { Injectable, inject } from '@angular/core';
import { finalize } from 'rxjs/operators';
@Injectable()
export class TenantBoxService {
+ private toasterService = inject(ToasterService);
+ private tenantService = inject(AbpTenantService);
+ private sessionState = inject(SessionStateService);
+ private configState = inject(ConfigStateService);
+
currentTenant$ = this.sessionState.getTenant$();
name?: string;
@@ -18,13 +23,6 @@ export class TenantBoxService {
modalBusy!: boolean;
- constructor(
- private toasterService: ToasterService,
- private tenantService: AbpTenantService,
- private sessionState: SessionStateService,
- private configState: ConfigStateService,
- ) {}
-
onSwitch() {
const tenant = this.sessionState.getTenant();
this.name = tenant?.name || '';
diff --git a/npm/ng-packs/packages/account/src/lib/components/change-password/change-password.component.ts b/npm/ng-packs/packages/account/src/lib/components/change-password/change-password.component.ts
index 9e1ae788f0..ad5db820ac 100644
--- a/npm/ng-packs/packages/account/src/lib/components/change-password/change-password.component.ts
+++ b/npm/ng-packs/packages/account/src/lib/components/change-password/change-password.component.ts
@@ -1,6 +1,6 @@
import { ProfileService } from '@abp/ng.account.core/proxy';
import { ButtonComponent, getPasswordValidators, ToasterService } from '@abp/ng.theme.shared';
-import { Component, Injector, OnInit } from '@angular/core';
+import { Component, Injector, OnInit, inject } from '@angular/core';
import {
ReactiveFormsModule,
UntypedFormBuilder,
@@ -32,6 +32,12 @@ const PASSWORD_FIELDS = ['newPassword', 'repeatNewPassword'];
export class ChangePasswordComponent
implements OnInit, Account.ChangePasswordComponentInputs, Account.ChangePasswordComponentOutputs
{
+ private fb = inject(UntypedFormBuilder);
+ private injector = inject(Injector);
+ private toasterService = inject(ToasterService);
+ private profileService = inject(ProfileService);
+ private manageProfileState = inject(ManageProfileStateService);
+
form!: UntypedFormGroup;
inProgress?: boolean;
@@ -44,14 +50,6 @@ export class ChangePasswordComponent
return errors.concat(groupErrors.filter(({ key }) => key === 'passwordMismatch'));
};
- constructor(
- private fb: UntypedFormBuilder,
- private injector: Injector,
- private toasterService: ToasterService,
- private profileService: ProfileService,
- private manageProfileState: ManageProfileStateService,
- ) {}
-
ngOnInit(): void {
this.hideCurrentPassword = !this.manageProfileState.getProfile()?.hasPassword;
diff --git a/npm/ng-packs/packages/account/src/lib/components/forgot-password/forgot-password.component.ts b/npm/ng-packs/packages/account/src/lib/components/forgot-password/forgot-password.component.ts
index 815c95d71c..873d45c243 100644
--- a/npm/ng-packs/packages/account/src/lib/components/forgot-password/forgot-password.component.ts
+++ b/npm/ng-packs/packages/account/src/lib/components/forgot-password/forgot-password.component.ts
@@ -1,5 +1,5 @@
import { AccountService } from '@abp/ng.account.core/proxy';
-import { Component } from '@angular/core';
+import { Component, inject } from '@angular/core';
import {
ReactiveFormsModule,
UntypedFormBuilder,
@@ -24,16 +24,16 @@ import { NgxValidateCoreModule } from '@ngx-validate/core';
],
})
export class ForgotPasswordComponent {
+ private fb = inject(UntypedFormBuilder);
+ private accountService = inject(AccountService);
+
form: UntypedFormGroup;
inProgress?: boolean;
isEmailSent = false;
- constructor(
- private fb: UntypedFormBuilder,
- private accountService: AccountService,
- ) {
+ constructor() {
this.form = this.fb.group({
email: ['', [Validators.required, Validators.email]],
});
diff --git a/npm/ng-packs/packages/account/src/lib/components/manage-profile/manage-profile.component.ts b/npm/ng-packs/packages/account/src/lib/components/manage-profile/manage-profile.component.ts
index a80c710ffa..675862bdfa 100644
--- a/npm/ng-packs/packages/account/src/lib/components/manage-profile/manage-profile.component.ts
+++ b/npm/ng-packs/packages/account/src/lib/components/manage-profile/manage-profile.component.ts
@@ -33,18 +33,23 @@ import { ChangePasswordComponent } from '../change-password/change-password.comp
],
})
export class ManageProfileComponent implements OnInit {
+ protected profileService = inject(ProfileService);
+ protected manageProfileState = inject(ManageProfileStateService);
+
protected readonly ssrService = inject(SSRService);
selectedTab = 0;
+
changePasswordKey = eAccountComponents.ChangePassword;
+
personalSettingsKey = eAccountComponents.PersonalSettings;
+
profile$ = this.manageProfileState.getProfile$();
+
hideChangePasswordTab?: boolean;
PROFILE_SETTINGS_KEY = makeStateKey('profileSettings');
constructor(
- private transferState: TransferState,
- protected profileService: ProfileService,
- protected manageProfileState: ManageProfileStateService,
+ private transferState: TransferState
) {}
ngOnInit() {
diff --git a/npm/ng-packs/packages/account/src/lib/components/personal-settings/personal-settings-half-row.component.ts b/npm/ng-packs/packages/account/src/lib/components/personal-settings/personal-settings-half-row.component.ts
index ac99a51c23..be6287e954 100644
--- a/npm/ng-packs/packages/account/src/lib/components/personal-settings/personal-settings-half-row.component.ts
+++ b/npm/ng-packs/packages/account/src/lib/components/personal-settings/personal-settings-half-row.component.ts
@@ -1,4 +1,4 @@
-import { Component, Inject } from '@angular/core';
+import { Component, inject } from '@angular/core';
import {
EXTENSIONS_FORM_PROP,
FormProp,
@@ -24,12 +24,16 @@ import { LocalizationPipe } from '@abp/ng.core';
imports: [ReactiveFormsModule, LocalizationPipe],
})
export class PersonalSettingsHalfRowComponent {
+ private propData = inject(EXTENSIONS_FORM_PROP);
+
public displayName: string;
public name: string;
public id: string;
public formGroup!: UntypedFormGroup;
- constructor(@Inject(EXTENSIONS_FORM_PROP) private propData: FormProp) {
+ constructor() {
+ const propData = this.propData;
+
this.displayName = propData.displayName;
this.name = propData.name;
this.id = propData.id || '';
diff --git a/npm/ng-packs/packages/account/src/lib/components/register/register.component.ts b/npm/ng-packs/packages/account/src/lib/components/register/register.component.ts
index 18b4935c92..93bbfe26f4 100644
--- a/npm/ng-packs/packages/account/src/lib/components/register/register.component.ts
+++ b/npm/ng-packs/packages/account/src/lib/components/register/register.component.ts
@@ -6,7 +6,7 @@ import {
LocalizationPipe,
} from '@abp/ng.core';
import { ButtonComponent, getPasswordValidators, ToasterService } from '@abp/ng.theme.shared';
-import { Component, Injector, OnInit } from '@angular/core';
+import { Component, Injector, OnInit, inject } from '@angular/core';
import {
ReactiveFormsModule,
UntypedFormBuilder,
@@ -35,6 +35,13 @@ const { maxLength, required, email } = Validators;
],
})
export class RegisterComponent implements OnInit {
+ protected fb = inject(UntypedFormBuilder);
+ protected accountService = inject(AccountService);
+ protected configState = inject(ConfigStateService);
+ protected toasterService = inject(ToasterService);
+ protected authService = inject(AuthService);
+ protected injector = inject(Injector);
+
form!: UntypedFormGroup;
inProgress?: boolean;
@@ -43,15 +50,6 @@ export class RegisterComponent implements OnInit {
authWrapperKey = eAccountComponents.AuthWrapper;
- constructor(
- protected fb: UntypedFormBuilder,
- protected accountService: AccountService,
- protected configState: ConfigStateService,
- protected toasterService: ToasterService,
- protected authService: AuthService,
- protected injector: Injector,
- ) {}
-
ngOnInit() {
this.init();
this.buildForm();
diff --git a/npm/ng-packs/packages/account/src/lib/components/reset-password/reset-password.component.ts b/npm/ng-packs/packages/account/src/lib/components/reset-password/reset-password.component.ts
index d04a99ae98..1e8d043000 100644
--- a/npm/ng-packs/packages/account/src/lib/components/reset-password/reset-password.component.ts
+++ b/npm/ng-packs/packages/account/src/lib/components/reset-password/reset-password.component.ts
@@ -1,6 +1,6 @@
import { AccountService } from '@abp/ng.account.core/proxy';
import { ButtonComponent, getPasswordValidators } from '@abp/ng.theme.shared';
-import { Component, Injector, OnInit } from '@angular/core';
+import { Component, Injector, OnInit, inject } from '@angular/core';
import {
ReactiveFormsModule,
UntypedFormBuilder,
@@ -26,6 +26,12 @@ const PASSWORD_FIELDS = ['password', 'confirmPassword'];
],
})
export class ResetPasswordComponent implements OnInit {
+ private fb = inject(UntypedFormBuilder);
+ private accountService = inject(AccountService);
+ private route = inject(ActivatedRoute);
+ private router = inject(Router);
+ private injector = inject(Injector);
+
form!: UntypedFormGroup;
inProgress = false;
@@ -38,14 +44,6 @@ export class ResetPasswordComponent implements OnInit {
return errors.concat(groupErrors.filter(({ key }) => key === 'passwordMismatch'));
};
- constructor(
- private fb: UntypedFormBuilder,
- private accountService: AccountService,
- private route: ActivatedRoute,
- private router: Router,
- private injector: Injector,
- ) {}
-
ngOnInit(): void {
this.route.queryParams.subscribe(({ userId, resetToken }) => {
if (!userId || !resetToken) this.router.navigateByUrl('/account/login');
diff --git a/npm/ng-packs/packages/components/chart.js/src/chart.component.ts b/npm/ng-packs/packages/components/chart.js/src/chart.component.ts
index c700a0bce8..9ab84aedcd 100644
--- a/npm/ng-packs/packages/components/chart.js/src/chart.component.ts
+++ b/npm/ng-packs/packages/components/chart.js/src/chart.component.ts
@@ -1,16 +1,17 @@
-import {
- AfterViewInit,
- ChangeDetectionStrategy,
- ChangeDetectorRef,
- Component,
- ElementRef,
- EventEmitter,
- Input,
- OnChanges,
- OnDestroy,
- Output,
- SimpleChanges,
- ViewChild,
+import {
+ AfterViewInit,
+ ChangeDetectionStrategy,
+ ChangeDetectorRef,
+ Component,
+ ElementRef,
+ EventEmitter,
+ Input,
+ OnChanges,
+ OnDestroy,
+ Output,
+ SimpleChanges,
+ ViewChild,
+ inject
} from '@angular/core';
let Chart: any;
@@ -35,6 +36,9 @@ let Chart: any;
exportAs: 'abpChart',
})
export class ChartComponent implements AfterViewInit, OnDestroy, OnChanges {
+ el = inject(ElementRef);
+ private cdr = inject(ChangeDetectorRef);
+
@Input() type!: string;
@Input() data: any = {};
@@ -57,11 +61,6 @@ export class ChartComponent implements AfterViewInit, OnDestroy, OnChanges {
chart: any;
- constructor(
- public el: ElementRef,
- private cdr: ChangeDetectorRef,
- ) {}
-
ngAfterViewInit() {
import('chart.js/auto').then(module => {
Chart = module.default;
diff --git a/npm/ng-packs/packages/components/extensible/src/lib/components/abstract-actions/abstract-actions.component.ts b/npm/ng-packs/packages/components/extensible/src/lib/components/abstract-actions/abstract-actions.component.ts
index 394e125798..465a18b813 100644
--- a/npm/ng-packs/packages/components/extensible/src/lib/components/abstract-actions/abstract-actions.component.ts
+++ b/npm/ng-packs/packages/components/extensible/src/lib/components/abstract-actions/abstract-actions.component.ts
@@ -1,4 +1,4 @@
-import { Directive, Injector, Input } from '@angular/core';
+import { Directive, Injector, Input, inject } from '@angular/core';
import { ActionData, ActionList, InferredAction } from '../../models/actions';
import { ExtensionsService } from '../../services/extensions.service';
import { EXTENSIONS_ACTION_TYPE, EXTENSIONS_IDENTIFIER } from '../../tokens/extensions.token';
@@ -16,7 +16,9 @@ export abstract class AbstractActionsComponent<
@Input() record!: InferredData['record'];
- protected constructor(injector: Injector) {
+ protected constructor() {
+ const injector = inject(Injector);
+
super();
this.getInjected = injector.get.bind(injector);
const extensions = injector.get(ExtensionsService);
diff --git a/npm/ng-packs/packages/components/extensible/src/lib/components/grid-actions/grid-actions.component.ts b/npm/ng-packs/packages/components/extensible/src/lib/components/grid-actions/grid-actions.component.ts
index 5307a4a671..0e3d25f26c 100644
--- a/npm/ng-packs/packages/components/extensible/src/lib/components/grid-actions/grid-actions.component.ts
+++ b/npm/ng-packs/packages/components/extensible/src/lib/components/grid-actions/grid-actions.component.ts
@@ -1,9 +1,8 @@
-import {
- ChangeDetectionStrategy,
- Component,
- Injector,
- Input,
- TrackByFunction,
+import {
+ ChangeDetectionStrategy,
+ Component,
+ Input,
+ TrackByFunction,
} from '@angular/core';
import { EntityAction, EntityActionList } from '../../models/entity-actions';
import { EXTENSIONS_ACTION_TYPE } from '../../tokens/extensions.token';
@@ -43,7 +42,7 @@ export class GridActionsComponent extends AbstractActionsComponent> = (_, item) => item.text;
- constructor(injector: Injector) {
- super(injector);
+ constructor() {
+ super();
}
}
diff --git a/npm/ng-packs/packages/components/extensible/src/lib/components/page-toolbar/page-toolbar.component.ts b/npm/ng-packs/packages/components/extensible/src/lib/components/page-toolbar/page-toolbar.component.ts
index 7492b6f94e..36b195f933 100644
--- a/npm/ng-packs/packages/components/extensible/src/lib/components/page-toolbar/page-toolbar.component.ts
+++ b/npm/ng-packs/packages/components/extensible/src/lib/components/page-toolbar/page-toolbar.component.ts
@@ -1,4 +1,4 @@
-import { ChangeDetectionStrategy, Component, Injector, TrackByFunction } from '@angular/core';
+import { ChangeDetectionStrategy, Component, Injector, TrackByFunction, inject } from '@angular/core';
import {
HasCreateInjectorPipe,
ToolbarAction,
@@ -35,6 +35,8 @@ export class PageToolbarComponent
extends AbstractActionsComponent>
implements HasCreateInjectorPipe
{
+ readonly injector: Injector;
+
defaultBtnClass = 'btn btn-sm btn-primary';
getData = () => this.data;
@@ -42,8 +44,12 @@ export class PageToolbarComponent
readonly trackByFn: TrackByFunction> = (_, item) =>
item.action || item.component;
- constructor(public readonly injector: Injector) {
- super(injector);
+ constructor() {
+ const injector = inject(Injector);
+
+ super();
+
+ this.injector = injector;
}
asToolbarAction(value: ToolbarActionDefault): { value: ToolbarAction } {
diff --git a/npm/ng-packs/packages/components/extensible/src/lib/directives/prop-data.directive.ts b/npm/ng-packs/packages/components/extensible/src/lib/directives/prop-data.directive.ts
index 2bba45ff70..b7a05d314b 100644
--- a/npm/ng-packs/packages/components/extensible/src/lib/directives/prop-data.directive.ts
+++ b/npm/ng-packs/packages/components/extensible/src/lib/directives/prop-data.directive.ts
@@ -1,12 +1,13 @@
/* eslint-disable @angular-eslint/no-input-rename */
-import {
- Directive,
- Injector,
- Input,
- OnChanges,
- OnDestroy,
- TemplateRef,
- ViewContainerRef,
+import {
+ Directive,
+ Injector,
+ Input,
+ OnChanges,
+ OnDestroy,
+ TemplateRef,
+ ViewContainerRef,
+ inject
} from '@angular/core';
import { PropData, PropList } from '../models/props';
@@ -18,6 +19,9 @@ export class PropDataDirective>
extends PropData>
implements OnChanges, OnDestroy
{
+ private tempRef = inject>(TemplateRef);
+ private vcRef = inject(ViewContainerRef);
+
@Input('abpPropDataFromList') propList?: L;
@Input('abpPropDataWithRecord') record!: InferredData['record'];
@@ -26,11 +30,9 @@ export class PropDataDirective>
readonly getInjected: InferredData['getInjected'];
- constructor(
- private tempRef: TemplateRef,
- private vcRef: ViewContainerRef,
- injector: Injector,
- ) {
+ constructor() {
+ const injector = inject(Injector);
+
super();
this.getInjected = injector.get.bind(injector);
diff --git a/npm/ng-packs/packages/components/page/src/page-part.directive.ts b/npm/ng-packs/packages/components/page/src/page-part.directive.ts
index a89302916b..bfaf1e60b6 100644
--- a/npm/ng-packs/packages/components/page/src/page-part.directive.ts
+++ b/npm/ng-packs/packages/components/page/src/page-part.directive.ts
@@ -1,18 +1,17 @@
-import {
- Directive,
- TemplateRef,
- ViewContainerRef,
- Input,
- InjectionToken,
- Optional,
- Inject,
- OnInit,
- OnDestroy,
- Injector,
- OnChanges,
- SimpleChanges,
- SimpleChange,
-} from '@angular/core';
+import {
+ Directive,
+ TemplateRef,
+ ViewContainerRef,
+ Input,
+ InjectionToken,
+ OnInit,
+ OnDestroy,
+ Injector,
+ OnChanges,
+ SimpleChanges,
+ SimpleChange,
+ inject
+ } from '@angular/core';
import { Observable, Subscription, of } from 'rxjs';
export interface PageRenderStrategy {
@@ -28,6 +27,11 @@ export const PAGE_RENDER_STRATEGY = new InjectionToken('PAGE
selector: '[abpPagePart]',
})
export class PagePartDirective implements OnInit, OnDestroy, OnChanges {
+ private templateRef = inject>(TemplateRef);
+ private viewContainer = inject(ViewContainerRef);
+ private renderLogic = inject(PAGE_RENDER_STRATEGY, { optional: true })!;
+ private injector = inject(Injector);
+
hasRendered = false;
type!: string;
subscription!: Subscription;
@@ -48,13 +52,6 @@ export class PagePartDirective implements OnInit, OnDestroy, OnChanges {
}
};
- constructor(
- private templateRef: TemplateRef,
- private viewContainer: ViewContainerRef,
- @Optional() @Inject(PAGE_RENDER_STRATEGY) private renderLogic: PageRenderStrategy,
- private injector: Injector,
- ) {}
-
ngOnChanges({ context }: SimpleChanges): void {
if (this.renderLogic?.onContextUpdate) {
this.renderLogic.onContextUpdate(context);
diff --git a/npm/ng-packs/packages/components/tree/src/lib/templates/expanded-icon-template.directive.ts b/npm/ng-packs/packages/components/tree/src/lib/templates/expanded-icon-template.directive.ts
index 35706bd25f..e7f1bdb913 100644
--- a/npm/ng-packs/packages/components/tree/src/lib/templates/expanded-icon-template.directive.ts
+++ b/npm/ng-packs/packages/components/tree/src/lib/templates/expanded-icon-template.directive.ts
@@ -1,8 +1,8 @@
-import { Directive, TemplateRef } from '@angular/core';
+import { Directive, TemplateRef, inject } from '@angular/core';
+
+@Directive({
+ selector: '[abpTreeExpandedIconTemplate],[abp-tree-expanded-icon-template]',
+})
+export class ExpandedIconTemplateDirective {
template = inject>(TemplateRef);
-@Directive({
- selector: '[abpTreeExpandedIconTemplate],[abp-tree-expanded-icon-template]',
-})
-export class ExpandedIconTemplateDirective {
- constructor(public template: TemplateRef) {}
-}
+}
diff --git a/npm/ng-packs/packages/components/tree/src/lib/templates/tree-node-template.directive.ts b/npm/ng-packs/packages/components/tree/src/lib/templates/tree-node-template.directive.ts
index 56c66af04b..70cf228021 100644
--- a/npm/ng-packs/packages/components/tree/src/lib/templates/tree-node-template.directive.ts
+++ b/npm/ng-packs/packages/components/tree/src/lib/templates/tree-node-template.directive.ts
@@ -1,8 +1,8 @@
-import { Directive, TemplateRef } from '@angular/core';
+import { Directive, TemplateRef, inject } from '@angular/core';
+
+@Directive({
+ selector: '[abpTreeNodeTemplate],[abp-tree-node-template]',
+})
+export class TreeNodeTemplateDirective {
template = inject>(TemplateRef);
-@Directive({
- selector: '[abpTreeNodeTemplate],[abp-tree-node-template]',
-})
-export class TreeNodeTemplateDirective {
- constructor(public template: TemplateRef) {}
-}
+}
diff --git a/npm/ng-packs/packages/core/src/lib/components/dynamic-layout.component.ts b/npm/ng-packs/packages/core/src/lib/components/dynamic-layout.component.ts
index 549702a1ad..a1961aef4d 100644
--- a/npm/ng-packs/packages/core/src/lib/components/dynamic-layout.component.ts
+++ b/npm/ng-packs/packages/core/src/lib/components/dynamic-layout.component.ts
@@ -1,4 +1,4 @@
-import { Component, inject, isDevMode, OnInit, Optional, SkipSelf, Type } from '@angular/core';
+import { Component, inject, isDevMode, OnInit, Type } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { eLayoutType } from '../enums/common';
import { ABP } from '../models';
@@ -39,7 +39,9 @@ export class DynamicLayoutComponent implements OnInit {
protected readonly routerEvents = inject(RouterEvents);
protected readonly environment = inject(EnvironmentService);
- constructor(@Optional() @SkipSelf() dynamicLayoutComponent: DynamicLayoutComponent) {
+ constructor() {
+ const dynamicLayoutComponent = inject(DynamicLayoutComponent, { optional: true, skipSelf: true })!;
+
if (dynamicLayoutComponent) {
if (isDevMode()) console.warn('DynamicLayoutComponent must be used only in AppComponent.');
return;
diff --git a/npm/ng-packs/packages/core/src/lib/components/replaceable-route-container.component.ts b/npm/ng-packs/packages/core/src/lib/components/replaceable-route-container.component.ts
index 680c7919a8..9ddc294c2b 100644
--- a/npm/ng-packs/packages/core/src/lib/components/replaceable-route-container.component.ts
+++ b/npm/ng-packs/packages/core/src/lib/components/replaceable-route-container.component.ts
@@ -1,4 +1,4 @@
-import { Component, OnInit, Type } from '@angular/core';
+import { Component, OnInit, Type, inject } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { distinctUntilChanged } from 'rxjs/operators';
import { ReplaceableComponents } from '../models/replaceable-components';
@@ -15,18 +15,16 @@ import { CommonModule } from '@angular/common';
imports: [CommonModule],
})
export class ReplaceableRouteContainerComponent implements OnInit {
+ private route = inject(ActivatedRoute);
+ private replaceableComponents = inject(ReplaceableComponentsService);
+ private subscription = inject(SubscriptionService);
+
defaultComponent!: Type;
componentKey!: string;
externalComponent?: Type;
- constructor(
- private route: ActivatedRoute,
- private replaceableComponents: ReplaceableComponentsService,
- private subscription: SubscriptionService,
- ) {}
-
ngOnInit() {
this.defaultComponent = this.route.snapshot.data.replaceableComponent.defaultComponent;
this.componentKey = (
diff --git a/npm/ng-packs/packages/core/src/lib/directives/autofocus.directive.ts b/npm/ng-packs/packages/core/src/lib/directives/autofocus.directive.ts
index f34d187939..398eaef9cc 100644
--- a/npm/ng-packs/packages/core/src/lib/directives/autofocus.directive.ts
+++ b/npm/ng-packs/packages/core/src/lib/directives/autofocus.directive.ts
@@ -1,9 +1,11 @@
-import { AfterViewInit, Directive, ElementRef, Input } from '@angular/core';
+import { AfterViewInit, Directive, ElementRef, Input, inject } from '@angular/core';
@Directive({
selector: '[autofocus]',
})
export class AutofocusDirective implements AfterViewInit {
+ private elRef = inject(ElementRef);
+
private _delay = 0;
@Input('autofocus')
@@ -15,8 +17,6 @@ export class AutofocusDirective implements AfterViewInit {
return this._delay;
}
- constructor(private elRef: ElementRef) {}
-
ngAfterViewInit(): void {
setTimeout(() => this.elRef.nativeElement.focus(), this.delay as number);
}
diff --git a/npm/ng-packs/packages/core/src/lib/directives/debounce.directive.ts b/npm/ng-packs/packages/core/src/lib/directives/debounce.directive.ts
index 204db6b418..239aed688d 100644
--- a/npm/ng-packs/packages/core/src/lib/directives/debounce.directive.ts
+++ b/npm/ng-packs/packages/core/src/lib/directives/debounce.directive.ts
@@ -1,4 +1,4 @@
-import { Directive, ElementRef, EventEmitter, Input, OnInit, Output } from '@angular/core';
+import { Directive, ElementRef, EventEmitter, Input, OnInit, Output, inject } from '@angular/core';
import { fromEvent } from 'rxjs';
import { debounceTime } from 'rxjs/operators';
import { SubscriptionService } from '../services/subscription.service';
@@ -8,15 +8,13 @@ import { SubscriptionService } from '../services/subscription.service';
providers: [SubscriptionService],
})
export class InputEventDebounceDirective implements OnInit {
+ private el = inject(ElementRef);
+ private subscription = inject(SubscriptionService);
+
@Input() debounce = 300;
@Output('input.debounce') readonly debounceEvent = new EventEmitter();
- constructor(
- private el: ElementRef,
- private subscription: SubscriptionService,
- ) {}
-
ngOnInit(): void {
const input$ = fromEvent(this.el.nativeElement, 'input').pipe(
debounceTime(this.debounce),
diff --git a/npm/ng-packs/packages/core/src/lib/directives/for.directive.ts b/npm/ng-packs/packages/core/src/lib/directives/for.directive.ts
index 1e37e1c908..7b3bd0319b 100644
--- a/npm/ng-packs/packages/core/src/lib/directives/for.directive.ts
+++ b/npm/ng-packs/packages/core/src/lib/directives/for.directive.ts
@@ -1,15 +1,16 @@
-import {
- Directive,
- EmbeddedViewRef,
- Input,
- IterableChangeRecord,
- IterableChanges,
- IterableDiffer,
- IterableDiffers,
- OnChanges,
- TemplateRef,
- TrackByFunction,
- ViewContainerRef,
+import {
+ Directive,
+ EmbeddedViewRef,
+ Input,
+ IterableChangeRecord,
+ IterableChanges,
+ IterableDiffer,
+ IterableDiffers,
+ OnChanges,
+ TemplateRef,
+ TrackByFunction,
+ ViewContainerRef,
+ inject
} from '@angular/core';
import clone from 'just-clone';
import compare from 'just-compare';
@@ -36,6 +37,10 @@ class RecordView {
selector: '[abpFor]',
})
export class ForDirective implements OnChanges {
+ private tempRef = inject>(TemplateRef);
+ private vcRef = inject(ViewContainerRef);
+ private differs = inject(IterableDiffers);
+
// eslint-disable-next-line @angular-eslint/no-input-rename
@Input('abpForOf')
items!: any[];
@@ -73,12 +78,6 @@ export class ForDirective implements OnChanges {
return this.trackBy || ((index: number, item: any) => (item as any).id || index);
}
- constructor(
- private tempRef: TemplateRef,
- private vcRef: ViewContainerRef,
- private differs: IterableDiffers,
- ) {}
-
private iterateOverAppliedOperations(changes: IterableChanges) {
const rw: RecordView[] = [];
diff --git a/npm/ng-packs/packages/core/src/lib/directives/form-submit.directive.ts b/npm/ng-packs/packages/core/src/lib/directives/form-submit.directive.ts
index 25972ccb71..879fbdf780 100644
--- a/npm/ng-packs/packages/core/src/lib/directives/form-submit.directive.ts
+++ b/npm/ng-packs/packages/core/src/lib/directives/form-submit.directive.ts
@@ -1,12 +1,12 @@
-import {
- ChangeDetectorRef,
- Directive,
- ElementRef,
- EventEmitter,
- Input,
- OnInit,
- Output,
- Self,
+import {
+ ChangeDetectorRef,
+ Directive,
+ ElementRef,
+ EventEmitter,
+ Input,
+ OnInit,
+ Output,
+ inject
} from '@angular/core';
import { FormGroupDirective, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
import { fromEvent } from 'rxjs';
@@ -22,6 +22,11 @@ type Controls = { [key: string]: UntypedFormControl } | UntypedFormGroup[];
providers: [SubscriptionService],
})
export class FormSubmitDirective implements OnInit {
+ private formGroupDirective = inject(FormGroupDirective, { self: true });
+ private host = inject>(ElementRef);
+ private cdRef = inject(ChangeDetectorRef);
+ private subscription = inject(SubscriptionService);
+
@Input()
debounce = 200;
@@ -36,13 +41,6 @@ export class FormSubmitDirective implements OnInit {
executedNgSubmit = false;
- constructor(
- @Self() private formGroupDirective: FormGroupDirective,
- private host: ElementRef,
- private cdRef: ChangeDetectorRef,
- private subscription: SubscriptionService,
- ) {}
-
ngOnInit() {
this.subscription.addOne(this.formGroupDirective.ngSubmit, () => {
if (this.markAsDirtyWhenSubmit) {
diff --git a/npm/ng-packs/packages/core/src/lib/directives/init.directive.ts b/npm/ng-packs/packages/core/src/lib/directives/init.directive.ts
index 293384e4e1..1271f031ba 100644
--- a/npm/ng-packs/packages/core/src/lib/directives/init.directive.ts
+++ b/npm/ng-packs/packages/core/src/lib/directives/init.directive.ts
@@ -1,12 +1,12 @@
-import { Directive, Output, EventEmitter, ElementRef, AfterViewInit } from '@angular/core';
+import { Directive, Output, EventEmitter, ElementRef, AfterViewInit, inject } from '@angular/core';
@Directive({
selector: '[abpInit]',
})
export class InitDirective implements AfterViewInit {
- @Output('abpInit') readonly init = new EventEmitter>();
+ private elRef = inject(ElementRef);
- constructor(private elRef: ElementRef) {}
+ @Output('abpInit') readonly init = new EventEmitter>();
ngAfterViewInit() {
this.init.emit(this.elRef);
diff --git a/npm/ng-packs/packages/core/src/lib/directives/permission.directive.ts b/npm/ng-packs/packages/core/src/lib/directives/permission.directive.ts
index f277bf50ee..50b805dba4 100644
--- a/npm/ng-packs/packages/core/src/lib/directives/permission.directive.ts
+++ b/npm/ng-packs/packages/core/src/lib/directives/permission.directive.ts
@@ -1,14 +1,13 @@
-import {
- AfterViewInit,
- ChangeDetectorRef,
- Directive,
- Inject,
- Input,
- OnChanges,
- OnDestroy,
- Optional,
- TemplateRef,
- ViewContainerRef,
+import {
+ AfterViewInit,
+ ChangeDetectorRef,
+ Directive,
+ Input,
+ OnChanges,
+ OnDestroy,
+ TemplateRef,
+ ViewContainerRef,
+ inject
} from '@angular/core';
import { ReplaySubject, Subscription } from 'rxjs';
import { distinctUntilChanged, take } from 'rxjs/operators';
@@ -20,6 +19,12 @@ import { QueueManager } from '../utils/queue';
selector: '[abpPermission]',
})
export class PermissionDirective implements OnDestroy, OnChanges, AfterViewInit {
+ private templateRef = inject>(TemplateRef, { optional: true })!;
+ private vcRef = inject(ViewContainerRef);
+ private permissionService = inject(PermissionService);
+ private cdRef = inject(ChangeDetectorRef);
+ queue = inject(QUEUE_MANAGER);
+
@Input('abpPermission') condition: string | undefined;
@Input('abpPermissionRunChangeDetection') runChangeDetection = true;
@@ -30,14 +35,6 @@ export class PermissionDirective implements OnDestroy, OnChanges, AfterViewInit
rendered = false;
- constructor(
- @Optional() private templateRef: TemplateRef,
- private vcRef: ViewContainerRef,
- private permissionService: PermissionService,
- private cdRef: ChangeDetectorRef,
- @Inject(QUEUE_MANAGER) public queue: QueueManager,
- ) {}
-
private check() {
if (this.subscription) {
this.subscription.unsubscribe();
diff --git a/npm/ng-packs/packages/core/src/lib/directives/replaceable-template.directive.ts b/npm/ng-packs/packages/core/src/lib/directives/replaceable-template.directive.ts
index 9a1bedcd71..7e948cc20f 100644
--- a/npm/ng-packs/packages/core/src/lib/directives/replaceable-template.directive.ts
+++ b/npm/ng-packs/packages/core/src/lib/directives/replaceable-template.directive.ts
@@ -1,13 +1,14 @@
-import {
- Directive,
- Injector,
- Input,
- OnChanges,
- OnInit,
- SimpleChanges,
- TemplateRef,
- Type,
- ViewContainerRef,
+import {
+ Directive,
+ Injector,
+ Input,
+ OnChanges,
+ OnInit,
+ SimpleChanges,
+ TemplateRef,
+ Type,
+ ViewContainerRef,
+ inject
} from '@angular/core';
import compare from 'just-compare';
import { Subscription } from 'rxjs';
@@ -22,6 +23,12 @@ import { SubscriptionService } from '../services/subscription.service';
providers: [SubscriptionService],
})
export class ReplaceableTemplateDirective implements OnInit, OnChanges {
+ private injector = inject(Injector);
+ private templateRef = inject>(TemplateRef);
+ private vcRef = inject(ViewContainerRef);
+ private replaceableComponents = inject(ReplaceableComponentsService);
+ private subscription = inject(SubscriptionService);
+
@Input('abpReplaceableTemplate')
data!: ReplaceableComponents.ReplaceableTemplateDirectiveInput;
@@ -40,13 +47,7 @@ export class ReplaceableTemplateDirective implements OnInit, OnChanges {
initialized = false;
- constructor(
- private injector: Injector,
- private templateRef: TemplateRef,
- private vcRef: ViewContainerRef,
- private replaceableComponents: ReplaceableComponentsService,
- private subscription: SubscriptionService,
- ) {
+ constructor() {
this.context = {
initTemplate: (ref: any) => {
this.resetDefaultComponent();
diff --git a/npm/ng-packs/packages/core/src/lib/directives/stop-propagation.directive.ts b/npm/ng-packs/packages/core/src/lib/directives/stop-propagation.directive.ts
index ddc92cb56b..a1af9bf07e 100644
--- a/npm/ng-packs/packages/core/src/lib/directives/stop-propagation.directive.ts
+++ b/npm/ng-packs/packages/core/src/lib/directives/stop-propagation.directive.ts
@@ -1,4 +1,4 @@
-import { Directive, ElementRef, EventEmitter, OnInit, Output } from '@angular/core';
+import { Directive, ElementRef, EventEmitter, OnInit, Output, inject } from '@angular/core';
import { fromEvent } from 'rxjs';
import { SubscriptionService } from '../services/subscription.service';
@@ -7,12 +7,10 @@ import { SubscriptionService } from '../services/subscription.service';
providers: [SubscriptionService],
})
export class StopPropagationDirective implements OnInit {
- @Output('click.stop') readonly stopPropEvent = new EventEmitter();
+ private el = inject(ElementRef);
+ private subscription = inject(SubscriptionService);
- constructor(
- private el: ElementRef,
- private subscription: SubscriptionService,
- ) {}
+ @Output('click.stop') readonly stopPropEvent = new EventEmitter();
ngOnInit(): void {
this.subscription.addOne(fromEvent(this.el.nativeElement, 'click'), event => {
diff --git a/npm/ng-packs/packages/core/src/lib/handlers/routes.handler.ts b/npm/ng-packs/packages/core/src/lib/handlers/routes.handler.ts
index 76dc66b3ae..d8880b4fbf 100644
--- a/npm/ng-packs/packages/core/src/lib/handlers/routes.handler.ts
+++ b/npm/ng-packs/packages/core/src/lib/handlers/routes.handler.ts
@@ -1,4 +1,4 @@
-import { Injectable, Optional } from '@angular/core';
+import { Injectable, inject } from '@angular/core';
import { Route, Router } from '@angular/router';
import { ABP } from '../models';
import { RoutesService } from '../services/routes.service';
@@ -7,10 +7,10 @@ import { RoutesService } from '../services/routes.service';
providedIn: 'root',
})
export class RoutesHandler {
- constructor(
- private routes: RoutesService,
- @Optional() private router: Router,
- ) {
+ private routes = inject(RoutesService);
+ private router = inject(Router, { optional: true })!;
+
+ constructor() {
this.addRoutes();
}
diff --git a/npm/ng-packs/packages/core/src/lib/interceptors/api.interceptor.ts b/npm/ng-packs/packages/core/src/lib/interceptors/api.interceptor.ts
index 9321521159..04be80638e 100644
--- a/npm/ng-packs/packages/core/src/lib/interceptors/api.interceptor.ts
+++ b/npm/ng-packs/packages/core/src/lib/interceptors/api.interceptor.ts
@@ -1,5 +1,5 @@
import { HttpHandler, HttpHeaders, HttpInterceptor, HttpRequest } from '@angular/common/http';
-import { Injectable } from '@angular/core';
+import { Injectable, inject } from '@angular/core';
import { finalize } from 'rxjs/operators';
import { HttpWaitService } from '../services';
@@ -7,7 +7,8 @@ import { HttpWaitService } from '../services';
providedIn: 'root',
})
export class ApiInterceptor implements IApiInterceptor {
- constructor(private httpWaitService: HttpWaitService) {}
+ private httpWaitService = inject(HttpWaitService);
+
getAdditionalHeaders(existingHeaders?: HttpHeaders) {
return existingHeaders || new HttpHeaders();
diff --git a/npm/ng-packs/packages/core/src/lib/pipes/localization.pipe.ts b/npm/ng-packs/packages/core/src/lib/pipes/localization.pipe.ts
index 2dbac68eb7..bbb2a71752 100644
--- a/npm/ng-packs/packages/core/src/lib/pipes/localization.pipe.ts
+++ b/npm/ng-packs/packages/core/src/lib/pipes/localization.pipe.ts
@@ -1,4 +1,4 @@
-import { Injectable, Pipe, PipeTransform } from '@angular/core';
+import { Injectable, Pipe, PipeTransform, inject } from '@angular/core';
import { LocalizationWithDefault } from '../models/localization';
import { LocalizationService } from '../services/localization.service';
@@ -7,7 +7,8 @@ import { LocalizationService } from '../services/localization.service';
name: 'abpLocalization',
})
export class LocalizationPipe implements PipeTransform {
- constructor(private localization: LocalizationService) {}
+ private localization = inject(LocalizationService);
+
transform(
value: string | LocalizationWithDefault = '',
diff --git a/npm/ng-packs/packages/core/src/lib/pipes/short-date-time.pipe.ts b/npm/ng-packs/packages/core/src/lib/pipes/short-date-time.pipe.ts
index b72ca45dde..8ed6dc55b4 100644
--- a/npm/ng-packs/packages/core/src/lib/pipes/short-date-time.pipe.ts
+++ b/npm/ng-packs/packages/core/src/lib/pipes/short-date-time.pipe.ts
@@ -1,5 +1,5 @@
import { DatePipe, DATE_PIPE_DEFAULT_TIMEZONE } from '@angular/common';
-import { Inject, LOCALE_ID, Optional, Pipe, PipeTransform } from '@angular/core';
+import { LOCALE_ID, Pipe, PipeTransform, inject } from '@angular/core';
import { ConfigStateService } from '../services';
import { getShortDateShortTimeFormat } from '../utils/date-utils';
@@ -8,11 +8,12 @@ import { getShortDateShortTimeFormat } from '../utils/date-utils';
pure: true,
})
export class ShortDateTimePipe extends DatePipe implements PipeTransform {
- constructor(
- private configStateService: ConfigStateService,
- @Inject(LOCALE_ID) locale: string,
- @Inject(DATE_PIPE_DEFAULT_TIMEZONE) @Optional() defaultTimezone?: string | null,
- ) {
+ private configStateService = inject(ConfigStateService);
+
+ constructor() {
+ const locale = inject(LOCALE_ID);
+ const defaultTimezone = inject(DATE_PIPE_DEFAULT_TIMEZONE, { optional: true });
+
super(locale, defaultTimezone);
}
diff --git a/npm/ng-packs/packages/core/src/lib/pipes/short-date.pipe.ts b/npm/ng-packs/packages/core/src/lib/pipes/short-date.pipe.ts
index 26a7e1552f..9968009e49 100644
--- a/npm/ng-packs/packages/core/src/lib/pipes/short-date.pipe.ts
+++ b/npm/ng-packs/packages/core/src/lib/pipes/short-date.pipe.ts
@@ -1,5 +1,5 @@
import { DatePipe, DATE_PIPE_DEFAULT_TIMEZONE } from '@angular/common';
-import { Inject, LOCALE_ID, Optional, Pipe, PipeTransform } from '@angular/core';
+import { LOCALE_ID, Pipe, PipeTransform, inject } from '@angular/core';
import { ConfigStateService } from '../services';
import { getShortDateFormat } from '../utils/date-utils';
@@ -8,11 +8,12 @@ import { getShortDateFormat } from '../utils/date-utils';
pure: true,
})
export class ShortDatePipe extends DatePipe implements PipeTransform {
- constructor(
- private configStateService: ConfigStateService,
- @Inject(LOCALE_ID) locale: string,
- @Inject(DATE_PIPE_DEFAULT_TIMEZONE) @Optional() defaultTimezone?: string | null,
- ) {
+ private configStateService = inject(ConfigStateService);
+
+ constructor() {
+ const locale = inject(LOCALE_ID);
+ const defaultTimezone = inject(DATE_PIPE_DEFAULT_TIMEZONE, { optional: true });
+
super(locale, defaultTimezone);
}
diff --git a/npm/ng-packs/packages/core/src/lib/pipes/short-time.pipe.ts b/npm/ng-packs/packages/core/src/lib/pipes/short-time.pipe.ts
index 54e70802f8..fac722af5e 100644
--- a/npm/ng-packs/packages/core/src/lib/pipes/short-time.pipe.ts
+++ b/npm/ng-packs/packages/core/src/lib/pipes/short-time.pipe.ts
@@ -1,5 +1,5 @@
import { DatePipe, DATE_PIPE_DEFAULT_TIMEZONE } from '@angular/common';
-import { Inject, LOCALE_ID, Optional, Pipe, PipeTransform } from '@angular/core';
+import { LOCALE_ID, Pipe, PipeTransform, inject } from '@angular/core';
import { ConfigStateService } from '../services';
import { getShortTimeFormat } from '../utils/date-utils';
@@ -8,11 +8,12 @@ import { getShortTimeFormat } from '../utils/date-utils';
pure: true,
})
export class ShortTimePipe extends DatePipe implements PipeTransform {
- constructor(
- private configStateService: ConfigStateService,
- @Inject(LOCALE_ID) locale: string,
- @Inject(DATE_PIPE_DEFAULT_TIMEZONE) @Optional() defaultTimezone?: string | null,
- ) {
+ private configStateService = inject(ConfigStateService);
+
+ constructor() {
+ const locale = inject(LOCALE_ID);
+ const defaultTimezone = inject(DATE_PIPE_DEFAULT_TIMEZONE, { optional: true });
+
super(locale, defaultTimezone);
}
diff --git a/npm/ng-packs/packages/core/src/lib/pipes/to-injector.pipe.ts b/npm/ng-packs/packages/core/src/lib/pipes/to-injector.pipe.ts
index 5a1ac4df29..77663a1262 100644
--- a/npm/ng-packs/packages/core/src/lib/pipes/to-injector.pipe.ts
+++ b/npm/ng-packs/packages/core/src/lib/pipes/to-injector.pipe.ts
@@ -1,4 +1,4 @@
-import { InjectionToken, Injector, Pipe, PipeTransform } from '@angular/core';
+import { InjectionToken, Injector, Pipe, PipeTransform, inject } from '@angular/core';
export const INJECTOR_PIPE_DATA_TOKEN = new InjectionToken(
'INJECTOR_PIPE_DATA_TOKEN',
@@ -8,7 +8,8 @@ export const INJECTOR_PIPE_DATA_TOKEN = new InjectionToken(
name: 'toInjector',
})
export class ToInjectorPipe implements PipeTransform {
- constructor(private injector: Injector) {}
+ private injector = inject(Injector);
+
transform(
value: any,
token: InjectionToken = INJECTOR_PIPE_DATA_TOKEN,
diff --git a/npm/ng-packs/packages/core/src/lib/providers/locale.provider.ts b/npm/ng-packs/packages/core/src/lib/providers/locale.provider.ts
index ca90c4bc33..9d34802da1 100644
--- a/npm/ng-packs/packages/core/src/lib/providers/locale.provider.ts
+++ b/npm/ng-packs/packages/core/src/lib/providers/locale.provider.ts
@@ -1,10 +1,12 @@
-import { LOCALE_ID, Provider } from '@angular/core';
+import { LOCALE_ID, Provider, inject } from '@angular/core';
import { differentLocales } from '../constants/different-locales';
import { LocalizationService } from '../services/localization.service';
import { checkHasProp } from '../utils/common-utils';
export class LocaleId extends String {
- constructor(private localizationService: LocalizationService) {
+ private localizationService = inject(LocalizationService);
+
+ constructor() {
super();
}
@@ -24,5 +26,4 @@ export class LocaleId extends String {
export const LocaleProvider: Provider = {
provide: LOCALE_ID,
useClass: LocaleId,
- deps: [LocalizationService],
-};
+};
\ No newline at end of file
diff --git a/npm/ng-packs/packages/core/src/lib/proxy/pages/abp/multi-tenancy/abp-tenant.service.ts b/npm/ng-packs/packages/core/src/lib/proxy/pages/abp/multi-tenancy/abp-tenant.service.ts
index 039ddc707e..d778e0a279 100644
--- a/npm/ng-packs/packages/core/src/lib/proxy/pages/abp/multi-tenancy/abp-tenant.service.ts
+++ b/npm/ng-packs/packages/core/src/lib/proxy/pages/abp/multi-tenancy/abp-tenant.service.ts
@@ -1,12 +1,14 @@
import { RestService } from '../../../../services';
import { Rest } from '../../../../models';
-import { Injectable } from '@angular/core';
+import { Injectable, inject } from '@angular/core';
import type { FindTenantResultDto } from '../../../volo/abp/asp-net-core/mvc/multi-tenancy/models';
@Injectable({
providedIn: 'root',
})
-export class AbpTenantService {
+export class AbpTenantService {
+ private restService = inject(RestService);
+
apiName = 'abp';
@@ -24,6 +26,4 @@ export class AbpTenantService {
url: `/api/abp/multi-tenancy/tenants/by-name/${name}`,
},
{ apiName: this.apiName,...config });
-
- constructor(private restService: RestService) {}
}
diff --git a/npm/ng-packs/packages/core/src/lib/proxy/volo/abp/asp-net-core/mvc/api-exploring/abp-api-definition.service.ts b/npm/ng-packs/packages/core/src/lib/proxy/volo/abp/asp-net-core/mvc/api-exploring/abp-api-definition.service.ts
index a331106214..770faca476 100644
--- a/npm/ng-packs/packages/core/src/lib/proxy/volo/abp/asp-net-core/mvc/api-exploring/abp-api-definition.service.ts
+++ b/npm/ng-packs/packages/core/src/lib/proxy/volo/abp/asp-net-core/mvc/api-exploring/abp-api-definition.service.ts
@@ -1,12 +1,14 @@
import { RestService } from '../../../../../../services';
import { Rest } from '../../../../../../models';
-import { Injectable } from '@angular/core';
+import { Injectable, inject } from '@angular/core';
import type { ApplicationApiDescriptionModel, ApplicationApiDescriptionModelRequestDto } from '../../../http/modeling/models';
@Injectable({
providedIn: 'root',
})
-export class AbpApiDefinitionService {
+export class AbpApiDefinitionService {
+ private restService = inject(RestService);
+
apiName = 'abp';
@@ -17,6 +19,4 @@ export class AbpApiDefinitionService {
params: { includeTypes: model.includeTypes },
},
{ apiName: this.apiName,...config });
-
- constructor(private restService: RestService) {}
}
diff --git a/npm/ng-packs/packages/core/src/lib/proxy/volo/abp/asp-net-core/mvc/application-configurations/abp-application-configuration.service.ts b/npm/ng-packs/packages/core/src/lib/proxy/volo/abp/asp-net-core/mvc/application-configurations/abp-application-configuration.service.ts
index 3c04af51fc..9dc35fa7b6 100644
--- a/npm/ng-packs/packages/core/src/lib/proxy/volo/abp/asp-net-core/mvc/application-configurations/abp-application-configuration.service.ts
+++ b/npm/ng-packs/packages/core/src/lib/proxy/volo/abp/asp-net-core/mvc/application-configurations/abp-application-configuration.service.ts
@@ -1,12 +1,14 @@
import type { ApplicationConfigurationDto, ApplicationConfigurationRequestOptions } from './models';
import { RestService } from '../../../../../../services';
import { Rest } from '../../../../../../models';
-import { Injectable } from '@angular/core';
+import { Injectable, inject } from '@angular/core';
@Injectable({
providedIn: 'root',
})
-export class AbpApplicationConfigurationService {
+export class AbpApplicationConfigurationService {
+ private restService = inject(RestService);
+
apiName = 'abp';
@@ -17,6 +19,4 @@ export class AbpApplicationConfigurationService {
params: { includeLocalizationResources: options.includeLocalizationResources },
},
{ apiName: this.apiName, ...config });
-
- constructor(private restService: RestService) { }
}
diff --git a/npm/ng-packs/packages/core/src/lib/proxy/volo/abp/asp-net-core/mvc/application-configurations/abp-application-localization.service.ts b/npm/ng-packs/packages/core/src/lib/proxy/volo/abp/asp-net-core/mvc/application-configurations/abp-application-localization.service.ts
index 3b9fd80584..aa3f495b53 100644
--- a/npm/ng-packs/packages/core/src/lib/proxy/volo/abp/asp-net-core/mvc/application-configurations/abp-application-localization.service.ts
+++ b/npm/ng-packs/packages/core/src/lib/proxy/volo/abp/asp-net-core/mvc/application-configurations/abp-application-localization.service.ts
@@ -1,12 +1,14 @@
import type { ApplicationLocalizationDto, ApplicationLocalizationRequestDto } from './models';
import { RestService } from '../../../../../../services';
import { Rest } from '../../../../../../models';
-import { Injectable } from '@angular/core';
+import { Injectable, inject } from '@angular/core';
@Injectable({
providedIn: 'root',
})
-export class AbpApplicationLocalizationService {
+export class AbpApplicationLocalizationService {
+ private restService = inject(RestService);
+
apiName = 'abp';
@@ -17,6 +19,4 @@ export class AbpApplicationLocalizationService {
params: { cultureName: input.cultureName, onlyDynamics: input.onlyDynamics },
},
{ apiName: this.apiName,...config });
-
- constructor(private restService: RestService) {}
}
diff --git a/npm/ng-packs/packages/core/src/lib/services/config-state.service.ts b/npm/ng-packs/packages/core/src/lib/services/config-state.service.ts
index 475f6d76f3..1243e8b2ba 100644
--- a/npm/ng-packs/packages/core/src/lib/services/config-state.service.ts
+++ b/npm/ng-packs/packages/core/src/lib/services/config-state.service.ts
@@ -1,4 +1,4 @@
-import { Inject, Injectable, Optional } from '@angular/core';
+import { Injectable, inject } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import { map, switchMap, take, tap } from 'rxjs/operators';
import { AbpApplicationConfigurationService } from '../proxy/volo/abp/asp-net-core/mvc/application-configurations/abp-application-configuration.service';
@@ -15,6 +15,10 @@ import { InternalStore } from '../utils/internal-store-utils';
providedIn: 'root',
})
export class ConfigStateService {
+ private abpConfigService = inject(AbpApplicationConfigurationService);
+ private abpApplicationLocalizationService = inject(AbpApplicationLocalizationService);
+ private readonly includeLocalizationResources = inject(INCUDE_LOCALIZATION_RESOURCES_TOKEN, { optional: true });
+
private updateSubject = new Subject();
private readonly store = new InternalStore({} as ApplicationConfigurationDto);
@@ -27,13 +31,7 @@ export class ConfigStateService {
get createOnUpdateStream() {
return this.store.sliceUpdate;
}
- constructor(
- private abpConfigService: AbpApplicationConfigurationService,
- private abpApplicationLocalizationService: AbpApplicationLocalizationService,
- @Optional()
- @Inject(INCUDE_LOCALIZATION_RESOURCES_TOKEN)
- private readonly includeLocalizationResources: boolean | null,
- ) {
+ constructor() {
this.initUpdateStream();
}
diff --git a/npm/ng-packs/packages/core/src/lib/services/content-projection.service.ts b/npm/ng-packs/packages/core/src/lib/services/content-projection.service.ts
index dfcdea330a..d9aac2bd48 100644
--- a/npm/ng-packs/packages/core/src/lib/services/content-projection.service.ts
+++ b/npm/ng-packs/packages/core/src/lib/services/content-projection.service.ts
@@ -1,9 +1,10 @@
-import { Injectable, Injector, TemplateRef, Type } from '@angular/core';
+import { Injectable, Injector, TemplateRef, Type, inject } from '@angular/core';
import { ProjectionStrategy } from '../strategies/projection.strategy';
@Injectable({ providedIn: 'root' })
export class ContentProjectionService {
- constructor(private injector: Injector) {}
+ private injector = inject(Injector);
+
projectContent | TemplateRef>(
projectionStrategy: ProjectionStrategy,
diff --git a/npm/ng-packs/packages/core/src/lib/services/http-wait.service.ts b/npm/ng-packs/packages/core/src/lib/services/http-wait.service.ts
index d80599fc25..d8073d8760 100644
--- a/npm/ng-packs/packages/core/src/lib/services/http-wait.service.ts
+++ b/npm/ng-packs/packages/core/src/lib/services/http-wait.service.ts
@@ -1,4 +1,4 @@
-import { Injectable, Injector } from '@angular/core';
+import { Injectable, Injector, inject } from '@angular/core';
import { HttpRequest } from '@angular/common/http';
import { InternalStore } from '../utils/internal-store-utils';
import { getPathName } from '../utils/http-utils';
@@ -26,7 +26,9 @@ export class HttpWaitService {
private delay: number;
private destroy$ = new Subject();
- constructor(injector: Injector) {
+ constructor() {
+ const injector = inject(Injector);
+
this.delay = injector.get(LOADER_DELAY, 500);
}
diff --git a/npm/ng-packs/packages/core/src/lib/services/lazy-load.service.ts b/npm/ng-packs/packages/core/src/lib/services/lazy-load.service.ts
index f50102e15a..8358570db9 100644
--- a/npm/ng-packs/packages/core/src/lib/services/lazy-load.service.ts
+++ b/npm/ng-packs/packages/core/src/lib/services/lazy-load.service.ts
@@ -1,4 +1,4 @@
-import { Injectable } from '@angular/core';
+import { Injectable, inject } from '@angular/core';
import { concat, Observable, of, pipe, throwError } from 'rxjs';
import { delay, retryWhen, shareReplay, take, tap } from 'rxjs/operators';
import { LoadingStrategy } from '../strategies';
@@ -8,9 +8,9 @@ import { ResourceWaitService } from './resource-wait.service';
providedIn: 'root',
})
export class LazyLoadService {
- readonly loaded = new Map();
+ private resourceWaitService = inject(ResourceWaitService);
- constructor(private resourceWaitService: ResourceWaitService) {}
+ readonly loaded = new Map();
load(strategy: LoadingStrategy, retryTimes?: number, retryDelay?: number): Observable {
if (this.loaded.has(strategy.path)) return of(new CustomEvent('load'));
diff --git a/npm/ng-packs/packages/core/src/lib/services/list.service.ts b/npm/ng-packs/packages/core/src/lib/services/list.service.ts
index 204833a66d..3cfc0ecac9 100644
--- a/npm/ng-packs/packages/core/src/lib/services/list.service.ts
+++ b/npm/ng-packs/packages/core/src/lib/services/list.service.ts
@@ -1,4 +1,4 @@
-import { Injectable, Injector, OnDestroy } from '@angular/core';
+import { Injectable, Injector, OnDestroy, inject } from '@angular/core';
import {
EMPTY,
BehaviorSubject,
@@ -119,7 +119,9 @@ export class ListService implements
this.next();
};
- constructor(injector: Injector) {
+ constructor() {
+ const injector = inject(Injector);
+
const delay = injector.get(LIST_QUERY_DEBOUNCE_TIME, 300);
this.delay = delay ? debounceTime(delay) : tap();
this.get();
diff --git a/npm/ng-packs/packages/core/src/lib/services/localization.service.ts b/npm/ng-packs/packages/core/src/lib/services/localization.service.ts
index 7b474e7881..dd6def0c24 100644
--- a/npm/ng-packs/packages/core/src/lib/services/localization.service.ts
+++ b/npm/ng-packs/packages/core/src/lib/services/localization.service.ts
@@ -1,5 +1,5 @@
import { registerLocaleData } from '@angular/common';
-import { Injectable, Injector, isDevMode, Optional, SkipSelf } from '@angular/core';
+import { Injectable, Injector, isDevMode, inject } from '@angular/core';
import { BehaviorSubject, combineLatest, from, Observable, Subject } from 'rxjs';
import { filter, map, switchMap } from 'rxjs/operators';
import { ABP } from '../models/common';
@@ -17,6 +17,10 @@ import { SessionStateService } from './session-state.service';
@Injectable({ providedIn: 'root' })
export class LocalizationService {
+ private sessionState = inject(SessionStateService);
+ private injector = inject(Injector);
+ private configState = inject(ConfigStateService);
+
private latestLang = this.sessionState.getLanguage();
private _languageChange$ = new Subject();
@@ -44,14 +48,9 @@ export class LocalizationService {
return this._languageChange$.asObservable();
}
- constructor(
- private sessionState: SessionStateService,
- private injector: Injector,
- @Optional()
- @SkipSelf()
- otherInstance: LocalizationService,
- private configState: ConfigStateService,
- ) {
+ constructor() {
+ const otherInstance = inject(LocalizationService, { optional: true, skipSelf: true })!;
+
if (otherInstance) throw new Error('LocalizationService should have only one instance.');
this.listenToSetLanguage();
diff --git a/npm/ng-packs/packages/core/src/lib/services/multi-tenancy.service.ts b/npm/ng-packs/packages/core/src/lib/services/multi-tenancy.service.ts
index 8fbde5cc8e..a88cba1c3d 100644
--- a/npm/ng-packs/packages/core/src/lib/services/multi-tenancy.service.ts
+++ b/npm/ng-packs/packages/core/src/lib/services/multi-tenancy.service.ts
@@ -1,4 +1,4 @@
-import { Inject, Injectable } from '@angular/core';
+import { Injectable, inject } from '@angular/core';
import { map, switchMap } from 'rxjs/operators';
import { AbpTenantService } from '../proxy/pages/abp/multi-tenancy';
import {
@@ -7,11 +7,15 @@ import {
} from '../proxy/volo/abp/asp-net-core/mvc/multi-tenancy/models';
import { TENANT_KEY } from '../tokens/tenant-key.token';
import { ConfigStateService } from './config-state.service';
-import { RestService } from './rest.service';
import { SessionStateService } from './session-state.service';
@Injectable({ providedIn: 'root' })
export class MultiTenancyService {
+ private sessionState = inject(SessionStateService);
+ private tenantService = inject(AbpTenantService);
+ private configStateService = inject(ConfigStateService);
+ tenantKey = inject(TENANT_KEY);
+
domainTenant: CurrentTenantDto | null = null;
isTenantBoxVisible = true;
@@ -23,14 +27,6 @@ export class MultiTenancyService {
return this.configStateService.refreshAppState().pipe(map(_ => tenant));
};
- constructor(
- private restService: RestService,
- private sessionState: SessionStateService,
- private tenantService: AbpTenantService,
- private configStateService: ConfigStateService,
- @Inject(TENANT_KEY) public tenantKey: string,
- ) { }
-
setTenantByName(tenantName: string) {
return this.tenantService
.findTenantByName(tenantName)
diff --git a/npm/ng-packs/packages/core/src/lib/services/permission.service.ts b/npm/ng-packs/packages/core/src/lib/services/permission.service.ts
index 70724ac814..b45b2a36f5 100644
--- a/npm/ng-packs/packages/core/src/lib/services/permission.service.ts
+++ b/npm/ng-packs/packages/core/src/lib/services/permission.service.ts
@@ -1,4 +1,4 @@
-import { Injectable } from '@angular/core';
+import { Injectable, inject } from '@angular/core';
import { map } from 'rxjs/operators';
import { ABP } from '../models/common';
import { ApplicationConfigurationDto } from '../proxy/volo/abp/asp-net-core/mvc/application-configurations/models';
@@ -6,7 +6,8 @@ import { ConfigStateService } from './config-state.service';
@Injectable({ providedIn: 'root' })
export class PermissionService {
- constructor(protected configState: ConfigStateService) {}
+ protected configState = inject(ConfigStateService);
+
getGrantedPolicy$(key: string) {
return this.getStream().pipe(
diff --git a/npm/ng-packs/packages/core/src/lib/services/replaceable-components.service.ts b/npm/ng-packs/packages/core/src/lib/services/replaceable-components.service.ts
index 1f02daa389..c156a237aa 100644
--- a/npm/ng-packs/packages/core/src/lib/services/replaceable-components.service.ts
+++ b/npm/ng-packs/packages/core/src/lib/services/replaceable-components.service.ts
@@ -1,4 +1,4 @@
-import { Injectable, NgZone } from '@angular/core';
+import { Injectable, NgZone, inject } from '@angular/core';
import { Router } from '@angular/router';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
@@ -8,6 +8,9 @@ import { reloadRoute } from '../utils/route-utils';
@Injectable({ providedIn: 'root' })
export class ReplaceableComponentsService {
+ private ngZone = inject(NgZone);
+ private router = inject(Router);
+
private readonly store: InternalStore;
get replaceableComponents$(): Observable {
@@ -22,7 +25,7 @@ export class ReplaceableComponentsService {
return this.store.sliceUpdate(state => state);
}
- constructor(private ngZone: NgZone, private router: Router) {
+ constructor() {
this.store = new InternalStore([] as ReplaceableComponents.ReplaceableComponent[]);
}
diff --git a/npm/ng-packs/packages/core/src/lib/services/rest.service.ts b/npm/ng-packs/packages/core/src/lib/services/rest.service.ts
index 83f91777ca..a331b6c742 100644
--- a/npm/ng-packs/packages/core/src/lib/services/rest.service.ts
+++ b/npm/ng-packs/packages/core/src/lib/services/rest.service.ts
@@ -1,5 +1,5 @@
import { HttpClient, HttpParameterCodec, HttpParams, HttpRequest } from '@angular/common/http';
-import { Inject, Injectable } from '@angular/core';
+import { Injectable, inject } from '@angular/core';
import { Observable, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { ExternalHttpClient } from '../clients/http.client';
@@ -14,13 +14,12 @@ import { HttpErrorReporterService } from './http-error-reporter.service';
providedIn: 'root',
})
export class RestService {
- constructor(
- @Inject(CORE_OPTIONS) protected options: ABP.Root,
- protected http: HttpClient,
- protected externalHttp: ExternalHttpClient,
- protected environment: EnvironmentService,
- protected httpErrorReporter: HttpErrorReporterService,
- ) { }
+ protected options = inject(CORE_OPTIONS);
+ protected http = inject(HttpClient);
+ protected externalHttp = inject(ExternalHttpClient);
+ protected environment = inject(EnvironmentService);
+ protected httpErrorReporter = inject(HttpErrorReporterService);
+
protected getApiFromStore(apiName: string | undefined): string {
return this.environment.getApiUrl(apiName);
diff --git a/npm/ng-packs/packages/core/src/lib/services/router-wait.service.ts b/npm/ng-packs/packages/core/src/lib/services/router-wait.service.ts
index 96e66a00e3..f68f6d065a 100644
--- a/npm/ng-packs/packages/core/src/lib/services/router-wait.service.ts
+++ b/npm/ng-packs/packages/core/src/lib/services/router-wait.service.ts
@@ -1,4 +1,4 @@
-import { Injectable, Injector } from '@angular/core';
+import { Injectable, Injector, inject } from '@angular/core';
import { NavigationStart } from '@angular/router';
import { of, Subject, timer } from 'rxjs';
import { map, mapTo, switchMap, takeUntil, tap } from 'rxjs/operators';
@@ -14,10 +14,14 @@ export interface RouterWaitState {
providedIn: 'root',
})
export class RouterWaitService {
+ private routerEvents = inject(RouterEvents);
+
private store = new InternalStore({ loading: false });
private destroy$ = new Subject();
private delay: number;
- constructor(private routerEvents: RouterEvents, injector: Injector) {
+ constructor() {
+ const injector = inject(Injector);
+
this.delay = injector.get(LOADER_DELAY, 500);
this.updateLoadingStatusOnNavigationEvents();
}
diff --git a/npm/ng-packs/packages/core/src/lib/services/routes.service.ts b/npm/ng-packs/packages/core/src/lib/services/routes.service.ts
index 393c724423..175bf76446 100644
--- a/npm/ng-packs/packages/core/src/lib/services/routes.service.ts
+++ b/npm/ng-packs/packages/core/src/lib/services/routes.service.ts
@@ -1,4 +1,4 @@
-import { Injectable, Injector, OnDestroy } from '@angular/core';
+import { Injectable, Injector, OnDestroy, inject } from '@angular/core';
import { BehaviorSubject, Observable, Subscription, map } from 'rxjs';
import { ABP } from '../models/common';
import { OTHERS_GROUP } from '../tokens';
@@ -201,6 +201,8 @@ export abstract class AbstractNavTreeService
extends AbstractTreeService
implements OnDestroy
{
+ protected injector = inject(Injector);
+
private subscription: Subscription;
private permissionService: PermissionService;
private compareFunc;
@@ -211,8 +213,10 @@ export abstract class AbstractNavTreeService
return this.compareFunc(a, b);
};
- constructor(protected injector: Injector) {
+ constructor() {
super();
+ const injector = this.injector;
+
const configState = this.injector.get(ConfigStateService);
this.subscription = configState
.createOnUpdateStream(state => state)
diff --git a/npm/ng-packs/packages/core/src/lib/services/session-state.service.ts b/npm/ng-packs/packages/core/src/lib/services/session-state.service.ts
index d6f423983c..7e519dc742 100644
--- a/npm/ng-packs/packages/core/src/lib/services/session-state.service.ts
+++ b/npm/ng-packs/packages/core/src/lib/services/session-state.service.ts
@@ -12,6 +12,9 @@ import { AbpLocalStorageService } from './local-storage.service';
providedIn: 'root',
})
export class SessionStateService {
+ private configState = inject(ConfigStateService);
+ private localStorageService = inject(AbpLocalStorageService);
+
private readonly store = new InternalStore({} as Session.State);
protected readonly document = inject(DOCUMENT);
@@ -19,10 +22,7 @@ export class SessionStateService {
this.localStorageService.setItem('abpSession', JSON.stringify(this.store.state));
};
- constructor(
- private configState: ConfigStateService,
- private localStorageService: AbpLocalStorageService,
- ) {
+ constructor() {
this.init();
this.setInitialLanguage();
}
diff --git a/npm/ng-packs/packages/core/src/lib/tests/dynamic-layout.component.spec.ts b/npm/ng-packs/packages/core/src/lib/tests/dynamic-layout.component.spec.ts
index 411a9e8041..aac6c41fcd 100644
--- a/npm/ng-packs/packages/core/src/lib/tests/dynamic-layout.component.spec.ts
+++ b/npm/ng-packs/packages/core/src/lib/tests/dynamic-layout.component.spec.ts
@@ -1,201 +1,201 @@
-import { HttpClient } from '@angular/common/http';
-import { Component, NgModule } from '@angular/core';
-import { ActivatedRoute, RouterModule } from '@angular/router';
-import { createRoutingFactory, SpectatorRouting } from '@ngneat/spectator/jest';
-import { DynamicLayoutComponent, RouterOutletComponent } from '../components';
-import { eLayoutType } from '../enums/common';
-import { ABP } from '../models';
-import { AbpApplicationConfigurationService } from '../proxy/volo/abp/asp-net-core/mvc/application-configurations/abp-application-configuration.service';
-import { ReplaceableComponentsService, RoutesService } from '../services';
-import { mockRoutesService } from './routes.service.spec';
-
-@Component({
- selector: 'abp-layout-application',
- template: ' ',
-})
-class DummyApplicationLayoutComponent {}
-
-@Component({
- selector: 'abp-layout-account',
- template: ' ',
-})
-class DummyAccountLayoutComponent {}
-
-@Component({
- selector: 'abp-layout-empty',
- template: ' ',
-})
-class DummyEmptyLayoutComponent {}
-
-const LAYOUTS = [
- DummyApplicationLayoutComponent,
- DummyAccountLayoutComponent,
- DummyEmptyLayoutComponent,
-];
-
-@NgModule({
- imports: [RouterModule],
- declarations: [...LAYOUTS],
-})
-class DummyLayoutModule {}
-
-@Component({
- selector: 'abp-dummy',
- template: '{{route.snapshot.data?.name}} works!',
-})
-class DummyComponent {
- constructor(public route: ActivatedRoute) {}
-}
-
-const routes: ABP.Route[] = [
- {
- path: '',
- name: 'Root',
- },
- {
- path: '/parentWithLayout',
- name: 'ParentWithLayout',
- parentName: 'Root',
- layout: eLayoutType.application,
- },
- {
- path: '/parentWithLayout/childWithoutLayout',
- name: 'ChildWithoutLayout',
- parentName: 'ParentWithLayout',
- },
- {
- path: '/parentWithLayout/childWithLayout',
- name: 'ChildWithLayout',
- parentName: 'ParentWithLayout',
- layout: eLayoutType.account,
- },
- {
- path: '/withData',
- name: 'WithData',
- layout: eLayoutType.application,
- },
-];
-
-describe('DynamicLayoutComponent', () => {
- const createComponent = createRoutingFactory({
- component: RouterOutletComponent,
- stubsEnabled: false,
- declarations: [DummyComponent, DynamicLayoutComponent],
- mocks: [AbpApplicationConfigurationService, HttpClient],
- providers: [
- {
- provide: RoutesService,
- useFactory: () => mockRoutesService(),
- },
- ReplaceableComponentsService,
- ],
- imports: [RouterModule, DummyLayoutModule],
- routes: [
- { path: '', component: RouterOutletComponent },
- {
- path: 'parentWithLayout',
- component: DynamicLayoutComponent,
- children: [
- {
- path: 'childWithoutLayout',
- component: DummyComponent,
- data: { name: 'childWithoutLayout' },
- },
- {
- path: 'childWithLayout',
- component: DummyComponent,
- data: { name: 'childWithLayout' },
- },
- ],
- },
- {
- path: 'withData',
- component: DynamicLayoutComponent,
- children: [
- {
- path: '',
- component: DummyComponent,
- data: { name: 'withData' },
- },
- ],
- data: { layout: eLayoutType.empty },
- },
- {
- path: 'withoutLayout',
- component: DynamicLayoutComponent,
- children: [
- {
- path: '',
- component: DummyComponent,
- data: { name: 'withoutLayout' },
- },
- ],
- data: { layout: null },
- },
- ],
- });
-
- let spectator: SpectatorRouting;
- let replaceableComponents: ReplaceableComponentsService;
-
- beforeEach(async () => {
- spectator = createComponent();
- replaceableComponents = spectator.inject(ReplaceableComponentsService);
- const routesService = spectator.inject(RoutesService);
- routesService.add(routes);
-
- replaceableComponents.add({
- key: 'Theme.ApplicationLayoutComponent',
- component: DummyApplicationLayoutComponent,
- });
- replaceableComponents.add({
- key: 'Theme.AccountLayoutComponent',
- component: DummyAccountLayoutComponent,
- });
- replaceableComponents.add({
- key: 'Theme.EmptyLayoutComponent',
- component: DummyEmptyLayoutComponent,
- });
- });
-
- it('should handle application layout from parent abp route and display it', async () => {
- spectator.router.navigateByUrl('/parentWithLayout/childWithoutLayout');
- await spectator.fixture.whenStable();
- spectator.detectComponentChanges();
- expect(spectator.query('abp-dynamic-layout')).toBeTruthy();
- expect(spectator.query('abp-layout-application')).toBeTruthy();
- });
-
- it('should handle account layout from own property and display it', async () => {
- spectator.router.navigateByUrl('/parentWithLayout/childWithLayout');
- await spectator.fixture.whenStable();
- spectator.detectComponentChanges();
- expect(spectator.query('abp-layout-account')).toBeTruthy();
- });
-
- it('should handle empty layout from route data and display it', async () => {
- spectator.router.navigateByUrl('/withData');
- await spectator.fixture.whenStable();
- spectator.detectComponentChanges();
- expect(spectator.query('abp-layout-empty')).toBeTruthy();
- });
-
- it('should display empty layout when layout is null', async () => {
- spectator.router.navigateByUrl('/withoutLayout');
- await spectator.fixture.whenStable();
- spectator.detectComponentChanges();
- expect(spectator.query('abp-layout-empty')).toBeTruthy();
- });
-
- it('should not display any layout when layouts are empty', async () => {
- const spy = jest.spyOn(replaceableComponents, 'get');
- spy.mockReturnValue(null);
- spectator.detectChanges();
-
- spectator.router.navigateByUrl('/withoutLayout');
- await spectator.fixture.whenStable();
- spectator.detectComponentChanges();
-
- expect(spectator.query('abp-layout-empty')).toBeFalsy();
- });
-});
+import { HttpClient } from '@angular/common/http';
+import { Component, NgModule, inject as inject_1 } from '@angular/core';
+import { ActivatedRoute, RouterModule } from '@angular/router';
+import { createRoutingFactory, SpectatorRouting } from '@ngneat/spectator/jest';
+import { DynamicLayoutComponent, RouterOutletComponent } from '../components';
+import { eLayoutType } from '../enums/common';
+import { ABP } from '../models';
+import { AbpApplicationConfigurationService } from '../proxy/volo/abp/asp-net-core/mvc/application-configurations/abp-application-configuration.service';
+import { ReplaceableComponentsService, RoutesService } from '../services';
+import { mockRoutesService } from './routes.service.spec';
+
+@Component({
+ selector: 'abp-layout-application',
+ template: ' ',
+})
+class DummyApplicationLayoutComponent {}
+
+@Component({
+ selector: 'abp-layout-account',
+ template: ' ',
+})
+class DummyAccountLayoutComponent {}
+
+@Component({
+ selector: 'abp-layout-empty',
+ template: ' ',
+})
+class DummyEmptyLayoutComponent {}
+
+const LAYOUTS = [
+ DummyApplicationLayoutComponent,
+ DummyAccountLayoutComponent,
+ DummyEmptyLayoutComponent,
+];
+
+@NgModule({
+ imports: [RouterModule],
+ declarations: [...LAYOUTS],
+})
+class DummyLayoutModule {}
+
+@Component({
+ selector: 'abp-dummy',
+ template: '{{route.snapshot.data?.name}} works!',
+})
+class DummyComponent {
route = inject_1(ActivatedRoute);
+
+}
+
+const routes: ABP.Route[] = [
+ {
+ path: '',
+ name: 'Root',
+ },
+ {
+ path: '/parentWithLayout',
+ name: 'ParentWithLayout',
+ parentName: 'Root',
+ layout: eLayoutType.application,
+ },
+ {
+ path: '/parentWithLayout/childWithoutLayout',
+ name: 'ChildWithoutLayout',
+ parentName: 'ParentWithLayout',
+ },
+ {
+ path: '/parentWithLayout/childWithLayout',
+ name: 'ChildWithLayout',
+ parentName: 'ParentWithLayout',
+ layout: eLayoutType.account,
+ },
+ {
+ path: '/withData',
+ name: 'WithData',
+ layout: eLayoutType.application,
+ },
+];
+
+describe('DynamicLayoutComponent', () => {
+ const createComponent = createRoutingFactory({
+ component: RouterOutletComponent,
+ stubsEnabled: false,
+ declarations: [DummyComponent, DynamicLayoutComponent],
+ mocks: [AbpApplicationConfigurationService, HttpClient],
+ providers: [
+ {
+ provide: RoutesService,
+ useFactory: () => mockRoutesService(),
+ },
+ ReplaceableComponentsService,
+ ],
+ imports: [RouterModule, DummyLayoutModule],
+ routes: [
+ { path: '', component: RouterOutletComponent },
+ {
+ path: 'parentWithLayout',
+ component: DynamicLayoutComponent,
+ children: [
+ {
+ path: 'childWithoutLayout',
+ component: DummyComponent,
+ data: { name: 'childWithoutLayout' },
+ },
+ {
+ path: 'childWithLayout',
+ component: DummyComponent,
+ data: { name: 'childWithLayout' },
+ },
+ ],
+ },
+ {
+ path: 'withData',
+ component: DynamicLayoutComponent,
+ children: [
+ {
+ path: '',
+ component: DummyComponent,
+ data: { name: 'withData' },
+ },
+ ],
+ data: { layout: eLayoutType.empty },
+ },
+ {
+ path: 'withoutLayout',
+ component: DynamicLayoutComponent,
+ children: [
+ {
+ path: '',
+ component: DummyComponent,
+ data: { name: 'withoutLayout' },
+ },
+ ],
+ data: { layout: null },
+ },
+ ],
+ });
+
+ let spectator: SpectatorRouting;
+ let replaceableComponents: ReplaceableComponentsService;
+
+ beforeEach(async () => {
+ spectator = createComponent();
+ replaceableComponents = spectator.inject(ReplaceableComponentsService);
+ const routesService = spectator.inject(RoutesService);
+ routesService.add(routes);
+
+ replaceableComponents.add({
+ key: 'Theme.ApplicationLayoutComponent',
+ component: DummyApplicationLayoutComponent,
+ });
+ replaceableComponents.add({
+ key: 'Theme.AccountLayoutComponent',
+ component: DummyAccountLayoutComponent,
+ });
+ replaceableComponents.add({
+ key: 'Theme.EmptyLayoutComponent',
+ component: DummyEmptyLayoutComponent,
+ });
+ });
+
+ it('should handle application layout from parent abp route and display it', async () => {
+ spectator.router.navigateByUrl('/parentWithLayout/childWithoutLayout');
+ await spectator.fixture.whenStable();
+ spectator.detectComponentChanges();
+ expect(spectator.query('abp-dynamic-layout')).toBeTruthy();
+ expect(spectator.query('abp-layout-application')).toBeTruthy();
+ });
+
+ it('should handle account layout from own property and display it', async () => {
+ spectator.router.navigateByUrl('/parentWithLayout/childWithLayout');
+ await spectator.fixture.whenStable();
+ spectator.detectComponentChanges();
+ expect(spectator.query('abp-layout-account')).toBeTruthy();
+ });
+
+ it('should handle empty layout from route data and display it', async () => {
+ spectator.router.navigateByUrl('/withData');
+ await spectator.fixture.whenStable();
+ spectator.detectComponentChanges();
+ expect(spectator.query('abp-layout-empty')).toBeTruthy();
+ });
+
+ it('should display empty layout when layout is null', async () => {
+ spectator.router.navigateByUrl('/withoutLayout');
+ await spectator.fixture.whenStable();
+ spectator.detectComponentChanges();
+ expect(spectator.query('abp-layout-empty')).toBeTruthy();
+ });
+
+ it('should not display any layout when layouts are empty', async () => {
+ const spy = jest.spyOn(replaceableComponents, 'get');
+ spy.mockReturnValue(null);
+ spectator.detectChanges();
+
+ spectator.router.navigateByUrl('/withoutLayout');
+ await spectator.fixture.whenStable();
+ spectator.detectComponentChanges();
+
+ expect(spectator.query('abp-layout-empty')).toBeFalsy();
+ });
+});
diff --git a/npm/ng-packs/packages/core/src/lib/tests/replaceable-template.directive.spec.ts b/npm/ng-packs/packages/core/src/lib/tests/replaceable-template.directive.spec.ts
index 10e59c86f6..94fdf8a527 100644
--- a/npm/ng-packs/packages/core/src/lib/tests/replaceable-template.directive.spec.ts
+++ b/npm/ng-packs/packages/core/src/lib/tests/replaceable-template.directive.spec.ts
@@ -1,178 +1,174 @@
-import { Component, EventEmitter, Inject, Input, Optional, Output } from '@angular/core';
-import { Router } from '@angular/router';
-import { createDirectiveFactory, SpectatorDirective } from '@ngneat/spectator/jest';
-import { BehaviorSubject } from 'rxjs';
-import { ReplaceableTemplateDirective } from '../directives/replaceable-template.directive';
-import { ReplaceableComponents } from '../models/replaceable-components';
-import { ReplaceableComponentsService } from '../services/replaceable-components.service';
-
-@Component({
- selector: 'abp-default-component',
- template: ' default
',
- exportAs: 'abpDefaultComponent',
-})
-class DefaultComponent {
- @Input()
- oneWay;
-
- @Input()
- twoWay: boolean;
-
- @Output()
- readonly twoWayChange = new EventEmitter();
-
- @Output()
- readonly someOutput = new EventEmitter();
-
- setTwoWay(value) {
- this.twoWay = value;
- this.twoWayChange.emit(value);
- }
-}
-
-@Component({
- selector: 'abp-external-component',
- template: ' external
',
-})
-class ExternalComponent {
- constructor(
- @Optional()
- @Inject('REPLACEABLE_DATA')
- public data: ReplaceableComponents.ReplaceableTemplateData,
- ) {}
-}
-
-describe('ReplaceableTemplateDirective', () => {
- let spectator: SpectatorDirective;
- const get$Res = new BehaviorSubject(undefined);
-
- const createDirective = createDirectiveFactory({
- directive: ReplaceableTemplateDirective,
- declarations: [DefaultComponent, ExternalComponent],
- entryComponents: [ExternalComponent],
- mocks: [Router],
- providers: [{ provide: ReplaceableComponentsService, useValue: { get$: () => get$Res } }],
- });
-
- describe('without external component', () => {
- const twoWayChange = jest.fn(a => a);
- const someOutput = jest.fn(a => a);
-
- beforeEach(() => {
- spectator = createDirective(
- `
-
- `,
- {
- hostProps: {
- oneWay: { label: 'Test' },
- twoWay: false,
- twoWayChange,
- someOutput,
- },
- },
- );
-
- const component = spectator.query(DefaultComponent);
- spectator.directive.context.initTemplate(component);
- spectator.detectChanges();
- });
-
- afterEach(() => twoWayChange.mockClear());
-
- it('should display the default template when store response is undefined', () => {
- expect(spectator.query('abp-default-component')).toBeTruthy();
- });
-
- it('should be setted inputs and outputs', () => {
- const component = spectator.query(DefaultComponent);
- expect(component.oneWay).toEqual({ label: 'Test' });
- expect(component.twoWay).toEqual(false);
- });
-
- it('should change the component inputs', () => {
- const component = spectator.query(DefaultComponent);
- spectator.setHostInput({ oneWay: 'test' });
- component.setTwoWay(true);
- component.someOutput.emit('someOutput emitted');
- expect(component.oneWay).toBe('test');
- expect(twoWayChange).toHaveBeenCalledWith(true);
- expect(someOutput).toHaveBeenCalledWith('someOutput emitted');
- });
- });
-
- describe('with external component', () => {
- const twoWayChange = jest.fn(a => a);
- const someOutput = jest.fn(a => a);
-
- beforeEach(() => {
- spectator = createDirective(
- `
-
- `,
- { hostProps: { oneWay: { label: 'Test' }, twoWay: false, twoWayChange, someOutput } },
- );
-
- get$Res.next({ component: ExternalComponent, key: 'TestModule.TestComponent' });
- });
-
- afterEach(() => twoWayChange.mockClear());
-
- it('should display the external component', () => {
- expect(spectator.query('p')).toHaveText('external');
- });
-
- it('should be injected the data object', () => {
- const externalComponent = spectator.query(ExternalComponent);
- expect(externalComponent.data).toEqual({
- componentKey: 'TestModule.TestComponent',
- inputs: { oneWay: { label: 'Test' }, twoWay: false },
- outputs: { someOutput, twoWayChange },
- });
- });
-
- it('should be worked all data properties', () => {
- const externalComponent = spectator.query(ExternalComponent);
- spectator.setHostInput({ oneWay: 'test' });
- externalComponent.data.inputs.twoWay = true;
- externalComponent.data.outputs.someOutput('someOutput emitted');
- expect(externalComponent.data.inputs.oneWay).toBe('test');
- expect(twoWayChange).toHaveBeenCalledWith(true);
- expect(someOutput).toHaveBeenCalledWith('someOutput emitted');
-
- spectator.setHostInput({ twoWay: 'twoWay test' });
- expect(externalComponent.data.inputs.twoWay).toBe('twoWay test');
- });
-
- it('should be worked correctly the default component when the external component has been removed from store', () => {
- expect(spectator.query('p')).toHaveText('external');
- const externalComponent = spectator.query(ExternalComponent);
- spectator.setHostInput({ oneWay: 'test' });
- externalComponent.data.inputs.twoWay = true;
- get$Res.next({ component: null, key: 'TestModule.TestComponent' });
- spectator.detectChanges();
- const component = spectator.query(DefaultComponent);
- spectator.directive.context.initTemplate(component);
- expect(spectator.query('abp-default-component')).toBeTruthy();
-
- expect(component.oneWay).toEqual('test');
- expect(component.twoWay).toEqual(true);
- });
-
- it('should reset default component subscriptions', () => {
- get$Res.next({ component: null, key: 'TestModule.TestComponent' });
- const component = spectator.query(DefaultComponent);
- spectator.directive.context.initTemplate(component);
- spectator.detectChanges();
- const unsubscribe = jest.fn(() => {});
- spectator.directive.defaultComponentSubscriptions.twoWayChange.unsubscribe = unsubscribe;
-
- get$Res.next({ component: ExternalComponent, key: 'TestModule.TestComponent' });
- expect(unsubscribe).toHaveBeenCalled();
- });
- });
-});
+import { Component, EventEmitter, Input, Output, inject } from '@angular/core';
+import { Router } from '@angular/router';
+import { createDirectiveFactory, SpectatorDirective } from '@ngneat/spectator/jest';
+import { BehaviorSubject } from 'rxjs';
+import { ReplaceableTemplateDirective } from '../directives/replaceable-template.directive';
+import { ReplaceableComponents } from '../models/replaceable-components';
+import { ReplaceableComponentsService } from '../services/replaceable-components.service';
+
+@Component({
+ selector: 'abp-default-component',
+ template: ' default
',
+ exportAs: 'abpDefaultComponent',
+})
+class DefaultComponent {
+ @Input()
+ oneWay;
+
+ @Input()
+ twoWay: boolean;
+
+ @Output()
+ readonly twoWayChange = new EventEmitter();
+
+ @Output()
+ readonly someOutput = new EventEmitter();
+
+ setTwoWay(value) {
+ this.twoWay = value;
+ this.twoWayChange.emit(value);
+ }
+}
+
+@Component({
+ selector: 'abp-external-component',
+ template: ' external
',
+})
+class ExternalComponent {
data = inject>('REPLACEABLE_DATA' as any, { optional: true })!;
+
+}
+
+describe('ReplaceableTemplateDirective', () => {
+ let spectator: SpectatorDirective;
+ const get$Res = new BehaviorSubject(undefined);
+
+ const createDirective = createDirectiveFactory({
+ directive: ReplaceableTemplateDirective,
+ declarations: [DefaultComponent, ExternalComponent],
+ entryComponents: [ExternalComponent],
+ mocks: [Router],
+ providers: [{ provide: ReplaceableComponentsService, useValue: { get$: () => get$Res } }],
+ });
+
+ describe('without external component', () => {
+ const twoWayChange = jest.fn(a => a);
+ const someOutput = jest.fn(a => a);
+
+ beforeEach(() => {
+ spectator = createDirective(
+ `
+
+ `,
+ {
+ hostProps: {
+ oneWay: { label: 'Test' },
+ twoWay: false,
+ twoWayChange,
+ someOutput,
+ },
+ },
+ );
+
+ const component = spectator.query(DefaultComponent);
+ spectator.directive.context.initTemplate(component);
+ spectator.detectChanges();
+ });
+
+ afterEach(() => twoWayChange.mockClear());
+
+ it('should display the default template when store response is undefined', () => {
+ expect(spectator.query('abp-default-component')).toBeTruthy();
+ });
+
+ it('should be setted inputs and outputs', () => {
+ const component = spectator.query(DefaultComponent);
+ expect(component.oneWay).toEqual({ label: 'Test' });
+ expect(component.twoWay).toEqual(false);
+ });
+
+ it('should change the component inputs', () => {
+ const component = spectator.query(DefaultComponent);
+ spectator.setHostInput({ oneWay: 'test' });
+ component.setTwoWay(true);
+ component.someOutput.emit('someOutput emitted');
+ expect(component.oneWay).toBe('test');
+ expect(twoWayChange).toHaveBeenCalledWith(true);
+ expect(someOutput).toHaveBeenCalledWith('someOutput emitted');
+ });
+ });
+
+ describe('with external component', () => {
+ const twoWayChange = jest.fn(a => a);
+ const someOutput = jest.fn(a => a);
+
+ beforeEach(() => {
+ spectator = createDirective(
+ `
+
+ `,
+ { hostProps: { oneWay: { label: 'Test' }, twoWay: false, twoWayChange, someOutput } },
+ );
+
+ get$Res.next({ component: ExternalComponent, key: 'TestModule.TestComponent' });
+ });
+
+ afterEach(() => twoWayChange.mockClear());
+
+ it('should display the external component', () => {
+ expect(spectator.query('p')).toHaveText('external');
+ });
+
+ it('should be injected the data object', () => {
+ const externalComponent = spectator.query(ExternalComponent);
+ expect(externalComponent.data).toEqual({
+ componentKey: 'TestModule.TestComponent',
+ inputs: { oneWay: { label: 'Test' }, twoWay: false },
+ outputs: { someOutput, twoWayChange },
+ });
+ });
+
+ it('should be worked all data properties', () => {
+ const externalComponent = spectator.query(ExternalComponent);
+ spectator.setHostInput({ oneWay: 'test' });
+ externalComponent.data.inputs.twoWay = true;
+ externalComponent.data.outputs.someOutput('someOutput emitted');
+ expect(externalComponent.data.inputs.oneWay).toBe('test');
+ expect(twoWayChange).toHaveBeenCalledWith(true);
+ expect(someOutput).toHaveBeenCalledWith('someOutput emitted');
+
+ spectator.setHostInput({ twoWay: 'twoWay test' });
+ expect(externalComponent.data.inputs.twoWay).toBe('twoWay test');
+ });
+
+ it('should be worked correctly the default component when the external component has been removed from store', () => {
+ expect(spectator.query('p')).toHaveText('external');
+ const externalComponent = spectator.query(ExternalComponent);
+ spectator.setHostInput({ oneWay: 'test' });
+ externalComponent.data.inputs.twoWay = true;
+ get$Res.next({ component: null, key: 'TestModule.TestComponent' });
+ spectator.detectChanges();
+ const component = spectator.query(DefaultComponent);
+ spectator.directive.context.initTemplate(component);
+ expect(spectator.query('abp-default-component')).toBeTruthy();
+
+ expect(component.oneWay).toEqual('test');
+ expect(component.twoWay).toEqual(true);
+ });
+
+ it('should reset default component subscriptions', () => {
+ get$Res.next({ component: null, key: 'TestModule.TestComponent' });
+ const component = spectator.query(DefaultComponent);
+ spectator.directive.context.initTemplate(component);
+ spectator.detectChanges();
+ const unsubscribe = jest.fn(() => {});
+ spectator.directive.defaultComponentSubscriptions.twoWayChange.unsubscribe = unsubscribe;
+
+ get$Res.next({ component: ExternalComponent, key: 'TestModule.TestComponent' });
+ expect(unsubscribe).toHaveBeenCalled();
+ });
+ });
+});
diff --git a/npm/ng-packs/packages/core/testing/src/lib/services/mock-permission.service.ts b/npm/ng-packs/packages/core/testing/src/lib/services/mock-permission.service.ts
index b4d180b17a..e7f03cdf48 100644
--- a/npm/ng-packs/packages/core/testing/src/lib/services/mock-permission.service.ts
+++ b/npm/ng-packs/packages/core/testing/src/lib/services/mock-permission.service.ts
@@ -1,12 +1,17 @@
import { ConfigStateService, PermissionService } from '@abp/ng.core';
-import { Injectable } from '@angular/core';
+import { Injectable, inject } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class MockPermissionService extends PermissionService {
- constructor(protected configState: ConfigStateService) {
- super(configState);
+ protected configState: ConfigStateService;
+
+ constructor() {
+ const configState = inject(ConfigStateService);
+ super();
+ this.configState = configState;
+
this.grantAllPolicies();
}
diff --git a/npm/ng-packs/packages/core/testing/src/lib/services/mock-rest.service.ts b/npm/ng-packs/packages/core/testing/src/lib/services/mock-rest.service.ts
index 7fd171c1d4..57d326ac4f 100644
--- a/npm/ng-packs/packages/core/testing/src/lib/services/mock-rest.service.ts
+++ b/npm/ng-packs/packages/core/testing/src/lib/services/mock-rest.service.ts
@@ -3,24 +3,33 @@ import {
CORE_OPTIONS,
EnvironmentService,
ExternalHttpClient,
- HttpErrorReporterService,
RestService,
} from '@abp/ng.core';
import { HttpClient } from '@angular/common/http';
-import { Inject, Injectable } from '@angular/core';
+import { Injectable, inject } from '@angular/core';
import { Observable, throwError } from 'rxjs';
@Injectable({
providedIn: 'root',
})
export class MockRestService extends RestService {
- constructor(
- @Inject(CORE_OPTIONS) protected options: ABP.Root,
- protected http: HttpClient,
- protected externalhttp: ExternalHttpClient,
- protected environment: EnvironmentService,
- ) {
- super(options, http,externalhttp, environment, null as unknown as HttpErrorReporterService);
+ protected options: ABP.Root;
+ protected http: HttpClient;
+ protected externalhttp: ExternalHttpClient;
+ protected environment: EnvironmentService;
+
+ constructor() {
+ const options = inject(CORE_OPTIONS);
+ const http = inject(HttpClient);
+ const externalhttp = inject(ExternalHttpClient);
+ const environment = inject(EnvironmentService);
+
+ super();
+
+ this.options = options;
+ this.http = http;
+ this.externalhttp = externalhttp;
+ this.environment = environment;
}
handleError(err: any): Observable {
diff --git a/npm/ng-packs/packages/feature-management/proxy/src/lib/proxy/feature-management/features.service.ts b/npm/ng-packs/packages/feature-management/proxy/src/lib/proxy/feature-management/features.service.ts
index 189076428d..67616fd4d1 100644
--- a/npm/ng-packs/packages/feature-management/proxy/src/lib/proxy/feature-management/features.service.ts
+++ b/npm/ng-packs/packages/feature-management/proxy/src/lib/proxy/feature-management/features.service.ts
@@ -1,11 +1,13 @@
import type { GetFeatureListResultDto, UpdateFeaturesDto } from './models';
import { RestService } from '@abp/ng.core';
-import { Injectable } from '@angular/core';
+import { Injectable, inject } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class FeaturesService {
+ private restService = inject(RestService);
+
apiName = 'AbpFeatureManagement';
delete = (providerName: string, providerKey: string) =>
@@ -38,6 +40,4 @@ export class FeaturesService {
},
{ apiName: this.apiName },
);
-
- constructor(private restService: RestService) {}
}
diff --git a/npm/ng-packs/packages/identity/proxy/src/lib/proxy/identity/identity-role.service.ts b/npm/ng-packs/packages/identity/proxy/src/lib/proxy/identity/identity-role.service.ts
index 6e296c171b..c1aabf7091 100644
--- a/npm/ng-packs/packages/identity/proxy/src/lib/proxy/identity/identity-role.service.ts
+++ b/npm/ng-packs/packages/identity/proxy/src/lib/proxy/identity/identity-role.service.ts
@@ -1,12 +1,14 @@
import type { GetIdentityRolesInput, IdentityRoleCreateDto, IdentityRoleDto, IdentityRoleUpdateDto } from './models';
import { RestService } from '@abp/ng.core';
import type { ListResultDto, PagedResultDto } from '@abp/ng.core';
-import { Injectable } from '@angular/core';
+import { Injectable, inject } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class IdentityRoleService {
+ private restService = inject(RestService);
+
apiName = 'AbpIdentity';
create = (input: IdentityRoleCreateDto) =>
@@ -53,6 +55,4 @@ export class IdentityRoleService {
body: input,
},
{ apiName: this.apiName });
-
- constructor(private restService: RestService) {}
}
diff --git a/npm/ng-packs/packages/identity/proxy/src/lib/proxy/identity/identity-user-lookup.service.ts b/npm/ng-packs/packages/identity/proxy/src/lib/proxy/identity/identity-user-lookup.service.ts
index af4583aa28..cf8d01e81f 100644
--- a/npm/ng-packs/packages/identity/proxy/src/lib/proxy/identity/identity-user-lookup.service.ts
+++ b/npm/ng-packs/packages/identity/proxy/src/lib/proxy/identity/identity-user-lookup.service.ts
@@ -1,13 +1,15 @@
import type { UserLookupCountInputDto, UserLookupSearchInputDto } from './models';
import { RestService } from '@abp/ng.core';
import type { ListResultDto } from '@abp/ng.core';
-import { Injectable } from '@angular/core';
+import { Injectable, inject } from '@angular/core';
import type { UserData } from '../users/models';
@Injectable({
providedIn: 'root',
})
export class IdentityUserLookupService {
+ private restService = inject(RestService);
+
apiName = 'AbpIdentity';
findById = (id: string) =>
@@ -39,6 +41,4 @@ export class IdentityUserLookupService {
params: { filter: input.filter, sorting: input.sorting, skipCount: input.skipCount, maxResultCount: input.maxResultCount },
},
{ apiName: this.apiName });
-
- constructor(private restService: RestService) {}
}
diff --git a/npm/ng-packs/packages/identity/proxy/src/lib/proxy/identity/identity-user.service.ts b/npm/ng-packs/packages/identity/proxy/src/lib/proxy/identity/identity-user.service.ts
index c3b6f203f2..a538a07feb 100644
--- a/npm/ng-packs/packages/identity/proxy/src/lib/proxy/identity/identity-user.service.ts
+++ b/npm/ng-packs/packages/identity/proxy/src/lib/proxy/identity/identity-user.service.ts
@@ -1,12 +1,14 @@
import type { GetIdentityUsersInput, IdentityRoleDto, IdentityUserCreateDto, IdentityUserDto, IdentityUserUpdateDto, IdentityUserUpdateRolesDto } from './models';
import { RestService } from '@abp/ng.core';
import type { ListResultDto, PagedResultDto } from '@abp/ng.core';
-import { Injectable } from '@angular/core';
+import { Injectable, inject } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class IdentityUserService {
+ private restService = inject(RestService);
+
apiName = 'AbpIdentity';
create = (input: IdentityUserCreateDto) =>
@@ -84,6 +86,4 @@ export class IdentityUserService {
body: input,
},
{ apiName: this.apiName });
-
- constructor(private restService: RestService) {}
}
diff --git a/npm/ng-packs/packages/oauth/src/lib/handlers/oauth-configuration.handler.ts b/npm/ng-packs/packages/oauth/src/lib/handlers/oauth-configuration.handler.ts
index a2a9228b78..42ddb89c90 100644
--- a/npm/ng-packs/packages/oauth/src/lib/handlers/oauth-configuration.handler.ts
+++ b/npm/ng-packs/packages/oauth/src/lib/handlers/oauth-configuration.handler.ts
@@ -1,4 +1,4 @@
-import { Inject, Injectable } from '@angular/core';
+import { Injectable, inject } from '@angular/core';
import { AuthConfig, OAuthService } from "angular-oauth2-oidc";
import compare from 'just-compare';
import { filter, map } from 'rxjs/operators';
@@ -8,11 +8,11 @@ import { ABP, EnvironmentService, CORE_OPTIONS } from '@abp/ng.core';
providedIn: 'root',
})
export class OAuthConfigurationHandler {
- constructor(
- private oAuthService: OAuthService,
- private environmentService: EnvironmentService,
- @Inject(CORE_OPTIONS) private options: ABP.Root,
- ) {
+ private oAuthService = inject(OAuthService);
+ private environmentService = inject(EnvironmentService);
+ private options = inject(CORE_OPTIONS);
+
+ constructor() {
this.listenToSetEnvironment();
}
diff --git a/npm/ng-packs/packages/oauth/src/lib/interceptors/api.interceptor.ts b/npm/ng-packs/packages/oauth/src/lib/interceptors/api.interceptor.ts
index e7ee208c47..e6921d5961 100644
--- a/npm/ng-packs/packages/oauth/src/lib/interceptors/api.interceptor.ts
+++ b/npm/ng-packs/packages/oauth/src/lib/interceptors/api.interceptor.ts
@@ -1,5 +1,5 @@
import { HttpHandler, HttpHeaders, HttpRequest } from '@angular/common/http';
-import { Inject, Injectable } from '@angular/core';
+import { Injectable, inject } from '@angular/core';
import { OAuthService } from 'angular-oauth2-oidc';
import { finalize } from 'rxjs/operators';
import {
@@ -14,12 +14,11 @@ import {
providedIn: 'root',
})
export class OAuthApiInterceptor implements IApiInterceptor {
- constructor(
- private oAuthService: OAuthService,
- private sessionState: SessionStateService,
- private httpWaitService: HttpWaitService,
- @Inject(TENANT_KEY) private tenantKey: string,
- ) {}
+ private oAuthService = inject(OAuthService);
+ private sessionState = inject(SessionStateService);
+ private httpWaitService = inject(HttpWaitService);
+ private tenantKey = inject(TENANT_KEY);
+
intercept(request: HttpRequest, next: HttpHandler) {
this.httpWaitService.addRequest(request);
diff --git a/npm/ng-packs/packages/oauth/src/lib/services/oauth.service.ts b/npm/ng-packs/packages/oauth/src/lib/services/oauth.service.ts
index a490f92dd2..51c97a8101 100644
--- a/npm/ng-packs/packages/oauth/src/lib/services/oauth.service.ts
+++ b/npm/ng-packs/packages/oauth/src/lib/services/oauth.service.ts
@@ -1,4 +1,4 @@
-import { Injectable, Injector } from '@angular/core';
+import { Injectable, Injector, inject } from '@angular/core';
import { Params } from '@angular/router';
import { from, Observable, lastValueFrom, EMPTY } from 'rxjs';
import { filter, map, switchMap, take, tap } from 'rxjs/operators';
@@ -13,6 +13,8 @@ import { HttpHeaders } from '@angular/common/http';
providedIn: 'root',
})
export class AbpOAuthService implements IAuthService {
+ protected injector = inject(Injector);
+
private strategy!: AuthFlowStrategy;
private readonly oAuthService: OAuthService;
@@ -28,7 +30,7 @@ export class AbpOAuthService implements IAuthService {
return this.strategy.isInternalAuth;
}
- constructor(protected injector: Injector) {
+ constructor() {
this.oAuthService = this.injector.get(OAuthService);
}
diff --git a/npm/ng-packs/packages/permission-management/proxy/src/lib/proxy/permissions.service.ts b/npm/ng-packs/packages/permission-management/proxy/src/lib/proxy/permissions.service.ts
index 45ac0b40e1..dbd13ca778 100644
--- a/npm/ng-packs/packages/permission-management/proxy/src/lib/proxy/permissions.service.ts
+++ b/npm/ng-packs/packages/permission-management/proxy/src/lib/proxy/permissions.service.ts
@@ -1,11 +1,13 @@
import type { GetPermissionListResultDto, UpdatePermissionsDto } from './models';
import { RestService } from '@abp/ng.core';
-import { Injectable } from '@angular/core';
+import { Injectable, inject } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class PermissionsService {
+ private restService = inject(RestService);
+
apiName = 'AbpPermissionManagement';
get = (providerName: string, providerKey: string) =>
@@ -24,6 +26,4 @@ export class PermissionsService {
body: input,
},
{ apiName: this.apiName });
-
- constructor(private restService: RestService) {}
}
diff --git a/npm/ng-packs/packages/schematics/src/commands/api/files-service/proxy/__namespace@dir__/__name@kebab__.service.ts.template b/npm/ng-packs/packages/schematics/src/commands/api/files-service/proxy/__namespace@dir__/__name@kebab__.service.ts.template
index aae3b43471..8b0c343173 100644
--- a/npm/ng-packs/packages/schematics/src/commands/api/files-service/proxy/__namespace@dir__/__name@kebab__.service.ts.template
+++ b/npm/ng-packs/packages/schematics/src/commands/api/files-service/proxy/__namespace@dir__/__name@kebab__.service.ts.template
@@ -5,6 +5,7 @@
providedIn: 'root',
})
export class <%= name %>Service {
+ private restService = inject(RestService);
apiName = '<%= apiName %>';<%
for (let {body, signature} of methods) { %>
<%
@@ -26,6 +27,4 @@ export class <%= name %>Service {
body: <%= body.body %>,<% } %>
},
{ apiName: this.apiName,...config });<% } %>
-
- constructor(private restService: RestService) {}
-}
+}
\ No newline at end of file
diff --git a/npm/ng-packs/packages/schematics/src/utils/service.ts b/npm/ng-packs/packages/schematics/src/utils/service.ts
index 8f48ed3693..1280aa3aef 100644
--- a/npm/ng-packs/packages/schematics/src/utils/service.ts
+++ b/npm/ng-packs/packages/schematics/src/utils/service.ts
@@ -46,7 +46,7 @@ export function createControllerToServiceMapper({
[],
);
imports.push(new Import({ path: '@abp/ng.core', specifiers: ['RestService', 'Rest'] }));
- imports.push(new Import({ path: '@angular/core', specifiers: ['Injectable'] }));
+ imports.push(new Import({ path: '@angular/core', specifiers: ['Injectable', 'inject'] }));
sortImports(imports);
const methods = actions.map(mapActionToMethod);
sortMethods(methods);
diff --git a/npm/ng-packs/packages/setting-management/config/src/lib/components/email-setting-group/email-setting-group.component.ts b/npm/ng-packs/packages/setting-management/config/src/lib/components/email-setting-group/email-setting-group.component.ts
index 1027ed0103..ec6ab1d5b7 100644
--- a/npm/ng-packs/packages/setting-management/config/src/lib/components/email-setting-group/email-setting-group.component.ts
+++ b/npm/ng-packs/packages/setting-management/config/src/lib/components/email-setting-group/email-setting-group.component.ts
@@ -46,6 +46,10 @@ const { required, email } = Validators;
],
})
export class EmailSettingGroupComponent implements OnInit {
+ private emailSettingsService = inject(EmailSettingsService);
+ private fb = inject(UntypedFormBuilder);
+ private toasterService = inject(ToasterService);
+
protected readonly localizationService = inject(LocalizationService);
protected readonly configStateSevice = inject(ConfigStateService);
protected readonly ssrService = inject(SSRService);
@@ -62,9 +66,6 @@ export class EmailSettingGroupComponent implements OnInit {
EMAIL_SETTINGS_KEY = makeStateKey('emailSettings');
constructor(
- private emailSettingsService: EmailSettingsService,
- private fb: UntypedFormBuilder,
- private toasterService: ToasterService,
private transferState: TransferState,
) {}
diff --git a/npm/ng-packs/packages/setting-management/config/src/lib/proxy/email-settings.service.ts b/npm/ng-packs/packages/setting-management/config/src/lib/proxy/email-settings.service.ts
index 0252b18c12..a1835e1a38 100644
--- a/npm/ng-packs/packages/setting-management/config/src/lib/proxy/email-settings.service.ts
+++ b/npm/ng-packs/packages/setting-management/config/src/lib/proxy/email-settings.service.ts
@@ -1,6 +1,6 @@
import type { EmailSettingsDto, SendTestEmailInput, UpdateEmailSettingsDto } from './models';
import { RestService } from '@abp/ng.core';
-import { Injectable } from '@angular/core';
+import { Injectable, inject } from '@angular/core';
/**
@deprecated This method is deprecated, use it from @abp/ng.setting-management/proxy
@@ -9,6 +9,8 @@ import { Injectable } from '@angular/core';
providedIn: 'root',
})
export class EmailSettingsService {
+ private restService = inject(RestService);
+
apiName = 'SettingManagement';
get = () =>
@@ -33,6 +35,4 @@ export class EmailSettingsService {
body: input,
},
{ apiName: this.apiName });
-
- constructor(private restService: RestService) {}
}
diff --git a/npm/ng-packs/packages/setting-management/proxy/src/lib/proxy/email-settings.service.ts b/npm/ng-packs/packages/setting-management/proxy/src/lib/proxy/email-settings.service.ts
index a05cfc27a7..af6a2f5843 100644
--- a/npm/ng-packs/packages/setting-management/proxy/src/lib/proxy/email-settings.service.ts
+++ b/npm/ng-packs/packages/setting-management/proxy/src/lib/proxy/email-settings.service.ts
@@ -1,11 +1,13 @@
import type { EmailSettingsDto, SendTestEmailInput, UpdateEmailSettingsDto } from './models';
import { RestService, Rest } from '@abp/ng.core';
-import { Injectable } from '@angular/core';
+import { Injectable, inject } from '@angular/core';
@Injectable({
providedIn: 'root',
})
-export class EmailSettingsService {
+export class EmailSettingsService {
+ private restService = inject(RestService);
+
apiName = 'SettingManagement';
@@ -33,6 +35,4 @@ export class EmailSettingsService {
body: input,
},
{ apiName: this.apiName,...config });
-
- constructor(private restService: RestService) {}
}
diff --git a/npm/ng-packs/packages/setting-management/proxy/src/lib/proxy/time-zone-settings.service.ts b/npm/ng-packs/packages/setting-management/proxy/src/lib/proxy/time-zone-settings.service.ts
index 7141bce27d..1a20916673 100644
--- a/npm/ng-packs/packages/setting-management/proxy/src/lib/proxy/time-zone-settings.service.ts
+++ b/npm/ng-packs/packages/setting-management/proxy/src/lib/proxy/time-zone-settings.service.ts
@@ -1,11 +1,13 @@
import type { NameValue } from './volo/abp/models';
import { RestService, Rest } from '@abp/ng.core';
-import { Injectable } from '@angular/core';
+import { Injectable, inject } from '@angular/core';
@Injectable({
providedIn: 'root',
})
-export class TimeZoneSettingsService {
+export class TimeZoneSettingsService {
+ private restService = inject(RestService);
+
apiName = 'SettingManagement';
@@ -33,6 +35,4 @@ export class TimeZoneSettingsService {
params: { timezone },
},
{ apiName: this.apiName,...config });
-
- constructor(private restService: RestService) {}
}
diff --git a/npm/ng-packs/packages/tenant-management/proxy/src/lib/proxy/tenant.service.ts b/npm/ng-packs/packages/tenant-management/proxy/src/lib/proxy/tenant.service.ts
index 61d1667be4..28174f8ad8 100644
--- a/npm/ng-packs/packages/tenant-management/proxy/src/lib/proxy/tenant.service.ts
+++ b/npm/ng-packs/packages/tenant-management/proxy/src/lib/proxy/tenant.service.ts
@@ -1,12 +1,14 @@
import type { GetTenantsInput, TenantCreateDto, TenantDto, TenantUpdateDto } from './models';
import { RestService } from '@abp/ng.core';
import type { PagedResultDto } from '@abp/ng.core';
-import { Injectable } from '@angular/core';
+import { Injectable, inject } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class TenantService {
+ private restService = inject(RestService);
+
apiName = 'AbpTenantManagement';
create = (input: TenantCreateDto) =>
@@ -69,6 +71,4 @@ export class TenantService {
params: { defaultConnectionString },
},
{ apiName: this.apiName });
-
- constructor(private restService: RestService) {}
}
diff --git a/npm/ng-packs/packages/theme-basic/src/lib/components/account-layout/account-layout.component.ts b/npm/ng-packs/packages/theme-basic/src/lib/components/account-layout/account-layout.component.ts
index e5b68e8901..96c3be352c 100644
--- a/npm/ng-packs/packages/theme-basic/src/lib/components/account-layout/account-layout.component.ts
+++ b/npm/ng-packs/packages/theme-basic/src/lib/components/account-layout/account-layout.component.ts
@@ -1,4 +1,4 @@
-import { AfterViewInit, Component } from '@angular/core';
+import { AfterViewInit, Component, inject } from '@angular/core';
import { eLayoutType, ReplaceableTemplateDirective, SubscriptionService } from '@abp/ng.core';
import { LayoutService } from '../../services/layout.service';
import { CommonModule } from '@angular/common';
@@ -8,10 +8,12 @@ import { NavItemsComponent } from '../nav-items/nav-items.component';
import { AuthWrapperComponent } from './auth-wrapper/auth-wrapper.component';
import { PageAlertContainerComponent } from '../page-alert-container/page-alert-container.component';
import { RouterModule } from '@angular/router';
+import { collapseWithMargin } from '@abp/ng.theme.shared';
@Component({
selector: 'abp-layout-account',
templateUrl: './account-layout.component.html',
+ animations: [collapseWithMargin],
providers: [LayoutService, SubscriptionService],
imports: [
CommonModule,
@@ -25,13 +27,13 @@ import { RouterModule } from '@angular/router';
],
})
export class AccountLayoutComponent implements AfterViewInit {
+ service = inject(LayoutService);
+
// required for dynamic component
static type = eLayoutType.account;
authWrapperKey = 'Account.AuthWrapperComponent';
- constructor(public service: LayoutService) {}
-
ngAfterViewInit() {
this.service.subscribeWindowSize();
}
diff --git a/npm/ng-packs/packages/theme-basic/src/lib/components/account-layout/auth-wrapper/auth-wrapper.component.ts b/npm/ng-packs/packages/theme-basic/src/lib/components/account-layout/auth-wrapper/auth-wrapper.component.ts
index 5094551ed2..3c2db0a33b 100644
--- a/npm/ng-packs/packages/theme-basic/src/lib/components/account-layout/auth-wrapper/auth-wrapper.component.ts
+++ b/npm/ng-packs/packages/theme-basic/src/lib/components/account-layout/auth-wrapper/auth-wrapper.component.ts
@@ -1,15 +1,15 @@
-import { AuthWrapperService } from '@abp/ng.account.core';
-import { Component } from '@angular/core';
-import { CommonModule } from '@angular/common';
-import { LocalizationPipe, ReplaceableTemplateDirective } from '@abp/ng.core';
-import { TenantBoxComponent } from '../tenant-box/tenant-box.component';
+import { AuthWrapperService } from '@abp/ng.account.core';
+import { Component, inject } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { LocalizationPipe, ReplaceableTemplateDirective } from '@abp/ng.core';
+import { TenantBoxComponent } from '../tenant-box/tenant-box.component';
+
+@Component({
+ selector: 'abp-auth-wrapper',
+ templateUrl: './auth-wrapper.component.html',
+ providers: [AuthWrapperService],
+ imports: [CommonModule, TenantBoxComponent, ReplaceableTemplateDirective, LocalizationPipe],
+})
+export class AuthWrapperComponent {
service = inject(AuthWrapperService);
-@Component({
- selector: 'abp-auth-wrapper',
- templateUrl: './auth-wrapper.component.html',
- providers: [AuthWrapperService],
- imports: [CommonModule, TenantBoxComponent, ReplaceableTemplateDirective, LocalizationPipe],
-})
-export class AuthWrapperComponent {
- constructor(public service: AuthWrapperService) {}
-}
+}
diff --git a/npm/ng-packs/packages/theme-basic/src/lib/components/account-layout/tenant-box/tenant-box.component.ts b/npm/ng-packs/packages/theme-basic/src/lib/components/account-layout/tenant-box/tenant-box.component.ts
index 4aadd1effb..af4807d2bb 100644
--- a/npm/ng-packs/packages/theme-basic/src/lib/components/account-layout/tenant-box/tenant-box.component.ts
+++ b/npm/ng-packs/packages/theme-basic/src/lib/components/account-layout/tenant-box/tenant-box.component.ts
@@ -1,23 +1,23 @@
-import { TenantBoxService } from '@abp/ng.account.core';
-import { Component } from '@angular/core';
-import { CommonModule } from '@angular/common';
-import { LocalizationPipe } from '@abp/ng.core';
-import { ButtonComponent, ModalCloseDirective, ModalComponent } from '@abp/ng.theme.shared';
-import { FormsModule } from '@angular/forms';
+import { TenantBoxService } from '@abp/ng.account.core';
+import { Component, inject } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { LocalizationPipe } from '@abp/ng.core';
+import { ButtonComponent, ModalCloseDirective, ModalComponent } from '@abp/ng.theme.shared';
+import { FormsModule } from '@angular/forms';
+
+@Component({
+ selector: 'abp-tenant-box',
+ templateUrl: './tenant-box.component.html',
+ providers: [TenantBoxService],
+ imports: [
+ CommonModule,
+ FormsModule,
+ ModalComponent,
+ LocalizationPipe,
+ ButtonComponent,
+ ModalCloseDirective,
+ ],
+})
+export class TenantBoxComponent {
service = inject(TenantBoxService);
-@Component({
- selector: 'abp-tenant-box',
- templateUrl: './tenant-box.component.html',
- providers: [TenantBoxService],
- imports: [
- CommonModule,
- FormsModule,
- ModalComponent,
- LocalizationPipe,
- ButtonComponent,
- ModalCloseDirective,
- ],
-})
-export class TenantBoxComponent {
- constructor(public service: TenantBoxService) {}
-}
+}
diff --git a/npm/ng-packs/packages/theme-basic/src/lib/components/logo/logo.component.ts b/npm/ng-packs/packages/theme-basic/src/lib/components/logo/logo.component.ts
index fcaeacdf1a..b3047d72ed 100644
--- a/npm/ng-packs/packages/theme-basic/src/lib/components/logo/logo.component.ts
+++ b/npm/ng-packs/packages/theme-basic/src/lib/components/logo/logo.component.ts
@@ -1,5 +1,5 @@
import { ApplicationInfo, EnvironmentService } from '@abp/ng.core';
-import { Component } from '@angular/core';
+import { Component, inject } from '@angular/core';
import { CommonModule } from '@angular/common';
@Component({
@@ -16,9 +16,9 @@ import { CommonModule } from '@angular/common';
imports: [CommonModule],
})
export class LogoComponent {
+ private environment = inject(EnvironmentService);
+
get appInfo(): ApplicationInfo {
return this.environment.getEnvironment().application;
}
-
- constructor(private environment: EnvironmentService) {}
}
diff --git a/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/current-user.component.ts b/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/current-user.component.ts
index e1db041b91..094c9dd594 100644
--- a/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/current-user.component.ts
+++ b/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/current-user.component.ts
@@ -10,7 +10,7 @@ import {
ToInjectorPipe,
} from '@abp/ng.core';
import { AbpVisibleDirective, UserMenu, UserMenuService } from '@abp/ng.theme.shared';
-import { Component, inject, Inject, TrackByFunction } from '@angular/core';
+import { Component, TrackByFunction, inject } from '@angular/core';
import { Observable } from 'rxjs';
import { CommonModule } from '@angular/common';
import { NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap';
@@ -28,6 +28,12 @@ import { NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap';
],
})
export class CurrentUserComponent {
+ readonly navigateToManageProfile = inject(NAVIGATE_TO_MANAGE_PROFILE);
+ readonly userMenu = inject(UserMenuService);
+ private authService = inject(AuthService);
+ private configState = inject(ConfigStateService);
+ private sessionState = inject(SessionStateService);
+
currentUser$: Observable = this.configState.getOne$('currentUser');
selectedTenant$ = this.sessionState.getTenant$();
trackByFn: TrackByFunction = (_, element) => element.id;
@@ -41,14 +47,6 @@ export class CurrentUserComponent {
}
}
- constructor(
- @Inject(NAVIGATE_TO_MANAGE_PROFILE) public readonly navigateToManageProfile: () => void,
- public readonly userMenu: UserMenuService,
- private authService: AuthService,
- private configState: ConfigStateService,
- private sessionState: SessionStateService,
- ) {}
-
navigateToLogin() {
this.authService.navigateToLogin();
}
diff --git a/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/languages.component.ts b/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/languages.component.ts
index cbabe382d0..16ffad47db 100644
--- a/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/languages.component.ts
+++ b/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/languages.component.ts
@@ -1,8 +1,8 @@
+import { ConfigStateService, LanguageInfo, SessionStateService } from '@abp/ng.core';
import { Component, inject } from '@angular/core';
import { CommonModule, DOCUMENT } from '@angular/common';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
-import { ConfigStateService, LanguageInfo, SessionStateService } from '@abp/ng.core';
import { NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap';
@Component({
@@ -42,7 +42,10 @@ import { NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap';
imports: [CommonModule, NgbDropdownModule],
})
export class LanguagesComponent {
+ private sessionState = inject(SessionStateService);
+ private configState = inject(ConfigStateService);
document = inject(DOCUMENT);
+
get smallScreen(): boolean {
return this.document.defaultView.innerWidth < 992;
}
@@ -70,11 +73,6 @@ export class LanguagesComponent {
return this.sessionState.getLanguage();
}
- constructor(
- private sessionState: SessionStateService,
- private configState: ConfigStateService,
- ) {}
-
onChangeLang(cultureName: string) {
this.sessionState.setLanguage(cultureName);
}
diff --git a/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/nav-items.component.ts b/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/nav-items.component.ts
index 369cf932f0..8e4bf45f1c 100644
--- a/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/nav-items.component.ts
+++ b/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/nav-items.component.ts
@@ -1,5 +1,5 @@
import { AbpVisibleDirective, NavItem, NavItemsService } from '@abp/ng.theme.shared';
-import { Component, inject, TrackByFunction } from '@angular/core';
+import { Component, TrackByFunction, inject } from '@angular/core';
import { CommonModule } from '@angular/common';
import { PermissionDirective, SSRService, ToInjectorPipe } from '@abp/ng.core';
@@ -10,7 +10,7 @@ import { PermissionDirective, SSRService, ToInjectorPipe } from '@abp/ng.core';
})
export class NavItemsComponent {
protected readonly ssrService = inject(SSRService);
- trackByFn: TrackByFunction = (_, element) => element.id;
+ readonly navItems = inject(NavItemsService);
- constructor(public readonly navItems: NavItemsService) {}
+ trackByFn: TrackByFunction = (_, element) => element.id;
}
diff --git a/npm/ng-packs/packages/theme-basic/src/lib/components/page-alert-container/page-alert-container.component.ts b/npm/ng-packs/packages/theme-basic/src/lib/components/page-alert-container/page-alert-container.component.ts
index b28cd6c81b..9347850b53 100644
--- a/npm/ng-packs/packages/theme-basic/src/lib/components/page-alert-container/page-alert-container.component.ts
+++ b/npm/ng-packs/packages/theme-basic/src/lib/components/page-alert-container/page-alert-container.component.ts
@@ -1,14 +1,14 @@
-import { Component, ViewEncapsulation } from '@angular/core';
-import { PageAlertService } from '@abp/ng.theme.shared';
-import { CommonModule } from '@angular/common';
-import { LocalizationPipe, SafeHtmlPipe } from '@abp/ng.core';
+import { Component, ViewEncapsulation, inject } from '@angular/core';
+import { PageAlertService } from '@abp/ng.theme.shared';
+import { CommonModule } from '@angular/common';
+import { LocalizationPipe, SafeHtmlPipe } from '@abp/ng.core';
+
+@Component({
+ selector: 'abp-page-alert-container',
+ templateUrl: './page-alert-container.component.html',
+ encapsulation: ViewEncapsulation.None,
+ imports: [CommonModule, LocalizationPipe, SafeHtmlPipe],
+})
+export class PageAlertContainerComponent {
service = inject(PageAlertService);
-@Component({
- selector: 'abp-page-alert-container',
- templateUrl: './page-alert-container.component.html',
- encapsulation: ViewEncapsulation.None,
- imports: [CommonModule, LocalizationPipe, SafeHtmlPipe],
-})
-export class PageAlertContainerComponent {
- constructor(public service: PageAlertService) {}
-}
+}
diff --git a/npm/ng-packs/packages/theme-basic/src/lib/handlers/lazy-style.handler.ts b/npm/ng-packs/packages/theme-basic/src/lib/handlers/lazy-style.handler.ts
index d302b87f58..5a74500560 100644
--- a/npm/ng-packs/packages/theme-basic/src/lib/handlers/lazy-style.handler.ts
+++ b/npm/ng-packs/packages/theme-basic/src/lib/handlers/lazy-style.handler.ts
@@ -1,6 +1,6 @@
import { LazyLoadService, LOADING_STRATEGY } from '@abp/ng.core';
import { DocumentDirHandlerService, LocaleDirection } from '@abp/ng.theme.shared';
-import { inject, Injectable, Injector } from '@angular/core';
+import { Injectable, Injector, inject } from '@angular/core';
import { LAZY_STYLES } from '../tokens/lazy-styles.token';
import { DOCUMENT } from '@angular/common';
export const BOOTSTRAP = 'bootstrap-{{dir}}.min.css';
@@ -25,7 +25,9 @@ export class LazyStyleHandler {
return this._dir;
}
- constructor(injector: Injector) {
+ constructor() {
+ const injector = inject(Injector);
+
this.setStyles(injector);
this.setLazyLoad(injector);
this.listenToDirectionChanges(injector);
@@ -90,8 +92,8 @@ export function createLazyStyleHref(style: string, dir: string): string {
return style.replace(/{{\s*dir\s*}}/g, dir);
}
-export function initLazyStyleHandler(injector: Injector) {
- return () => new LazyStyleHandler(injector);
+export function initLazyStyleHandler() {
+ return () => new LazyStyleHandler();
}
interface LoadedStyle {
diff --git a/npm/ng-packs/packages/theme-basic/src/lib/services/layout.service.ts b/npm/ng-packs/packages/theme-basic/src/lib/services/layout.service.ts
index 038d582c87..884a979e3f 100644
--- a/npm/ng-packs/packages/theme-basic/src/lib/services/layout.service.ts
+++ b/npm/ng-packs/packages/theme-basic/src/lib/services/layout.service.ts
@@ -1,5 +1,5 @@
-import { RouterEvents, SubscriptionService } from '@abp/ng.core';
-import { ChangeDetectorRef, inject, Injectable } from '@angular/core';
+import {RouterEvents, SubscriptionService} from '@abp/ng.core';
+import { ChangeDetectorRef, Injectable, inject } from '@angular/core';
import { fromEvent } from 'rxjs';
import { debounceTime } from 'rxjs/operators';
import { eThemeBasicComponents } from '../enums';
@@ -7,6 +7,9 @@ import { DOCUMENT } from '@angular/common';
@Injectable()
export class LayoutService {
+ private subscription = inject(SubscriptionService);
+ private cdRef = inject(ChangeDetectorRef);
+
document = inject(DOCUMENT);
isCollapsed = true;
@@ -18,14 +21,13 @@ export class LayoutService {
navItemsComponentKey = eThemeBasicComponents.NavItems;
- constructor(
- private subscription: SubscriptionService,
- private cdRef: ChangeDetectorRef,
- routerEvents: RouterEvents,
- ) {
- subscription.addOne(routerEvents.getNavigationEvents('End'), () => {
+ constructor() {
+ const subscription = this.subscription;
+ const routerEvents = inject(RouterEvents);
+
+ subscription.addOne(routerEvents.getNavigationEvents("End"),() => {
this.isCollapsed = true;
- });
+ })
}
private checkWindowWidth() {
diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/breadcrumb/breadcrumb.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/breadcrumb/breadcrumb.component.ts
index 4c7bd3cf30..f269be8d1e 100644
--- a/npm/ng-packs/packages/theme-shared/src/lib/components/breadcrumb/breadcrumb.component.ts
+++ b/npm/ng-packs/packages/theme-shared/src/lib/components/breadcrumb/breadcrumb.component.ts
@@ -6,7 +6,7 @@ import {
SubscriptionService,
TreeNode,
} from '@abp/ng.core';
-import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit } from '@angular/core';
+import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit, inject } from '@angular/core';
import { Router } from '@angular/router';
import { map, startWith } from 'rxjs/operators';
import { eThemeSharedRouteNames } from '../../enums/route-names';
@@ -20,15 +20,13 @@ import { BreadcrumbItemsComponent } from '../breadcrumb-items/breadcrumb-items.c
imports: [BreadcrumbItemsComponent],
})
export class BreadcrumbComponent implements OnInit {
- segments: Partial[] = [];
+ readonly cdRef = inject(ChangeDetectorRef);
+ private router = inject(Router);
+ private routes = inject(RoutesService);
+ private subscription = inject(SubscriptionService);
+ private routerEvents = inject(RouterEvents);
- constructor(
- public readonly cdRef: ChangeDetectorRef,
- private router: Router,
- private routes: RoutesService,
- private subscription: SubscriptionService,
- private routerEvents: RouterEvents,
- ) {}
+ segments: Partial[] = [];
ngOnInit(): void {
this.subscription.addOne(
diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/button/button.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/button/button.component.ts
index fdebb542a7..4c89b9ac10 100644
--- a/npm/ng-packs/packages/theme-shared/src/lib/components/button/button.component.ts
+++ b/npm/ng-packs/packages/theme-shared/src/lib/components/button/button.component.ts
@@ -1,13 +1,14 @@
/* eslint-disable @angular-eslint/no-output-native */
-import {
- Component,
- ElementRef,
- EventEmitter,
- Input,
- OnInit,
- Output,
- Renderer2,
- ViewChild,
+import {
+ Component,
+ ElementRef,
+ EventEmitter,
+ Input,
+ OnInit,
+ Output,
+ Renderer2,
+ ViewChild,
+ inject
} from '@angular/core';
import { CommonModule } from '@angular/common';
import { ABP } from '@abp/ng.core';
@@ -32,6 +33,8 @@ import { ABP } from '@abp/ng.core';
imports: [CommonModule],
})
export class ButtonComponent implements OnInit {
+ private renderer = inject(Renderer2);
+
@Input()
buttonId = '';
@@ -75,8 +78,6 @@ export class ButtonComponent implements OnInit {
return `${this.loading ? 'fa fa-spinner fa-spin' : this.iconClass || 'd-none'}`;
}
- constructor(private renderer: Renderer2) {}
-
ngOnInit() {
if (this.attributes) {
Object.keys(this.attributes).forEach(key => {
diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/confirmation/confirmation.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/confirmation/confirmation.component.ts
index f211b758e3..dcf7d4c952 100644
--- a/npm/ng-packs/packages/theme-shared/src/lib/components/confirmation/confirmation.component.ts
+++ b/npm/ng-packs/packages/theme-shared/src/lib/components/confirmation/confirmation.component.ts
@@ -1,4 +1,4 @@
-import { Component, Inject } from '@angular/core';
+import { Component, inject } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ReplaySubject } from 'rxjs';
import { Confirmation } from '../../models/confirmation';
@@ -12,7 +12,8 @@ import { LocalizationPipe } from '@abp/ng.core';
imports: [CommonModule, LocalizationPipe],
})
export class ConfirmationComponent {
- constructor(@Inject(CONFIRMATION_ICONS) private icons: ConfirmationIcons) {}
+ private icons = inject(CONFIRMATION_ICONS);
+
confirm = Confirmation.Status.confirm;
reject = Confirmation.Status.reject;
diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/loader-bar/loader-bar.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/loader-bar/loader-bar.component.ts
index 501fbbb82a..d611bc5f3d 100644
--- a/npm/ng-packs/packages/theme-shared/src/lib/components/loader-bar/loader-bar.component.ts
+++ b/npm/ng-packs/packages/theme-shared/src/lib/components/loader-bar/loader-bar.component.ts
@@ -1,5 +1,4 @@
-import { ChangeDetectorRef, Component, Input, OnDestroy, OnInit } from '@angular/core';
-import { Router } from '@angular/router';
+import { ChangeDetectorRef, Component, Input, OnDestroy, OnInit, inject } from '@angular/core';
import { CommonModule } from '@angular/common';
import { combineLatest, Subscription, timer } from 'rxjs';
import { HttpWaitService, RouterWaitService, SubscriptionService } from '@abp/ng.core';
@@ -24,6 +23,11 @@ import { HttpWaitService, RouterWaitService, SubscriptionService } from '@abp/ng
imports: [CommonModule],
})
export class LoaderBarComponent implements OnDestroy, OnInit {
+ private cdRef = inject(ChangeDetectorRef);
+ private subscription = inject(SubscriptionService);
+ private httpWaitService = inject(HttpWaitService);
+ private routerWaitService = inject(RouterWaitService);
+
protected _isLoading!: boolean;
@Input()
@@ -73,14 +77,6 @@ export class LoaderBarComponent implements OnDestroy, OnInit {
return `0 0 10px rgba(${this.color}, 0.5)`;
}
- constructor(
- private router: Router,
- private cdRef: ChangeDetectorRef,
- private subscription: SubscriptionService,
- private httpWaitService: HttpWaitService,
- private routerWaitService: RouterWaitService,
- ) {}
-
ngOnInit() {
this.subscribeLoading();
}
diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal-close.directive.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal-close.directive.ts
index 96455d1151..e15422d31b 100644
--- a/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal-close.directive.ts
+++ b/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal-close.directive.ts
@@ -1,11 +1,15 @@
-import { Directive, HostListener, Optional } from '@angular/core';
+import { Directive, HostListener, inject } from '@angular/core';
import { ModalComponent } from './modal.component';
@Directive({
selector: '[abpClose]',
})
export class ModalCloseDirective {
- constructor(@Optional() private modal: ModalComponent) {
+ private modal = inject(ModalComponent, { optional: true })!;
+
+ constructor() {
+ const modal = this.modal;
+
if (!modal) {
console.error('Please use abpClose within an abp-modal');
}
diff --git a/npm/ng-packs/packages/theme-shared/src/lib/directives/disabled.directive.ts b/npm/ng-packs/packages/theme-shared/src/lib/directives/disabled.directive.ts
index c0a1a74995..e00d827ba7 100644
--- a/npm/ng-packs/packages/theme-shared/src/lib/directives/disabled.directive.ts
+++ b/npm/ng-packs/packages/theme-shared/src/lib/directives/disabled.directive.ts
@@ -1,15 +1,15 @@
-import { Directive, Host, Input, OnChanges, SimpleChanges } from '@angular/core';
+import { Directive, Input, OnChanges, SimpleChanges, inject } from '@angular/core';
import { NgControl } from '@angular/forms';
@Directive({
selector: '[abpDisabled]',
})
export class DisabledDirective implements OnChanges {
+ private ngControl = inject(NgControl, { host: true });
+
@Input()
abpDisabled = false;
- constructor(@Host() private ngControl: NgControl) {}
-
// Related issue: https://github.com/angular/angular/issues/35330
ngOnChanges({ abpDisabled }: SimpleChanges) {
if (this.ngControl.control && abpDisabled) {
diff --git a/npm/ng-packs/packages/theme-shared/src/lib/directives/ellipsis.directive.ts b/npm/ng-packs/packages/theme-shared/src/lib/directives/ellipsis.directive.ts
index 94d963ce2e..b26be01a34 100644
--- a/npm/ng-packs/packages/theme-shared/src/lib/directives/ellipsis.directive.ts
+++ b/npm/ng-packs/packages/theme-shared/src/lib/directives/ellipsis.directive.ts
@@ -1,17 +1,20 @@
-import {
- AfterViewInit,
- ChangeDetectorRef,
- Directive,
- ElementRef,
- HostBinding,
- Input,
- NgModule,
+import {
+ AfterViewInit,
+ ChangeDetectorRef,
+ Directive,
+ ElementRef,
+ HostBinding,
+ Input,
+ inject
} from '@angular/core';
@Directive({
selector: '[abpEllipsis]',
})
export class EllipsisDirective implements AfterViewInit {
+ private cdRef = inject(ChangeDetectorRef);
+ private elRef = inject(ElementRef);
+
@Input('abpEllipsis')
width?: string;
@@ -37,11 +40,6 @@ export class EllipsisDirective implements AfterViewInit {
return this.enabled && this.width ? this.width || '170px' : undefined;
}
- constructor(
- private cdRef: ChangeDetectorRef,
- private elRef: ElementRef,
- ) {}
-
ngAfterViewInit() {
this.title = this.title || (this.elRef.nativeElement as HTMLElement).innerText;
this.cdRef.detectChanges();
diff --git a/npm/ng-packs/packages/theme-shared/src/lib/directives/loading.directive.ts b/npm/ng-packs/packages/theme-shared/src/lib/directives/loading.directive.ts
index 9de000e15f..c117262583 100644
--- a/npm/ng-packs/packages/theme-shared/src/lib/directives/loading.directive.ts
+++ b/npm/ng-packs/packages/theme-shared/src/lib/directives/loading.directive.ts
@@ -1,16 +1,16 @@
-import {
- ComponentFactoryResolver,
- ComponentRef,
- Directive,
- ElementRef,
- EmbeddedViewRef,
- HostBinding,
- Injector,
- Input,
- OnDestroy,
- OnInit,
- Renderer2,
- ViewContainerRef,
+import {
+ ComponentFactoryResolver,
+ ComponentRef,
+ Directive,
+ ElementRef,
+ EmbeddedViewRef,
+ HostBinding,
+ Injector,
+ Input,
+ OnDestroy,
+ OnInit,
+ Renderer2,
+ inject
} from '@angular/core';
import { Subscription, timer } from 'rxjs';
import { take } from 'rxjs/operators';
@@ -20,6 +20,11 @@ import { LoadingComponent } from '../components';
selector: '[abpLoading]',
})
export class LoadingDirective implements OnInit, OnDestroy {
+ private elRef = inject>(ElementRef);
+ private cdRes = inject(ComponentFactoryResolver);
+ private injector = inject(Injector);
+ private renderer = inject(Renderer2);
+
private _loading!: boolean;
@HostBinding('style.position')
@@ -77,14 +82,6 @@ export class LoadingDirective implements OnInit, OnDestroy {
rootNode: HTMLDivElement | null = null;
timerSubscription: Subscription | null = null;
- constructor(
- private elRef: ElementRef,
- private vcRef: ViewContainerRef,
- private cdRes: ComponentFactoryResolver,
- private injector: Injector,
- private renderer: Renderer2,
- ) {}
-
ngOnInit() {
if (!this.targetElement) {
const { offsetHeight, offsetWidth } = this.elRef.nativeElement;
diff --git a/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-default.directive.ts b/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-default.directive.ts
index d52fd7ccfd..7877677961 100644
--- a/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-default.directive.ts
+++ b/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-default.directive.ts
@@ -1,13 +1,5 @@
import { DOCUMENT, isPlatformBrowser } from '@angular/common';
-import {
- AfterViewInit,
- Directive,
- HostBinding,
- Inject,
- Input,
- OnDestroy,
- PLATFORM_ID,
-} from '@angular/core';
+import { AfterViewInit, Directive, HostBinding, Input, OnDestroy, inject, PLATFORM_ID } from '@angular/core';
import { ColumnMode, DatatableComponent, ScrollerComponent } from '@swimlane/ngx-datatable';
import { fromEvent, Subscription } from 'rxjs';
import { debounceTime } from 'rxjs/operators';
@@ -18,6 +10,9 @@ import { debounceTime } from 'rxjs/operators';
exportAs: 'ngxDatatableDefault',
})
export class NgxDatatableDefaultDirective implements AfterViewInit, OnDestroy {
+ private table = inject(DatatableComponent);
+ private document = inject(DOCUMENT);
+
private subscription = new Subscription();
private resizeDiff = 0;
@@ -28,11 +23,7 @@ export class NgxDatatableDefaultDirective implements AfterViewInit, OnDestroy {
return `ngx-datatable ${this.class}`;
}
- constructor(
- private table: DatatableComponent,
- @Inject(PLATFORM_ID) private platformId: object,
- @Inject(DOCUMENT) private document: MockDocument,
- ) {
+ constructor(@Inject(PLATFORM_ID) private platformId: object) {
this.table.columnMode = ColumnMode.force;
this.table.footerHeight = 50;
this.table.headerHeight = 50;
diff --git a/npm/ng-packs/packages/theme-shared/src/lib/directives/visible.directive.ts b/npm/ng-packs/packages/theme-shared/src/lib/directives/visible.directive.ts
index 9613779472..7532041462 100644
--- a/npm/ng-packs/packages/theme-shared/src/lib/directives/visible.directive.ts
+++ b/npm/ng-packs/packages/theme-shared/src/lib/directives/visible.directive.ts
@@ -1,10 +1,13 @@
-import { OnInit, Directive, OnDestroy, Input, ViewContainerRef, TemplateRef } from '@angular/core';
+import { OnInit, Directive, OnDestroy, Input, ViewContainerRef, TemplateRef, inject } from '@angular/core';
import { EMPTY, from, Observable, of, Subscription } from 'rxjs';
@Directive({
selector: '[abpVisible]',
})
export class AbpVisibleDirective implements OnDestroy, OnInit {
+ private viewContainerRef = inject(ViewContainerRef);
+ private templateRef = inject>(TemplateRef);
+
conditionSubscription: Subscription | undefined;
isVisible: boolean | undefined;
@@ -16,11 +19,6 @@ export class AbpVisibleDirective implements OnDestroy, OnInit {
}
private condition$: Observable = of(false);
-
- constructor(
- private viewContainerRef: ViewContainerRef,
- private templateRef: TemplateRef,
- ) {}
ngOnInit(): void {
this.updateVisibility();
}
diff --git a/npm/ng-packs/packages/theme-shared/src/lib/handlers/document-dir.handler.ts b/npm/ng-packs/packages/theme-shared/src/lib/handlers/document-dir.handler.ts
index 3c1863cc21..fba4afa886 100644
--- a/npm/ng-packs/packages/theme-shared/src/lib/handlers/document-dir.handler.ts
+++ b/npm/ng-packs/packages/theme-shared/src/lib/handlers/document-dir.handler.ts
@@ -1,5 +1,5 @@
import { getLocaleDirection, LocalizationService } from '@abp/ng.core';
-import { Injectable, Injector } from '@angular/core';
+import { Injectable, Injector, inject } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import { map } from 'rxjs/operators';
import { LocaleDirection } from '../models/common';
@@ -7,9 +7,11 @@ import { DOCUMENT } from '@angular/common';
@Injectable()
export class DocumentDirHandlerService {
+ protected injector = inject(Injector);
+
private dir = new BehaviorSubject('ltr');
dir$ = this.dir.asObservable();
- constructor(protected injector: Injector) {
+ constructor() {
this.listenToLanguageChanges();
}
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 07c5721625..f4a799ba1b 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
@@ -17,6 +17,8 @@ import { RouterErrorHandlerService } from '../services/router-error-handler.serv
@Injectable({ providedIn: 'root' })
export class ErrorHandler {
+ protected injector = inject(Injector);
+
protected readonly httpErrorReporter = inject(HttpErrorReporterService);
protected readonly confirmationService = inject(ConfirmationService);
protected readonly routerErrorHandlerService = inject(RouterErrorHandlerService);
@@ -24,7 +26,7 @@ export class ErrorHandler {
protected readonly customErrorHandlers = inject(CUSTOM_ERROR_HANDLERS);
protected readonly httpErrorHandler = inject(HTTP_ERROR_HANDLER, { optional: true });
- constructor(protected injector: Injector) {
+ constructor() {
this.listenToRestError();
this.listenToRouterError();
}
diff --git a/npm/ng-packs/packages/theme-shared/src/lib/services/confirmation.service.ts b/npm/ng-packs/packages/theme-shared/src/lib/services/confirmation.service.ts
index 5eeadb0ab6..ead1f0c91a 100644
--- a/npm/ng-packs/packages/theme-shared/src/lib/services/confirmation.service.ts
+++ b/npm/ng-packs/packages/theme-shared/src/lib/services/confirmation.service.ts
@@ -1,5 +1,5 @@
import { ContentProjectionService, LocalizationParam, PROJECTION_STRATEGY } from '@abp/ng.core';
-import { ComponentRef, Injectable } from '@angular/core';
+import { ComponentRef, Injectable, inject } from '@angular/core';
import { fromEvent, Observable, ReplaySubject, Subject } from 'rxjs';
import { debounceTime, filter, takeUntil } from 'rxjs/operators';
import { ConfirmationComponent } from '../components/confirmation/confirmation.component';
@@ -7,6 +7,8 @@ import { Confirmation } from '../models/confirmation';
@Injectable({ providedIn: 'root' })
export class ConfirmationService {
+ private contentProjectionService = inject(ContentProjectionService);
+
status$!: Subject;
confirmation$ = new ReplaySubject(1);
@@ -17,8 +19,6 @@ export class ConfirmationService {
this.status$.next(status);
};
- constructor(private contentProjectionService: ContentProjectionService) {}
-
private setContainer() {
this.containerComponentRef = this.contentProjectionService.projectContent(
PROJECTION_STRATEGY.AppendComponentToBody(ConfirmationComponent, {
diff --git a/npm/ng-packs/packages/theme-shared/src/lib/utils/date-parser-formatter.ts b/npm/ng-packs/packages/theme-shared/src/lib/utils/date-parser-formatter.ts
index 4a85a4dab6..40a99d98da 100644
--- a/npm/ng-packs/packages/theme-shared/src/lib/utils/date-parser-formatter.ts
+++ b/npm/ng-packs/packages/theme-shared/src/lib/utils/date-parser-formatter.ts
@@ -1,6 +1,6 @@
import { ApplicationLocalizationConfigurationDto, ConfigStateService } from '@abp/ng.core';
import { formatDate } from '@angular/common';
-import { Inject, Injectable, LOCALE_ID } from '@angular/core';
+import { Injectable, LOCALE_ID, inject } from '@angular/core';
import { NgbDateParserFormatter, NgbDateStruct } from '@ng-bootstrap/ng-bootstrap';
function isNumber(value: any): boolean {
@@ -13,10 +13,14 @@ function toInteger(value: any): number {
@Injectable()
export class DateParserFormatter extends NgbDateParserFormatter {
- constructor(private configState: ConfigStateService, @Inject(LOCALE_ID) private locale: string) {
+ private configState = inject(ConfigStateService);
+ private locale = inject(LOCALE_ID);
+
+ constructor() {
super();
}
+
parse(value: string): NgbDateStruct | null {
if (value) {
const dateParts = value.trim().split('-');
diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20250707124203_Initial.Designer.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20250717081711_Initial.Designer.cs
similarity index 99%
rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20250707124203_Initial.Designer.cs
rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20250717081711_Initial.Designer.cs
index e15d92f0b0..db85e2f5d5 100644
--- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20250707124203_Initial.Designer.cs
+++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20250717081711_Initial.Designer.cs
@@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
namespace MyCompanyName.MyProjectName.Blazor.Server.Migrations
{
[DbContext(typeof(MyProjectNameDbContext))]
- [Migration("20250707124203_Initial")]
+ [Migration("20250717081711_Initial")]
partial class Initial
{
///
@@ -1455,8 +1455,8 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Migrations
.HasColumnType("nvarchar(400)");
b.Property("Type")
- .HasMaxLength(50)
- .HasColumnType("nvarchar(50)");
+ .HasMaxLength(150)
+ .HasColumnType("nvarchar(150)");
b.HasKey("Id");
diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20250707124203_Initial.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20250717081711_Initial.cs
similarity index 99%
rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20250707124203_Initial.cs
rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20250717081711_Initial.cs
index b49581a787..ca5e31e7c4 100644
--- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20250707124203_Initial.cs
+++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20250717081711_Initial.cs
@@ -767,7 +767,7 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Migrations
ReferenceId = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true),
Status = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: true),
Subject = table.Column(type: "nvarchar(400)", maxLength: 400, nullable: true),
- Type = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: true),
+ Type = table.Column(type: "nvarchar(150)", maxLength: 150, nullable: true),
ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false),
ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false)
},
diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/MyProjectNameDbContextModelSnapshot.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/MyProjectNameDbContextModelSnapshot.cs
index 713984fed8..aa06ad1bbe 100644
--- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/MyProjectNameDbContextModelSnapshot.cs
+++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/MyProjectNameDbContextModelSnapshot.cs
@@ -1452,8 +1452,8 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Migrations
.HasColumnType("nvarchar(400)");
b.Property("Type")
- .HasMaxLength(50)
- .HasColumnType("nvarchar(50)");
+ .HasMaxLength(150)
+ .HasColumnType("nvarchar(150)");
b.HasKey("Id");
diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20250707124326_Initial.Designer.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20250717081855_Initial.Designer.cs
similarity index 99%
rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20250707124326_Initial.Designer.cs
rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20250717081855_Initial.Designer.cs
index 7f42d54b55..961580c3c6 100644
--- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20250707124326_Initial.Designer.cs
+++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20250717081855_Initial.Designer.cs
@@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
namespace MyCompanyName.MyProjectName.Migrations
{
[DbContext(typeof(MyProjectNameDbContext))]
- [Migration("20250707124326_Initial")]
+ [Migration("20250717081855_Initial")]
partial class Initial
{
///
@@ -1455,8 +1455,8 @@ namespace MyCompanyName.MyProjectName.Migrations
.HasColumnType("nvarchar(400)");
b.Property("Type")
- .HasMaxLength(50)
- .HasColumnType("nvarchar(50)");
+ .HasMaxLength(150)
+ .HasColumnType("nvarchar(150)");
b.HasKey("Id");
diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20250707124326_Initial.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20250717081855_Initial.cs
similarity index 99%
rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20250707124326_Initial.cs
rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20250717081855_Initial.cs
index 4baf413779..d4990d59a7 100644
--- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20250707124326_Initial.cs
+++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20250717081855_Initial.cs
@@ -767,7 +767,7 @@ namespace MyCompanyName.MyProjectName.Migrations
ReferenceId = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true),
Status = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: true),
Subject = table.Column(type: "nvarchar(400)", maxLength: 400, nullable: true),
- Type = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: true),
+ Type = table.Column(type: "nvarchar(150)", maxLength: 150, nullable: true),
ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false),
ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false)
},
diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/MyProjectNameDbContextModelSnapshot.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/MyProjectNameDbContextModelSnapshot.cs
index df0aa1aa34..d216c5d155 100644
--- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/MyProjectNameDbContextModelSnapshot.cs
+++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/MyProjectNameDbContextModelSnapshot.cs
@@ -1452,8 +1452,8 @@ namespace MyCompanyName.MyProjectName.Migrations
.HasColumnType("nvarchar(400)");
b.Property("Type")
- .HasMaxLength(50)
- .HasColumnType("nvarchar(50)");
+ .HasMaxLength(150)
+ .HasColumnType("nvarchar(150)");
b.HasKey("Id");
diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20250707124118_Initial.Designer.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20250717081619_Initial.Designer.cs
similarity index 99%
rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20250707124118_Initial.Designer.cs
rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20250717081619_Initial.Designer.cs
index 57a12bdda5..c90ff0bb2e 100644
--- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20250707124118_Initial.Designer.cs
+++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20250717081619_Initial.Designer.cs
@@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
namespace MyCompanyName.MyProjectName.Host.Migrations
{
[DbContext(typeof(MyProjectNameDbContext))]
- [Migration("20250707124118_Initial")]
+ [Migration("20250717081619_Initial")]
partial class Initial
{
///
@@ -1455,8 +1455,8 @@ namespace MyCompanyName.MyProjectName.Host.Migrations
.HasColumnType("nvarchar(400)");
b.Property("Type")
- .HasMaxLength(50)
- .HasColumnType("nvarchar(50)");
+ .HasMaxLength(150)
+ .HasColumnType("nvarchar(150)");
b.HasKey("Id");
diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20250707124118_Initial.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20250717081619_Initial.cs
similarity index 99%
rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20250707124118_Initial.cs
rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20250717081619_Initial.cs
index df72fe0aa0..b08f2c0b80 100644
--- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20250707124118_Initial.cs
+++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20250717081619_Initial.cs
@@ -767,7 +767,7 @@ namespace MyCompanyName.MyProjectName.Host.Migrations
ReferenceId = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true),
Status = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: true),
Subject = table.Column(type: "nvarchar(400)", maxLength: 400, nullable: true),
- Type = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: true),
+ Type = table.Column(type: "nvarchar(150)", maxLength: 150, nullable: true),
ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false),
ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false)
},
diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/MyProjectNameDbContextModelSnapshot.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/MyProjectNameDbContextModelSnapshot.cs
index 9a5d77c39a..fffa45164c 100644
--- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/MyProjectNameDbContextModelSnapshot.cs
+++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/MyProjectNameDbContextModelSnapshot.cs
@@ -1452,8 +1452,8 @@ namespace MyCompanyName.MyProjectName.Host.Migrations
.HasColumnType("nvarchar(400)");
b.Property("Type")
- .HasMaxLength(50)
- .HasColumnType("nvarchar(50)");
+ .HasMaxLength(150)
+ .HasColumnType("nvarchar(150)");
b.HasKey("Id");
diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20250707124141_Initial.Designer.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20250717081642_Initial.Designer.cs
similarity index 99%
rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20250707124141_Initial.Designer.cs
rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20250717081642_Initial.Designer.cs
index 8a651eb02b..5e5d98d72e 100644
--- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20250707124141_Initial.Designer.cs
+++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20250717081642_Initial.Designer.cs
@@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
namespace MyCompanyName.MyProjectName.Mvc.Migrations
{
[DbContext(typeof(MyProjectNameDbContext))]
- [Migration("20250707124141_Initial")]
+ [Migration("20250717081642_Initial")]
partial class Initial
{
///
@@ -1455,8 +1455,8 @@ namespace MyCompanyName.MyProjectName.Mvc.Migrations
.HasColumnType("nvarchar(400)");
b.Property("Type")
- .HasMaxLength(50)
- .HasColumnType("nvarchar(50)");
+ .HasMaxLength(150)
+ .HasColumnType("nvarchar(150)");
b.HasKey("Id");
diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20250707124141_Initial.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20250717081642_Initial.cs
similarity index 99%
rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20250707124141_Initial.cs
rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20250717081642_Initial.cs
index 772bbb6b85..fa3bbe7aed 100644
--- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20250707124141_Initial.cs
+++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20250717081642_Initial.cs
@@ -767,7 +767,7 @@ namespace MyCompanyName.MyProjectName.Mvc.Migrations
ReferenceId = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true),
Status = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: true),
Subject = table.Column(type: "nvarchar(400)", maxLength: 400, nullable: true),
- Type = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: true),
+ Type = table.Column(type: "nvarchar(150)", maxLength: 150, nullable: true),
ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false),
ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false)
},
diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/MyProjectNameDbContextModelSnapshot.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/MyProjectNameDbContextModelSnapshot.cs
index c7ac0ea099..5df74a87ff 100644
--- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/MyProjectNameDbContextModelSnapshot.cs
+++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/MyProjectNameDbContextModelSnapshot.cs
@@ -1452,8 +1452,8 @@ namespace MyCompanyName.MyProjectName.Mvc.Migrations
.HasColumnType("nvarchar(400)");
b.Property("Type")
- .HasMaxLength(50)
- .HasColumnType("nvarchar(50)");
+ .HasMaxLength(150)
+ .HasColumnType("nvarchar(150)");
b.HasKey("Id");
diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20250707124211_Initial.Designer.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20250717081721_Initial.Designer.cs
similarity index 99%
rename from templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20250707124211_Initial.Designer.cs
rename to templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20250717081721_Initial.Designer.cs
index fe1cc7ed42..4ee8dc1ff3 100644
--- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20250707124211_Initial.Designer.cs
+++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20250717081721_Initial.Designer.cs
@@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
namespace MyCompanyName.MyProjectName.Migrations
{
[DbContext(typeof(MyProjectNameDbContext))]
- [Migration("20250707124211_Initial")]
+ [Migration("20250717081721_Initial")]
partial class Initial
{
///
@@ -1511,8 +1511,8 @@ namespace MyCompanyName.MyProjectName.Migrations
.HasColumnType("nvarchar(400)");
b.Property("Type")
- .HasMaxLength(50)
- .HasColumnType("nvarchar(50)");
+ .HasMaxLength(150)
+ .HasColumnType("nvarchar(150)");
b.HasKey("Id");
diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20250707124211_Initial.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20250717081721_Initial.cs
similarity index 99%
rename from templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20250707124211_Initial.cs
rename to templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20250717081721_Initial.cs
index 07f1cbab3a..579fe19395 100644
--- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20250707124211_Initial.cs
+++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20250717081721_Initial.cs
@@ -789,7 +789,7 @@ namespace MyCompanyName.MyProjectName.Migrations
ReferenceId = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true),
Status = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: true),
Subject = table.Column(type: "nvarchar(400)", maxLength: 400, nullable: true),
- Type = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: true),
+ Type = table.Column(type: "nvarchar(150)", maxLength: 150, nullable: true),
ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false),
ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false)
},
diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/MyProjectNameDbContextModelSnapshot.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/MyProjectNameDbContextModelSnapshot.cs
index 7c44024ec7..51c2b336bc 100644
--- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/MyProjectNameDbContextModelSnapshot.cs
+++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/MyProjectNameDbContextModelSnapshot.cs
@@ -1508,8 +1508,8 @@ namespace MyCompanyName.MyProjectName.Migrations
.HasColumnType("nvarchar(400)");
b.Property("Type")
- .HasMaxLength(50)
- .HasColumnType("nvarchar(50)");
+ .HasMaxLength(150)
+ .HasColumnType("nvarchar(150)");
b.HasKey("Id");
diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20250707124242_Initial.Designer.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20250717081803_Initial.Designer.cs
similarity index 99%
rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20250707124242_Initial.Designer.cs
rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20250717081803_Initial.Designer.cs
index a62bea292c..0d0867486b 100644
--- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20250707124242_Initial.Designer.cs
+++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20250717081803_Initial.Designer.cs
@@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
namespace MyCompanyName.MyProjectName.Migrations
{
[DbContext(typeof(AuthServerDbContext))]
- [Migration("20250707124242_Initial")]
+ [Migration("20250717081803_Initial")]
partial class Initial
{
///
@@ -1455,8 +1455,8 @@ namespace MyCompanyName.MyProjectName.Migrations
.HasColumnType("nvarchar(400)");
b.Property("Type")
- .HasMaxLength(50)
- .HasColumnType("nvarchar(50)");
+ .HasMaxLength(150)
+ .HasColumnType("nvarchar(150)");
b.HasKey("Id");
diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20250707124242_Initial.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20250717081803_Initial.cs
similarity index 99%
rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20250707124242_Initial.cs
rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20250717081803_Initial.cs
index 4baf413779..d4990d59a7 100644
--- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20250707124242_Initial.cs
+++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20250717081803_Initial.cs
@@ -767,7 +767,7 @@ namespace MyCompanyName.MyProjectName.Migrations
ReferenceId = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true),
Status = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: true),
Subject = table.Column(type: "nvarchar(400)", maxLength: 400, nullable: true),
- Type = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: true),
+ Type = table.Column(type: "nvarchar(150)", maxLength: 150, nullable: true),
ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false),
ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false)
},
diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/AuthServerDbContextModelSnapshot.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/AuthServerDbContextModelSnapshot.cs
index 270471c1d9..a9dc5b7efa 100644
--- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/AuthServerDbContextModelSnapshot.cs
+++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/AuthServerDbContextModelSnapshot.cs
@@ -1452,8 +1452,8 @@ namespace MyCompanyName.MyProjectName.Migrations
.HasColumnType("nvarchar(400)");
b.Property("Type")
- .HasMaxLength(50)
- .HasColumnType("nvarchar(50)");
+ .HasMaxLength(150)
+ .HasColumnType("nvarchar(150)");
b.HasKey("Id");
diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20250707124228_Initial.Designer.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20250717081744_Initial.Designer.cs
similarity index 99%
rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20250707124228_Initial.Designer.cs
rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20250717081744_Initial.Designer.cs
index e579c8c3d8..956e6e89d1 100644
--- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20250707124228_Initial.Designer.cs
+++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20250717081744_Initial.Designer.cs
@@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
namespace MyCompanyName.MyProjectName.Blazor.Server.Host.Migrations
{
[DbContext(typeof(UnifiedDbContext))]
- [Migration("20250707124228_Initial")]
+ [Migration("20250717081744_Initial")]
partial class Initial
{
///
diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20250707124228_Initial.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20250717081744_Initial.cs
similarity index 100%
rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20250707124228_Initial.cs
rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20250717081744_Initial.cs
diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/20250707124251_Initial.Designer.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/20250717081812_Initial.Designer.cs
similarity index 96%
rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/20250707124251_Initial.Designer.cs
rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/20250717081812_Initial.Designer.cs
index 4e2be97fd1..3cd1db524a 100644
--- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/20250707124251_Initial.Designer.cs
+++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/20250717081812_Initial.Designer.cs
@@ -12,7 +12,7 @@ using Volo.Abp.EntityFrameworkCore;
namespace MyCompanyName.MyProjectName.Migrations
{
[DbContext(typeof(MyProjectNameHttpApiHostMigrationsDbContext))]
- [Migration("20250707124251_Initial")]
+ [Migration("20250717081812_Initial")]
partial class Initial
{
///
diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/20250707124251_Initial.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/20250717081812_Initial.cs
similarity index 100%
rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/20250707124251_Initial.cs
rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/20250717081812_Initial.cs
diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20250707124303_Initial.Designer.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20250717081828_Initial.Designer.cs
similarity index 99%
rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20250707124303_Initial.Designer.cs
rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20250717081828_Initial.Designer.cs
index 11e391b638..0746c415d6 100644
--- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20250707124303_Initial.Designer.cs
+++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20250717081828_Initial.Designer.cs
@@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
namespace MyCompanyName.MyProjectName.Migrations
{
[DbContext(typeof(UnifiedDbContext))]
- [Migration("20250707124303_Initial")]
+ [Migration("20250717081828_Initial")]
partial class Initial
{
///
diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20250707124303_Initial.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20250717081828_Initial.cs
similarity index 100%
rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20250707124303_Initial.cs
rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20250717081828_Initial.cs