diff --git a/Directory.Packages.props b/Directory.Packages.props index 016445c47d..fc2e01a3f5 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -49,36 +49,36 @@ - - - - - - - - - - - + + + + + + + + + + + - - - + + + - - + + - - - - - - - - - + + + + + + + + + @@ -123,7 +123,7 @@ - + diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/en.json index 8470709c99..44ab5b3e31 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/en.json @@ -12,6 +12,7 @@ "CommunityWebSite": "ABP community website", "ManageAccount": "My Account | ABP.IO", "ManageYourProfile": "Manage your profile", - "ReturnToApplication": "Return to application" + "ReturnToApplication": "Return to application", + "IdentityUserNotAvailable:Deleted": "This email address is not available. Reason: Already deleted." } } diff --git a/docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/POST.md b/docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/POST.md new file mode 100644 index 0000000000..6d0c60407d --- /dev/null +++ b/docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/POST.md @@ -0,0 +1,85 @@ +# Deploy Your ABP Framework MVC Project to Azure Container Apps + +![](azure-container-abp.png) + +In this article, we will show the seamless deployment of an ABP Framework MVC project to Azure Container Apps. enabling you to deploy and run containerized applications without the hassle of managing the infrastructure underneath. It provides an uncomplicated and cost-effective method for deploying and scaling your applications. + +### Getting Started with ABP Framework MVC and Azure Container Apps + +To get started, you will need an ABP Framework MVC project that you want to deploy. If you don't have one, you can [create a new project using the ABP CLI](https://docs.abp.io/en/abp/latest/Startup-Templates/Application). You will also need [an Azure subscription](https://azure.microsoft.com) and [an Azure SQL database](https://azure.microsoft.com/en-gb/products/azure-sql). + +Before creating Azure container apps resources and deploying the ABP Framework MVC project, I show you how you can effortlessly create Docker images and push them to Docker Hub, leveraging the pre-configured Docker file and scripts that come with the ABP MVC framework. + +### Creating a Docker Image for ABP Framework MVC + +To create a Docker image for your ABP Framework MVC project, navigate to `etc/build/build-images-locally.ps1` and fix the script to match your Docker Hub username and image name. Then, run the script to build the Docker image locally. + +![Build Docker Image](build-docker-image.png) + +Next, check the Docker Hub repository to confirm that the image has been pushed successfully. + +![Docker Hub Repository](docker-hub-repository.png) + +### Deploying to Azure Container Apps + +Now that you have Docker images for your ABP Framework MVC project, you can proceed to deploy it to Azure Container Apps. To do this, navigate to the Azure portal and create a new Azure Container Apps resource. Ypu will not need just an Azure Container Apps resource, but also an Azure Container Apps Job resource to migrate the database schema and seed data for your ABP Framework MVC project. + +![Create Azure Container Apps](create-azure-container-apps.png) + +#### Step 1: Deploy the Docker Image + +Firstly, create a new Azure Container Apps resource without environment variables. You will need web url so that you can set it as an environment variable in the next step. Then, check the deployment status to confirm that the deployment was successful. + +![Deploy Docker Image](deploy-docker-image.png) + +#### Step 2: Migrate Database Schema and Seed Data + +Secondly, create a new Azure Container Apps Job resource to migrate the database schema and seed data. You can do this by creating a new job with the following environment variables: + +```text +ConnectionStrings__Default - Server=tcp:demoabpapp.database.windows.net,1433;Initial Catalog=mvcapppro;Persist Security Info=False;User ID=demoapppro;Password={your_password};MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30; + +OpenIddict__Applications__mvcapppro_Web__RootUrl - https://mvcwebapp.victoriousgrass-8b06438d.northeurope.azurecontainerapps.io + +To get ConnectionStrings of Sql Database and url of the web app, you can navigate to the Azure portal and check the properties of the Azure SQL database and Azure Container Apps resource. +``` + +![Azure SQL Database Connection Strings](azure-sql-database-connection-strings.png) + +![Create Azure Container Apps Job](create-azure-container-apps-job.png) + +Finally, check the job status to confirm that the database migration and seeding were successful. You can connect to the Azure SQL database to verify that the schema and seed data have been applied. + +![Check Job Status](check-job-status.png) + +#### Step 3: Edit the Azure Container Apps Resource + +After completing these steps, you have to edit the Azure Container Apps resource to add the required environment variables for your ABP Framework MVC project. You can do this by adding the following environment variables: + +```text +App__SelfUrl - https://mvcwebapp.victoriousgrass-8b06438d.northeurope.azurecontainerapps.io + +ASPNETCORE_URLS - http://+:80 + +AuthServer__Authority - https://mvcwebapp.victoriousgrass-8b06438d.northeurope.azurecontainerapps.io + +ConnectionStrings__Default - Server=tcp:demoabpapp.database.windows.net,1433;Initial Catalog=mvcapppro;Persist Security Info=False;User ID=demoapppro;Password={your_password};MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30; +``` + +![Add Environment Variables](add-environment-variables.png) + +#### Step 4: Create a New Deployment + +Once you have added the environment variables, save and create a new deployment to apply the changes. You can now access your ABP Framework MVC project running on Azure Container Apps by navigating to the URL provided in the environment variables. + +![Access ABP Framework MVC Project](access-abp-framework-mvc-project.png) + +You can see the Azure resources created for the ABP Framework MVC project deployment that includes the Azure Container Apps resource, Azure Container Apps Job resource, and Azure SQL database. + +![Azure Resources](azure-resources.png) + +### Conclusion + +Azure Container Apps provides a simple and cost-effective way to deploy and scale your ABP Framework MVC projects without managing the underlying infrastructure. By following the steps outlined in this article, you can seamlessly deploy your ABP Framework MVC projects to Azure Container Apps and enjoy the benefits it offers. + +I hope you found this article helpful. If you have any questions or feedback, please feel free to leave a comment below. diff --git a/docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/access-abp-framework-mvc-project.png b/docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/access-abp-framework-mvc-project.png new file mode 100644 index 0000000000..ff0aa2f811 Binary files /dev/null and b/docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/access-abp-framework-mvc-project.png differ diff --git a/docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/add-environment-variables.png b/docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/add-environment-variables.png new file mode 100644 index 0000000000..56f9df7fa4 Binary files /dev/null and b/docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/add-environment-variables.png differ diff --git a/docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/azure-container-abp.png b/docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/azure-container-abp.png new file mode 100644 index 0000000000..ec96dd0b2e Binary files /dev/null and b/docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/azure-container-abp.png differ diff --git a/docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/azure-resources.png b/docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/azure-resources.png new file mode 100644 index 0000000000..3bab322580 Binary files /dev/null and b/docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/azure-resources.png differ diff --git a/docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/azure-sql-database-connection-strings.png b/docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/azure-sql-database-connection-strings.png new file mode 100644 index 0000000000..5ec51f6edb Binary files /dev/null and b/docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/azure-sql-database-connection-strings.png differ diff --git a/docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/build-docker-image.png b/docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/build-docker-image.png new file mode 100644 index 0000000000..496dd637cd Binary files /dev/null and b/docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/build-docker-image.png differ diff --git a/docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/check-job-status.png b/docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/check-job-status.png new file mode 100644 index 0000000000..e87ee2081f Binary files /dev/null and b/docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/check-job-status.png differ diff --git a/docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/create-azure-container-apps-job.png b/docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/create-azure-container-apps-job.png new file mode 100644 index 0000000000..10229d5707 Binary files /dev/null and b/docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/create-azure-container-apps-job.png differ diff --git a/docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/create-azure-container-apps.png b/docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/create-azure-container-apps.png new file mode 100644 index 0000000000..3e8e899960 Binary files /dev/null and b/docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/create-azure-container-apps.png differ diff --git a/docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/deploy-docker-image.png b/docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/deploy-docker-image.png new file mode 100644 index 0000000000..df431b6c51 Binary files /dev/null and b/docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/deploy-docker-image.png differ diff --git a/docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/docker-hub-repository.png b/docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/docker-hub-repository.png new file mode 100644 index 0000000000..b25e01a629 Binary files /dev/null and b/docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/docker-hub-repository.png differ diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/en.json b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/en.json index 76cfcc5b6a..d4b3ef586c 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/en.json +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/en.json @@ -85,11 +85,11 @@ "AuditLogSettingsGeneral": "General", "AuditLogSettingsGlobal": "Global", "DisplayName:IsPeriodicDeleterEnabled": "Enable clean up service system wide", - "Description:IsPeriodicDeleterEnabled": "If this option is disable the periodic deleter won't work. Audit logs won't be deleted automatically.", + "Description:IsPeriodicDeleterEnabled": "If this option is disabled the periodic deleter won't work. Audit logs won't be deleted automatically.", "DisplayName:GlobalIsExpiredDeleterEnabled": "Enable clean up service for all tenants and host", - "Description:GlobalIsExpiredDeleterEnabled": "If this option is enable all tenants and host expired items deleted automatically. Unless has a specific setting.", + "Description:GlobalIsExpiredDeleterEnabled": "If this option is enabled all the tenants and the host expired items will be deleted automatically unless it has a specific setting.", "DisplayName:IsExpiredDeleterEnabled": "Enable clean up service", - "Description:IsExpiredDeleterEnabled": "If this option is enable expired items deleted automatically.", + "Description:IsExpiredDeleterEnabled": "If this option is enabled the expired items will be deleted automatically.", "DisplayName:ExpiredDeleterPeriod": "Expired item deletion period", "Description:ExpiredDeleterPeriod": "Set the number of days after which expired items will be automatically deleted.", "ExpiredDeleterPeriodUnit": "day(s)", diff --git a/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-form/extensible-form-prop.component.html b/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-form/extensible-form-prop.component.html index e565a0ac86..8054133a76 100644 --- a/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-form/extensible-form-prop.component.html +++ b/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-form/extensible-form-prop.component.html @@ -21,11 +21,9 @@ class="form-control" /> } - @case ('hidden') { } - @case ('checkbox') {
} - @case ('select') { } - @case ('typeahead') {
@@ -100,7 +95,6 @@
} - @case ('date') { } - @case ('dateTime') { } - @case ('textarea') { } - @case ('passwordinputgroup') {
diff --git a/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.ts b/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.ts index 4e60ab9851..a99ba37907 100644 --- a/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.ts +++ b/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.ts @@ -207,7 +207,7 @@ export class ExtensibleTableComponent implements OnChanges { } hasAvailableActions(index, data): boolean { - const { permission, visible } = this.actionList.get(index).value; + const { permission, visible } = this.actionList.get(index)?.value || {}; let isActionAvailable = this.permissionService.getGrantedPolicy(permission); if (data && data.record) { isActionAvailable &&= visible(data); 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 6a6fbdbc46..7b474e7881 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 @@ -99,7 +99,7 @@ export class LocalizationService { return local; }), - filter(Boolean) + filter(Boolean), ) .subscribe(val => this.localizations$.next(val)); } @@ -211,9 +211,12 @@ export class LocalizationService { key: string | LocalizationWithDefault, ...interpolateParams: string[] ) { - if (!key) key = ''; let defaultValue = ''; + if (!key) { + return defaultValue; + } + if (typeof key !== 'string') { defaultValue = key.defaultValue; key = key.key; @@ -265,7 +268,10 @@ export class LocalizationService { } } -function recursivelyMergeBaseResources(baseResourceName: string, source: ResourceDto): ApplicationLocalizationResourceDto { +function recursivelyMergeBaseResources( + baseResourceName: string, + source: ResourceDto, +): ApplicationLocalizationResourceDto { const item = source[baseResourceName]; if (item.baseResources.length === 0) { @@ -280,10 +286,12 @@ function recursivelyMergeBaseResources(baseResourceName: string, source: Resourc } function mergeResourcesWithBaseResource(resource: ResourceDto): ResourceDto { - const entities: Array<[string, ApplicationLocalizationResourceDto]> = Object.keys(resource).map(key => { - const newValue = recursivelyMergeBaseResources(key, resource); - return [key, newValue]; - }); + const entities: Array<[string, ApplicationLocalizationResourceDto]> = Object.keys(resource).map( + key => { + const newValue = recursivelyMergeBaseResources(key, resource); + return [key, newValue]; + }, + ); return entities.reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}); } diff --git a/npm/ng-packs/packages/core/src/lib/tokens/compare-func.token.ts b/npm/ng-packs/packages/core/src/lib/tokens/compare-func.token.ts index 2c5185ce23..208589e06e 100644 --- a/npm/ng-packs/packages/core/src/lib/tokens/compare-func.token.ts +++ b/npm/ng-packs/packages/core/src/lib/tokens/compare-func.token.ts @@ -1,5 +1,5 @@ import { InjectionToken, inject } from '@angular/core'; -import { SortableItem } from '../models'; +import type { SortableItem } from '../models'; import { LocalizationService } from '../services'; export const SORT_COMPARE_FUNC = new InjectionToken<(a: SortableItem, b: SortableItem) => number>( @@ -9,23 +9,24 @@ export const SORT_COMPARE_FUNC = new InjectionToken<(a: SortableItem, b: Sortabl export function compareFuncFactory() { const localizationService = inject(LocalizationService); const fn = (a: SortableItem, b: SortableItem) => { - const aName = localizationService.instant(a.name); - const bName = localizationService.instant(b.name); const aNumber = a.order; const bNumber = b.order; + if (aNumber > bNumber) return 1; + if (aNumber < bNumber) return -1; + + if (a.id > b.id) return 1; + if (a.id < b.id) return -1; + if (!Number.isInteger(aNumber)) return 1; if (!Number.isInteger(bNumber)) return -1; - if (aNumber > bNumber) return 1; - if (aNumber < bNumber) return -1; + const aName = localizationService.instant(a.name); + const bName = localizationService.instant(b.name); if (aName > bName) return 1; if (aName < bName) return -1; - if (a.id > b.id) return 1; - if (a.id < b.id) return -1; - return 0; }; diff --git a/npm/ng-packs/packages/oauth/src/lib/strategies/auth-code-flow-strategy.ts b/npm/ng-packs/packages/oauth/src/lib/strategies/auth-code-flow-strategy.ts index 7b1e0c108a..0452fdc899 100644 --- a/npm/ng-packs/packages/oauth/src/lib/strategies/auth-code-flow-strategy.ts +++ b/npm/ng-packs/packages/oauth/src/lib/strategies/auth-code-flow-strategy.ts @@ -51,6 +51,10 @@ export class AuthCodeFlowStrategy extends AuthFlowStrategy { logout(queryParams?: Params) { this.rememberMeService.remove(); + if (queryParams?.noRedirectToLogoutUrl) { + this.router.navigate(['/']); + return from(this.oAuthService.revokeTokenAndLogout(true)); + } return from(this.oAuthService.revokeTokenAndLogout(this.getCultureParams(queryParams))); } diff --git a/npm/ng-packs/packages/theme-shared/src/lib/adapters/time.adapter.ts b/npm/ng-packs/packages/theme-shared/src/lib/adapters/time.adapter.ts index de2c47b349..2a10cada51 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/adapters/time.adapter.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/adapters/time.adapter.ts @@ -24,7 +24,7 @@ export class TimeAdapter extends NgbTimeAdapter { if (!value) return ''; const date = new Date(0, 0, 1, value.hour, value.minute, value.second); - const formattedDate = formatDate(date, 'HH:mm', 'en'); + const formattedDate = formatDate(date, 'HH:mm:ss', 'en'); return formattedDate; } diff --git a/npm/ng-packs/packages/theme-shared/src/lib/services/authentication-error-handler.service.ts b/npm/ng-packs/packages/theme-shared/src/lib/services/authentication-error-handler.service.ts index 602514bee8..44dab7e0a1 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/services/authentication-error-handler.service.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/services/authentication-error-handler.service.ts @@ -17,7 +17,7 @@ export class AbpAuthenticationErrorHandler implements CustomHttpErrorHandlerServ execute() { this.configStateService.refreshAppState().subscribe(({ currentUser }) => { if (!currentUser.isAuthenticated) { - this.authService.logout(); + this.authService.logout({ noRedirectToLogoutUrl: true }); } }); } diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Client/Menus/MyProjectNameMenuContributor.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Client/Menus/MyProjectNameMenuContributor.cs index 0d3d77e298..93067729fa 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Client/Menus/MyProjectNameMenuContributor.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Client/Menus/MyProjectNameMenuContributor.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System; +using System.Threading.Tasks; using Microsoft.Extensions.Configuration; using MyCompanyName.MyProjectName.Localization; using MyCompanyName.MyProjectName.MultiTenancy; @@ -65,15 +66,22 @@ public class MyProjectNameMenuContributor : IMenuContributor private Task ConfigureUserMenuAsync(MenuConfigurationContext context) { + if (!OperatingSystem.IsBrowser()) + { + return Task.CompletedTask; + } + + var authServerUrl = _configuration["AuthServer:Authority"] ?? ""; var accountStringLocalizer = context.GetLocalizer(); context.Menu.AddItem(new ApplicationMenuItem( - "Account.Manage", - accountStringLocalizer["MyAccount"], - $"Account/Manage", - icon: "fa fa-cog", - order: 1000, - null).RequireAuthenticated()); + "Account.Manage", + accountStringLocalizer["MyAccount"], + $"{authServerUrl.EnsureEndsWith('/')}Account/Manage", + icon: "fa fa-cog", + order: 1000, + target: "_blank") + .RequireAuthenticated()); return Task.CompletedTask; } diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.Client/Menus/MyProjectNameMenuContributor.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.Client/Menus/MyProjectNameMenuContributor.cs index 6a2100cf1b..75dd7244ef 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.Client/Menus/MyProjectNameMenuContributor.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.Client/Menus/MyProjectNameMenuContributor.cs @@ -66,16 +66,22 @@ public class MyProjectNameMenuContributor : IMenuContributor private Task ConfigureUserMenuAsync(MenuConfigurationContext context) { - var accountStringLocalizer = context.GetLocalizer(); + if (!OperatingSystem.IsBrowser()) + { + return Task.CompletedTask; + } var authServerUrl = _configuration["AuthServer:Authority"] ?? ""; + var accountStringLocalizer = context.GetLocalizer(); + context.Menu.AddItem(new ApplicationMenuItem( - "Account.Manage", - accountStringLocalizer["MyAccount"], - $"{authServerUrl.EnsureEndsWith('/')}Account/Manage", - icon: "fa fa-cog", - order: 1000, - target: "_blank").RequireAuthenticated()); + "Account.Manage", + accountStringLocalizer["MyAccount"], + $"{authServerUrl.EnsureEndsWith('/')}Account/Manage", + icon: "fa fa-cog", + order: 1000, + target: "_blank") + .RequireAuthenticated()); return Task.CompletedTask; } diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered/Menus/MyProjectNameMenuContributor.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered/Menus/MyProjectNameMenuContributor.cs deleted file mode 100644 index 8b15e7aae7..0000000000 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered/Menus/MyProjectNameMenuContributor.cs +++ /dev/null @@ -1,79 +0,0 @@ -using System; -using System.Threading.Tasks; -using Microsoft.Extensions.Configuration; -using MyCompanyName.MyProjectName.Localization; -using MyCompanyName.MyProjectName.MultiTenancy; -using Volo.Abp.Account.Localization; -using Volo.Abp.Authorization.Permissions; -using Volo.Abp.Identity.Blazor; -using Volo.Abp.SettingManagement.Blazor.Menus; -using Volo.Abp.TenantManagement.Blazor.Navigation; -using Volo.Abp.UI.Navigation; - -namespace MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.Menus; - -public class MyProjectNameMenuContributor : IMenuContributor -{ - private readonly IConfiguration _configuration; - - public MyProjectNameMenuContributor(IConfiguration configuration) - { - _configuration = configuration; - } - - public async Task ConfigureMenuAsync(MenuConfigurationContext context) - { - if (context.Menu.Name == StandardMenus.Main) - { - await ConfigureMainMenuAsync(context); - } - else if (context.Menu.Name == StandardMenus.User) - { - await ConfigureUserMenuAsync(context); - } - } - - private Task ConfigureMainMenuAsync(MenuConfigurationContext context) - { - var administration = context.Menu.GetAdministration(); - var l = context.GetLocalizer(); - - context.Menu.Items.Insert( - 0, - new ApplicationMenuItem( - MyProjectNameMenus.Home, - l["Menu:Home"], - "/", - icon: "fas fa-home", - order: 0 - ) - ); - - if (MultiTenancyConsts.IsEnabled) - { - administration.SetSubItemOrder(TenantManagementMenuNames.GroupName, 1); - } - else - { - administration.TryRemoveMenuItem(TenantManagementMenuNames.GroupName); - } - - administration.SetSubItemOrder(IdentityMenuNames.GroupName, 2); - administration.SetSubItemOrder(SettingManagementMenus.GroupName, 3); - - return Task.CompletedTask; - } - - private Task ConfigureUserMenuAsync(MenuConfigurationContext context) - { - var l = context.GetLocalizer(); - var accountStringLocalizer = context.GetLocalizer(); - var authServerUrl = _configuration["AuthServer:Authority"] ?? ""; - - context.Menu.AddItem(new ApplicationMenuItem("Account.Manage", accountStringLocalizer["MyAccount"], - $"{authServerUrl.EnsureEndsWith('/')}Account/Manage?returnUrl={_configuration["App:SelfUrl"]}", icon: "fa fa-cog", order: 1000, null, "_blank").RequireAuthenticated()); - context.Menu.AddItem(new ApplicationMenuItem("Account.Logout", l["Logout"], url: "~/Account/Logout", icon: "fa fa-power-off", order: int.MaxValue - 1000).RequireAuthenticated()); - - return Task.CompletedTask; - } -} diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered/Menus/MyProjectNameMenus.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered/Menus/MyProjectNameMenus.cs deleted file mode 100644 index 6f08562645..0000000000 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered/Menus/MyProjectNameMenus.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.Menus; - -public class MyProjectNameMenus -{ - private const string Prefix = "MyProjectName"; - public const string Home = Prefix + ".Home"; - - //Add your menu items here... - -} diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered/MyProjectNameBlazorModule.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered/MyProjectNameBlazorModule.cs index a1787d15dd..92f0e9faf0 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered/MyProjectNameBlazorModule.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered/MyProjectNameBlazorModule.cs @@ -16,6 +16,7 @@ using Microsoft.Extensions.Options; using Microsoft.IdentityModel.Protocols.OpenIdConnect; using Microsoft.OpenApi.Models; using MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.Client; +using MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.Client.Menus; using MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.Components; using MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.Menus; using MyCompanyName.MyProjectName.Localization; diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp/Menus/MyProjectNameMenuContributor.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp/Menus/MyProjectNameMenuContributor.cs deleted file mode 100644 index 4998bb002a..0000000000 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp/Menus/MyProjectNameMenuContributor.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System.Threading.Tasks; -using MyCompanyName.MyProjectName.Localization; -using MyCompanyName.MyProjectName.MultiTenancy; -using Volo.Abp.Identity.Blazor; -using Volo.Abp.SettingManagement.Blazor.Menus; -using Volo.Abp.TenantManagement.Blazor.Navigation; -using Volo.Abp.UI.Navigation; - -namespace MyCompanyName.MyProjectName.Blazor.WebApp.Menus; - -public class MyProjectNameMenuContributor : IMenuContributor -{ - public async Task ConfigureMenuAsync(MenuConfigurationContext context) - { - if (context.Menu.Name == StandardMenus.Main) - { - await ConfigureMainMenuAsync(context); - } - } - - private Task ConfigureMainMenuAsync(MenuConfigurationContext context) - { - var administration = context.Menu.GetAdministration(); - var l = context.GetLocalizer(); - - context.Menu.Items.Insert( - 0, - new ApplicationMenuItem( - MyProjectNameMenus.Home, - l["Menu:Home"], - "/", - icon: "fas fa-home", - order: 0 - ) - ); - - if (MultiTenancyConsts.IsEnabled) - { - administration.SetSubItemOrder(TenantManagementMenuNames.GroupName, 1); - } - else - { - administration.TryRemoveMenuItem(TenantManagementMenuNames.GroupName); - } - - administration.SetSubItemOrder(IdentityMenuNames.GroupName, 2); - administration.SetSubItemOrder(SettingManagementMenus.GroupName, 3); - - return Task.CompletedTask; - } -} diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp/Menus/MyProjectNameMenus.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp/Menus/MyProjectNameMenus.cs deleted file mode 100644 index acf9533ea0..0000000000 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp/Menus/MyProjectNameMenus.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace MyCompanyName.MyProjectName.Blazor.WebApp.Menus; - -public class MyProjectNameMenus -{ - private const string Prefix = "MyProjectName"; - public const string Home = Prefix + ".Home"; - - //Add your menu items here... - -} diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp/MyProjectNameBlazorModule.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp/MyProjectNameBlazorModule.cs index ab87807219..2452d3e2ea 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp/MyProjectNameBlazorModule.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp/MyProjectNameBlazorModule.cs @@ -11,8 +11,8 @@ using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Options; using Microsoft.OpenApi.Models; using MyCompanyName.MyProjectName.Blazor.WebApp.Client; +using MyCompanyName.MyProjectName.Blazor.WebApp.Client.Menus; using MyCompanyName.MyProjectName.Blazor.WebApp.Components; -using MyCompanyName.MyProjectName.Blazor.WebApp.Menus; using MyCompanyName.MyProjectName.EntityFrameworkCore; using MyCompanyName.MyProjectName.Localization; using MyCompanyName.MyProjectName.MultiTenancy; @@ -226,7 +226,7 @@ public class MyProjectNameBlazorModule : AbpModule { Configure(options => { - options.MenuContributors.Add(new MyProjectNameMenuContributor()); + options.MenuContributors.Add(new MyProjectNameMenuContributor(context.Services.GetConfiguration())); }); } diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj index ff3b990745..cc449f8408 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj @@ -16,6 +16,9 @@ + + + diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj index fa81f11282..96c1759c7c 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj @@ -17,6 +17,9 @@ + + +