Merge branch 'dev' into cms-kit/content-admin

pull/6926/head
Ahmet 5 years ago
commit 59ef9907c9

@ -10,10 +10,8 @@
<RepositoryUrl>https://github.com/abpframework/abp/</RepositoryUrl>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<!-- https://github.com/dotnet/sourcelink -->
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<!-- Include symbol files (*.pdb) in the built .nupkg -->
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.0-beta-20204-02">

@ -1,3 +1,57 @@
# Blazor UI: Page Progress
TODO
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)
```

@ -689,7 +689,7 @@
"items": [
{
"text": "SubmitButton",
"path": "UI/Blazor/SubmitButton.md"
"path": "UI/Blazor/Components/SubmitButton.md"
}
]
},

@ -21,4 +21,5 @@
<UiMessageAlert />
<UiNotificationAlert />
<UiPageProgress />
</div>

@ -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<IClientScopeServiceProviderAccessor>();
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<IAsyncInitialize>())
{
@ -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<ICachedApplicationConfigurationClient>();
var utilsService = scope.ServiceProvider.GetRequiredService<IAbpUtilsService>();

@ -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<IUiPageProgressService>();
}
protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
protected override async Task<HttpResponseMessage> 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)

@ -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; }
}
}

@ -0,0 +1,21 @@
using System;
using System.Threading.Tasks;
namespace Volo.Abp.AspNetCore.Components.Progression
{
public interface IUiPageProgressService
{
/// <summary>
/// An event raised after the notification is received.
/// </summary>
public event EventHandler<UiPageProgressEventArgs> ProgressChanged;
/// <summary>
/// Sets the progress percentage.
/// </summary>
/// <param name="percentage">Value of the progress from 0 to 100, or null for indeterminate progress.</param>
/// <param name="options">Additional options.</param>
/// <returns>Awaitable task.</returns>
Task Go(int? percentage, Action<UiPageProgressOptions> options = null);
}
}

@ -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<UiPageProgressEventArgs> ProgressChanged;
public Task Go(int? percentage, Action<UiPageProgressOptions> options = null)
{
return Task.CompletedTask;
}
}
}

@ -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; }
}
}

@ -0,0 +1,13 @@
namespace Volo.Abp.AspNetCore.Components.Progression
{
/// <summary>
/// Options to override page progress appearance.
/// </summary>
public class UiPageProgressOptions
{
/// <summary>
/// Type or color, of the page progress.
/// </summary>
public UiPageProgressType Type { get; set; }
}
}

@ -0,0 +1,11 @@
namespace Volo.Abp.AspNetCore.Components.Progression
{
public enum UiPageProgressType
{
Default,
Info,
Success,
Warning,
Error,
}
}

@ -23,10 +23,10 @@ namespace Microsoft.AspNetCore.RequestLocalization
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
var middleware = new RequestLocalizationMiddleware(
next,
new OptionsWrapper<RequestLocalizationOptions>(await _requestLocalizationOptionsProvider.GetLocalizationOptionsAsync()), _loggerFactory
new OptionsWrapper<RequestLocalizationOptions>(await _requestLocalizationOptionsProvider.GetLocalizationOptionsAsync()),
_loggerFactory
);
await middleware.Invoke(context);

@ -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<Func<IServiceProvider, RequestLocalizationOptions, Task>> RequestLocalizationOptionConfigurators { get; }
public AbpRequestLocalizationOptions()
{
RequestLocalizationOptionConfigurators = new List<Func<IServiceProvider, RequestLocalizationOptions, Task>>();
}
}
}

@ -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<IOptions<AbpRequestLocalizationOptions>>()
.Value.RequestLocalizationOptionConfigurators)
{
await configurator(serviceScope.ServiceProvider, options);
}
_optionsAction?.Invoke(options);
_requestLocalizationOptions = options;
}

@ -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;
}
}
}

@ -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
{

@ -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
{
/// <summary>
/// An event raised after the notification is received.
/// </summary>
public event EventHandler<UiPageProgressEventArgs> ProgressChanged;
public Task Go(int? percentage, Action<UiPageProgressOptions> 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();
}
}
}

@ -0,0 +1 @@
<PageProgress @ref="@PageProgressRef" Visible="@Visible" Color="@Color" />

@ -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,
};
}
}
}

@ -12,9 +12,9 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Blazorise" Version="0.9.3-preview3" />
<PackageReference Include="Blazorise.DataGrid" Version="0.9.3-preview3" />
<PackageReference Include="Blazorise.Snackbar" Version="0.9.3-preview3" />
<PackageReference Include="Blazorise" Version="0.9.3-preview4" />
<PackageReference Include="Blazorise.DataGrid" Version="0.9.3-preview4" />
<PackageReference Include="Blazorise.Snackbar" Version="0.9.3-preview4" />
</ItemGroup>
</Project>

@ -0,0 +1,9 @@
using System;
namespace Volo.Abp.DependencyInjection
{
public interface IClientScopeServiceProviderAccessor
{
IServiceProvider ServiceProvider { get; }
}
}

@ -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();
}
}
}
}

@ -9,7 +9,7 @@ namespace Volo.Abp.RabbitMQ
public class RabbitMqConnections : Dictionary<string, ConnectionFactory>
{
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;
}
}
}
}

@ -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)
{

@ -144,6 +144,7 @@ namespace Volo.Abp.TextTemplating
}
context.PushGlobal(scriptObject);
context.PushCulture(System.Globalization.CultureInfo.CurrentCulture);
return context;
}

@ -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;
}
}
}

@ -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<ProviderCultureResult> DetermineProviderCultureResult(HttpContext httpContext)
{
return Task.FromResult(new ProviderCultureResult((StringSegment) "tr", (StringSegment) "hu"));
}
}
protected override void ConfigureServices(HostBuilderContext context, IServiceCollection services)
{
services.Configure<AbpRequestLocalizationOptions>(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");
}
}
}

@ -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<string, decimal>(new List<KeyValuePair<string, decimal>> {new("amount", 123.45M)}),
cultureName: "en"
)).ShouldBe("*BEGIN*123.45*END*");
(await _templateRenderer.RenderAsync(
TestTemplates.ShowDecimalNumber,
new Dictionary<string, decimal>(new List<KeyValuePair<string, decimal>> {new("amount", 123.45M)}),
cultureName: "de"
)).ShouldBe("*BEGIN*123,45*END*");
}
private class WelcomeEmailModel
{

@ -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)
);
}
}
}

@ -5,5 +5,6 @@
public const string WelcomeEmail = "WelcomeEmail";
public const string ForgotPasswordEmail = "ForgotPasswordEmail";
public const string TestTemplateLayout1 = "TestTemplateLayout1";
public const string ShowDecimalNumber = "ShowDecimalNumber";
}
}

@ -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));

@ -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; }

@ -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<EntityTag>(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 });
});
}

@ -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; }
}
}

@ -7,6 +7,6 @@ namespace Volo.CmsKit.Public.Tags
{
public interface ITagAppService : IApplicationService
{
Task<List<TagDto>> GetAllRelatedTagsAsync(GetRelatedTagsInput input);
Task<List<TagDto>> GetAllRelatedTagsAsync(string entityType, string entityId);
}
}
}

@ -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<List<TagDto>> GetAllRelatedTagsAsync(GetRelatedTagsInput input)
public virtual async Task<List<TagDto>> GetAllRelatedTagsAsync(string entityType, string entityId)
{
var entities = await TagRepository.GetAllRelatedTagsAsync(
input.EntityType,
input.EntityId,
CurrentTenant.Id);
entityType,
entityId,
CurrentTenant.Id);
return ObjectMapper.Map<List<Tag>, List<TagDto>>(entities);
}
}
}
}

@ -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<List<TagDto>> GetAllRelatedTagsAsync(GetRelatedTagsInput input)
{
return TagAppService.GetAllRelatedTagsAsync(input);
}
}
}

@ -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<List<TagDto>> GetAllRelatedTagsAsync(string entityType, string entityId)
{
return TagAppService.GetAllRelatedTagsAsync(entityType, entityId);
}
}
}

@ -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
{

@ -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<AbpValidationException>(async () =>
await _tagAppService.GetAllRelatedTagsAsync(new GetRelatedTagsInput
{
EntityType = null,
EntityId = _cmsKitTestData.EntityId1
}));
}
[Fact]
public async Task GetRelatedTagsAsync_ShouldThrowValidationException_WithoutEntityId()
{
await Assert.ThrowsAsync<AbpValidationException>(async () =>
await _tagAppService.GetAllRelatedTagsAsync(new GetRelatedTagsInput
{
EntityType = null,
EntityId = _cmsKitTestData.EntityId1
}));
}
}
}
}

@ -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<DefaultClaimsService> logger)
: base(profile, logger)
{
@ -16,13 +27,20 @@ namespace Volo.Abp.IdentityServer
protected override IEnumerable<Claim> GetOptionalClaims(ClaimsPrincipal subject)
{
var tenantClaim = subject.FindFirst(AbpClaimTypes.TenantId);
if (tenantClaim == null)
return base.GetOptionalClaims(subject)
.Union(GetAdditionalOptionalClaims(subject));
}
protected virtual IEnumerable<Claim> 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 });
}
}
}

@ -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;

@ -12,7 +12,7 @@ import { VALIDATION_ERROR_TEMPLATE, VALIDATION_TARGET_SELECTOR } from '@ngx-vali
imports: [BaseThemeBasicModule],
})
export class ThemeBasicTestingModule {
static forRoot(): ModuleWithProviders<ThemeBasicTestingModule> {
static withConfig(): ModuleWithProviders<ThemeBasicTestingModule> {
return {
ngModule: ThemeBasicTestingModule,
providers: [

@ -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

@ -7,8 +7,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Blazorise.Bootstrap" Version="0.9.3-preview3" />
<PackageReference Include="Blazorise.Icons.FontAwesome" Version="0.9.3-preview3" />
<PackageReference Include="Blazorise.Bootstrap" Version="0.9.3-preview4" />
<PackageReference Include="Blazorise.Icons.FontAwesome" Version="0.9.3-preview4" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="5.0.*" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="5.0.*" />
</ItemGroup>

@ -8,8 +8,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Blazorise.Bootstrap" Version="0.9.3-preview3" />
<PackageReference Include="Blazorise.Icons.FontAwesome" Version="0.9.3-preview3" />
<PackageReference Include="Blazorise.Bootstrap" Version="0.9.3-preview4" />
<PackageReference Include="Blazorise.Icons.FontAwesome" Version="0.9.3-preview4" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="5.0.*" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="5.0.*" />
</ItemGroup>

Loading…
Cancel
Save