diff --git a/docs/en/Application-Services.md b/docs/en/Application-Services.md index c6108c477e..e0f7ef2560 100644 --- a/docs/en/Application-Services.md +++ b/docs/en/Application-Services.md @@ -430,17 +430,17 @@ Task DeleteAsync(TKey id); #### Querying -These methods are low level methods those can be control how to query entities from the database. +These methods are low level methods that can control how to query entities from the database. * `CreateFilteredQuery` can be overridden to create an `IQueryable` that is filtered by the given input. If your `TGetListInput` class contains any filter, it is proper to override this method and filter the query. It returns the (unfiltered) repository (which is already `IQueryable`) by default. * `ApplyPaging` is used to make paging on the query. If your `TGetListInput` already implements `IPagedResultRequest`, you don't need to override this since the ABP Framework automatically understands it and performs the paging. -* `ApplySorting` is used to sort (order by...) the query. If your `TGetListInput` already implements the `ISortedResultRequest`, ABP Framework automatically sorts the query. If not, it fallbacks to the `ApplyDefaultSorting` which tries to sort by creating time, if your entity implements the standard `IHasCreationTime` interface. +* `ApplySorting` is used to sort (order by...) the query. If your `TGetListInput` already implements the `ISortedResultRequest`, ABP Framework automatically sorts the query. If not, it fallbacks to the `ApplyDefaultSorting` which tries to sort by creation time, if your entity implements the standard `IHasCreationTime` interface. * `GetEntityByIdAsync` is used to get an entity by id, which calls `Repository.GetAsync(id)` by default. * `DeleteByIdAsync` is used to delete an entity by id, which calls `Repository.DeleteAsync(id)` by default. #### Object to Object Mapping -These methods are used to convert Entities to DTOs and vice verse. They uses the [IObjectMapper](Object-To-Object-Mapping.md) by default. +These methods are used to convert Entities to DTOs and vice verse. They use the [IObjectMapper](Object-To-Object-Mapping.md) by default. * `MapToGetOutputDtoAsync` is used to map the entity to the DTO returned from the `GetAsync`, `CreateAsync` and `UpdateAsync` methods. Alternatively, you can override the `MapToGetOutputDto` if you don't need to perform any async operation. * `MapToGetListOutputDtosAsync` is used to map a list of entities to a list of DTOs returned from the `GetListAsync` method. It uses the `MapToGetListOutputDtoAsync` to map each entity in the list. You can override one of them based on your case. Alternatively, you can override the `MapToGetListOutputDto` if you don't need to perform any async operation. diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelper.cs index 268e5acf6d..fdab58203a 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelper.cs @@ -38,7 +38,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form public bool SuppressLabel { get; set; } - public CheckBoxHiddenInputRenderMode CheckBoxHiddenInputRenderMode { get; set; } + public CheckBoxHiddenInputRenderMode? CheckBoxHiddenInputRenderMode { get; set; } public AbpInputTagHelper(AbpInputTagHelperService tagHelperService) : base(tagHelperService) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs index 90dbc5f198..6dc050b118 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs @@ -30,9 +30,9 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form { var (innerHtml, isCheckBox) = await GetFormInputGroupAsHtmlAsync(context, output); - if (isCheckBox) + if (isCheckBox && TagHelper.CheckBoxHiddenInputRenderMode.HasValue) { - TagHelper.ViewContext.CheckBoxHiddenInputRenderMode = TagHelper.CheckBoxHiddenInputRenderMode; + TagHelper.ViewContext.CheckBoxHiddenInputRenderMode = TagHelper.CheckBoxHiddenInputRenderMode.Value; } var order = TagHelper.AspFor.ModelExplorer.GetDisplayOrder(); diff --git a/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/AbpAspNetCoreSignalRModule.cs b/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/AbpAspNetCoreSignalRModule.cs index 767f81b452..a0b57db54d 100644 --- a/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/AbpAspNetCoreSignalRModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/AbpAspNetCoreSignalRModule.cs @@ -8,6 +8,9 @@ using Microsoft.AspNetCore.SignalR; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Volo.Abp.AspNetCore.Auditing; +using Volo.Abp.AspNetCore.SignalR.Auditing; +using Volo.Abp.AspNetCore.SignalR.Authentication; +using Volo.Abp.Auditing; using Volo.Abp.DependencyInjection; using Volo.Abp.Modularity; @@ -34,7 +37,9 @@ namespace Volo.Abp.AspNetCore.SignalR var routePatterns = new List {"/signalr-hubs"}; var signalRServerBuilder = context.Services.AddSignalR(options => { - options.AddFilter(); + options.AddFilter(); + options.AddFilter(); + options.AddFilter(); }); context.Services.ExecutePreConfiguredActions(signalRServerBuilder); @@ -75,6 +80,11 @@ namespace Volo.Abp.AspNetCore.SignalR options.IgnoredUrls.AddIfNotContains(x => routePattern.StartsWith(x), () => routePattern); } }); + + Configure(options => + { + options.Contributors.Add(new AspNetCoreSignalRAuditLogContributor()); + }); } private void AutoAddHubTypes(IServiceCollection services) diff --git a/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/AbpHubContext.cs b/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/AbpHubContext.cs new file mode 100644 index 0000000000..29308feeb8 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/AbpHubContext.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using Microsoft.AspNetCore.SignalR; + +namespace Volo.Abp.AspNetCore.SignalR +{ + public class AbpHubContext + { + public IServiceProvider ServiceProvider { get; } + + public Hub Hub { get; } + + public MethodInfo HubMethod { get; } + + public IReadOnlyList HubMethodArguments { get; } + + public AbpHubContext(IServiceProvider serviceProvider, Hub hub, MethodInfo hubMethod, IReadOnlyList hubMethodArguments) + { + ServiceProvider = serviceProvider; + Hub = hub; + HubMethod = hubMethod; + HubMethodArguments = hubMethodArguments; + } + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/AbpHubContextAccessorHubFilter.cs b/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/AbpHubContextAccessorHubFilter.cs new file mode 100644 index 0000000000..8a68a8ebbc --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/AbpHubContextAccessorHubFilter.cs @@ -0,0 +1,23 @@ +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.SignalR; +using Microsoft.Extensions.DependencyInjection; + +namespace Volo.Abp.AspNetCore.SignalR +{ + public class AbpHubContextAccessorHubFilter : IHubFilter + { + public virtual async ValueTask InvokeMethodAsync(HubInvocationContext invocationContext, Func> next) + { + var hubContextAccessor = invocationContext.ServiceProvider.GetRequiredService(); + using (hubContextAccessor.Change(new AbpHubContext( + invocationContext.ServiceProvider, + invocationContext.Hub, + invocationContext.HubMethod, + invocationContext.HubMethodArguments))) + { + return await next(invocationContext); + } + } + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/Auditing/AbpAuditHubFilter.cs b/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/Auditing/AbpAuditHubFilter.cs new file mode 100644 index 0000000000..ec51b93bf6 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/Auditing/AbpAuditHubFilter.cs @@ -0,0 +1,92 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.SignalR; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Volo.Abp.Auditing; +using Volo.Abp.Uow; +using Volo.Abp.Users; + +namespace Volo.Abp.AspNetCore.SignalR.Auditing +{ + public class AbpAuditHubFilter : IHubFilter + { + public virtual async ValueTask InvokeMethodAsync(HubInvocationContext invocationContext, Func> next) + { + var options = invocationContext.ServiceProvider.GetRequiredService>().Value; + if (!options.IsEnabled) + { + return await next(invocationContext); + } + + var hasError = false; + var auditingManager = invocationContext.ServiceProvider.GetRequiredService(); + using (var saveHandle = auditingManager.BeginScope()) + { + Debug.Assert(auditingManager.Current != null); + object result; + try + { + result = await next(invocationContext); + + if (auditingManager.Current.Log.Exceptions.Any()) + { + hasError = true; + } + } + catch (Exception ex) + { + hasError = true; + + if (!auditingManager.Current.Log.Exceptions.Contains(ex)) + { + auditingManager.Current.Log.Exceptions.Add(ex); + } + + throw; + } + finally + { + if (ShouldWriteAuditLog(invocationContext.ServiceProvider, hasError)) + { + var unitOfWorkManager = invocationContext.ServiceProvider.GetRequiredService(); + if (unitOfWorkManager.Current != null) + { + await unitOfWorkManager.Current.SaveChangesAsync(); + } + + await saveHandle.SaveAsync(); + } + } + + return result; + } + } + + private bool ShouldWriteAuditLog(IServiceProvider serviceProvider, bool hasError) + { + var options = serviceProvider.GetRequiredService>().Value; + if (options.AlwaysLogOnException && hasError) + { + return true; + } + + if (!options.IsEnabledForAnonymousUsers && !serviceProvider.GetRequiredService().IsAuthenticated) + { + return false; + } + + var auditingManager = serviceProvider.GetRequiredService(); + if (auditingManager.Current == null || + auditingManager.Current.Log.Actions.IsNullOrEmpty()) + { + return false; + } + + return true; + } + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/Auditing/AspNetCoreSignalRAuditLogContributor.cs b/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/Auditing/AspNetCoreSignalRAuditLogContributor.cs new file mode 100644 index 0000000000..7b20bc0586 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/Auditing/AspNetCoreSignalRAuditLogContributor.cs @@ -0,0 +1,55 @@ +using System.Linq; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Volo.Abp.AspNetCore.WebClientInfo; +using Volo.Abp.Auditing; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.AspNetCore.SignalR.Auditing +{ + public class AspNetCoreSignalRAuditLogContributor : AuditLogContributor, ITransientDependency + { + public ILogger Logger { get; set; } + + public AspNetCoreSignalRAuditLogContributor() + { + Logger = NullLogger.Instance; + } + + public override void PreContribute(AuditLogContributionContext context) + { + var hubContext = context.ServiceProvider.GetRequiredService().Context; + if (hubContext == null) + { + return; + } + + var clientInfoProvider = context.ServiceProvider.GetRequiredService(); + if (context.AuditInfo.ClientIpAddress == null) + { + context.AuditInfo.ClientIpAddress = clientInfoProvider.ClientIpAddress; + } + + if (context.AuditInfo.BrowserInfo == null) + { + context.AuditInfo.BrowserInfo = clientInfoProvider.BrowserInfo; + } + + //TODO: context.AuditInfo.ClientName + } + + public override void PostContribute(AuditLogContributionContext context) + { + var hubContext = context.ServiceProvider.GetRequiredService().Context; + if (hubContext == null) + { + return; + } + + var firstAction = context.AuditInfo.Actions.FirstOrDefault(); + context.AuditInfo.Url = firstAction?.ServiceName + "." + firstAction?.MethodName; + context.AuditInfo.HttpStatusCode = null; + } + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/AbpSignalRHubFilter.cs b/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/Authentication/AbpAuthenticationHubFilter.cs similarity index 93% rename from framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/AbpSignalRHubFilter.cs rename to framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/Authentication/AbpAuthenticationHubFilter.cs index 2695629304..eed252bfe6 100644 --- a/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/AbpSignalRHubFilter.cs +++ b/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/Authentication/AbpAuthenticationHubFilter.cs @@ -4,9 +4,9 @@ using Microsoft.AspNetCore.SignalR; using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Security.Claims; -namespace Volo.Abp.AspNetCore.SignalR +namespace Volo.Abp.AspNetCore.SignalR.Authentication { - public class AbpSignalRHubFilter : IHubFilter + public class AbpAuthenticationHubFilter : IHubFilter { public virtual async ValueTask InvokeMethodAsync(HubInvocationContext invocationContext, Func> next) { diff --git a/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/DefaultAbpHubContextAccessor.cs b/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/DefaultAbpHubContextAccessor.cs new file mode 100644 index 0000000000..6ef0c02d82 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/DefaultAbpHubContextAccessor.cs @@ -0,0 +1,23 @@ +using System; +using System.Threading; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.AspNetCore.SignalR +{ + public class DefaultAbpHubContextAccessor : IAbpHubContextAccessor, ISingletonDependency + { + public AbpHubContext Context => _currentHubContext.Value; + + private readonly AsyncLocal _currentHubContext = new AsyncLocal(); + + public virtual IDisposable Change(AbpHubContext context) + { + var parent = Context; + _currentHubContext.Value = context; + return new DisposeAction(() => + { + _currentHubContext.Value = parent; + }); + } + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/IAbpHubContextAccessor.cs b/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/IAbpHubContextAccessor.cs new file mode 100644 index 0000000000..052c6a9be1 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/IAbpHubContextAccessor.cs @@ -0,0 +1,12 @@ +using System; + +namespace Volo.Abp.AspNetCore.SignalR +{ + public interface IAbpHubContextAccessor + { + AbpHubContext Context { get; } + + IDisposable Change(AbpHubContext context); + } +} + diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Auditing/AspNetCoreAuditLogContributor.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Auditing/AspNetCoreAuditLogContributor.cs index 04238a9a45..2d3fd11705 100644 --- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Auditing/AspNetCoreAuditLogContributor.cs +++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Auditing/AspNetCoreAuditLogContributor.cs @@ -26,6 +26,11 @@ namespace Volo.Abp.AspNetCore.Auditing return; } + if (httpContext.WebSockets.IsWebSocketRequest) + { + return; + } + if (context.AuditInfo.HttpMethod == null) { context.AuditInfo.HttpMethod = httpContext.Request.Method; diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AspNetCoreUnitOfWorkTransactionBehaviourProvider.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AspNetCoreUnitOfWorkTransactionBehaviourProvider.cs index fd1d20d905..0e7c54d4fa 100644 --- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AspNetCoreUnitOfWorkTransactionBehaviourProvider.cs +++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AspNetCoreUnitOfWorkTransactionBehaviourProvider.cs @@ -22,6 +22,11 @@ namespace Volo.Abp.AspNetCore.Uow return null; } + if (httpContext.WebSockets.IsWebSocketRequest) + { + return null; + } + var currentUrl = httpContext.Request.Path.Value; if (currentUrl != null) { diff --git a/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/NavMenu.razor.cs b/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/NavMenu.razor.cs index af408aab57..eba195a9e3 100644 --- a/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/NavMenu.razor.cs +++ b/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/NavMenu.razor.cs @@ -1,19 +1,36 @@ -using System.Threading.Tasks; +using System; +using System.Threading.Tasks; using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.Components.Authorization; using Volo.Abp.UI.Navigation; namespace Volo.Abp.AspNetCore.Components.Web.BasicTheme.Themes.Basic { - public partial class NavMenu + public partial class NavMenu : IDisposable { [Inject] protected IMenuManager MenuManager { get; set; } + + [Inject] + protected AuthenticationStateProvider AuthenticationStateProvider { get; set; } protected ApplicationMenu Menu { get; set; } protected override async Task OnInitializedAsync() { Menu = await MenuManager.GetMainMenuAsync(); + AuthenticationStateProvider.AuthenticationStateChanged += AuthenticationStateProviderOnAuthenticationStateChanged; + } + + public void Dispose() + { + AuthenticationStateProvider.AuthenticationStateChanged -= AuthenticationStateProviderOnAuthenticationStateChanged; + } + + private async void AuthenticationStateProviderOnAuthenticationStateChanged(Task task) + { + Menu = await MenuManager.GetMainMenuAsync(); + await InvokeAsync(StateHasChanged); } } } diff --git a/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor.cs b/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor.cs index 0ec9caa23c..285e0a59da 100644 --- a/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor.cs +++ b/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor.cs @@ -34,11 +34,8 @@ namespace Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.Themes.Basic if (AuthenticationStateProvider != null) { - AuthenticationStateProvider.AuthenticationStateChanged += async (task) => - { - Menu = await MenuManager.GetAsync(StandardMenus.User); - await InvokeAsync(StateHasChanged); - }; + AuthenticationStateProvider.AuthenticationStateChanged += + AuthenticationStateProviderOnAuthenticationStateChanged; } } @@ -46,10 +43,21 @@ namespace Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.Themes.Basic { InvokeAsync(StateHasChanged); } + + private async void AuthenticationStateProviderOnAuthenticationStateChanged(Task task) + { + Menu = await MenuManager.GetAsync(StandardMenus.User); + await InvokeAsync(StateHasChanged); + } public void Dispose() { Navigation.LocationChanged -= OnLocationChanged; + if (AuthenticationStateProvider != null) + { + AuthenticationStateProvider.AuthenticationStateChanged -= + AuthenticationStateProviderOnAuthenticationStateChanged; + } } private async Task NavigateToAsync(string uri, string target = null) diff --git a/modules/cms-kit/angular/projects/cms-kit/package.json b/modules/cms-kit/angular/projects/cms-kit/package.json index 6e1eafa1e9..1d596576f4 100644 --- a/modules/cms-kit/angular/projects/cms-kit/package.json +++ b/modules/cms-kit/angular/projects/cms-kit/package.json @@ -4,8 +4,8 @@ "peerDependencies": { "@angular/common": "^9.1.11", "@angular/core": "^9.1.11", - "@abp/ng.core": ">=5.0.0-beta.1-1", - "@abp/ng.theme.shared": ">=5.0.0-beta.1-1" + "@abp/ng.core": ">=5.0.0-beta.3-1", + "@abp/ng.theme.shared": ">=5.0.0-beta.3-1" }, "dependencies": { "tslib": "^2.0.0" diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/ReactionSelection/default.js b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/ReactionSelection/default.js index 93150ec909..bc7f5af444 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/ReactionSelection/default.js +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/ReactionSelection/default.js @@ -2,10 +2,10 @@ var l = abp.localization.getResource('CmsKit'); - var myDefaultWhiteList = $.fn.tooltip.Constructor.Default.whiteList; + var myDefaultAllowList = $.fn.tooltip.Constructor.Default.allowList; - if (myDefaultWhiteList.span.indexOf('data-reaction-name') < 0) { - myDefaultWhiteList.span.push('data-reaction-name'); + if (myDefaultAllowList.span.indexOf('data-reaction-name') < 0) { + myDefaultAllowList.span.push('data-reaction-name'); } abp.widgets.CmsReactionSelection = function ($widget) { diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/PermissionManagementModal.cshtml b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/PermissionManagementModal.cshtml index c5dfed0c20..02743d2f3d 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/PermissionManagementModal.cshtml +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/PermissionManagementModal.cshtml @@ -13,7 +13,7 @@ - +
@@ -27,7 +27,7 @@
this.elRef.nativeElement.focus(), this.delay); + setTimeout(() => this.elRef.nativeElement.focus(), this.delay as number); } } diff --git a/npm/ng-packs/packages/core/src/lib/directives/permission.directive.ts b/npm/ng-packs/packages/core/src/lib/directives/permission.directive.ts index 891c4c6e8c..2054a0d529 100644 --- a/npm/ng-packs/packages/core/src/lib/directives/permission.directive.ts +++ b/npm/ng-packs/packages/core/src/lib/directives/permission.directive.ts @@ -1,12 +1,10 @@ import { ChangeDetectorRef, Directive, - ElementRef, Input, OnChanges, OnDestroy, Optional, - Renderer2, TemplateRef, ViewContainerRef, } from '@angular/core'; @@ -18,13 +16,11 @@ import { PermissionService } from '../services/permission.service'; selector: '[abpPermission]', }) export class PermissionDirective implements OnDestroy, OnChanges { - @Input('abpPermission') condition: string; + @Input('abpPermission') condition: string | undefined; - subscription: Subscription; + subscription!: Subscription; constructor( - private elRef: ElementRef, - private renderer: Renderer2, @Optional() private templateRef: TemplateRef, private vcRef: ViewContainerRef, private permissionService: PermissionService, @@ -37,7 +33,7 @@ export class PermissionDirective implements OnDestroy, OnChanges { } this.subscription = this.permissionService - .getGrantedPolicy$(this.condition) + .getGrantedPolicy$(this.condition || '') .pipe(distinctUntilChanged()) .subscribe(isGranted => { this.vcRef.clear(); diff --git a/npm/ng-packs/packages/core/src/lib/directives/replaceable-template.directive.ts b/npm/ng-packs/packages/core/src/lib/directives/replaceable-template.directive.ts index f83af059f6..5a96ada9a9 100644 --- a/npm/ng-packs/packages/core/src/lib/directives/replaceable-template.directive.ts +++ b/npm/ng-packs/packages/core/src/lib/directives/replaceable-template.directive.ts @@ -33,7 +33,7 @@ export class ReplaceableTemplateDirective implements OnInit, OnChanges { context = {} as any; - externalComponent: Type; + externalComponent!: Type; defaultComponentRef: any; @@ -50,7 +50,7 @@ export class ReplaceableTemplateDirective implements OnInit, OnChanges { private subscription: SubscriptionService, ) { this.context = { - initTemplate: ref => { + initTemplate: (ref: any) => { this.resetDefaultComponent(); this.defaultComponentRef = ref; this.setDefaultComponentInputs(); @@ -121,8 +121,8 @@ export class ReplaceableTemplateDirective implements OnInit, OnChanges { if (Object.prototype.hasOwnProperty.call(this.data.outputs, key)) { if (!this.defaultComponentSubscriptions[key]) { this.defaultComponentSubscriptions[key] = this.defaultComponentRef[key].subscribe( - value => { - this.data.outputs[key](value); + (value: any) => { + this.data.outputs?.[key](value); }, ); } @@ -132,7 +132,7 @@ export class ReplaceableTemplateDirective implements OnInit, OnChanges { } setProvidedData() { - this.providedData = { ...this.data, inputs: {} }; + this.providedData = { ...this.data, inputs: {}, outputs: {} }; if (!this.data.inputs) return; Object.defineProperties(this.providedData.inputs, { @@ -142,9 +142,9 @@ export class ReplaceableTemplateDirective implements OnInit, OnChanges { [key]: { enumerable: true, configurable: true, - get: () => this.data.inputs[key].value, - ...(this.data.inputs[key].twoWay && { - set: newValue => { + get: () => this.data.inputs[key]?.value, + ...(this.data.inputs[key]?.twoWay && { + set: (newValue: any) => { this.data.inputs[key].value = newValue; this.data.outputs[`${key}Change`](newValue); }, diff --git a/npm/ng-packs/packages/core/src/lib/models/common.ts b/npm/ng-packs/packages/core/src/lib/models/common.ts index d99d591ad4..0196ce385a 100644 --- a/npm/ng-packs/packages/core/src/lib/models/common.ts +++ b/npm/ng-packs/packages/core/src/lib/models/common.ts @@ -52,7 +52,7 @@ export namespace ABP { } export interface Route extends Nav { - path: string; + path?: string; layout?: eLayoutType; iconClass?: string; } diff --git a/npm/ng-packs/packages/core/src/lib/models/replaceable-components.ts b/npm/ng-packs/packages/core/src/lib/models/replaceable-components.ts index d20768e7ff..ebdc7d1b8b 100644 --- a/npm/ng-packs/packages/core/src/lib/models/replaceable-components.ts +++ b/npm/ng-packs/packages/core/src/lib/models/replaceable-components.ts @@ -16,8 +16,8 @@ export namespace ReplaceableComponents { I, O extends { [K in keyof O]: EventEmitter | Subject }, > { - inputs: { -readonly [K in keyof I]: { value: I[K]; twoWay?: boolean } }; - outputs: { -readonly [K in keyof O]: (value: ABP.ExtractFromOutput) => void }; + inputs?: { -readonly [K in keyof I]: { value: I[K]; twoWay?: boolean } }; + outputs?: { -readonly [K in keyof O]: (value: ABP.ExtractFromOutput) => void }; componentKey: string; } diff --git a/npm/ng-packs/packages/core/src/lib/pipes/localization.pipe.ts b/npm/ng-packs/packages/core/src/lib/pipes/localization.pipe.ts index 50427ec5ed..2dbac68eb7 100644 --- a/npm/ng-packs/packages/core/src/lib/pipes/localization.pipe.ts +++ b/npm/ng-packs/packages/core/src/lib/pipes/localization.pipe.ts @@ -9,13 +9,20 @@ import { LocalizationService } from '../services/localization.service'; export class LocalizationPipe implements PipeTransform { constructor(private localization: LocalizationService) {} - transform(value: string | LocalizationWithDefault = '', ...interpolateParams: string[]): string { - return this.localization.instant( - value, - ...interpolateParams.reduce( - (acc, val) => (Array.isArray(val) ? [...acc, ...val] : [...acc, val]), - [], - ), - ); + transform( + value: string | LocalizationWithDefault = '', + ...interpolateParams: (string | string[] | undefined)[] + ): string { + const params = + interpolateParams.reduce((acc, val) => { + if (!acc) { + return val; + } + if (!val) { + return acc; + } + return Array.isArray(val) ? [...acc, ...val] : [...acc, val]; + }, []) || []; + return this.localization.instant(value, ...params); } } diff --git a/npm/ng-packs/packages/core/src/lib/services/config-state.service.ts b/npm/ng-packs/packages/core/src/lib/services/config-state.service.ts index 3aadfa898b..4223ea97de 100644 --- a/npm/ng-packs/packages/core/src/lib/services/config-state.service.ts +++ b/npm/ng-packs/packages/core/src/lib/services/config-state.service.ts @@ -48,14 +48,14 @@ export class ConfigStateService { return this.store.state; } - getDeep$(keys: string[] | string) { + getDeep$(keys: string[] | string): Observable { keys = splitKeys(keys); return this.store .sliceState(state => state) .pipe( map(state => { - return (keys as string[]).reduce((acc, val) => { + return (keys as string[]).reduce((acc: any, val) => { if (acc) { return acc[val]; } @@ -66,10 +66,10 @@ export class ConfigStateService { ); } - getDeep(keys: string[] | string) { + getDeep(keys: string[] | string): any { keys = splitKeys(keys); - return (keys as string[]).reduce((acc, val) => { + return (keys as string[]).reduce((acc: any, val) => { if (acc) { return acc[val]; } diff --git a/npm/ng-packs/packages/core/src/lib/services/environment.service.ts b/npm/ng-packs/packages/core/src/lib/services/environment.service.ts index 10d7664acb..9fd1e280a3 100644 --- a/npm/ng-packs/packages/core/src/lib/services/environment.service.ts +++ b/npm/ng-packs/packages/core/src/lib/services/environment.service.ts @@ -23,11 +23,11 @@ export class EnvironmentService { return this.store.state; } - getApiUrl(key?: string) { + getApiUrl(key: string) { return mapToApiUrl(key)(this.store.state.apis); } - getApiUrl$(key?: string) { + getApiUrl$(key: string) { return this.store.sliceState(state => state.apis).pipe(map(mapToApiUrl(key))); } diff --git a/npm/ng-packs/packages/core/src/lib/services/http-error-reporter.service.ts b/npm/ng-packs/packages/core/src/lib/services/http-error-reporter.service.ts index b34402c8cd..65d063f82d 100644 --- a/npm/ng-packs/packages/core/src/lib/services/http-error-reporter.service.ts +++ b/npm/ng-packs/packages/core/src/lib/services/http-error-reporter.service.ts @@ -4,7 +4,7 @@ import { BehaviorSubject, Subject } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class HttpErrorReporterService { - private _reporter$ = new Subject(); + private _reporter$ = new Subject(); private _errors$ = new BehaviorSubject([]); get reporter$() { diff --git a/npm/ng-packs/packages/core/src/lib/services/lazy-load.service.ts b/npm/ng-packs/packages/core/src/lib/services/lazy-load.service.ts index 0aca94c94a..3254396b82 100644 --- a/npm/ng-packs/packages/core/src/lib/services/lazy-load.service.ts +++ b/npm/ng-packs/packages/core/src/lib/services/lazy-load.service.ts @@ -8,7 +8,7 @@ import { ResourceWaitService } from './resource-wait.service'; providedIn: 'root', }) export class LazyLoadService { - readonly loaded = new Map(); + readonly loaded = new Map(); constructor(private resourceWaitService: ResourceWaitService) {} diff --git a/npm/ng-packs/packages/core/src/lib/services/list.service.ts b/npm/ng-packs/packages/core/src/lib/services/list.service.ts index dc79e67f66..e130e3d64f 100644 --- a/npm/ng-packs/packages/core/src/lib/services/list.service.ts +++ b/npm/ng-packs/packages/core/src/lib/services/list.service.ts @@ -21,7 +21,7 @@ import { PagedResultDto } from '../models/dtos'; import { LIST_QUERY_DEBOUNCE_TIME } from '../tokens/list.token'; @Injectable() -export class ListService implements OnDestroy { +export class ListService implements OnDestroy { private _filter = ''; set filter(value: string) { this._filter = value; @@ -112,7 +112,7 @@ export class ListService implements OnDes switchMap(query => streamCreatorCallback(query).pipe(catchError(() => of(null)))), filter(Boolean), tap(() => this._isLoading$.next(false)), - shareReplay({ bufferSize: 1, refCount: true }), + shareReplay({ bufferSize: 1, refCount: true }), takeUntil(this.destroy$), ); } diff --git a/npm/ng-packs/packages/core/src/lib/utils/localization-utils.ts b/npm/ng-packs/packages/core/src/lib/utils/localization-utils.ts index 02bbc3f338..59a0e99051 100644 --- a/npm/ng-packs/packages/core/src/lib/utils/localization-utils.ts +++ b/npm/ng-packs/packages/core/src/lib/utils/localization-utils.ts @@ -35,7 +35,7 @@ export function createLocalizationPipeKeyGenerator( ) { const findLocalization = createLocalizationFinder(localization); - return (resourceNames: string[], keys: string[], defaultKey: string) => { + return (resourceNames: string[], keys: string[], defaultKey: string | undefined) => { const { resourceName, key } = findLocalization(resourceNames, keys); return !resourceName ? defaultKey : resourceName === '_' ? key : `${resourceName}::${key}`; }; @@ -45,7 +45,7 @@ function createLocalizationFinder(localization: ApplicationLocalizationConfigura const localize = createLocalizer(localization); return (resourceNames: string[], keys: string[]) => { - resourceNames = resourceNames.concat(localization.defaultResourceName).filter(Boolean); + resourceNames = resourceNames.concat(localization.defaultResourceName || '').filter(Boolean); const resourceCount = resourceNames.length; const keyCount = keys.length; diff --git a/npm/ng-packs/packages/setting-management/config/src/components/email-setting-group/email-setting-group.component.html b/npm/ng-packs/packages/setting-management/config/src/components/email-setting-group/email-setting-group.component.html index 6017609d1e..ff6d51f692 100644 --- a/npm/ng-packs/packages/setting-management/config/src/components/email-setting-group/email-setting-group.component.html +++ b/npm/ng-packs/packages/setting-management/config/src/components/email-setting-group/email-setting-group.component.html @@ -2,7 +2,7 @@
-
+
@@ -41,7 +41,7 @@ - +
@@ -63,7 +63,7 @@ providerKey: { value: providerKey }, visible: { value: visibleFeatures, twoWay: true } }, - outputs: { visibleChange: onVisibleFeaturesChange }, + outputs: { visibleChange: $any(onVisibleFeaturesChange) }, componentKey: featureManagementKey }" [(visible)]="visibleFeatures" diff --git a/npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.ts b/npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.ts index b3ebca01b1..dfee9ada2e 100644 --- a/npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.ts +++ b/npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.ts @@ -26,17 +26,15 @@ import { eTenantManagementComponents } from '../../enums/components'; export class TenantsComponent implements OnInit { data: PagedResultDto = { items: [], totalCount: 0 }; - selected: TenantDto; + selected!: TenantDto; - tenantForm: FormGroup; + tenantForm!: FormGroup; - isModalVisible: boolean; + isModalVisible!: boolean; visibleFeatures = false; - providerKey: string; - - _useSharedDatabase: boolean; + providerKey!: string; modalBusy = false; @@ -142,7 +140,7 @@ export class TenantsComponent implements OnInit { }, 0); } - sort(data) { + sort(data: any) { const { prop, dir } = data.sorts[0]; this.list.sortKey = prop; this.list.sortOrder = dir; diff --git a/npm/ng-packs/packages/tenant-management/src/lib/defaults/default-tenants-toolbar-actions.ts b/npm/ng-packs/packages/tenant-management/src/lib/defaults/default-tenants-toolbar-actions.ts index e305186276..8bd590d2f6 100644 --- a/npm/ng-packs/packages/tenant-management/src/lib/defaults/default-tenants-toolbar-actions.ts +++ b/npm/ng-packs/packages/tenant-management/src/lib/defaults/default-tenants-toolbar-actions.ts @@ -7,7 +7,7 @@ export const DEFAULT_TENANTS_TOOLBAR_ACTIONS = ToolbarAction.createMany { const component = data.getInjected(TenantsComponent); - component.openFeaturesModal(null); + component.openFeaturesModal(''); }, permission: 'FeatureManagement.ManageHostFeatures', icon: 'fa fa-cog', diff --git a/npm/ng-packs/packages/theme-basic/src/lib/components/account-layout/tenant-box/tenant-box.component.html b/npm/ng-packs/packages/theme-basic/src/lib/components/account-layout/tenant-box/tenant-box.component.html index f0f80b599e..1804050cf8 100644 --- a/npm/ng-packs/packages/theme-basic/src/lib/components/account-layout/tenant-box/tenant-box.component.html +++ b/npm/ng-packs/packages/theme-basic/src/lib/components/account-layout/tenant-box/tenant-box.component.html @@ -1,4 +1,4 @@ - +
diff --git a/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/current-user.component.ts b/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/current-user.component.ts index aa2a144be6..fbfa01882a 100644 --- a/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/current-user.component.ts +++ b/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/current-user.component.ts @@ -21,7 +21,7 @@ export class CurrentUserComponent { } constructor( - @Inject(NAVIGATE_TO_MANAGE_PROFILE) public navigateToManageProfile, + @Inject(NAVIGATE_TO_MANAGE_PROFILE) public navigateToManageProfile: () => void, private authService: AuthService, private configState: ConfigStateService, private sessionState: SessionStateService, diff --git a/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/languages.component.ts b/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/languages.component.ts index 04b6cfa3bd..9dd27b28e1 100644 --- a/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/languages.component.ts +++ b/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/languages.component.ts @@ -7,7 +7,7 @@ import { map } from 'rxjs/operators'; selector: 'abp-languages', template: ` @@ -52,7 +52,7 @@ export class LanguagesComponent { return this.languages$.pipe( map( languages => - languages?.find(lang => lang.cultureName === this.selectedLangCulture).displayName || '', + languages?.find(lang => lang.cultureName === this.selectedLangCulture)?.displayName || '', ), ); } diff --git a/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/nav-items.component.html b/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/nav-items.component.html index d781ad90b2..ac571d7680 100644 --- a/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/nav-items.component.html +++ b/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/nav-items.component.html @@ -1,6 +1,6 @@