diff --git a/docs/en/cli/index.md b/docs/en/cli/index.md index 940c8acccd..38503b73be 100644 --- a/docs/en/cli/index.md +++ b/docs/en/cli/index.md @@ -918,6 +918,8 @@ Usage: abp bundle [options] ```` +> This command is no longer needed if you are using Global Assets feature. See [Managing Global Scripts & Styles](../framework/ui/blazor/global-scripts-styles.md) for more information. + #### Options * ```--working-directory``` or ```-wd```: Specifies the working directory. This option is useful when executing directory doesn't contain a Blazor project file. diff --git a/docs/en/docs-nav.json b/docs/en/docs-nav.json index 03640f506c..d6d24fa271 100644 --- a/docs/en/docs-nav.json +++ b/docs/en/docs-nav.json @@ -783,78 +783,6 @@ "path": "framework/architecture", "isIndex": true }, - { - "text": "Module Development Best Practices", - "items": [ - { - "text": "Overview", - "path": "framework/architecture/best-practices", - "isIndex": true - }, - { - "text": "Module Architecture", - "path": "framework/architecture/best-practices/module-architecture.md" - }, - { - "text": "Domain Layer", - "items": [ - { - "text": "Overview", - "path": "framework/architecture/best-practices/domain-layer-overview.md", - "isIndex": true - }, - { - "text": "Entities", - "path": "framework/architecture/best-practices/entities.md" - }, - { - "text": "Repositories", - "path": "framework/architecture/best-practices/repositories.md" - }, - { - "text": "Domain Services", - "path": "framework/architecture/best-practices/domain-services.md" - } - ] - }, - { - "text": "Application Layer", - "items": [ - { - "text": "Overview", - "path": "framework/architecture/best-practices/application-layer-overview.md", - "isIndex": true - }, - { - "text": "Application Services", - "path": "framework/architecture/best-practices/application-services.md" - }, - { - "text": "Data Transfer Objects", - "path": "framework/architecture/best-practices/data-transfer-objects.md" - } - ] - }, - { - "text": "Data Access", - "items": [ - { - "text": "Overview", - "path": "framework/architecture/best-practices/data-access-overview.md", - "isIndex": true - }, - { - "text": "Entity Framework Core Integration", - "path": "framework/architecture/best-practices/entity-framework-core-integration.md" - }, - { - "text": "MongoDB Integration", - "path": "framework/architecture/best-practices/mongodb-integration.md" - } - ] - } - ] - }, { "text": "Modularity", "items": [ @@ -970,7 +898,8 @@ "items": [ { "text": "Overview", - "path": "framework/architecture/best-practices" + "path": "framework/architecture/best-practices", + "isIndex": true }, { "text": "Module Architecture", @@ -981,7 +910,8 @@ "items": [ { "text": "Overview", - "path": "framework/architecture/best-practices/domain-layer-overview.md" + "path": "framework/architecture/best-practices/domain-layer-overview.md", + "isIndex": true }, { "text": "Entities", @@ -1002,7 +932,8 @@ "items": [ { "text": "Overview", - "path": "framework/architecture/best-practices/application-layer-overview.md" + "path": "framework/architecture/best-practices/application-layer-overview.md", + "isIndex": true }, { "text": "Application Services", @@ -1019,7 +950,8 @@ "items": [ { "text": "Overview", - "path": "framework/architecture/best-practices/data-access-overview.md" + "path": "framework/architecture/best-practices/data-access-overview.md", + "isIndex": true }, { "text": "Entity Framework Core Integration", @@ -1032,7 +964,7 @@ ] } ] - } + }, ] }, { diff --git a/docs/en/framework/api-development/dynamic-csharp-clients.md b/docs/en/framework/api-development/dynamic-csharp-clients.md index def0b76360..a5dc2ec1cf 100644 --- a/docs/en/framework/api-development/dynamic-csharp-clients.md +++ b/docs/en/framework/api-development/dynamic-csharp-clients.md @@ -163,6 +163,30 @@ context.Services.AddHttpClientProxies( `remoteServiceConfigurationName` parameter matches the service endpoint configured via `AbpRemoteServiceOptions`. If the `BookStore` endpoint is not defined then it fallbacks to the `Default` endpoint. +#### Remote Service Configuration Provider + +You may need to get the remote service configuration for a specific remote service in some cases. For this, you can use the `IRemoteServiceConfigurationProvider` interface. + +**Example: Get the remote service configuration for the "BookStore" remote service** + +````csharp +public class MyService : ITransientDependency +{ + private readonly IRemoteServiceConfigurationProvider _remoteServiceConfigurationProvider; + + public MyService(IRemoteServiceConfigurationProvider remoteServiceConfigurationProvider) + { + _remoteServiceConfigurationProvider = remoteServiceConfigurationProvider; + } + + public async Task GetRemoteServiceConfiguration() + { + var configuration = await _remoteServiceConfigurationProvider.GetConfigurationOrDefaultAsync("BookStore"); + Console.WriteLine(configuration.BaseUrl); + } +} +```` + ### As Default Services When you create a service proxy for `IBookAppService`, you can directly inject the `IBookAppService` to use the proxy client (as shown in the usage section). You can pass `asDefaultServices: false` to the `AddHttpClientProxies` method to disable this feature. @@ -204,6 +228,8 @@ public override void PreConfigureServices(ServiceConfigurationContext context) This example uses the [Microsoft.Extensions.Http.Polly](https://www.nuget.org/packages/Microsoft.Extensions.Http.Polly) package. You also need to import the `Polly` namespace (`using Polly;`) to be able to use the `WaitAndRetryAsync` method. + + ## See Also * [Static C# Client Proxies](./static-csharp-clients.md) diff --git a/docs/en/framework/api-development/static-csharp-clients.md b/docs/en/framework/api-development/static-csharp-clients.md index 696507bd09..c8eaea4231 100644 --- a/docs/en/framework/api-development/static-csharp-clients.md +++ b/docs/en/framework/api-development/static-csharp-clients.md @@ -244,6 +244,30 @@ context.Services.AddStaticHttpClientProxies( `remoteServiceConfigurationName` parameter matches the service endpoint configured via `AbpRemoteServiceOptions`. If the `BookStore` endpoint is not defined then it fallbacks to the `Default` endpoint. +#### Remote Service Configuration Provider + +You may need to get the remote service configuration for a specific remote service in some cases. For this, you can use the `IRemoteServiceConfigurationProvider` interface. + +**Example: Get the remote service configuration for the "BookStore" remote service** + +````csharp +public class MyService : ITransientDependency +{ + private readonly IRemoteServiceConfigurationProvider _remoteServiceConfigurationProvider; + + public MyService(IRemoteServiceConfigurationProvider remoteServiceConfigurationProvider) + { + _remoteServiceConfigurationProvider = remoteServiceConfigurationProvider; + } + + public async Task GetRemoteServiceConfiguration() + { + var configuration = await _remoteServiceConfigurationProvider.GetConfigurationOrDefaultAsync("BookStore"); + Console.WriteLine(configuration.BaseUrl); + } +} +```` + ### Retry/Failure Logic & Polly Integration If you want to add retry logic for the failing remote HTTP calls for the client proxies, you can configure the `AbpHttpClientBuilderOptions` in the `PreConfigureServices` method of your module class. diff --git a/docs/en/framework/data/mongodb/index.md b/docs/en/framework/data/mongodb/index.md index 57532f4f59..d5bb4124aa 100644 --- a/docs/en/framework/data/mongodb/index.md +++ b/docs/en/framework/data/mongodb/index.md @@ -309,16 +309,39 @@ public class BookService ### Transactions -MongoDB supports multi-document transactions starting from the version 4.0 and the ABP supports it. However, the [startup template](../../../solution-templates) **disables** transactions by default. If your MongoDB **server** supports transactions, you can enable the it in the *YourProjectMongoDbModule* class: +MongoDB supports multi-document transactions starting from the version 4.0 and the ABP supports it. However, the [startup template](../../../solution-templates) **disables** transactions by default. If your MongoDB **server** supports transactions, you can enable them in the *YourProjectMongoDbModule* class: -```csharp -Configure(options => -{ - options.TransactionBehavior = UnitOfWorkTransactionBehavior.Auto; -}); +Remove the following code to enable transactions: + +```diff +- context.Services.AddAlwaysDisableUnitOfWorkTransaction(); +- Configure(options => +- { +- options.TransactionBehavior = UnitOfWorkTransactionBehavior.Disabled; +- }); ``` -> Or you can delete this code since this is already the default behavior. +#### Setting up a Transaction-Enabled MongoDB Replica Set in Docker + +Use the following `docker-compose.yml` to create a local MongoDB Replica Set that supports transactions. The connection string will be `mongodb://localhost:27017/YourProjectName?replicaSet=rs0`. + +```yaml +version: "3.8" + +services: + mongo: + image: mongo:8.0 + command: ["--replSet", "rs0", "--bind_ip_all", "--port", "27017"] + ports: + - 27017:27017 + healthcheck: + test: echo "try { rs.status() } catch (err) { rs.initiate({_id:'rs0',members:[{_id:0,host:'127.0.0.1:27017'}]}) }" | mongosh --port 27017 --quiet + interval: 5s + timeout: 30s + start_period: 0s + start_interval: 1s + retries: 30 +``` ### Advanced Topics @@ -510,4 +533,4 @@ public class MyCustomMongoDbBulkOperationProvider * [Entities](../../architecture/domain-driven-design/entities.md) * [Repositories](../../architecture/domain-driven-design/repositories.md) -* [Video tutorial](https://abp.io/video-courses/essentials/abp-mongodb) \ No newline at end of file +* [Video tutorial](https://abp.io/video-courses/essentials/abp-mongodb) diff --git a/docs/en/framework/ui/blazor/basic-theme.md b/docs/en/framework/ui/blazor/basic-theme.md index 031a5f0fd5..bf4684b668 100644 --- a/docs/en/framework/ui/blazor/basic-theme.md +++ b/docs/en/framework/ui/blazor/basic-theme.md @@ -19,17 +19,26 @@ If you need to manually this theme, follow the steps below: {{if UI == "Blazor"}} -* Install the [Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme](https://www.nuget.org/packages/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme) NuGet package to your web project. -* Add `AbpAspNetCoreComponentsWebAssemblyBasicThemeModule` into the `[DependsOn(...)]` attribute for your [module class](../../architecture/modularity/basics.md) in the your Blazor UI project. -* Use `Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.Themes.Basic.App` as the root component of your application in the `ConfigureServices` method of your module: - - ```csharp - var builder = context.Services.GetSingletonInstance(); - builder.RootComponents.Add("#ApplicationContainer"); - ``` - `#ApplicationContainer` is a selector (like `
Loading...
`) in the `index.html`. - -* Execute `abp bundle` command under blazor project once. +* Install the [Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.Bundling](https://www.nuget.org/packages/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.Bundling) NuGet package to your `Blazor` project. +* Add `AbpAspNetCoreComponentsWebAssemblyBasicThemeBundlingModule` into the `[DependsOn(...)]` attribute for your [module class](../../architecture/modularity/basics.md) in the your `Blazor` project. +* Install the [Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme](https://www.nuget.org/packages/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme) NuGet package to your `Blazor.Client` project. +* Add `AbpAspNetCoreComponentsWebAssemblyBasicThemeModule` into the `[DependsOn(...)]` attribute for your [module class](../../architecture/modularity/basics.md) in the your `Blazor.Client` project. + +Update `Routes.razor` file in `Blazor.Client` project as below: + +````csharp +@using Volo.Abp.AspNetCore.Components.Web.BasicTheme.Themes.Basic +@using Volo.Abp.AspNetCore.Components.WebAssembly.WebApp + + + + + + + + + +```` {{end}} @@ -41,21 +50,38 @@ If you need to manually this theme, follow the steps below: * Add `AbpAspNetCoreComponentsServerBasicThemeModule` into the `[DependsOn(...)]` attribute for your [module class](../../architecture/modularity/basics.md) in the your Blazor UI project. -* Perform following changes in `Pages/_Host.cshtml` file +* Perform following changes in `App.razor` file * Add usings at the top of the page. ```html @using Volo.Abp.AspNetCore.Components.Server.BasicTheme.Bundling - @using Volo.Abp.AspNetCore.Components.Web.BasicTheme.Themes.Basic ``` - * Add Basic theme style bundles between `` tags. - ```html - + * Then replace script & style bunles as following ``` - * Add `App` component of Basic Theme in the body section of page. - ```html - + ``` + ``` + + ``` + +Update `Routes.razor` file as below: + +````csharp +@using Volo.Abp.AspNetCore.Components.Web.BasicTheme.Themes.Basic +@using Volo.Abp.AspNetCore.Components.Web.Theming.Routing +@using Microsoft.Extensions.Options +@inject IOptions RouterOptions + + + + + + + + + +```` + {{end}} ## The Layout diff --git a/docs/en/framework/ui/blazor/theming.md b/docs/en/framework/ui/blazor/theming.md index 9a056580bb..dd942fd92f 100644 --- a/docs/en/framework/ui/blazor/theming.md +++ b/docs/en/framework/ui/blazor/theming.md @@ -106,22 +106,35 @@ using Volo.Abp.Bundling; namespace MyTheme { - public class MyThemeBundleContributor : IBundleContributor + public class MyThemeBundleContributor : BundleContributor { - public void AddScripts(BundleContext context) + public override void ConfigureBundle(BundleConfigurationContext context) { - + context.Files.AddIfNotContains("_content/MyTheme/styles.css"); } + } +} +```` - public void AddStyles(BundleContext context) +```cs +[DependsOn( + typeof(AbpAspNetCoreComponentsWebAssemblyThemingBundlingModule) +)] +public class MyBlazorWebAssemblyBundlingModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => { - context.Add("_content/MyTheme/styles.css"); - } + // Add style bundle + options.StyleBundles.Get(BlazorWebAssemblyStandardBundles.Styles.Global) + .AddContributors(typeof(MyThemeBundleContributor)); + }); } } -```` +``` -`styles.css` file should be added into the `wwwroot` folder of the theme project for this example. When you use the `abp bundle` command, this class is automatically discovered and executed to add the style to the page. +`styles.css` file should be added into the `wwwroot` folder of the theme project for this example. See the [Global Styles and Scripts](global-scripts-styles.md) document for more. diff --git a/docs/en/get-started/images/abp-studio-new-microservice-solution-dialog-optional-modules.png b/docs/en/get-started/images/abp-studio-new-microservice-solution-dialog-optional-modules.png index 2ac5685438..a268e4cde5 100644 Binary files a/docs/en/get-started/images/abp-studio-new-microservice-solution-dialog-optional-modules.png and b/docs/en/get-started/images/abp-studio-new-microservice-solution-dialog-optional-modules.png differ diff --git a/docs/en/get-started/images/abp-studio-new-microservice-solution-dialog-properties.png b/docs/en/get-started/images/abp-studio-new-microservice-solution-dialog-properties.png index 509033348d..fd811125c7 100644 Binary files a/docs/en/get-started/images/abp-studio-new-microservice-solution-dialog-properties.png and b/docs/en/get-started/images/abp-studio-new-microservice-solution-dialog-properties.png differ diff --git a/docs/en/get-started/images/abp-studio-new-solution-dialog-additional-options-microservice.png b/docs/en/get-started/images/abp-studio-new-solution-dialog-additional-options-microservice.png index af701b00d8..da7a5f22ea 100644 Binary files a/docs/en/get-started/images/abp-studio-new-solution-dialog-additional-options-microservice.png and b/docs/en/get-started/images/abp-studio-new-solution-dialog-additional-options-microservice.png differ diff --git a/docs/en/get-started/images/abp-studio-new-solution-dialog-additional-services.png b/docs/en/get-started/images/abp-studio-new-solution-dialog-additional-services.png new file mode 100644 index 0000000000..f7f088804b Binary files /dev/null and b/docs/en/get-started/images/abp-studio-new-solution-dialog-additional-services.png differ diff --git a/docs/en/get-started/images/abp-studio-new-solution-dialog-database-configurations-microservice.png b/docs/en/get-started/images/abp-studio-new-solution-dialog-database-configurations-microservice.png index 375e196fa5..910b522dd3 100644 Binary files a/docs/en/get-started/images/abp-studio-new-solution-dialog-database-configurations-microservice.png and b/docs/en/get-started/images/abp-studio-new-solution-dialog-database-configurations-microservice.png differ diff --git a/docs/en/get-started/images/abp-studio-new-solution-dialog-database-provider-microservice.png b/docs/en/get-started/images/abp-studio-new-solution-dialog-database-provider-microservice.png index 230e987365..4b8965456c 100644 Binary files a/docs/en/get-started/images/abp-studio-new-solution-dialog-database-provider-microservice.png and b/docs/en/get-started/images/abp-studio-new-solution-dialog-database-provider-microservice.png differ diff --git a/docs/en/get-started/images/abp-studio-new-solution-dialog-dynamic-localization.png b/docs/en/get-started/images/abp-studio-new-solution-dialog-dynamic-localization.png new file mode 100644 index 0000000000..3dedb0aba0 Binary files /dev/null and b/docs/en/get-started/images/abp-studio-new-solution-dialog-dynamic-localization.png differ diff --git a/docs/en/get-started/images/abp-studio-new-solution-dialog-mobile-framework-microservice.png b/docs/en/get-started/images/abp-studio-new-solution-dialog-mobile-framework-microservice.png index 7e43e784f3..f883555e4a 100644 Binary files a/docs/en/get-started/images/abp-studio-new-solution-dialog-mobile-framework-microservice.png and b/docs/en/get-started/images/abp-studio-new-solution-dialog-mobile-framework-microservice.png differ diff --git a/docs/en/get-started/images/abp-studio-new-solution-dialog-multi-tenancy.png b/docs/en/get-started/images/abp-studio-new-solution-dialog-multi-tenancy.png new file mode 100644 index 0000000000..2bc29805ee Binary files /dev/null and b/docs/en/get-started/images/abp-studio-new-solution-dialog-multi-tenancy.png differ diff --git a/docs/en/get-started/images/abp-studio-new-solution-dialog-public-web-site.png b/docs/en/get-started/images/abp-studio-new-solution-dialog-public-web-site.png index bb9f57e693..3dff0567fd 100644 Binary files a/docs/en/get-started/images/abp-studio-new-solution-dialog-public-web-site.png and b/docs/en/get-started/images/abp-studio-new-solution-dialog-public-web-site.png differ diff --git a/docs/en/get-started/images/abp-studio-new-solution-dialog-ui-framework-microservice.png b/docs/en/get-started/images/abp-studio-new-solution-dialog-ui-framework-microservice.png index 8969beba47..4a6fbf2d40 100644 Binary files a/docs/en/get-started/images/abp-studio-new-solution-dialog-ui-framework-microservice.png and b/docs/en/get-started/images/abp-studio-new-solution-dialog-ui-framework-microservice.png differ diff --git a/docs/en/get-started/images/abp-studio-new-solution-dialog-ui-theme-microservice.png b/docs/en/get-started/images/abp-studio-new-solution-dialog-ui-theme-microservice.png index 15d74ec7c2..553f0ca395 100644 Binary files a/docs/en/get-started/images/abp-studio-new-solution-dialog-ui-theme-microservice.png and b/docs/en/get-started/images/abp-studio-new-solution-dialog-ui-theme-microservice.png differ diff --git a/docs/en/get-started/microservice.md b/docs/en/get-started/microservice.md index e29c4cbe10..cca7d3c02e 100644 --- a/docs/en/get-started/microservice.md +++ b/docs/en/get-started/microservice.md @@ -49,7 +49,11 @@ On that screen, you can decide on your database provider by selecting one of the ![abp-studio-new-solution-dialog-database-configurations](images/abp-studio-new-solution-dialog-database-configurations-microservice.png) -Here, select the DBMS right for you, then click the *Next* button to navigate to the *UI Framework* selection: +Here, select the DBMS right for you, then click the *Next* button to navigate to the *Multi-Tenancy* selection: + +![abp-studio-new-solution-dialog-multi-tenancy](images/abp-studio-new-solution-dialog-multi-tenancy.png) + +On that screen, you can enable multi-tenancy for your solution. After selecting this option, click the Next button to proceed to the *UI Framework* selection screen. ![abp-studio-new-solution-dialog-ui-framework](images/abp-studio-new-solution-dialog-ui-framework-microservice.png) @@ -67,6 +71,10 @@ Pick the one best for you, or select the *None* if you don't want a mobile appli You can select a public website to be created in your solution. The public website is a simple landing page that can be used to introduce your product, provide documentation, and so on. +![abp-studio-new-solution-dialog-dynamic-localization](images/abp-studio-new-solution-dialog-dynamic-localization.png) + +On that screen, you can enable dynamic localization. After selecting this option, click the Next button to proceed to the *Optional Modules* selection screen. + ![abp-studio-new-microservice-solution-dialog-optional-modules](images/abp-studio-new-microservice-solution-dialog-optional-modules.png) Each item in that list is a pre-built application module. You can click the blue icon near to the module name to get more information about the module. You can leave the list as is (so, it installs the most common and used modules for you) or customize based on your preference. @@ -88,6 +96,12 @@ Click the Next button to see *Additional Options* selection: If you unchecked the *Kubernetes Configuration* option, the solution will not include the Kubernetes configuration files which include the Helm charts and other Kubernetes related files. You can also specify *Social Logins*; if you uncheck this option, the solution will not be configured for social login. Lastly, you can specify the *Include Tests* option to include the test projects in the solution. +Click the Next button to see *Additional Services* screen: + +![abp-studio-new-solution-dialog-additional-services](images/abp-studio-new-solution-dialog-additional-services.png) + +On that screen, allows you to include extra microservices in your ABP solution during the creation process. This feature lets you extend your solution with business-specific services right from the start. + Now, we are ready to allow ABP Studio to create our solution. Just click the *Create* button and let the ABP Studio do the rest for you. After clicking the *Create* button, the dialog is closed and your solution is loaded into ABP Studio: ![abp-studio-created-new-microservice-solution](images/abp-studio-created-new-microservice-solution.png) diff --git a/docs/en/release-info/migration-guides/abp-9-1.md b/docs/en/release-info/migration-guides/abp-9-1.md index 0e80da824a..5808f8f028 100644 --- a/docs/en/release-info/migration-guides/abp-9-1.md +++ b/docs/en/release-info/migration-guides/abp-9-1.md @@ -2,6 +2,8 @@ This document is a guide for upgrading ABP v9.0 solutions to ABP v9.1. There are no breaking changes in this version that would affect your application. -Only you might need to update some constant names due to the OpenIddict 6.0 upgrade, which is explained in the following migration guide: +You might need to update some constant names due to the OpenIddict 6.0 upgrade, which is explained in the following migration guide: -- [OpenIddict 5.x to 6.x Migration Guide](./openiddict5-to-6.md) \ No newline at end of file +- [OpenIddict 5.x to 6.x Migration Guide](./openiddict5-to-6.md) + +In addition, ABP version 9.1 has been upgraded to incorporate Angular version 19. Consequently, we recommend migrating your application to [Angular v19](https://angular.dev/update-guide) to ensure compatibility. \ No newline at end of file diff --git a/docs/en/solution-templates/layered-web-application/cors-configuration.md b/docs/en/solution-templates/layered-web-application/cors-configuration.md index 6df207c107..73e7b6952b 100644 --- a/docs/en/solution-templates/layered-web-application/cors-configuration.md +++ b/docs/en/solution-templates/layered-web-application/cors-configuration.md @@ -8,8 +8,8 @@ "Path": "solution-templates/layered-web-application/blob-storing" }, "Next": { - "Name": "Helm Charts and Kubernetes", - "Path": "solution-templates/layered-web-application/helm-charts-and-kubernetes" + "Name": "Health Check Configuration", + "Path": "solution-templates/layered-web-application/health-check-configuration" } } ``` diff --git a/docs/en/solution-templates/layered-web-application/health-check-configuration.md b/docs/en/solution-templates/layered-web-application/health-check-configuration.md new file mode 100644 index 0000000000..cd1f69c99b --- /dev/null +++ b/docs/en/solution-templates/layered-web-application/health-check-configuration.md @@ -0,0 +1,121 @@ +# Layered Solution: Health Check Configuration + +```json +//[doc-nav] +{ + "Previous": { + "Name": "CORS Configuration", + "Path": "solution-templates/single-layer-web-application/cors-configuration" + }, + "Next": { + "Name": "Helm Charts and Kubernetes", + "Path": "solution-templates/layered-web-application/helm-charts-and-kubernetes" + } +} +``` + +Health Check is a feature that allows applications to monitor their health and diagnose potential issues. The layered solution template comes with pre-configured Health Check system. + +In the layered solution template, Health Check configuration is applied in the following cases: + +- When [MVC](https://abp.io/docs/latest/solution-templates/single-layer-web-application/web-applications#mvc) is selected as the web application type. +- When [Blazor Server](https://abp.io/docs/latest/solution-templates/single-layer-web-application/web-applications#blazor-server) is selected as the web application type. +- When [Blazor WebAssembly](https://abp.io/docs/latest/solution-templates/single-layer-web-application/web-applications#blazor-webassembly) is selected as the web application type (configured at the backend). +- When [Blazor WebApp](https://abp.io/docs/latest/solution-templates/single-layer-web-application/web-applications#blazor-webapp) is selected as the web application type (configured at the backend). +- When [Angular](https://abp.io/docs/latest/solution-templates/single-layer-web-application/web-applications#angular) is selected as the web application type (configured at the backend). +- When [No UI](https://abp.io/docs/latest/solution-templates/single-layer-web-application/web-applications#no-ui) is selected as the web application type (configured at the backend). + +### Configuration in `HealthChecksBuilderExtensions.cs` + +Health Checks are configured in the `HealthChecksBuilderExtensions` class. This class extends `IServiceCollection` to register health check services and configure health check UI endpoints. + +#### Default Configuration + +The default setup is as follows: + +```csharp +using HealthChecks.UI.Client; +using Microsoft.AspNetCore.Diagnostics.HealthChecks; + +namespace MyCompanyName.MyProjectName.HealthChecks; + +public static class HealthChecksBuilderExtensions +{ + public static void AddMyProjectNameHealthChecks(this IServiceCollection services) + { + // Add your health checks here + var healthChecksBuilder = services.AddHealthChecks(); + healthChecksBuilder.AddCheck("MyProjectName DbContext Check", tags: new string[] { "database" }); + + // Read configuration for health check URL + var configuration = services.GetConfiguration(); + var healthCheckUrl = configuration["App:HealthCheckUrl"] ?? "/health-status"; + + services.ConfigureHealthCheckEndpoint(healthCheckUrl); + + // Configure HealthChecks UI + var healthChecksUiBuilder = services.AddHealthChecksUI(settings => + { + settings.AddHealthCheckEndpoint("MyProjectName Health Status", healthCheckUrl); + }); + + // Set HealthCheck UI storage + healthChecksUiBuilder.AddInMemoryStorage(); + + services.MapHealthChecksUiEndpoints(options => + { + options.UIPath = "/health-ui"; + options.ApiPath = "/health-api"; + }); + } + + private static IServiceCollection ConfigureHealthCheckEndpoint(this IServiceCollection services, string path) + { + .... + } + + private static IServiceCollection MapHealthChecksUiEndpoints(this IServiceCollection services, Action? setupOption = null) + { + .... + } +} +``` + +### Database Health Check Implementation + +The `MyProjectNameDatabaseCheck` class is a custom implementation of a health check that verifies database connectivity using `IIdentityRoleRepository`. + +```csharp +using System; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Diagnostics.HealthChecks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Identity; + +namespace MyCompanyName.MyProjectName.HealthChecks; + +public class MyProjectNameDatabaseCheck : IHealthCheck, ITransientDependency +{ + protected readonly IIdentityRoleRepository IdentityRoleRepository; + + public MyProjectNameDatabaseCheck(IIdentityRoleRepository identityRoleRepository) + { + IdentityRoleRepository = identityRoleRepository; + } + + public async Task CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) + { + try + { + await IdentityRoleRepository.GetListAsync(sorting: nameof(IdentityRole.Id), maxResultCount: 1, cancellationToken: cancellationToken); + return HealthCheckResult.Healthy($"Could connect to database and get record."); + } + catch (Exception e) + { + return HealthCheckResult.Unhealthy($"Error when trying to get database record. ", e); + } + } +} +``` + diff --git a/docs/en/solution-templates/microservice/adding-new-microservices.md b/docs/en/solution-templates/microservice/adding-new-microservices.md index 9cb482c552..610beaef7f 100644 --- a/docs/en/solution-templates/microservice/adding-new-microservices.md +++ b/docs/en/solution-templates/microservice/adding-new-microservices.md @@ -24,6 +24,8 @@ To add a new microservice to the solution, you can use the `service_nolayers` te In ABP Studio [Solution Explorer](../../studio/solution-explorer.md#adding-a-new-microservice-module), right-click on the `services` folder and select `Add` -> `New Module` -> `Microservice`. +You can also add microservices during the project creation process by using the Additional Services screen. For more details, refer to the [Additional Services](../../get-started/microservice.md) section. + ![new-microservice](images/new-microservice.png) It opens the `Create New Module` dialog. Enter the name of the new microservice, specify the output directory if needed, and click the `Next` button. There is a naming convention: the *Module name* should include the solution name as a prefix, and the use of the dot (.) character in the *Module name* is not allowed. diff --git a/docs/en/solution-templates/microservice/cors-configuration.md b/docs/en/solution-templates/microservice/cors-configuration.md index 2ca44342f4..8157bb95ae 100644 --- a/docs/en/solution-templates/microservice/cors-configuration.md +++ b/docs/en/solution-templates/microservice/cors-configuration.md @@ -4,8 +4,8 @@ //[doc-nav] { "Next": { - "Name": "Communication in the Microservice solution", - "Path": "solution-templates/microservice/communication" + "Name": "Health Check Configuration", + "Path": "solution-templates/microservice/health-check-configuration" } } ```` diff --git a/docs/en/solution-templates/microservice/health-check-configuration.md b/docs/en/solution-templates/microservice/health-check-configuration.md new file mode 100644 index 0000000000..37cd515209 --- /dev/null +++ b/docs/en/solution-templates/microservice/health-check-configuration.md @@ -0,0 +1,110 @@ +# Microservice Solution: Health Check Configuration + +```json +//[doc-nav] +{ + "Next": { + "Name": "Communication in the Microservice solution", + "Path": "solution-templates/microservice/communication" + } +} +``` + +Health Check is a feature that allows applications to monitor their health and diagnose potential issues. The Microservice solution template comes with pre-configured Health Check system. + +In the Microservice solution template, Health Check configuration is applied in all the services, gateways and UI applications (except Blazor Wasm & Blazor WebApp applications UI applications). + +### Configuration in `HealthChecksBuilderExtensions.cs` + +Health Checks are configured in the `HealthChecksBuilderExtensions` class. This class extends `IServiceCollection` to register health check services and configure health check UI endpoints. + +#### Default Configuration + +The default setup is as follows: + +```csharp +using HealthChecks.UI.Client; +using Microsoft.AspNetCore.Diagnostics.HealthChecks; + +namespace MyCompanyName.MyProjectName.HealthChecks; + +public static class HealthChecksBuilderExtensions +{ + public static void AddMyProjectNameHealthChecks(this IServiceCollection services) + { + // Add your health checks here + var healthChecksBuilder = services.AddHealthChecks(); + healthChecksBuilder.AddCheck("MyProjectName DbContext Check", tags: new string[] { "database" }); + + // Read configuration for health check URL + var configuration = services.GetConfiguration(); + var healthCheckUrl = configuration["App:HealthCheckUrl"] ?? "/health-status"; + + services.ConfigureHealthCheckEndpoint(healthCheckUrl); + + // Configure HealthChecks UI + var healthChecksUiBuilder = services.AddHealthChecksUI(settings => + { + settings.AddHealthCheckEndpoint("MyProjectName Health Status", healthCheckUrl); + }); + + // Set HealthCheck UI storage + healthChecksUiBuilder.AddInMemoryStorage(); + + services.MapHealthChecksUiEndpoints(options => + { + options.UIPath = "/health-ui"; + options.ApiPath = "/health-api"; + }); + } + + private static IServiceCollection ConfigureHealthCheckEndpoint(this IServiceCollection services, string path) + { + .... + } + + private static IServiceCollection MapHealthChecksUiEndpoints(this IServiceCollection services, Action? setupOption = null) + { + .... + } +} +``` + +### Database Health Check Implementation + +The `MyProjectNameDatabaseCheck` class is a custom implementation of a health check that verifies database connectivity in the applications with database connection. Example: + +```csharp +using System; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Diagnostics.HealthChecks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Identity; + +namespace MyCompanyName.MyProjectName.HealthChecks; + +public class MyProjectNameDatabaseCheck : IHealthCheck, ITransientDependency +{ + protected readonly IIdentityRoleRepository IdentityRoleRepository; + + public MyProjectNameDatabaseCheck(IIdentityRoleRepository identityRoleRepository) + { + IdentityRoleRepository = identityRoleRepository; + } + + public async Task CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) + { + try + { + await IdentityRoleRepository.GetListAsync(sorting: nameof(IdentityRole.Id), maxResultCount: 1, cancellationToken: cancellationToken); + return HealthCheckResult.Healthy($"Could connect to database and get record."); + } + catch (Exception e) + { + return HealthCheckResult.Unhealthy($"Error when trying to get database record. ", e); + } + } +} +``` + diff --git a/docs/en/solution-templates/single-layer-web-application/cors-configuration.md b/docs/en/solution-templates/single-layer-web-application/cors-configuration.md index f54c73ad79..71f1991e59 100644 --- a/docs/en/solution-templates/single-layer-web-application/cors-configuration.md +++ b/docs/en/solution-templates/single-layer-web-application/cors-configuration.md @@ -6,6 +6,10 @@ "Previous": { "Name": "BLOB Storing", "Path": "solution-templates/single-layer-web-application/blob-storing" + }, + "Next": { + "Name": "Health Check Configuration", + "Path": "solution-templates/single-layer-web-application/health-check-configuration" } } ``` diff --git a/docs/en/solution-templates/single-layer-web-application/health-check-configuration.md b/docs/en/solution-templates/single-layer-web-application/health-check-configuration.md new file mode 100644 index 0000000000..b62b544cbd --- /dev/null +++ b/docs/en/solution-templates/single-layer-web-application/health-check-configuration.md @@ -0,0 +1,115 @@ +# Single Layer Solution: Health Check Configuration + +```json +//[doc-nav] +{ + "Previous": { + "Name": "CORS Configuration", + "Path": "solution-templates/single-layer-web-application/cors-configuration" + } +} +``` + +Health Check is a feature that allows applications to monitor their health and diagnose potential issues. The single-layer solution template comes with pre-configured Health Check system. + +In the single-layer solution template, Health Check configuration is applied in the following cases: + +- When [MVC](https://abp.io/docs/latest/solution-templates/single-layer-web-application/web-applications#mvc) is selected as the web application type. +- When [Blazor Server](https://abp.io/docs/latest/solution-templates/single-layer-web-application/web-applications#blazor-server) is selected as the web application type. +- When [Angular](https://abp.io/docs/latest/solution-templates/single-layer-web-application/web-applications#angular) is selected as the web application type (configured at the backend). +- When [No UI](https://abp.io/docs/latest/solution-templates/single-layer-web-application/web-applications#no-ui) is selected as the web application type (configured at the backend). + +### Configuration in `HealthChecksBuilderExtensions.cs` + +Health Checks are configured in the `HealthChecksBuilderExtensions` class. This class extends `IServiceCollection` to register health check services and configure health check UI endpoints. + +#### Default Configuration + +The default setup is as follows: + +```csharp +using HealthChecks.UI.Client; +using Microsoft.AspNetCore.Diagnostics.HealthChecks; + +namespace MyCompanyName.MyProjectName.HealthChecks; + +public static class HealthChecksBuilderExtensions +{ + public static void AddMyProjectNameHealthChecks(this IServiceCollection services) + { + // Add your health checks here + var healthChecksBuilder = services.AddHealthChecks(); + healthChecksBuilder.AddCheck("MyProjectName DbContext Check", tags: new string[] { "database" }); + + // Read configuration for health check URL + var configuration = services.GetConfiguration(); + var healthCheckUrl = configuration["App:HealthCheckUrl"] ?? "/health-status"; + + services.ConfigureHealthCheckEndpoint(healthCheckUrl); + + // Configure HealthChecks UI + var healthChecksUiBuilder = services.AddHealthChecksUI(settings => + { + settings.AddHealthCheckEndpoint("MyProjectName Health Status", healthCheckUrl); + }); + + // Set HealthCheck UI storage + healthChecksUiBuilder.AddInMemoryStorage(); + + services.MapHealthChecksUiEndpoints(options => + { + options.UIPath = "/health-ui"; + options.ApiPath = "/health-api"; + }); + } + + private static IServiceCollection ConfigureHealthCheckEndpoint(this IServiceCollection services, string path) + { + .... + } + + private static IServiceCollection MapHealthChecksUiEndpoints(this IServiceCollection services, Action? setupOption = null) + { + .... + } +} +``` + +### Database Health Check Implementation + +The `MyProjectNameDatabaseCheck` class is a custom implementation of a health check that verifies database connectivity using `IIdentityRoleRepository`. + +```csharp +using System; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Diagnostics.HealthChecks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Identity; + +namespace MyCompanyName.MyProjectName.HealthChecks; + +public class MyProjectNameDatabaseCheck : IHealthCheck, ITransientDependency +{ + protected readonly IIdentityRoleRepository IdentityRoleRepository; + + public MyProjectNameDatabaseCheck(IIdentityRoleRepository identityRoleRepository) + { + IdentityRoleRepository = identityRoleRepository; + } + + public async Task CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) + { + try + { + await IdentityRoleRepository.GetListAsync(sorting: nameof(IdentityRole.Id), maxResultCount: 1, cancellationToken: cancellationToken); + return HealthCheckResult.Healthy($"Could connect to database and get record."); + } + catch (Exception e) + { + return HealthCheckResult.Unhealthy($"Error when trying to get database record. ", e); + } + } +} +``` + diff --git a/docs/en/studio/images/monitoring-applications/overall.png b/docs/en/studio/images/monitoring-applications/overall.png index a56ed043f9..dfd0f71ae3 100644 Binary files a/docs/en/studio/images/monitoring-applications/overall.png and b/docs/en/studio/images/monitoring-applications/overall.png differ diff --git a/docs/en/studio/images/solution-runner/csharp-application-context-menu-build.png b/docs/en/studio/images/solution-runner/csharp-application-context-menu-build.png index aec7d5d0d7..5b0fe32119 100644 Binary files a/docs/en/studio/images/solution-runner/csharp-application-context-menu-build.png and b/docs/en/studio/images/solution-runner/csharp-application-context-menu-build.png differ diff --git a/docs/en/studio/images/solution-runner/csharp-application-context-menu-monitor.png b/docs/en/studio/images/solution-runner/csharp-application-context-menu-monitor.png index 42eca8cf00..bdc601c2a9 100644 Binary files a/docs/en/studio/images/solution-runner/csharp-application-context-menu-monitor.png and b/docs/en/studio/images/solution-runner/csharp-application-context-menu-monitor.png differ diff --git a/docs/en/studio/images/solution-runner/csharp-application-context-menu.png b/docs/en/studio/images/solution-runner/csharp-application-context-menu.png index 76c90a2e95..fbe7e6993d 100644 Binary files a/docs/en/studio/images/solution-runner/csharp-application-context-menu.png and b/docs/en/studio/images/solution-runner/csharp-application-context-menu.png differ diff --git a/docs/en/studio/images/solution-runner/solutioın-runner-properties.png b/docs/en/studio/images/solution-runner/solutioın-runner-properties.png index 8611f8be3d..9a6505a7d1 100644 Binary files a/docs/en/studio/images/solution-runner/solutioın-runner-properties.png and b/docs/en/studio/images/solution-runner/solutioın-runner-properties.png differ diff --git a/docs/en/studio/monitoring-applications.md b/docs/en/studio/monitoring-applications.md index 6d0c5523a3..5ef2dc0f91 100644 --- a/docs/en/studio/monitoring-applications.md +++ b/docs/en/studio/monitoring-applications.md @@ -59,6 +59,7 @@ In the data grid, details for each application are displayed. It's possible to s - `Name`: The name of the application. - `State`: The state of the application. It can take on several values such as *Scheduled*, *Starting*, *Started*, *Stopping* and *Stopped*. In the event of an application crash during its starting, the state is mark as *Scheduled*, we can cancel the starting process at that stage. +- `Health` : The health state of the application. Clicking on the icon shows the latest health check response. Displays `N/A` if the application is not running or health check is not configured for the application. - `Instances`: Indicates the count of running instances for the application. This value is particularly helpful when scaling the application within a Kubernetes, providing visibility into the number of currently active instances. - `Uptime`: The time elapsed since the application started. - `Requests`: The number of HTTP requests received by the application. diff --git a/docs/en/studio/release-notes.md b/docs/en/studio/release-notes.md index 10f76880ab..ef498fcac5 100644 --- a/docs/en/studio/release-notes.md +++ b/docs/en/studio/release-notes.md @@ -2,6 +2,10 @@ This document contains **brief release notes** for each ABP Studio release. Release notes only include **major features** and **visible enhancements**. Therefore, they don't include all the development done in the related version. +## 0.9.25 (2025-03-12) + +* Added ready/health check for solution runner. + ## 0.9.24 (2025-03-11) * Added automatic installation of necessary dependencies. diff --git a/docs/en/studio/running-applications.md b/docs/en/studio/running-applications.md index 5392250153..9188f202ae 100644 --- a/docs/en/studio/running-applications.md +++ b/docs/en/studio/running-applications.md @@ -196,16 +196,19 @@ When the C# application is connected to ABP Studio, it starts sending telemetry ![csharp-application-context-menu-monitor](images/solution-runner/csharp-application-context-menu-monitor.png) - `Browse`: ABP Studio includes a browser tool for accessing websites and running applications. You can click this option to view the application in the ABP Studio browser. However, this option is only accessible if the application is started. +- Health Status : If Health Check endpoints are defined, it allows you to browse Health UI and see the latest health check response. - `Requests`: It opens the *HTTP Requests* tab with adding the selected application filter. You can view all *HTTP Requests* received by your applications. - `Exceptions`: We can display all exceptions on this tab. It opens the *Exceptions* tab with selected application. - `Logs`: Clicking this option opens the *Logs* tab with adding the selected application filter. ### Properties -We can open the *Application Properties* window to change *Launch url*, *Kubernetes service* and *run* information. To access the *Application Properties* window, navigate to a C# application, right-click to view the context menu, and select the Properties option. +We can open the *Application Properties* window to change *Launch url*, *Health check endpoints*, *Kubernetes service* and *run* information. To access the *Application Properties* window, navigate to a C# application, right-click to view the context menu, and select the Properties option. ![solutioın-runner-properties](images/solution-runner/solutioın-runner-properties.png) +- **Health check endpoint**: Endpoint for controlling the health status of the application periodically. If the application doesn't have a endpoint for health check, you can enter `/` to use the home page of the application as health check endpoint. +- **Health UI endpoint**: Endpoint of the Health UI page of the application. - **Skip build before starting**: When enabled, application is started without build and it makes starting faster. This is useful when you are working on a single application out of multiple, so you don't need to build others everytime they start. - **Watch changes while running**: When enabled, you should see an *eye* icon next to the application name. diff --git a/docs/en/studio/version-mapping.md b/docs/en/studio/version-mapping.md index 3aa2a1cd7e..cd82da602a 100644 --- a/docs/en/studio/version-mapping.md +++ b/docs/en/studio/version-mapping.md @@ -4,7 +4,7 @@ This document provides a general overview of the relationship between various ve | **ABP Studio Version** | **ABP Version of Startup Template** | |------------------------|---------------------------| -| 0.9.24 | 9.1.0 | +| 0.9.24 - 0.9.25 | 9.1.0 | | 0.9.22 - 0.9.23 | 9.0.4 | | 0.9.20 - 0.9.21 | 9.0.3 | | 0.9.17 to 0.9.19 | 9.0.2 | diff --git a/docs/en/tutorials/book-store/part-01.md b/docs/en/tutorials/book-store/part-01.md index 51bfcd1b09..61de79d035 100644 --- a/docs/en/tutorials/book-store/part-01.md +++ b/docs/en/tutorials/book-store/part-01.md @@ -36,22 +36,6 @@ abp install-libs > We suggest you install [Yarn v1.22+ (not v2)](https://classic.yarnpkg.com/en/docs/install) to prevent possible package inconsistencies, if you haven't installed it yet. -{{if UI=="Blazor" || UI=="BlazorWebApp"}} - -### Bundling and Minification - -`abp bundle` command offers bundling and minification support for client-side resources (JavaScript and CSS files) for Blazor projects. This command automatically run when you create a new solution with the [ABP CLI](../../cli). - -However, sometimes you might need to run this command manually. To update script & style references without worrying about dependencies, ordering, etc. in a project, you can run this command in the directory of your `*.Blazor.Client` project: - -```bash -abp bundle -``` - -> For more details about managing style and script references in Blazor or MAUI Blazor apps, see [Managing Global Scripts & Styles](../../framework/ui/blazor/global-scripts-styles.md). - -{{end}} - ## Create the Book Entity **Domain layer** in the startup template is separated into two projects: diff --git a/docs/en/tutorials/todo/layered/index.md b/docs/en/tutorials/todo/layered/index.md index 5ba38380f3..e6e310a39a 100644 --- a/docs/en/tutorials/todo/layered/index.md +++ b/docs/en/tutorials/todo/layered/index.md @@ -113,23 +113,6 @@ abp install-libs > We suggest you install [Yarn v1.22+ (not v2)](https://classic.yarnpkg.com/en/docs/install) to prevent possible package inconsistencies, if you haven't installed it yet. -{{if UI=="Blazor" || UI=="BlazorWebApp" || UI=="MAUIBlazor"}} - -#### Bundling and Minification - -`abp bundle` command offers bundling and minification support for client-side resources (JavaScript and CSS files) for Blazor projects. This command automatically run when you create a new solution with the [ABP CLI](../../../cli/index.md). - -However, sometimes you might need to run this command manually. To update script & style references without worrying about dependencies, ordering, etc. in a project, you can run this command in the directory of your `Blazor.Client` application: - - -````bash -abp bundle -```` - -> For more details about managing style and script references in Blazor or MAUI Blazor apps, see [Managing Global Scripts & Styles](../../../framework/ui/blazor/global-scripts-styles.md). - -{{end}} - ### Run the Application {{if UI=="MVC" || UI=="BlazorServer" || UI=="BlazorWebApp"}} diff --git a/docs/en/tutorials/todo/single-layer/index.md b/docs/en/tutorials/todo/single-layer/index.md index c96c3715ef..dc865a0a75 100644 --- a/docs/en/tutorials/todo/single-layer/index.md +++ b/docs/en/tutorials/todo/single-layer/index.md @@ -115,20 +115,6 @@ abp install-libs > We suggest you install [Yarn v1.22+ (not v2)](https://classic.yarnpkg.com/en/docs/install) to prevent possible package inconsistencies, if you haven't installed it yet. -{{if UI=="Blazor" || UI=="BlazorServer"}} - -#### Bundling and Minification - -Run the following command in the directory of your blazor application: - -```bash -abp bundle -``` - -> For more details about managing style and script references in Blazor or MAUI Blazor apps, see [Managing Global Scripts & Styles](../../../framework/ui/blazor/global-scripts-styles.md). - -{{end}} - ### Run the Application {{if UI=="MVC" || UI=="BlazorServer"}} diff --git a/docs/en/ui-themes/lepton-x-lite/blazor.md b/docs/en/ui-themes/lepton-x-lite/blazor.md index 3a9051b760..3f9a7ce7a5 100644 --- a/docs/en/ui-themes/lepton-x-lite/blazor.md +++ b/docs/en/ui-themes/lepton-x-lite/blazor.md @@ -21,7 +21,27 @@ This theme is **already installed** when you create a new solution using the sta - Complete the [MVC Razor Pages Installation](asp-net-core.md#installation) for the **HttpApi.Host** application first. _If the solution is tiered/micro-service, complete the MVC steps for all MVC applications such as **HttpApi.Host** and if Auth Server is separated, install to the **OpenIddict**_. -- Add **Volo.Abp.AspNetCore.Components.WebAssembly.LeptonXLiteTheme** package to your **Blazor WebAssembly** application with the following command: +- Add **Volo.Abp.AspNetCore.Components.WebAssembly.LeptonXLiteTheme.Bundling** package to your **Blazor** application with the following command: + + ```bash + dotnet add package Volo.Abp.AspNetCore.Components.WebAssembly.LeptonXLiteTheme.Bundling --prerelease + ``` + +- Remove **Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.Bundling** reference from the project since it's not necessary after switching to LeptonX Lite. + +- Remove the old theme from the **DependsOn** attribute in your module class and add the **AbpAspNetCoreComponentsWebAssemblyLeptonXLiteThemeBundlingModule** type to the **DependsOn** attribute. + +```diff +[DependsOn( + // Remove BasicTheme module from DependsOn attribute +- typeof(AbpAspNetCoreComponentsWebAssemblyBasicThemeBundlingModule), + + // Add LeptonX Lite module to DependsOn attribute ++ typeof(AbpAspNetCoreComponentsWebAssemblyLeptonXLiteThemeBundlingModule), +)] +``` + +- Add **Volo.Abp.AspNetCore.Components.WebAssembly.LeptonXLiteTheme** package to your **Blazor.Client** application with the following command: ```bash dotnet add package Volo.Abp.AspNetCore.Components.WebAssembly.LeptonXLiteTheme --prerelease @@ -41,14 +61,21 @@ This theme is **already installed** when you create a new solution using the sta )] ``` -- Change startup App component with the LeptonX one. - -```csharp -// Make sure the 'App' comes from 'Volo.Abp.AspNetCore.Components.Web.LeptonXLiteTheme.Themes.LeptonXLite' namespace. -builder.RootComponents.Add("#ApplicationContainer"); -``` - -- Run the `abp bundle` command in your **Blazor** application folder. +Update `Routes.razor` file in `Blazor.Client` project as below: + +````csharp +@using Volo.Abp.AspNetCore.Components.Web.LeptonXLiteTheme.Themes.LeptonXLite +@using Volo.Abp.AspNetCore.Components.WebAssembly.WebApp + + + + + + + + + +```` {{end}} @@ -93,27 +120,37 @@ builder.RootComponents.Add("#ApplicationContainer"); }); ``` -- Update `_Host.cshtml` file. _(located under **Pages** folder by default.)_ - - - Add following usings to Locate **App** and **BlazorLeptonXLiteThemeBundles** classes. +- Update `App.razor` file. _(located under **Components** folder by default.)_ + - Add following namespace at the top of the page. ```csharp - @using Volo.Abp.AspNetCore.Components.Web.LeptonXLiteTheme.Themes.LeptonXLite - @using Volo.Abp.AspNetCore.Components.Server.LeptonXLiteTheme.Bundling + @ using Volo.Abp.AspNetCore.Components.Server.LeptonXLiteTheme.Bundling ``` - - Then replace script & style bundles as following: - ```diff - // Remove following line - - - // Add following line instead - + + - Then replace script & style bunles as following + ``` + ``` - ```diff - // Remove following line - - - // Add following line instead - + ``` + + ``` + +Update `Routes.razor` file as below: + +````csharp +@using Volo.Abp.AspNetCore.Components.Web.LeptonXLiteTheme.Themes.LeptonXLite +@using Volo.Abp.AspNetCore.Components.Web.Theming.Routing +@using Microsoft.Extensions.Options +@inject IOptions RouterOptions + + + + + + + + + +```` {{end}} diff --git a/docs/en/ui-themes/lepton-x/blazor.md b/docs/en/ui-themes/lepton-x/blazor.md index 24f17b50ea..5e49752ebb 100644 --- a/docs/en/ui-themes/lepton-x/blazor.md +++ b/docs/en/ui-themes/lepton-x/blazor.md @@ -13,37 +13,95 @@ LeptonX theme is implemented and ready to use with ABP. No custom implementation {{if UI == "Blazor"}} -- Add **Volo.Abp.AspNetCore.Components.WebAssembly.LeptonXTheme** package to your **Blazor WASM** application. +- Complete the [MVC Razor Pages Installation](asp-net-core.md#installation) for the **HttpApi.Host** application first. _If the solution is tiered/micro-service, complete the MVC steps for all MVC applications such as **HttpApi.Host** and if Auth Server is separated, install to the **OpenIddict**_. + + +- Add **Volo.Abp.AspNetCore.Components.WebAssembly.LeptonXTheme.Bundling** package to your **Blazor** application with the following command: + ```bash - dotnet add package Volo.Abp.AspNetCore.Components.WebAssembly.LeptonXTheme + dotnet add package Volo.Abp.AspNetCore.Components.WebAssembly.LeptonXTheme.Bundling --prerelease ``` -- Remove old theme from **DependsOn** attribute in your module class and add **AbpAspNetCoreComponentsWebAssemblyLeptonXThemeModule** type to **DependsOn** attribute. +- Remove **Volo.Abp.AspNetCore.Components.WebAssembly.LeptonTheme.Bundling** reference from the project since it's not necessary after switching to LeptonX Lite. + +- Remove the old theme from the **DependsOn** attribute in your module class and add the **AbpAspNetCoreComponentsWebAssemblyLeptonXThemeBundlingModule** type to the **DependsOn** attribute. ```diff [DependsOn( -- typeof(LeptonThemeManagementBlazorModule), -- typeof(AbpAspNetCoreComponentsWebAssemblyLeptonThemeModule), -+ typeof(AbpAspNetCoreComponentsWebAssemblyLeptonXThemeModule) + // Remove LeptonTheme module from DependsOn attribute +- typeof(AbpAspNetCoreComponentsWebAssemblyLeptonThemeBundlingModule), + + // Add LeptonX Lite module to DependsOn attribute ++ typeof(AbpAspNetCoreComponentsWebAssemblyLeptonXThemeBundlingModule), )] ``` -- Change startup `App` component with the LeptonX one. - - Add following using declaration and remove your old theme using declaration. - ```csharp - using Volo.Abp.AspNetCore.Components.Web.LeptonXTheme.Components; - ``` +- Add **Volo.Abp.AspNetCore.Components.WebAssembly.LeptonXTheme** package to your **Blazor.Client** application with the following command: - - Make sure `App` component in following block is `Volo.Abp.AspNetCore.Components.Web.LeptonXTheme.Components.App` - ```csharp - // Make sure the 'App' comes from 'Volo.Abp.AspNetCore.Components.Web.LeptonXTheme.Components' namespace. - builder.RootComponents.Add("#ApplicationContainer"); - ``` - - If you can't remove or not sure which one is the old theme's using statements, you can use full name of that class: - ```csharp - builder.RootComponents.Add("#ApplicationContainer"); - ``` + ```bash + dotnet add package Volo.Abp.AspNetCore.Components.WebAssembly.LeptonXTheme --prerelease + ``` + +- Remove **Volo.Abp.AspNetCore.Components.WebAssembly.LeptonTheme** reference from the project since it's not necessary after switching to LeptonX Lite. + +- Remove the old theme from the **DependsOn** attribute in your module class and add the **AbpAspNetCoreComponentsWebAssemblyLeptonXThemeModule** type to the **DependsOn** attribute. + +```diff +[DependsOn( + // Remove LeptonTheme module from DependsOn attribute +- typeof(AbpAspNetCoreComponentsWebAssemblyLeptonThemeModule), + + // Add LeptonX Lite module to DependsOn attribute ++ typeof(AbpAspNetCoreComponentsWebAssemblyLeptonXThemeModule), +)] +``` + +Update `Routes.razor` file in `Blazor.Client` project as below: + +````csharp +@using Microsoft.Extensions.Options +@using Microsoft.Extensions.Localization +@using global::Localization.Resources.AbpUi +@using Volo.Abp.AspNetCore.Components.Web.LeptonXTheme +@using Volo.Abp.AspNetCore.Components.Web.LeptonXTheme.Components +@using Volo.Abp.AspNetCore.Components.Web.LeptonXTheme.Components.ApplicationLayout +@using Volo.Abp.AspNetCore.Components.Web.Theming.Routing +@using Volo.Abp.AspNetCore.Components.WebAssembly.WebApp +@inject IOptions RouterOptions +@inject IOptions LayoutOptions +@inject IStringLocalizer UiLocalizer + + + + + + + @if (context.User?.Identity?.IsAuthenticated != true) + { + + } + else + { + + } + + + + + + + + + + +```` {{end}} @@ -78,22 +136,66 @@ LeptonX theme is implemented and ready to use with ABP. No custom implementation }); ``` -- Update `_Host.cshtml` file. _(located under **Pages** folder by default.)_ - - Add following usings to Locate **App** and **BlazorLeptonXThemeBundles** classes. +- Update `App.razor` file. _(located under **Components** folder by default.)_ + - Add following namespace at the top of the page. ```csharp - @using Volo.Abp.AspNetCore.Components.Web.LeptonXTheme.Components @using Volo.Abp.AspNetCore.Components.Server.LeptonXTheme.Bundling ``` - Then replace script & style bunles as following - ```diff - - - + + ``` + ``` - ```diff - - - + ``` + + ``` + +Update `Routes.razor` file as below: + +````csharp +@using Microsoft.Extensions.Options +@using Microsoft.Extensions.Localization +@using global::Localization.Resources.AbpUi +@using Volo.Abp.AspNetCore.Components.Web.LeptonXTheme +@using Volo.Abp.AspNetCore.Components.Web.LeptonXTheme.Components +@using Volo.Abp.AspNetCore.Components.Web.LeptonXTheme.Components.ApplicationLayout +@using Volo.Abp.AspNetCore.Components.Web.Theming.Routing +@using Volo.Abp.AspNetCore.Components.WebAssembly.WebApp +@inject IOptions RouterOptions +@inject IOptions LayoutOptions +@inject IStringLocalizer UiLocalizer + + + + + + + @if (context.User?.Identity?.IsAuthenticated != true) + { + + } + else + { + + } + + + + + + + + + + +```` + {{end}} --- @@ -167,33 +269,6 @@ Layout options of Blazor UI can be manageable via using **LeptonXThemeMvcOptions }); ``` -{{if UI == "Blazor"}} - -#### Updating Bundles on Layout Changes -Layout changes requires bundling and restarting the application. Before bundling, you have to add your layout to `appsettings.json`. Make sure `AbpCli:Bundle:Paramters` has `LeptonXTheme.Layout` key with your layout name. Available values are `side-menu` & `top-menu`. - - -_You can add the following section to root level of your appsettings.json file if not added._ -```json - "AbpCli": { - "Bundle": { - "Mode": "BundleAndMinify", /* Options: None, Bundle, BundleAndMinify */ - "Name": "global", - "Parameters": { - "LeptonXTheme.Layout": "top-menu" /* Options: side-menu, top-menu */ - } - } - } -``` - -Then you can run bundling command with ABP Cli - -```bash -abp bundle -``` - -{{end}} - ### Toolbars LeptonX includes separeted toolbars for desktop & mobile. You can manage toolbars independently. Toolbar names can be accessible in the **LeptonXToolbars** class. @@ -224,6 +299,7 @@ public async Task ConfigureToolbarAsync(IToolbarConfigurationContext context) {{end}} + ## Layouts **LeptonX** offers two **ready-made layouts** for your web application. One of them is **placed** with the **menu items** on the **top** and the other with the **menu items** on the **sides**. @@ -258,7 +334,7 @@ You can override layouts by following the steps below: using Volo.Abp.AspNetCore.Components.Web.LeptonXTheme.Components.ApplicationLayout; using Volo.Abp.DependencyInjection; -namespace LeptonXLite.DemoApp.Blazor.MyComponents +namespace LeptonX.DemoApp.Blazor.MyComponents { [ExposeServices(typeof(SideMenuLayout))] [Dependency(ReplaceServices = true)] @@ -305,7 +381,7 @@ If you need to replace the component, you can follow the steps below. using Volo.Abp.AspNetCore.Components.Web.LeptonXTheme.Components.ApplicationLayout.Common; using Volo.Abp.DependencyInjection; -namespace LeptonXLite.DemoApp.Blazor.MyComponents +namespace LeptonX.DemoApp.Blazor.MyComponents { [ExposeServices(typeof(Breadcrumbs))] [Dependency(ReplaceServices = true)] @@ -338,7 +414,7 @@ namespace LeptonXLite.DemoApp.Blazor.MyComponents using Volo.Abp.AspNetCore.Components.Web.LeptonXTheme.Components.ApplicationLayout.Common; using Volo.Abp.DependencyInjection; -namespace LeptonXLite.DemoApp.Blazor.MyComponents +namespace LeptonX.DemoApp.Blazor.MyComponents { [ExposeServices(typeof(ContentToolbar))] [Dependency(ReplaceServices = true)] @@ -371,7 +447,7 @@ namespace LeptonXLite.DemoApp.Blazor.MyComponents using Volo.Abp.AspNetCore.Components.Web.LeptonXTheme.Components.ApplicationLayout.Common; using Volo.Abp.DependencyInjection; -namespace LeptonXLite.DemoApp.Blazor.MyComponents +namespace LeptonX.DemoApp.Blazor.MyComponents { [ExposeServices(typeof(GeneralSettings))] [Dependency(ReplaceServices = true)] @@ -404,7 +480,7 @@ namespace LeptonXLite.DemoApp.Blazor.MyComponents using Volo.Abp.AspNetCore.Components.Web.LeptonXTheme.Components.ApplicationLayout.Common; using Volo.Abp.DependencyInjection; -namespace LeptonXLite.DemoApp.Blazor.MyComponents +namespace LeptonX.DemoApp.Blazor.MyComponents { [ExposeServices(typeof(MobileGeneralSettings))] [Dependency(ReplaceServices = true)] @@ -443,7 +519,7 @@ Components used in the side menu layout. using Volo.Abp.AspNetCore.Components.Web.LeptonXTheme.Components.ApplicationLayout.SideMenu.Navigation; using Volo.Abp.DependencyInjection; -namespace LeptonXLite.DemoApp.Blazor.MyComponents +namespace LeptonX.DemoApp.Blazor.MyComponents { [ExposeServices(typeof(MainMenu))] [Dependency(ReplaceServices = true)] @@ -474,7 +550,7 @@ namespace LeptonXLite.DemoApp.Blazor.MyComponents using Volo.Abp.AspNetCore.Components.Web.LeptonXTheme.Components.ApplicationLayout.SideMenu.Navigation; using Volo.Abp.DependencyInjection; -namespace LeptonXLite.DemoApp.Blazor.MyComponents +namespace LeptonX.DemoApp.Blazor.MyComponents { [ExposeServices(typeof(MainMenu))] [Dependency(ReplaceServices = true)] @@ -507,7 +583,7 @@ namespace LeptonXLite.DemoApp.Blazor.MyComponents using Volo.Abp.AspNetCore.Components.Web.LeptonXTheme.Components.ApplicationLayout.SideMenu.Navigation; using Volo.Abp.DependencyInjection; -namespace LeptonXLite.DemoApp.Blazor.MyComponents +namespace LeptonX.DemoApp.Blazor.MyComponents { [ExposeServices(typeof(MobileNavbar))] [Dependency(ReplaceServices = true)] @@ -540,7 +616,7 @@ namespace LeptonXLite.DemoApp.Blazor.MyComponents using Volo.Abp.AspNetCore.Components.Web.LeptonXTheme.Components.ApplicationLayout.SideMenu.MainHeader; using Volo.Abp.DependencyInjection; -namespace LeptonXLite.DemoApp.Blazor.MyComponents +namespace LeptonX.DemoApp.Blazor.MyComponents { [ExposeServices(typeof(MainHeader))] [Dependency(ReplaceServices = true)] @@ -577,7 +653,7 @@ If you need to replace the component, you can follow the steps below. using Volo.Abp.AspNetCore.Components.Web.LeptonXTheme.Components.ApplicationLayout.SideMenu.MainHeader; using Volo.Abp.DependencyInjection; -namespace LeptonXLite.DemoApp.Blazor.MyComponents +namespace LeptonX.DemoApp.Blazor.MyComponents { [ExposeServices(typeof(MainHeaderBranding))] [Dependency(ReplaceServices = true)] @@ -614,7 +690,7 @@ If you need to replace the component, you can follow the steps below. using Volo.Abp.AspNetCore.Components.Web.LeptonXTheme.Components.ApplicationLayout.SideMenu.MainHeader; using Volo.Abp.DependencyInjection; -namespace LeptonXLite.DemoApp.Blazor.MyComponents +namespace LeptonX.DemoApp.Blazor.MyComponents { [ExposeServices(typeof(MainHeaderToolbar))] [Dependency(ReplaceServices = true)] @@ -653,7 +729,7 @@ Components used in the top menu layout. using Volo.Abp.AspNetCore.Components.Web.LeptonXTheme.Components.ApplicationLayout.TopMenu.Navigation; using Volo.Abp.DependencyInjection; -namespace LeptonXLite.DemoApp.Blazor.MyComponents +namespace LeptonX.DemoApp.Blazor.MyComponents { [ExposeServices(typeof(MainMenu))] [Dependency(ReplaceServices = true)] @@ -684,7 +760,7 @@ namespace LeptonXLite.DemoApp.Blazor.MyComponents using Volo.Abp.AspNetCore.Components.Web.LeptonXTheme.Components.ApplicationLayout.TopMenu.Navigation; using Volo.Abp.DependencyInjection; -namespace LeptonXLite.DemoApp.Blazor.MyComponents +namespace LeptonX.DemoApp.Blazor.MyComponents { [ExposeServices(typeof(MainMenu))] [Dependency(ReplaceServices = true)] @@ -717,7 +793,7 @@ namespace LeptonXLite.DemoApp.Blazor.MyComponents using Volo.Abp.AspNetCore.Components.Web.LeptonXTheme.Components.ApplicationLayout.TopMenu.Navigation; using Volo.Abp.DependencyInjection; -namespace LeptonXLite.DemoApp.Blazor.MyComponents +namespace LeptonX.DemoApp.Blazor.MyComponents { [ExposeServices(typeof(MobileNavbar))] [Dependency(ReplaceServices = true)] @@ -750,7 +826,7 @@ namespace LeptonXLite.DemoApp.Blazor.MyComponents using Volo.Abp.AspNetCore.Components.Web.LeptonXTheme.Components.ApplicationLayout.TopMenu.MainHeader; using Volo.Abp.DependencyInjection; -namespace LeptonXLite.DemoApp.Blazor.MyComponents +namespace LeptonX.DemoApp.Blazor.MyComponents { [ExposeServices(typeof(MainHeader))] [Dependency(ReplaceServices = true)] @@ -785,7 +861,7 @@ Application branding can be customized with the `IBrandingProvider`. See the [Br using Volo.Abp.AspNetCore.Components.Web.LeptonXTheme.Components.ApplicationLayout.TopMenu.MainHeader; using Volo.Abp.DependencyInjection; -namespace LeptonXLite.DemoApp.Blazor.MyComponents +namespace LeptonX.DemoApp.Blazor.MyComponents { [ExposeServices(typeof(MainHeaderBranding))] [Dependency(ReplaceServices = true)] @@ -822,7 +898,7 @@ If you need to replace the component, you can follow the steps below. using Volo.Abp.AspNetCore.Components.Web.LeptonXTheme.Components.ApplicationLayout.TopMenu.MainHeader; using Volo.Abp.DependencyInjection; -namespace LeptonXLite.DemoApp.Blazor.MyComponents +namespace LeptonX.DemoApp.Blazor.MyComponents { [ExposeServices(typeof(MainHeaderToolbar))] [Dependency(ReplaceServices = true)] diff --git a/docs/en/ui-themes/lepton/customizing-lepton-theme.md b/docs/en/ui-themes/lepton/customizing-lepton-theme.md index c94ccaafce..33cdcfc5c2 100644 --- a/docs/en/ui-themes/lepton/customizing-lepton-theme.md +++ b/docs/en/ui-themes/lepton/customizing-lepton-theme.md @@ -229,12 +229,6 @@ Configure<(op } ``` -Run the following ABP CLI command to bundle the `custom.css` - -```bash -abp bundle -``` - {{end}} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js index 58b570253c..bcb043a196 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js @@ -84,12 +84,9 @@ var abp = abp || {}; }; var _createButtonDropdown = function (record, field, tableInstance) { - if (field.items.length === 1) { + if (field.items.length === 1 && getVisibilityValue(field.items[0].visible, record, tableInstance)) { var firstItem = field.items[0]; - if (!getVisibilityValue(firstItem.visible, record, tableInstance)) { - return $(''); - } - + var $button = $(''); if (firstItem.displayNameHtml) { @@ -159,8 +156,9 @@ var abp = abp || {}; $dropdownButton.addClass(field.cssClass); } + var isEntityActionsDisabled = true; var $dropdownItemsContainer = $('
    ').addClass('dropdown-menu'); - + for (var i = 0; i < field.items.length; i++) { var fieldItem = field.items[i]; @@ -169,6 +167,7 @@ var abp = abp || {}; continue; } + isEntityActionsDisabled = false; var $dropdownItem = _createDropdownItem(record, fieldItem, tableInstance); if (fieldItem.enabled && !fieldItem.enabled({ record: record, table: tableInstance })) { @@ -180,11 +179,22 @@ var abp = abp || {}; if ($dropdownItemsContainer.find('li').length > 0) { $dropdownItemsContainer.appendTo($container); - } else { - $dropdownButton.addClass('d-none'); } - $dropdownButton.prependTo($container); + if (isEntityActionsDisabled) { + + $dropdownButton.attr('disabled', 'disabled'); + + var $tooltip = $('
    '); + $tooltip.attr('title', localize("EntityActionsDisabledTooltip")); + $tooltip.attr('data-bs-toggle', 'tooltip'); + new bootstrap.Tooltip($tooltip); + + $dropdownButton.appendTo($tooltip); + $tooltip.prependTo($container); + }else{ + $dropdownButton.prependTo($container); + } if (bootstrap) { new bootstrap.Dropdown($dropdownButton, { diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/EntityActions.razor b/framework/src/Volo.Abp.BlazoriseUI/Components/EntityActions.razor index 5e686afbda..cd1f908dcc 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/Components/EntityActions.razor +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/EntityActions.razor @@ -1,27 +1,29 @@ @typeparam TItem - @if ( Type == ActionType.Dropdown ) + @if ( Type == ActionType.Dropdown || (Type == ActionType.Button && DisabledOrNoActions())) { - @if ( HasPrimaryAction ) - { - - - } - else - { - - @ToggleText - - } - - @ChildContent - + + @if ( HasPrimaryAction ) + { + + + } + else + { + + @ToggleText + + } + + @ChildContent + + } else diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/CreateMigrationAndRunMigratorCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/CreateMigrationAndRunMigratorCommand.cs index fcdbe094aa..b8b6a02d72 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/CreateMigrationAndRunMigratorCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/CreateMigrationAndRunMigratorCommand.cs @@ -5,12 +5,14 @@ using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp.Cli.Args; +using Volo.Abp.Cli.Commands.Internal; using Volo.Abp.Cli.Commands.Services; using Volo.Abp.Cli.Utils; using Volo.Abp.DependencyInjection; namespace Volo.Abp.Cli.Commands; +[HideFromCommandList] public class CreateMigrationAndRunMigratorCommand : IConsoleCommand, ITransientDependency { private readonly InitialMigrationCreator _initialMigrationCreator; diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/HelpCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/HelpCommand.cs index 5b6c80d3be..9fb647806b 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/HelpCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/HelpCommand.cs @@ -1,4 +1,6 @@ -using System.Linq; +using System; +using System.Collections.Generic; +using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; @@ -7,6 +9,7 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; using Volo.Abp.Cli.Args; +using Volo.Abp.Cli.Commands.Internal; using Volo.Abp.DependencyInjection; namespace Volo.Abp.Cli.Commands; @@ -65,7 +68,7 @@ public class HelpCommand : IConsoleCommand, ITransientDependency sb.AppendLine("Command List:"); sb.AppendLine(""); - foreach (var command in AbpCliOptions.Commands.ToArray()) + foreach (var command in AbpCliOptions.Commands.ToArray().Where(NotHiddenFromCommandList)) { var method = command.Value.GetMethod("GetShortDescription", BindingFlags.Static | BindingFlags.Public); if (method == null) @@ -92,6 +95,11 @@ public class HelpCommand : IConsoleCommand, ITransientDependency return sb.ToString(); } + private bool NotHiddenFromCommandList(KeyValuePair command) + { + return command.Value.GetCustomAttribute(typeof(HideFromCommandList)) == null; + } + public static string GetShortDescription() { return "Show command line help. Write ` abp help `"; diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Internal/HideFromCommandList.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Internal/HideFromCommandList.cs new file mode 100644 index 0000000000..9660223a96 --- /dev/null +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Internal/HideFromCommandList.cs @@ -0,0 +1,6 @@ +using System; + +namespace Volo.Abp.Cli.Commands.Internal; + +public class HideFromCommandList : Attribute +{} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Internal/RecreateInitialMigrationCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Internal/RecreateInitialMigrationCommand.cs index 47c1ac78f4..857edf6bd7 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Internal/RecreateInitialMigrationCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Internal/RecreateInitialMigrationCommand.cs @@ -9,6 +9,7 @@ using Volo.Abp.DependencyInjection; namespace Volo.Abp.Cli.Commands.Internal; +[HideFromCommandList] public class RecreateInitialMigrationCommand : IConsoleCommand, ITransientDependency { public const string Name = "recreate-initial-migration"; diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ar.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ar.json index c1097000c1..93cf62ab84 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ar.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ar.json @@ -60,6 +60,7 @@ "AddNew": "اضف جديد", "ProfilePicture": "الصوره الشخصيه", "Theme": "سمة", - "NotAssigned": "غيرمعتمد" + "NotAssigned": "غيرمعتمد", + "EntityActionsDisabledTooltip": "ليس لديك إذن لتنفيذ أي إجراء." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/cs.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/cs.json index 710a57a2a9..ff2d09fdf8 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/cs.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/cs.json @@ -60,6 +60,7 @@ "AddNew": "Přidat nový", "ProfilePicture": "Profilový obrázek", "Theme": "Téma", - "NotAssigned": "Nepřiřazena" + "NotAssigned": "Nepřiřazena", + "EntityActionsDisabledTooltip": "Nemáte oprávnění provést žádnou akci." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/de.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/de.json index a955a9066d..37c361c1e3 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/de.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/de.json @@ -60,6 +60,7 @@ "AddNew": "Neue hinzufügen", "ProfilePicture": "Profilbild", "Theme": "Thema", - "NotAssigned": "Nicht zugeordnet" + "NotAssigned": "Nicht zugeordnet", + "EntityActionsDisabledTooltip": "Sie haben keine Berechtigung, Aktionen auszuführen." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/el.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/el.json index 2abb92eab7..f7d837a361 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/el.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/el.json @@ -54,6 +54,7 @@ "ManageYourAccount": "Διαχείριση Λογαριασμού", "OthersGroup": "άλλος", "Today": "Σήμερα", - "Apply": "Ισχύουν" + "Apply": "Ισχύουν", + "EntityActionsDisabledTooltip": "Δεν έχετε δικαίωμα να εκτελέσετε καμία ενέργεια." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en-GB.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en-GB.json index 7bbcc9d82f..c5aaa5957c 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en-GB.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en-GB.json @@ -55,6 +55,7 @@ "OthersGroup": "Other", "NotAssigned": "Not Assigned", "Today": "Today", - "Apply": "Apply" + "Apply": "Apply", + "EntityActionsDisabledTooltip": "You do not have permission to perform any action." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json index 8ea53bba77..7a5a806124 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json @@ -60,6 +60,7 @@ "AddNew": "Add new", "ProfilePicture": "Profile picture", "Theme": "Theme", - "NotAssigned": "Not Assigned" + "NotAssigned": "Not Assigned", + "EntityActionsDisabledTooltip": "You do not have permission to perform any action." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/es.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/es.json index 7870ccff7b..132243a740 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/es.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/es.json @@ -60,6 +60,7 @@ "AddNew": "Agregar nuevo", "ProfilePicture": "Foto de perfil", "Theme": "Tema", - "NotAssigned": "No asignado" + "NotAssigned": "No asignado", + "EntityActionsDisabledTooltip": "No tienes permisos para realizar ninguna acción." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fa.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fa.json index c5cb5960bd..f1738957c9 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fa.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fa.json @@ -54,6 +54,7 @@ "ManageYourAccount": "حساب خود را مدیریت کنید", "OthersGroup": "دیگر", "Today": "امروز", - "Apply": "درخواست دادن" + "Apply": "درخواست دادن", + "EntityActionsDisabledTooltip": "شما دسترسی به انجام هر گونه عملیات ندارید." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fi.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fi.json index d2b5018e73..1af59eb720 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fi.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fi.json @@ -60,6 +60,7 @@ "AddNew": "Lisää uusi", "ProfilePicture": "Profiilikuva", "Theme": "Teema", - "NotAssigned": "Ei määritetty" + "NotAssigned": "Ei määritetty", + "EntityActionsDisabledTooltip": "Sinulla ei ole oikeutta suorittaa mitään toimintoa." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fr.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fr.json index 66e37491fb..8af5661d1a 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fr.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fr.json @@ -60,6 +60,7 @@ "AddNew": "Ajouter un nouveau", "ProfilePicture": "Image de profil", "Theme": "Thème", - "NotAssigned": "Non attribué" + "NotAssigned": "Non attribué", + "EntityActionsDisabledTooltip": "Vous n'avez pas les permissions pour effectuer une action." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hi.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hi.json index 7da0065d95..ba873b7685 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hi.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hi.json @@ -60,6 +60,7 @@ "AddNew": "नया जोड़ो", "ProfilePicture": "प्रोफ़ाइल फोटो", "Theme": "विषय", - "NotAssigned": "सौंपा नहीं गया है" + "NotAssigned": "सौंपा नहीं गया है", + "EntityActionsDisabledTooltip": "आपके पास कोई कार्रवाई नहीं है जो करने के लिए है।" } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hr.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hr.json index b1073d62e7..5b16c84963 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hr.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hr.json @@ -60,6 +60,7 @@ "AddNew": "Dodaj novi", "ProfilePicture": "Profilna slika", "Theme": "Tema", - "NotAssigned": "Nije dodijeljeno" + "NotAssigned": "Nije dodijeljeno", + "EntityActionsDisabledTooltip": "Nemate dozvolu za izvođenje bilo kakve akcije." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hu.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hu.json index 3df6177a9f..0539276498 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hu.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hu.json @@ -60,6 +60,7 @@ "AddNew": "Új hozzáadása", "ProfilePicture": "Profil kép", "Theme": "Téma", - "NotAssigned": "Nem kijelölt" + "NotAssigned": "Nem kijelölt", + "EntityActionsDisabledTooltip": "Nincs jogosultsága bármely művelethez." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/is.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/is.json index d2eba16bd8..8a1eda9e4e 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/is.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/is.json @@ -60,6 +60,7 @@ "AddNew": "Bæta við nýju", "ProfilePicture": "Forsíðumynd", "Theme": "Þema", - "NotAssigned": "Ekki skráður" + "NotAssigned": "Ekki skráður", + "EntityActionsDisabledTooltip": "Þú hefur ekki aðgang að þessum aðgerðum." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/it.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/it.json index ef255274df..77d4742680 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/it.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/it.json @@ -60,6 +60,7 @@ "AddNew": "Aggiungere nuova", "ProfilePicture": "Immagine del profilo", "Theme": "Tema", - "NotAssigned": "Non assegnato" + "NotAssigned": "Non assegnato", + "EntityActionsDisabledTooltip": "Non hai i permessi per eseguire alcuna azione." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/nl.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/nl.json index 85b8b4f88b..38182ec9e6 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/nl.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/nl.json @@ -60,6 +60,7 @@ "AddNew": "Nieuw toevoegen", "ProfilePicture": "Profielfoto", "Theme": "Thema", - "NotAssigned": "Niet toegekend" + "NotAssigned": "Niet toegekend", + "EntityActionsDisabledTooltip": "U hebt geen toegang tot deze acties." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pl-PL.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pl-PL.json index 6739b673d7..d7f321f3d6 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pl-PL.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pl-PL.json @@ -60,6 +60,7 @@ "AddNew": "Dodaj nowe", "ProfilePicture": "Zdjęcie profilowe", "Theme": "Temat", - "NotAssigned": "Nie przypisano" + "NotAssigned": "Nie przypisano", + "EntityActionsDisabledTooltip": "Nie masz uprawnień do wykonania żadnej akcji." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pt-BR.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pt-BR.json index 5c4a6790f7..13c8380fa3 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pt-BR.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pt-BR.json @@ -60,6 +60,7 @@ "AddNew": "Adicionar novo", "ProfilePicture": "Foto do perfil", "Theme": "Tema", - "NotAssigned": "Não atribuído" + "NotAssigned": "Não atribuído", + "EntityActionsDisabledTooltip": "Você não tem permissão para executar qualquer ação." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ro-RO.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ro-RO.json index c5850bef00..e03fd91f50 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ro-RO.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ro-RO.json @@ -60,6 +60,7 @@ "AddNew": "Adăuga nou", "ProfilePicture": "Poză de profil", "Theme": "Temă", - "NotAssigned": "Nealocat" + "NotAssigned": "Nealocat", + "EntityActionsDisabledTooltip": "Nu aveți permisiune să efectuați nicio acțiune." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ru.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ru.json index f329315488..57f3079cb4 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ru.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ru.json @@ -60,6 +60,7 @@ "AddNew": "Добавить новое", "ProfilePicture": "Изображение профиля", "Theme": "Тема", - "NotAssigned": "Не назначен" + "NotAssigned": "Не назначен", + "EntityActionsDisabledTooltip": "У вас нет прав на выполнение каких-либо действий." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sk.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sk.json index 6cc73f0cc6..eb0ba2958f 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sk.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sk.json @@ -60,6 +60,7 @@ "AddNew": "Pridať nové", "ProfilePicture": "Profilový obrázok", "Theme": "Téma", - "NotAssigned": "Nepridelené" + "NotAssigned": "Nepridelené", + "EntityActionsDisabledTooltip": "Nemáte oprávnenie vykonávať žiadnu akciu." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sl.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sl.json index 36d1bb14a6..bc3f795b34 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sl.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sl.json @@ -60,6 +60,7 @@ "AddNew": "Dodaj novo", "ProfilePicture": "Profilna slika", "Theme": "Tema", - "NotAssigned": "Ni dodeljena" + "NotAssigned": "Ni dodeljena", + "EntityActionsDisabledTooltip": "Nimate pravic za izvajanje kakršne koli dejanje." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sv.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sv.json index 40aaa0073f..f0257637c1 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sv.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sv.json @@ -59,6 +59,7 @@ "AddNew": "Lägg till ny", "ProfilePicture": "Profilbild", "Theme": "Tema", - "NotAssigned": "Ej tilldelad" + "NotAssigned": "Ej tilldelad", + "EntityActionsDisabledTooltip": "Du har inte tillgång till dessa åtgärder." } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/tr.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/tr.json index 2636d1087a..b21adf632a 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/tr.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/tr.json @@ -60,6 +60,7 @@ "AddNew": "Yeni ekle", "ProfilePicture": "Profil resmi", "Theme": "Tema", - "NotAssigned": "Atanmadı" + "NotAssigned": "Atanmadı", + "EntityActionsDisabledTooltip": "Bu işlemi gerçekleştirmek için yeterli yetkiniz yok." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/vi.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/vi.json index fca1f0954c..700798895f 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/vi.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/vi.json @@ -60,6 +60,7 @@ "AddNew": "Thêm mới", "ProfilePicture": "Ảnh đại diện", "Theme": "chủ đề", - "NotAssigned": "Không được chỉ định" + "NotAssigned": "Không được chỉ định", + "EntityActionsDisabledTooltip": "Bạn không có quyền thực hiện bất kỳ hành động nào." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hans.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hans.json index 2824c1bbbc..60f70e1545 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hans.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hans.json @@ -60,6 +60,7 @@ "AddNew": "添新", "ProfilePicture": "个人资料图片", "Theme": "主题", - "NotAssigned": "未分配" + "NotAssigned": "未分配", + "EntityActionsDisabledTooltip": "您没有权限执行任何操作。" } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hant.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hant.json index 17dac54739..0f8fdeb254 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hant.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hant.json @@ -60,6 +60,7 @@ "AddNew": "添新", "ProfilePicture": "個人資料圖片", "Theme": "主題", - "NotAssigned": "未分配" + "NotAssigned": "未分配", + "EntityActionsDisabledTooltip": "您沒有權限執行任何操作。" } } diff --git a/npm/ng-packs/packages/permission-management/src/lib/components/permission-management.component.ts b/npm/ng-packs/packages/permission-management/src/lib/components/permission-management.component.ts index 2742cedcee..c68c9afc85 100644 --- a/npm/ng-packs/packages/permission-management/src/lib/components/permission-management.component.ts +++ b/npm/ng-packs/packages/permission-management/src/lib/components/permission-management.component.ts @@ -40,27 +40,34 @@ type PermissionWithGroupName = PermissionGrantInfoDto & { exportAs: 'abpPermissionManagement', styles: [ ` - .overflow-scroll { - max-height: 70vh; - overflow-y: scroll; - } - .scroll-in-modal { overflow: auto; - max-height: calc(100vh - 15rem); - } - - fieldset legend { - float: none; - width: auto; + /* + To maintain a 28px top margin and 28px bottom margin when the modal reaches full height, the scrollable area needs to be 100vh - 23.1rem + */ + max-height: calc(100vh - 23.1rem); } .lpx-scroll-pills-container ul { display: block; - max-height: 500px; overflow-y: auto; } + /* Target mobile screens */ + @media (max-width: 768px) { + .scroll-in-modal { + max-height: calc(100vh - 15rem); + } + .lpx-scroll-pills-container ul { + max-height: 500px; + } + } + + fieldset legend { + float: none; + width: auto; + } + .lpx-scroll-pills-container .tab-content { padding-top: 0 !important; padding-bottom: 0 !important;