diff --git a/common.props b/common.props index ccfc483027..f5db446396 100644 --- a/common.props +++ b/common.props @@ -10,10 +10,8 @@ https://github.com/abpframework/abp/ true - - true - snupkg - + + $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb diff --git a/docs/en/UI/Blazor/Page-Progress.md b/docs/en/UI/Blazor/Page-Progress.md index 149c35293e..b1d5b0df12 100644 --- a/docs/en/UI/Blazor/Page-Progress.md +++ b/docs/en/UI/Blazor/Page-Progress.md @@ -1,3 +1,57 @@ # Blazor UI: Page Progress -TODO \ No newline at end of file +Page Progress is used to show a progress bar indicator on top of the page and to show to the user that currently a long running process is in the work. + +By default you don't need to do anything to show the progress indicator, as all the work is done automatically by the ABP Framework internals. This means that all calls to the ABP backend (through your HTTP API) will activate page progress and show the loading indicator. + +This doesn't mean that you don't have the control over it. On the contrary, if you want to show progress for your own processes, it is really easy to do. All you have to do is to use inject and use the `IUiPageProgressService`. + +## Example + +First, inject the `IUiPageProgressService` into your page/component. + +```cs +@inject IUiPageProgressService pageProgressService +``` + +Next, invoke the `Go` method in `IUiPageProgressService`. It's that simple: + +```cs +Task OnClick() +{ + return pageProgressService.Go(null); +} +``` + +The previous example will show the progress with a default settings. If, for example you want to change the progress color you can override it by setting the options through the `Go` method. + +```cs +Task OnClick() +{ + return pageProgressService.Go(null, options => + { + options.Type = UiPageProgressType.Warning; + }); +} +``` + +## Breakdown + +The first parameter of the `Go` needs a little explanation. In the previous example we have set it to `null` which means, once called it will show an _indeterminate_ indicator and will cycle the loading animation indefinitely, until we hide the progress. You also have the option of defining the actual percentage of the progress and the code is the same, just instead of sending it the `null` you will send it a number between `0` and `100`. + +```cs +pageProgressService.Go(25) +``` + +### Valid values + +1. `null` - show _indeterminate_ indicator +2. `>= 0` and `<= 100` - show the regular _percentage_ progress + +### Hiding progress + +To hide the progress just set the actual values to something other then the _Valid value_. + +```cs +pageProgressService.Go(-1) +``` \ No newline at end of file diff --git a/docs/en/docs-nav.json b/docs/en/docs-nav.json index 217467e666..c7a7554fdc 100644 --- a/docs/en/docs-nav.json +++ b/docs/en/docs-nav.json @@ -689,7 +689,7 @@ "items": [ { "text": "SubmitButton", - "path": "UI/Blazor/SubmitButton.md" + "path": "UI/Blazor/Components/SubmitButton.md" } ] }, diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/MainLayout.razor b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/MainLayout.razor index e85e899123..5993d17e0d 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/MainLayout.razor +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/MainLayout.razor @@ -21,4 +21,5 @@ + diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Microsoft/AspNetCore/Components/WebAssembly/Hosting/AbpWebAssemblyHostBuilderExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Microsoft/AspNetCore/Components/WebAssembly/Hosting/AbpWebAssemblyHostBuilderExtensions.cs index 7cba7ce9b3..9e1752ffda 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Microsoft/AspNetCore/Components/WebAssembly/Hosting/AbpWebAssemblyHostBuilderExtensions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Microsoft/AspNetCore/Components/WebAssembly/Hosting/AbpWebAssemblyHostBuilderExtensions.cs @@ -1,6 +1,5 @@ using System; using System.Globalization; -using System.Reflection; using System.Runtime.CompilerServices; using System.Threading.Tasks; using JetBrains.Annotations; @@ -8,7 +7,9 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Volo.Abp; using Volo.Abp.AspNetCore.Components.WebAssembly; +using Volo.Abp.AspNetCore.Components.WebAssembly.DependencyInjection; using Volo.Abp.AspNetCore.Mvc.Client; +using Volo.Abp.DependencyInjection; using Volo.Abp.Modularity; namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting @@ -39,13 +40,17 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting return application; } - public async static Task InitializeAsync( + public static async Task InitializeAsync( [NotNull] this IAbpApplicationWithExternalServiceProvider application, [NotNull] IServiceProvider serviceProvider) { Check.NotNull(application, nameof(application)); Check.NotNull(serviceProvider, nameof(serviceProvider)); + var serviceProviderAccessor = (WebAssemblyClientScopeServiceProviderAccessor) + serviceProvider.GetRequiredService(); + serviceProviderAccessor.ServiceProvider = serviceProvider; + application.Initialize(serviceProvider); using (var scope = serviceProvider.CreateScope()) @@ -55,7 +60,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting } } - private async static Task InitializeModulesAsync(IServiceProvider serviceProvider) + private static async Task InitializeModulesAsync(IServiceProvider serviceProvider) { foreach (var service in serviceProvider.GetServices()) { @@ -63,7 +68,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting } } - private async static Task SetCurrentLanguageAsync(IServiceScope scope) + private static async Task SetCurrentLanguageAsync(IServiceScope scope) { var configurationClient = scope.ServiceProvider.GetRequiredService(); var utilsService = scope.ServiceProvider.GetRequiredService(); diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/AbpBlazorClientHttpMessageHandler.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/AbpBlazorClientHttpMessageHandler.cs index 84f9743a1e..7b40ca5286 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/AbpBlazorClientHttpMessageHandler.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/AbpBlazorClientHttpMessageHandler.cs @@ -4,8 +4,9 @@ using System.Net.Http.Headers; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Components; -using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; using Microsoft.JSInterop; +using Volo.Abp.AspNetCore.Components.Progression; using Volo.Abp.DependencyInjection; namespace Volo.Abp.AspNetCore.Components.WebAssembly @@ -18,6 +19,8 @@ namespace Volo.Abp.AspNetCore.Components.WebAssembly private readonly NavigationManager _navigationManager; + private readonly IUiPageProgressService _uiPageProgressService; + private const string AntiForgeryCookieName = "XSRF-TOKEN"; private const string AntiForgeryHeaderName = "RequestVerificationToken"; @@ -25,19 +28,33 @@ namespace Volo.Abp.AspNetCore.Components.WebAssembly public AbpBlazorClientHttpMessageHandler( IJSRuntime jsRuntime, ICookieService cookieService, - NavigationManager navigationManager) + NavigationManager navigationManager, + IClientScopeServiceProviderAccessor clientScopeServiceProviderAccessor) { _jsRuntime = jsRuntime; _cookieService = cookieService; _navigationManager = navigationManager; + _uiPageProgressService = clientScopeServiceProviderAccessor.ServiceProvider.GetRequiredService(); } - protected async override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { - await SetLanguageAsync(request, cancellationToken); - await SetAntiForgeryTokenAsync(request); + try + { + await _uiPageProgressService.Go(null, options => + { + options.Type = UiPageProgressType.Info; + }); + + await SetLanguageAsync(request, cancellationToken); + await SetAntiForgeryTokenAsync(request); - return await base.SendAsync(request, cancellationToken); + return await base.SendAsync(request, cancellationToken); + } + finally + { + await _uiPageProgressService.Go(-1); + } } private async Task SetLanguageAsync(HttpRequestMessage request, CancellationToken cancellationToken) diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/DependencyInjection/WebAssemblyClientScopeServiceProviderAccessor.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/DependencyInjection/WebAssemblyClientScopeServiceProviderAccessor.cs new file mode 100644 index 0000000000..74b16ec951 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/DependencyInjection/WebAssemblyClientScopeServiceProviderAccessor.cs @@ -0,0 +1,12 @@ +using System; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.AspNetCore.Components.WebAssembly.DependencyInjection +{ + public class WebAssemblyClientScopeServiceProviderAccessor : + IClientScopeServiceProviderAccessor, + ISingletonDependency + { + public IServiceProvider ServiceProvider { get; set; } + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Progression/IUiPageProgressService.cs b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Progression/IUiPageProgressService.cs new file mode 100644 index 0000000000..fa9781e2d9 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Progression/IUiPageProgressService.cs @@ -0,0 +1,21 @@ +using System; +using System.Threading.Tasks; + +namespace Volo.Abp.AspNetCore.Components.Progression +{ + public interface IUiPageProgressService + { + /// + /// An event raised after the notification is received. + /// + public event EventHandler ProgressChanged; + + /// + /// Sets the progress percentage. + /// + /// Value of the progress from 0 to 100, or null for indeterminate progress. + /// Additional options. + /// Awaitable task. + Task Go(int? percentage, Action options = null); + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Progression/NullUiPageProgressService.cs b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Progression/NullUiPageProgressService.cs new file mode 100644 index 0000000000..5c375e2b40 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Progression/NullUiPageProgressService.cs @@ -0,0 +1,16 @@ +using System; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.AspNetCore.Components.Progression +{ + public class NullUiPageProgressService : IUiPageProgressService, ISingletonDependency + { + public event EventHandler ProgressChanged; + + public Task Go(int? percentage, Action options = null) + { + return Task.CompletedTask; + } + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Progression/UiPageProgressEventArgs.cs b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Progression/UiPageProgressEventArgs.cs new file mode 100644 index 0000000000..74af5cb971 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Progression/UiPageProgressEventArgs.cs @@ -0,0 +1,17 @@ +using System; + +namespace Volo.Abp.AspNetCore.Components.Progression +{ + public class UiPageProgressEventArgs : EventArgs + { + public UiPageProgressEventArgs(int? percentage, UiPageProgressOptions options) + { + Percentage = percentage; + Options = options; + } + + public int? Percentage { get; } + + public UiPageProgressOptions Options { get; } + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Progression/UiPageProgressOptions.cs b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Progression/UiPageProgressOptions.cs new file mode 100644 index 0000000000..0ce243552d --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Progression/UiPageProgressOptions.cs @@ -0,0 +1,13 @@ +namespace Volo.Abp.AspNetCore.Components.Progression +{ + /// + /// Options to override page progress appearance. + /// + public class UiPageProgressOptions + { + /// + /// Type or color, of the page progress. + /// + public UiPageProgressType Type { get; set; } + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Progression/UiPageProgressType.cs b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Progression/UiPageProgressType.cs new file mode 100644 index 0000000000..db1d00932d --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Progression/UiPageProgressType.cs @@ -0,0 +1,11 @@ +namespace Volo.Abp.AspNetCore.Components.Progression +{ + public enum UiPageProgressType + { + Default, + Info, + Success, + Warning, + Error, + } +} diff --git a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationMiddleware.cs b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationMiddleware.cs index e83e240c85..06f3922b22 100644 --- a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationMiddleware.cs +++ b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationMiddleware.cs @@ -23,10 +23,10 @@ namespace Microsoft.AspNetCore.RequestLocalization public async Task InvokeAsync(HttpContext context, RequestDelegate next) { - var middleware = new RequestLocalizationMiddleware( next, - new OptionsWrapper(await _requestLocalizationOptionsProvider.GetLocalizationOptionsAsync()), _loggerFactory + new OptionsWrapper(await _requestLocalizationOptionsProvider.GetLocalizationOptionsAsync()), + _loggerFactory ); await middleware.Invoke(context); diff --git a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationOptions.cs b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationOptions.cs new file mode 100644 index 0000000000..ccf2aeb3f4 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationOptions.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; + +namespace Microsoft.AspNetCore.RequestLocalization +{ + public class AbpRequestLocalizationOptions + { + public List> RequestLocalizationOptionConfigurators { get; } + + public AbpRequestLocalizationOptions() + { + RequestLocalizationOptionConfigurators = new List>(); + } + } +} diff --git a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/DefaultAbpRequestLocalizationOptionsProvider.cs b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/DefaultAbpRequestLocalizationOptionsProvider.cs index 93ced35c45..226c0a9f6c 100644 --- a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/DefaultAbpRequestLocalizationOptionsProvider.cs +++ b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/DefaultAbpRequestLocalizationOptionsProvider.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Localization; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; using Volo.Abp.Localization; using Volo.Abp.Settings; @@ -67,6 +68,13 @@ namespace Microsoft.AspNetCore.RequestLocalization .ToArray() }; + foreach (var configurator in serviceScope.ServiceProvider + .GetRequiredService>() + .Value.RequestLocalizationOptionConfigurators) + { + await configurator(serviceScope.ServiceProvider, options); + } + _optionsAction?.Invoke(options); _requestLocalizationOptions = options; } diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/DependencyInjection/HttpContextClientScopeServiceProviderAccessor.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/DependencyInjection/HttpContextClientScopeServiceProviderAccessor.cs new file mode 100644 index 0000000000..943c11ebc3 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/DependencyInjection/HttpContextClientScopeServiceProviderAccessor.cs @@ -0,0 +1,33 @@ +using System; +using Microsoft.AspNetCore.Http; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.AspNetCore.DependencyInjection +{ + public class HttpContextClientScopeServiceProviderAccessor : + IClientScopeServiceProviderAccessor, + ISingletonDependency + { + public IServiceProvider ServiceProvider + { + get + { + var httpContext = _httpContextAccessor.HttpContext; + if (httpContext == null) + { + throw new AbpException("HttpContextClientScopeServiceProviderAccessor should only be used in a web request scope!"); + } + + return httpContext.RequestServices; + } + } + + private readonly IHttpContextAccessor _httpContextAccessor; + + public HttpContextClientScopeServiceProviderAccessor( + IHttpContextAccessor httpContextAccessor) + { + _httpContextAccessor = httpContextAccessor; + } + } +} diff --git a/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs b/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs index 9a820600bd..4a4d4df722 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs +++ b/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs @@ -8,15 +8,12 @@ using JetBrains.Annotations; using Localization.Resources.AbpUi; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Components; -using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Localization; using Volo.Abp.Application.Dtos; using Volo.Abp.Application.Services; using Volo.Abp.AspNetCore.Components; -using Volo.Abp.AspNetCore.Components.WebAssembly; using Volo.Abp.Authorization; using Volo.Abp.BlazoriseUI.Components; -using Volo.Abp.ObjectMapping; namespace Volo.Abp.BlazoriseUI { diff --git a/framework/src/Volo.Abp.BlazoriseUI/BlazoriseUiPageProgressService.cs b/framework/src/Volo.Abp.BlazoriseUI/BlazoriseUiPageProgressService.cs new file mode 100644 index 0000000000..5285669c00 --- /dev/null +++ b/framework/src/Volo.Abp.BlazoriseUI/BlazoriseUiPageProgressService.cs @@ -0,0 +1,32 @@ +using System; +using System.Threading.Tasks; +using Volo.Abp.AspNetCore.Components.Progression; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.BlazoriseUI +{ + [Dependency(ReplaceServices = true)] + public class BlazoriseUiPageProgressService : IUiPageProgressService, + IScopedDependency + { + /// + /// An event raised after the notification is received. + /// + public event EventHandler ProgressChanged; + + public Task Go(int? percentage, Action options = null) + { + var uiPageProgressOptions = CreateDefaultOptions(); + options?.Invoke(uiPageProgressOptions); + + ProgressChanged?.Invoke(this, new UiPageProgressEventArgs(percentage, uiPageProgressOptions)); + + return Task.CompletedTask; + } + + protected virtual UiPageProgressOptions CreateDefaultOptions() + { + return new UiPageProgressOptions(); + } + } +} diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/UiPageProgress.razor b/framework/src/Volo.Abp.BlazoriseUI/Components/UiPageProgress.razor new file mode 100644 index 0000000000..91799182dd --- /dev/null +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/UiPageProgress.razor @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/UiPageProgress.razor.cs b/framework/src/Volo.Abp.BlazoriseUI/Components/UiPageProgress.razor.cs new file mode 100644 index 0000000000..8a0a8e28d2 --- /dev/null +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/UiPageProgress.razor.cs @@ -0,0 +1,58 @@ +using System; +using Blazorise; +using Microsoft.AspNetCore.Components; +using Volo.Abp.AspNetCore.Components.Progression; + +namespace Volo.Abp.BlazoriseUI.Components +{ + public partial class UiPageProgress : ComponentBase, IDisposable + { + protected PageProgress PageProgressRef { get; set; } + + protected int? Percentage { get; set; } + + protected bool Visible { get; set; } + + protected Color Color { get; set; } + + [Inject] protected IUiPageProgressService UiPageProgressService { get; set; } + + protected override void OnInitialized() + { + base.OnInitialized(); + + UiPageProgressService.ProgressChanged += OnProgressChanged; + } + + private async void OnProgressChanged(object sender, UiPageProgressEventArgs e) + { + Percentage = e.Percentage; + Visible = e.Percentage == null || (e.Percentage >= 0 && e.Percentage <= 100); + Color = GetColor(e.Options.Type); + + await PageProgressRef.SetValueAsync(e.Percentage); + + await InvokeAsync(StateHasChanged); + } + + public virtual void Dispose() + { + if (UiPageProgressService != null) + { + UiPageProgressService.ProgressChanged -= OnProgressChanged; + } + } + + protected virtual Color GetColor(UiPageProgressType pageProgressType) + { + return pageProgressType switch + { + UiPageProgressType.Info => Color.Info, + UiPageProgressType.Success => Color.Success, + UiPageProgressType.Warning => Color.Warning, + UiPageProgressType.Error => Color.Danger, + _ => Color.None, + }; + } + } +} diff --git a/framework/src/Volo.Abp.BlazoriseUI/Volo.Abp.BlazoriseUI.csproj b/framework/src/Volo.Abp.BlazoriseUI/Volo.Abp.BlazoriseUI.csproj index 1dce47face..de793e078f 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/Volo.Abp.BlazoriseUI.csproj +++ b/framework/src/Volo.Abp.BlazoriseUI/Volo.Abp.BlazoriseUI.csproj @@ -12,9 +12,9 @@ - - - + + + diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/IClientScopeServiceProviderAccessor.cs b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/IClientScopeServiceProviderAccessor.cs new file mode 100644 index 0000000000..7c1d1ed08d --- /dev/null +++ b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/IClientScopeServiceProviderAccessor.cs @@ -0,0 +1,9 @@ +using System; + +namespace Volo.Abp.DependencyInjection +{ + public interface IClientScopeServiceProviderAccessor + { + IServiceProvider ServiceProvider { get; } + } +} diff --git a/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/ConnectionPool.cs b/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/ConnectionPool.cs index 08d9d48036..5856f7bb16 100644 --- a/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/ConnectionPool.cs +++ b/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/ConnectionPool.cs @@ -22,8 +22,7 @@ namespace Volo.Abp.RabbitMQ public virtual IConnection Get(string connectionName = null) { - connectionName = connectionName - ?? RabbitMqConnections.DefaultConnectionName; + connectionName ??= RabbitMqConnections.DefaultConnectionName; return Connections.GetOrAdd( connectionName, @@ -58,4 +57,4 @@ namespace Volo.Abp.RabbitMQ Connections.Clear(); } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/RabbitMqConnections.cs b/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/RabbitMqConnections.cs index a30db4c96a..f2b5168d82 100644 --- a/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/RabbitMqConnections.cs +++ b/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/RabbitMqConnections.cs @@ -9,7 +9,7 @@ namespace Volo.Abp.RabbitMQ public class RabbitMqConnections : Dictionary { public const string DefaultConnectionName = "Default"; - + [NotNull] public ConnectionFactory Default { @@ -19,7 +19,7 @@ namespace Volo.Abp.RabbitMQ public RabbitMqConnections() { - Default = new ConnectionFactory(); + Default = new ConnectionFactory() { DispatchConsumersAsync = true }; } public ConnectionFactory GetOrDefault(string connectionName) @@ -32,4 +32,4 @@ namespace Volo.Abp.RabbitMQ return Default; } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/RabbitMqMessageConsumer.cs b/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/RabbitMqMessageConsumer.cs index fb1b0c7fe2..b94663d886 100644 --- a/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/RabbitMqMessageConsumer.cs +++ b/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/RabbitMqMessageConsumer.cs @@ -143,10 +143,10 @@ namespace Volo.Abp.RabbitMQ try { - var channel = ConnectionPool + Channel = ConnectionPool .Get(ConnectionName) .CreateModel(); - channel.ExchangeDeclare( + Channel.ExchangeDeclare( exchange: Exchange.ExchangeName, type: Exchange.Type, durable: Exchange.Durable, @@ -154,7 +154,7 @@ namespace Volo.Abp.RabbitMQ arguments: Exchange.Arguments ); - channel.QueueDeclare( + Channel.QueueDeclare( queue: Queue.QueueName, durable: Queue.Durable, exclusive: Queue.Exclusive, @@ -162,19 +162,14 @@ namespace Volo.Abp.RabbitMQ arguments: Queue.Arguments ); - var consumer = new EventingBasicConsumer(channel); - consumer.Received += async (model, basicDeliverEventArgs) => - { - await HandleIncomingMessageAsync(channel, basicDeliverEventArgs); - }; + var consumer = new AsyncEventingBasicConsumer(Channel); + consumer.Received += HandleIncomingMessageAsync; - channel.BasicConsume( + Channel.BasicConsume( queue: Queue.QueueName, autoAck: false, consumer: consumer ); - - Channel = channel; } catch (Exception ex) { @@ -183,16 +178,16 @@ namespace Volo.Abp.RabbitMQ } } - protected virtual async Task HandleIncomingMessageAsync(IModel channel, BasicDeliverEventArgs basicDeliverEventArgs) + protected virtual async Task HandleIncomingMessageAsync(object sender, BasicDeliverEventArgs basicDeliverEventArgs) { try { foreach (var callback in Callbacks) { - await callback(channel, basicDeliverEventArgs); + await callback(Channel, basicDeliverEventArgs); } - channel.BasicAck(basicDeliverEventArgs.DeliveryTag, multiple: false); + Channel.BasicAck(basicDeliverEventArgs.DeliveryTag, multiple: false); } catch (Exception ex) { diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateRenderer.cs b/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateRenderer.cs index c7d7b9d016..1d89dc3b68 100644 --- a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateRenderer.cs +++ b/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateRenderer.cs @@ -144,6 +144,7 @@ namespace Volo.Abp.TextTemplating } context.PushGlobal(scriptObject); + context.PushCulture(System.Globalization.CultureInfo.CurrentCulture); return context; } diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/LocalizationTestController.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/LocalizationTestController.cs new file mode 100644 index 0000000000..7426f95148 --- /dev/null +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/LocalizationTestController.cs @@ -0,0 +1,15 @@ +using System.Globalization; +using Microsoft.AspNetCore.Mvc; + +namespace Volo.Abp.AspNetCore.Mvc.Localization +{ + [Route("api/LocalizationTestController")] + public class LocalizationTestController : AbpController + { + [HttpGet] + public string Culture() + { + return CultureInfo.CurrentCulture.Name + ":" + CultureInfo.CurrentUICulture.Name; + } + } +} diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/LocalizationTestController_Tests.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/LocalizationTestController_Tests.cs new file mode 100644 index 0000000000..872d85013c --- /dev/null +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/LocalizationTestController_Tests.cs @@ -0,0 +1,44 @@ +using System.Net; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Localization; +using Microsoft.AspNetCore.RequestLocalization; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Primitives; +using Shouldly; +using Xunit; + +namespace Volo.Abp.AspNetCore.Mvc.Localization +{ + public class LocalizationTestController_Tests : AspNetCoreMvcTestBase + { + class TestRequestCultureProvider : RequestCultureProvider + { + public override Task DetermineProviderCultureResult(HttpContext httpContext) + { + return Task.FromResult(new ProviderCultureResult((StringSegment) "tr", (StringSegment) "hu")); + } + } + + protected override void ConfigureServices(HostBuilderContext context, IServiceCollection services) + { + services.Configure(options => + { + options.RequestLocalizationOptionConfigurators.Add((serviceProvider, localizationOptions) => + { + localizationOptions.RequestCultureProviders.Insert(0, new TestRequestCultureProvider()); + return Task.CompletedTask; + }); + }); + } + + [Fact] + public async Task TestRequestCultureProvider_Test() + { + var response = await GetResponseAsync("api/LocalizationTestController", HttpStatusCode.OK); + var resultAsString = await response.Content.ReadAsStringAsync(); + resultAsString.ToLower().ShouldBe("tr:hu"); + } + } +} diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/SampleTemplates/ShowDecimalNumber.tpl b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/SampleTemplates/ShowDecimalNumber.tpl new file mode 100644 index 0000000000..1c54056382 --- /dev/null +++ b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/SampleTemplates/ShowDecimalNumber.tpl @@ -0,0 +1 @@ +{{ model.amount}} \ No newline at end of file diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TemplateRenderer_Tests.cs b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TemplateRenderer_Tests.cs index fef287a2b1..ca4ae3e3fd 100644 --- a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TemplateRenderer_Tests.cs +++ b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TemplateRenderer_Tests.cs @@ -91,6 +91,22 @@ namespace Volo.Abp.TextTemplating cultureName: "tr" )).ShouldBe("*BEGIN*Merhaba John, nasılsın?. Please click to the following link to get an email to reset your password!*END*"); } + + [Fact] + public async Task Should_Get_Localized_Numbers() + { + (await _templateRenderer.RenderAsync( + TestTemplates.ShowDecimalNumber, + new Dictionary(new List> {new("amount", 123.45M)}), + cultureName: "en" + )).ShouldBe("*BEGIN*123.45*END*"); + + (await _templateRenderer.RenderAsync( + TestTemplates.ShowDecimalNumber, + new Dictionary(new List> {new("amount", 123.45M)}), + cultureName: "de" + )).ShouldBe("*BEGIN*123,45*END*"); + } private class WelcomeEmailModel { diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TestTemplateDefinitionProvider.cs b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TestTemplateDefinitionProvider.cs index af6386e9f7..9db711d70c 100644 --- a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TestTemplateDefinitionProvider.cs +++ b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TestTemplateDefinitionProvider.cs @@ -27,6 +27,14 @@ namespace Volo.Abp.TextTemplating isLayout: true ).WithVirtualFilePath("/SampleTemplates/TestTemplateLayout1.tpl", true) ); + + context.Add( + new TemplateDefinition( + TestTemplates.ShowDecimalNumber, + localizationResource: typeof(TestLocalizationSource), + layout: TestTemplates.TestTemplateLayout1 + ).WithVirtualFilePath("/SampleTemplates/ShowDecimalNumber.tpl", true) + ); } } } diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TestTemplates.cs b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TestTemplates.cs index a2b605c213..29a8604f3b 100644 --- a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TestTemplates.cs +++ b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TestTemplates.cs @@ -5,5 +5,6 @@ public const string WelcomeEmail = "WelcomeEmail"; public const string ForgotPasswordEmail = "ForgotPasswordEmail"; public const string TestTemplateLayout1 = "TestTemplateLayout1"; + public const string ShowDecimalNumber = "ShowDecimalNumber"; } } \ No newline at end of file diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/VirtualFiles/LocalizedTemplateContentReaderFactory_Tests.cs b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/VirtualFiles/LocalizedTemplateContentReaderFactory_Tests.cs index b1dba4bdb5..63e526ac1d 100644 --- a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/VirtualFiles/LocalizedTemplateContentReaderFactory_Tests.cs +++ b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/VirtualFiles/LocalizedTemplateContentReaderFactory_Tests.cs @@ -23,7 +23,7 @@ namespace Volo.Abp.TextTemplating.VirtualFiles var localizedTemplateContentReaderFactory = new LocalizedTemplateContentReaderFactory( new PhysicalFileVirtualFileProvider( new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), - @"Volo\Abp\TextTemplating\")))); + "Volo", "Abp", "TextTemplating")))); var reader = await localizedTemplateContentReaderFactory.CreateAsync(_templateDefinitionManager.Get(TestTemplates.WelcomeEmail)); diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Tags/TagAdminController.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Tags/TagAdminController.cs index 54cc4b1499..cc755fa63f 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Tags/TagAdminController.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Tags/TagAdminController.cs @@ -2,13 +2,21 @@ using Microsoft.AspNetCore.Mvc; using System; using System.Threading.Tasks; +using Volo.Abp; using Volo.Abp.Application.Dtos; +using Volo.Abp.GlobalFeatures; using Volo.CmsKit.Admin.Tags; +using Volo.CmsKit.GlobalFeatures; using Volo.CmsKit.Permissions; using Volo.CmsKit.Tags; namespace Volo.CmsKit.Admin.Tags { + [RequiresGlobalFeature(typeof(TagsFeature))] + [RemoteService(Name = CmsKitCommonRemoteServiceConsts.RemoteServiceName)] + [Area("cms-kit")] + [Authorize(CmsKitAdminPermissions.Tags.Default)] + [Route("api/cms-kit-admin/tags")] public class TagAdminController : CmsKitAdminController, ITagAdminAppService { protected ITagAdminAppService TagAdminAppService { get; } diff --git a/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/EntityFrameworkCore/CmsKitDbContextModelCreatingExtensions.cs b/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/EntityFrameworkCore/CmsKitDbContextModelCreatingExtensions.cs index 5de45ed8b8..2cc5e8a52a 100644 --- a/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/EntityFrameworkCore/CmsKitDbContextModelCreatingExtensions.cs +++ b/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/EntityFrameworkCore/CmsKitDbContextModelCreatingExtensions.cs @@ -41,8 +41,8 @@ namespace Volo.CmsKit.EntityFrameworkCore b.ConfigureByConvention(); b.ConfigureAbpUser(); - b.HasIndex(x => new {x.TenantId, x.UserName}); - b.HasIndex(x => new {x.TenantId, x.Email}); + b.HasIndex(x => new { x.TenantId, x.UserName }); + b.HasIndex(x => new { x.TenantId, x.Email }); }); } @@ -93,7 +93,7 @@ namespace Volo.CmsKit.EntityFrameworkCore r.Property(x => x.EntityType).IsRequired().HasMaxLength(RatingConsts.MaxEntityTypeLength); r.Property(x => x.EntityId).IsRequired().HasMaxLength(RatingConsts.MaxEntityIdLength); - r.HasIndex(x => new {x.TenantId, x.EntityType, x.EntityId, x.CreatorId}); + r.HasIndex(x => new { x.TenantId, x.EntityType, x.EntityId, x.CreatorId }); }); } @@ -109,7 +109,7 @@ namespace Volo.CmsKit.EntityFrameworkCore b.Property(x => x.EntityId).IsRequired().HasMaxLength(ContentConsts.MaxEntityIdLength); b.Property(x => x.Value).IsRequired().HasMaxLength(ContentConsts.MaxValueLength); - b.HasIndex(x => new {x.TenantId, x.EntityType, x.EntityId}); + b.HasIndex(x => new { x.TenantId, x.EntityType, x.EntityId }); }); } @@ -124,7 +124,11 @@ namespace Volo.CmsKit.EntityFrameworkCore b.Property(x => x.EntityType).IsRequired().HasMaxLength(TagConsts.MaxEntityTypeLength); b.Property(x => x.Name).IsRequired().HasMaxLength(TagConsts.MaxNameLength); - b.HasIndex(x => new {x.TenantId, x.Name}); + b.HasIndex(x => new + { + x.TenantId, + x.Name + }); }); builder.Entity(b => @@ -133,12 +137,12 @@ namespace Volo.CmsKit.EntityFrameworkCore b.ConfigureByConvention(); - b.HasKey(x => new {x.EntityId, x.TagId}); + b.HasKey(x => new { x.EntityId, x.TagId }); b.Property(x => x.EntityId).IsRequired(); b.Property(x => x.TagId).IsRequired(); - b.HasIndex(x => new {x.TenantId, x.EntityId, x.TagId}); + b.HasIndex(x => new { x.TenantId, x.EntityId, x.TagId }); }); } @@ -154,7 +158,7 @@ namespace Volo.CmsKit.EntityFrameworkCore b.Property(x => x.Url).IsRequired().HasMaxLength(PageConsts.MaxUrlLength); b.Property(x => x.Description).HasMaxLength(PageConsts.MaxDescriptionLength); - b.HasIndex(x => new {x.TenantId, x.Url}); + b.HasIndex(x => new { x.TenantId, x.Url }); }); } diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo/CmsKit/Public/Tags/GetRelatedTagsInput.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo/CmsKit/Public/Tags/GetRelatedTagsInput.cs deleted file mode 100644 index b8df8ec439..0000000000 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo/CmsKit/Public/Tags/GetRelatedTagsInput.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace Volo.CmsKit.Public.Tags -{ - public class GetRelatedTagsInput - { - [Required] - public string EntityType { get; set; } - - [Required] - public string EntityId { get; set; } - } -} diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo/CmsKit/Public/Tags/ITagAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo/CmsKit/Public/Tags/ITagAppService.cs index 29d786f086..34d54b9006 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo/CmsKit/Public/Tags/ITagAppService.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo/CmsKit/Public/Tags/ITagAppService.cs @@ -7,6 +7,6 @@ namespace Volo.CmsKit.Public.Tags { public interface ITagAppService : IApplicationService { - Task> GetAllRelatedTagsAsync(GetRelatedTagsInput input); + Task> GetAllRelatedTagsAsync(string entityType, string entityId); } -} +} \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Tags/TagAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Tags/TagAppService.cs index 8feaaa0130..593f011b02 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Tags/TagAppService.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Tags/TagAppService.cs @@ -9,28 +9,21 @@ namespace Volo.CmsKit.Public.Tags { public class TagAppService : CmsKitAppServiceBase, ITagAppService { - protected readonly ITagManager TagManager; protected readonly ITagRepository TagRepository; - protected readonly IEntityTagRepository EntityTagRepository; - public TagAppService( - ITagManager tagManager, - ITagRepository tagRepository, - IEntityTagRepository entityTagRepository) + public TagAppService(ITagRepository tagRepository) { - TagManager = tagManager; TagRepository = tagRepository; - EntityTagRepository = entityTagRepository; } - public virtual async Task> GetAllRelatedTagsAsync(GetRelatedTagsInput input) + public virtual async Task> GetAllRelatedTagsAsync(string entityType, string entityId) { var entities = await TagRepository.GetAllRelatedTagsAsync( - input.EntityType, - input.EntityId, - CurrentTenant.Id); + entityType, + entityId, + CurrentTenant.Id); return ObjectMapper.Map, List>(entities); } } -} +} \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Tags/TagController.cs b/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Tags/TagController.cs deleted file mode 100644 index 307c5a4247..0000000000 --- a/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Tags/TagController.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using System.Collections.Generic; -using System.Threading.Tasks; -using Volo.Abp; -using Volo.CmsKit.Tags; - -namespace Volo.CmsKit.Public.Tags -{ - [RemoteService(Name = CmsKitCommonRemoteServiceConsts.RemoteServiceName)] - [Area("cms-kit")] - [Route("api/cms-kit/tags")] - public class TagController : CmsKitPublicControllerBase, ITagAppService - { - protected readonly ITagAppService TagAppService; - - public TagController(ITagAppService tagAppService) - { - TagAppService = tagAppService; - } - - [HttpGet] - public Task> GetAllRelatedTagsAsync(GetRelatedTagsInput input) - { - return TagAppService.GetAllRelatedTagsAsync(input); - } - } -} diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Tags/TagPublicController.cs b/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Tags/TagPublicController.cs new file mode 100644 index 0000000000..55041e5c6e --- /dev/null +++ b/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Tags/TagPublicController.cs @@ -0,0 +1,31 @@ +using Microsoft.AspNetCore.Mvc; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.GlobalFeatures; +using Volo.CmsKit.GlobalFeatures; +using Volo.CmsKit.Tags; + +namespace Volo.CmsKit.Public.Tags +{ + [RequiresGlobalFeature(typeof(TagsFeature))] + [RemoteService(Name = CmsKitCommonRemoteServiceConsts.RemoteServiceName)] + [Area("cms-kit")] + [Route("api/cms-kit-public/tags")] + public class TagPublicController : CmsKitPublicControllerBase, ITagAppService + { + protected readonly ITagAppService TagAppService; + + public TagPublicController(ITagAppService tagAppService) + { + TagAppService = tagAppService; + } + + [HttpGet] + [Route("{entityType}/{entityId}")] + public Task> GetAllRelatedTagsAsync(string entityType, string entityId) + { + return TagAppService.GetAllRelatedTagsAsync(entityType, entityId); + } + } +} \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Tags/TagViewComponent.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Tags/TagViewComponent.cs index 44deaad0ed..c40408117a 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Tags/TagViewComponent.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Tags/TagViewComponent.cs @@ -24,11 +24,7 @@ namespace Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.Tags string entityType, string entityId) { - var tagDtos = await TagAppService.GetAllRelatedTagsAsync(new GetRelatedTagsInput - { - EntityId = entityId, - EntityType = entityType - }); + var tagDtos = await TagAppService.GetAllRelatedTagsAsync(entityType, entityId); var viewModel = new TagViewModel { diff --git a/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Tags/TagPublicAppService_Tests.cs b/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Tags/TagPublicAppService_Tests.cs index 6ad1136167..50eefd186b 100644 --- a/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Tags/TagPublicAppService_Tests.cs +++ b/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Tags/TagPublicAppService_Tests.cs @@ -2,9 +2,7 @@ using NSubstitute; using Shouldly; using System.Threading.Tasks; -using Volo.Abp.Clients; using Volo.Abp.Users; -using Volo.Abp.Validation; using Volo.CmsKit.Public.Tags; using Xunit; @@ -31,11 +29,8 @@ namespace Volo.CmsKit.Tags [Fact] public async Task GetAllRelatedTagsAsync() { - var list = await _tagAppService.GetAllRelatedTagsAsync(new GetRelatedTagsInput - { - EntityType = _cmsKitTestData.Content_1_EntityType, - EntityId = _cmsKitTestData.EntityId1 - }); + var list = await _tagAppService.GetAllRelatedTagsAsync(_cmsKitTestData.Content_1_EntityType, + _cmsKitTestData.EntityId1); list.ShouldNotBeEmpty(); list.Count.ShouldBe(2); @@ -44,35 +39,9 @@ namespace Volo.CmsKit.Tags [Fact] public async Task ShouldntGet_GetAllRelatedTagsAsync() { - var list = await _tagAppService.GetAllRelatedTagsAsync(new GetRelatedTagsInput - { - EntityType = "any_other_type", - EntityId = "1" - }); + var list = await _tagAppService.GetAllRelatedTagsAsync("any_other_type", "1"); list.ShouldBeEmpty(); } - - [Fact] - public async Task GetRelatedTagsAsync_ShouldThrowValidationException_WithoutEntityType() - { - await Assert.ThrowsAsync(async () => - await _tagAppService.GetAllRelatedTagsAsync(new GetRelatedTagsInput - { - EntityType = null, - EntityId = _cmsKitTestData.EntityId1 - })); - } - - [Fact] - public async Task GetRelatedTagsAsync_ShouldThrowValidationException_WithoutEntityId() - { - await Assert.ThrowsAsync(async () => - await _tagAppService.GetAllRelatedTagsAsync(new GetRelatedTagsInput - { - EntityType = null, - EntityId = _cmsKitTestData.EntityId1 - })); - } } -} +} \ No newline at end of file diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpClaimsService.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpClaimsService.cs index c60c241209..3e6a7c76b2 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpClaimsService.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpClaimsService.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Linq; using System.Security.Claims; +using IdentityModel; using IdentityServer4.Services; using Microsoft.Extensions.Logging; using Volo.Abp.Security.Claims; @@ -9,6 +10,16 @@ namespace Volo.Abp.IdentityServer { public class AbpClaimsService : DefaultClaimsService { + private static readonly string[] AdditionalOptionalClaimNames = + { + AbpClaimTypes.TenantId, + AbpClaimTypes.Name, + AbpClaimTypes.SurName, + JwtClaimTypes.PreferredUserName, + JwtClaimTypes.GivenName, + JwtClaimTypes.FamilyName, + }; + public AbpClaimsService(IProfileService profile, ILogger logger) : base(profile, logger) { @@ -16,13 +27,20 @@ namespace Volo.Abp.IdentityServer protected override IEnumerable GetOptionalClaims(ClaimsPrincipal subject) { - var tenantClaim = subject.FindFirst(AbpClaimTypes.TenantId); - if (tenantClaim == null) + return base.GetOptionalClaims(subject) + .Union(GetAdditionalOptionalClaims(subject)); + } + + protected virtual IEnumerable GetAdditionalOptionalClaims(ClaimsPrincipal subject) + { + foreach (var claimName in AdditionalOptionalClaimNames) { - return base.GetOptionalClaims(subject); + var claim = subject.FindFirst(claimName); + if (claim != null) + { + yield return claim; + } } - - return base.GetOptionalClaims(subject).Union(new[] { tenantClaim }); } } } diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpResourceOwnerPasswordValidator.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpResourceOwnerPasswordValidator.cs index eee4c001ed..e024976548 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpResourceOwnerPasswordValidator.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpResourceOwnerPasswordValidator.cs @@ -200,7 +200,12 @@ namespace Volo.Abp.IdentityServer.AspNetIdentity { if (user.TenantId.HasValue) { - customClaims.Add(new Claim(AbpClaimTypes.TenantId, user.TenantId?.ToString())); + customClaims.Add( + new Claim( + AbpClaimTypes.TenantId, + user.TenantId?.ToString() + ) + ); } return Task.CompletedTask; diff --git a/npm/ng-packs/packages/theme-basic/testing/src/lib/theme-basic-testing.module.ts b/npm/ng-packs/packages/theme-basic/testing/src/lib/theme-basic-testing.module.ts index 7df6d40231..0bcab2ed08 100644 --- a/npm/ng-packs/packages/theme-basic/testing/src/lib/theme-basic-testing.module.ts +++ b/npm/ng-packs/packages/theme-basic/testing/src/lib/theme-basic-testing.module.ts @@ -12,7 +12,7 @@ import { VALIDATION_ERROR_TEMPLATE, VALIDATION_TARGET_SELECTOR } from '@ngx-vali imports: [BaseThemeBasicModule], }) export class ThemeBasicTestingModule { - static forRoot(): ModuleWithProviders { + static withConfig(): ModuleWithProviders { return { ngModule: ThemeBasicTestingModule, providers: [ diff --git a/nupkg/pack.ps1 b/nupkg/pack.ps1 index 8c1dcdf10c..4799ba36f2 100644 --- a/nupkg/pack.ps1 +++ b/nupkg/pack.ps1 @@ -26,8 +26,6 @@ foreach($project in $projects) { $projectName = $project.Substring($project.LastIndexOf("/") + 1) $projectPackPath = Join-Path $projectFolder ("/bin/Release/" + $projectName + ".*.nupkg") Move-Item $projectPackPath $packFolder - $projectSymbolPackPath = Join-Path $projectFolder ("/bin/Release/" + $projectName + ".*.snupkg") - Move-Item $projectSymbolPackPath $packFolder } # Go back to the pack folder diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyCompanyName.MyProjectName.Blazor.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyCompanyName.MyProjectName.Blazor.csproj index 9bc6fb7092..8ac2e020e5 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyCompanyName.MyProjectName.Blazor.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyCompanyName.MyProjectName.Blazor.csproj @@ -7,8 +7,8 @@ - - + + diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Host/MyCompanyName.MyProjectName.Blazor.Host.csproj b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Host/MyCompanyName.MyProjectName.Blazor.Host.csproj index 444e49801f..6bd1d01269 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Host/MyCompanyName.MyProjectName.Blazor.Host.csproj +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Host/MyCompanyName.MyProjectName.Blazor.Host.csproj @@ -8,8 +8,8 @@ - - + +