diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Identity.Blazor/AbpElsaNextStudioIdentityBlazorModule.cs b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Identity.Blazor/AbpElsaNextStudioIdentityBlazorModule.cs new file mode 100644 index 000000000..238bdd4dc --- /dev/null +++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Identity.Blazor/AbpElsaNextStudioIdentityBlazorModule.cs @@ -0,0 +1,17 @@ +using LINGYUN.Abp.ElsaNext.Studio.Blazor; +using LINGYUN.Abp.ElsaNext.Studio.Identity.Blazor.Extensions; +using Volo.Abp.Identity; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.ElsaNext.Studio.Identity.Blazor; + +[DependsOn( + typeof(AbpIdentityDomainModule), + typeof(AbpElsaNextStudioBlazorModule))] +public class AbpElsaNextStudioIdentityBlazorModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddIdentityUIHintHandlers(); + } +} diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Identity.Blazor/Components/IdentityUserPicker.razor b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Identity.Blazor/Components/IdentityUserPicker.razor new file mode 100644 index 000000000..c876a1083 --- /dev/null +++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Identity.Blazor/Components/IdentityUserPicker.razor @@ -0,0 +1,128 @@ +@using Elsa.Api.Client.Shared.UIHints.DropDown +@using Elsa.Studio.Models +@using LINGYUN.Abp.ElsaNext.Studio.Blazor.Components +@using Volo.Abp.Identity +@inject ILocalizer Localizer + +@inherits StudioComponentBase +@{ + var inputDescriptor = EditorContext.InputDescriptor; + var displayName = inputDescriptor.DisplayName; + var description = inputDescriptor.Description; +} + + + + + + + +@code { + private SelectListItem? _selectedItem; + + [Parameter] public DisplayInputEditorContext EditorContext { get; set; } = null!; + + [Inject] protected IIdentityUserRepository IdentityUserRepository { get; set; } = null!; + [Inject] protected IDialogService DialogService { get; set; } = null!; + + protected override async Task OnInitializedAsync() + { + var selectedItem = await ResolveSelectedItemAsync(); + + if (selectedItem != null) + { + await InvokeAsync(() => _selectedItem = selectedItem); + } + } + + private async Task OpenSelectDialogAsync() + { + if (EditorContext.IsReadOnly) + { + return; + } + + var inputDescriptor = EditorContext.InputDescriptor; + var parameters = new DialogParameters + { + { x => x.Title, Localizer[inputDescriptor.DisplayName ?? inputDescriptor.Name] }, + { x => x.SelectedValue, _selectedItem?.Value } + }; + var options = new DialogOptions + { + CloseOnEscapeKey = true, + FullWidth = true, + MaxWidth = MaxWidth.Medium + }; + + var dialog = await DialogService.ShowAsync(string.Empty, parameters, options); + var result = await dialog.Result; + + if (result is { Canceled: false, Data: SelectListItem item }) + { + await InvokeAsync(async () => + { + _selectedItem = item; + await EditorContext.UpdateValueOrLiteralExpressionAsync(item.Value); + }); + } + } + + private MudTextFieldExIcon[] GetAdornmentIcons() => + [ + new() + { + Icon = Icons.Material.Filled.Search, + Tooltip = Localizer["Search"], + Disabled = EditorContext.IsReadOnly, + OnClick = OpenSelectDialogAsync + }, + new() + { + Icon = Icons.Material.Filled.Clear, + Tooltip = Localizer["Clear"], + Visible = _selectedItem != null, + Disabled = EditorContext.IsReadOnly, + OnClick = ClearAsync + } + ]; + + private async Task ClearAsync() + { + await InvokeAsync(async () => + { + _selectedItem = null; + await EditorContext.UpdateValueOrLiteralExpressionAsync(string.Empty); + }); + } + + private async Task ResolveSelectedItemAsync() + { + var value = EditorContext.GetLiteralValueOrDefault(); + + if (string.IsNullOrWhiteSpace(value)) + { + return null; + } + + if (Guid.TryParse(value, out var userId)) + { + var user = await IdentityUserRepository.FindAsync(userId); + + if (user != null) + { + return new SelectListItem(user.Name ?? user.UserName, user.Id.ToString()); + } + } + + return new SelectListItem(value, value); + } +} diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Identity.Blazor/Components/IdentityUserSelectDialog.razor b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Identity.Blazor/Components/IdentityUserSelectDialog.razor new file mode 100644 index 000000000..2eee7e131 --- /dev/null +++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Identity.Blazor/Components/IdentityUserSelectDialog.razor @@ -0,0 +1,152 @@ +@using Elsa.Api.Client.Shared.UIHints.DropDown +@using System.Threading +@using Volo.Abp.Identity +@inject ILocalizer Localizer + +@implements IDisposable + + + + @Title + + + + + + + + @Localizer["Name"] + + + + @context.Text + + @if (context.Value == SelectedValue) + { + + } + else + { + + @Localizer["Select"] + + } + + + + @Localizer["No results found"] + + + + + + @Localizer["Cancel"] + + + +@code { + private const int DebounceIntervalMilliseconds = 350; + + private MudTable? _table; + private string? _searchText; + private CancellationTokenSource? _debounceCancellationTokenSource; + + [CascadingParameter] private IMudDialogInstance MudDialog { get; set; } = null!; + + [Parameter] public string Title { get; set; } = string.Empty; + + [Parameter] public string? SelectedValue { get; set; } + + [Inject] protected IIdentityUserRepository IdentityUserRepository { get; set; } = null!; + + public void Dispose() + { + _debounceCancellationTokenSource?.Cancel(); + _debounceCancellationTokenSource?.Dispose(); + } + + private async Task OnSearchTextChangedAsync(string? searchValue) + { + _searchText = searchValue; + + _debounceCancellationTokenSource?.Cancel(); + _debounceCancellationTokenSource?.Dispose(); + _debounceCancellationTokenSource = new CancellationTokenSource(); + + try + { + await Task.Delay(DebounceIntervalMilliseconds, _debounceCancellationTokenSource.Token); + + var table = _table; + + if (table != null) + { + await InvokeAsync(() => table.ReloadServerData()); + } + } + catch (OperationCanceledException) + { + } + } + + private async Task> LoadUsersAsync(TableState state, CancellationToken cancellationToken) + { + var filter = string.IsNullOrWhiteSpace(_searchText) ? null : _searchText.Trim(); + + var users = await IdentityUserRepository.GetListAsync( + sorting: null, + maxResultCount: state.PageSize, + skipCount: state.Page * state.PageSize, + filter: filter, + cancellationToken: cancellationToken); + + var totalCount = await IdentityUserRepository.GetCountAsync( + filter: filter, + cancellationToken: cancellationToken); + + var items = users + .Select(user => new SelectListItem(user.Name ?? user.UserName, user.Id.ToString())) + .ToList(); + + return new TableData + { + Items = items, + TotalItems = (int)totalCount + }; + } + + private async Task OnRowClickAsync(TableRowClickEventArgs args) + { + await SelectAsync(args.Item); + } + + private Task SelectAsync(SelectListItem? item) + { + if (item == null) + { + return Task.CompletedTask; + } + + MudDialog.Close(DialogResult.Ok(item)); + return Task.CompletedTask; + } + + private void CancelAsync() + { + MudDialog.Cancel(); + } +} diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Identity.Blazor/Extensions/ServiceCollectionExtensions.cs b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Identity.Blazor/Extensions/ServiceCollectionExtensions.cs new file mode 100644 index 000000000..ec079e1b0 --- /dev/null +++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Identity.Blazor/Extensions/ServiceCollectionExtensions.cs @@ -0,0 +1,13 @@ +using Elsa.Studio.Extensions; +using LINGYUN.Abp.ElsaNext.Studio.Identity.Blazor.Handlers; +using Microsoft.Extensions.DependencyInjection; + +namespace LINGYUN.Abp.ElsaNext.Studio.Identity.Blazor.Extensions; + +public static class ServiceCollectionExtensions +{ + public static IServiceCollection AddIdentityUIHintHandlers(this IServiceCollection services) + { + return services.AddUIHintHandler(); + } +} diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Identity.Blazor/FodyWeavers.xml b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Identity.Blazor/FodyWeavers.xml new file mode 100644 index 000000000..5d6962159 --- /dev/null +++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Identity.Blazor/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Identity.Blazor/FodyWeavers.xsd b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Identity.Blazor/FodyWeavers.xsd new file mode 100644 index 000000000..3f3946e28 --- /dev/null +++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Identity.Blazor/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Identity.Blazor/Handlers/IdentityPickerHandler.cs b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Identity.Blazor/Handlers/IdentityPickerHandler.cs new file mode 100644 index 000000000..c02377f42 --- /dev/null +++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Identity.Blazor/Handlers/IdentityPickerHandler.cs @@ -0,0 +1,25 @@ +using Elsa.Studio; +using Elsa.Studio.Contracts; +using Elsa.Studio.Models; +using LINGYUN.Abp.ElsaNext.Studio.Identity.Blazor.Components; +using LINGYUN.Abp.ElsaNext.UIHints; +using Microsoft.AspNetCore.Components; + +namespace LINGYUN.Abp.ElsaNext.Studio.Identity.Blazor.Handlers; + +public class IdentityPickerHandler : IUIHintHandler +{ + public bool GetSupportsUIHint(string uiHint) => uiHint is AbpElsaUIHints.UserPicker; + + public string UISyntax => WellKnownSyntaxNames.Object; + + public RenderFragment DisplayInputEditor(DisplayInputEditorContext context) + { + return builder => + { + builder.OpenComponent(0, typeof(IdentityUserPicker)); + builder.AddAttribute(1, nameof(IdentityUserPicker.EditorContext), context); + builder.CloseComponent(); + }; + } +} diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Identity.Blazor/LINGYUN.Abp.ElsaNext.Studio.Identity.Blazor.csproj b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Identity.Blazor/LINGYUN.Abp.ElsaNext.Studio.Identity.Blazor.csproj new file mode 100644 index 000000000..5457ddac3 --- /dev/null +++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Identity.Blazor/LINGYUN.Abp.ElsaNext.Studio.Identity.Blazor.csproj @@ -0,0 +1,23 @@ + + + + + + + net10.0 + LINGYUN.Abp.ElsaNext.Studio.Identity.Blazor + LINGYUN.Abp.ElsaNext.Studio.Identity.Blazor + false + false + false + + + + + + + + + + + diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Identity.Blazor/_Imports.razor b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Identity.Blazor/_Imports.razor new file mode 100644 index 000000000..1f6d130e9 --- /dev/null +++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Identity.Blazor/_Imports.razor @@ -0,0 +1,5 @@ +@using Microsoft.AspNetCore.Components.Web +@using Elsa.Studio.Components +@using Elsa.Studio.Localization +@using MudBlazor +@using MudExtensions \ No newline at end of file diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Saas.Blazor/AbpElsaNextStudioSaasBlazorModule.cs b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Saas.Blazor/AbpElsaNextStudioSaasBlazorModule.cs new file mode 100644 index 000000000..b0a02a7ae --- /dev/null +++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Saas.Blazor/AbpElsaNextStudioSaasBlazorModule.cs @@ -0,0 +1,17 @@ +using LINGYUN.Abp.ElsaNext.Studio.Blazor; +using LINGYUN.Abp.ElsaNext.Studio.Saas.Blazor.Extensions; +using LINGYUN.Abp.Saas; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.ElsaNext.Studio.Saas.Blazor; + +[DependsOn( + typeof(AbpSaasDomainModule), + typeof(AbpElsaNextStudioBlazorModule))] +public class AbpElsaNextStudioSaasBlazorModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddSaasUIHintHandlers(); + } +} diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Saas.Blazor/Components/TenantPicker.razor b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Saas.Blazor/Components/TenantPicker.razor new file mode 100644 index 000000000..7fe21fe08 --- /dev/null +++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Saas.Blazor/Components/TenantPicker.razor @@ -0,0 +1,128 @@ +@using Elsa.Api.Client.Shared.UIHints.DropDown +@using Elsa.Studio.Models +@using LINGYUN.Abp.ElsaNext.Studio.Blazor.Components +@using LINGYUN.Abp.Saas.Tenants +@inject ILocalizer Localizer + +@inherits StudioComponentBase +@{ + var inputDescriptor = EditorContext.InputDescriptor; + var displayName = inputDescriptor.DisplayName; + var description = inputDescriptor.Description; +} + + + + + + + +@code { + private SelectListItem? _selectedItem; + + [Parameter] public DisplayInputEditorContext EditorContext { get; set; } = null!; + + [Inject] protected ITenantRepository TenantRepository { get; set; } = null!; + [Inject] protected IDialogService DialogService { get; set; } = null!; + + protected override async Task OnInitializedAsync() + { + var selectedItem = await ResolveSelectedItemAsync(); + + if (selectedItem != null) + { + await InvokeAsync(() => _selectedItem = selectedItem); + } + } + + private async Task OpenSelectDialogAsync() + { + if (EditorContext.IsReadOnly) + { + return; + } + + var inputDescriptor = EditorContext.InputDescriptor; + var parameters = new DialogParameters + { + { x => x.Title, Localizer[inputDescriptor.DisplayName ?? inputDescriptor.Name] }, + { x => x.SelectedValue, _selectedItem?.Value } + }; + var options = new DialogOptions + { + CloseOnEscapeKey = true, + FullWidth = true, + MaxWidth = MaxWidth.Medium + }; + + var dialog = await DialogService.ShowAsync(string.Empty, parameters, options); + var result = await dialog.Result; + + if (result is { Canceled: false, Data: SelectListItem item }) + { + await InvokeAsync(async () => + { + _selectedItem = item; + await EditorContext.UpdateValueOrLiteralExpressionAsync(item.Value); + }); + } + } + + private MudTextFieldExIcon[] GetAdornmentIcons() => + [ + new() + { + Icon = Icons.Material.Filled.Search, + Tooltip = Localizer["Search"], + Disabled = EditorContext.IsReadOnly, + OnClick = OpenSelectDialogAsync + }, + new() + { + Icon = Icons.Material.Filled.Clear, + Tooltip = Localizer["Clear"], + Visible = _selectedItem != null, + Disabled = EditorContext.IsReadOnly, + OnClick = ClearAsync + } + ]; + + private async Task ClearAsync() + { + await InvokeAsync(async () => + { + _selectedItem = null; + await EditorContext.UpdateValueOrLiteralExpressionAsync(string.Empty); + }); + } + + private async Task ResolveSelectedItemAsync() + { + var value = EditorContext.GetLiteralValueOrDefault(); + + if (string.IsNullOrWhiteSpace(value)) + { + return null; + } + + if (Guid.TryParse(value, out var tenantId)) + { + var tenant = await TenantRepository.FindAsync(tenantId); + + if (tenant != null) + { + return new SelectListItem(tenant.Name, tenant.Id.ToString()); + } + } + + return new SelectListItem(value, value); + } +} diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Saas.Blazor/Components/TenantSelectDialog.razor b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Saas.Blazor/Components/TenantSelectDialog.razor new file mode 100644 index 000000000..253f7040f --- /dev/null +++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Saas.Blazor/Components/TenantSelectDialog.razor @@ -0,0 +1,151 @@ +@using Elsa.Api.Client.Shared.UIHints.DropDown +@using System.Threading +@using LINGYUN.Abp.Saas.Tenants +@inject ILocalizer Localizer + +@implements IDisposable + + + + @Title + + + + + + + + @Localizer["Name"] + + + + @context.Text + + @if (context.Value == SelectedValue) + { + + } + else + { + + @Localizer["Select"] + + } + + + + @Localizer["No results found"] + + + + + + @Localizer["Cancel"] + + + +@code { + private const int DebounceIntervalMilliseconds = 350; + + private MudTable? _table; + private string? _searchText; + private CancellationTokenSource? _debounceCancellationTokenSource; + + [CascadingParameter] private IMudDialogInstance MudDialog { get; set; } = null!; + + [Parameter] public string Title { get; set; } = string.Empty; + + [Parameter] public string? SelectedValue { get; set; } + + [Inject] protected ITenantRepository TenantRepository { get; set; } = null!; + + public void Dispose() + { + _debounceCancellationTokenSource?.Cancel(); + _debounceCancellationTokenSource?.Dispose(); + } + + private async Task OnSearchTextChangedAsync(string? searchValue) + { + _searchText = searchValue; + + _debounceCancellationTokenSource?.Cancel(); + _debounceCancellationTokenSource?.Dispose(); + _debounceCancellationTokenSource = new CancellationTokenSource(); + + try + { + await Task.Delay(DebounceIntervalMilliseconds, _debounceCancellationTokenSource.Token); + + var table = _table; + + if (table != null) + { + await InvokeAsync(() => table.ReloadServerData()); + } + } + catch (OperationCanceledException) + { + } + } + + private async Task> LoadTenantsAsync(TableState state, CancellationToken cancellationToken) + { + var filter = string.IsNullOrWhiteSpace(_searchText) ? null : _searchText.Trim(); + + var tenants = await TenantRepository.GetListAsync( + filter: filter, + maxResultCount: state.PageSize, + skipCount: state.Page * state.PageSize, + cancellationToken: cancellationToken); + + var totalCount = await TenantRepository.GetCountAsync( + filter: filter, + cancellationToken: cancellationToken); + + var items = tenants + .Select(tenant => new SelectListItem(tenant.Name, tenant.Id.ToString())) + .ToList(); + + return new TableData + { + Items = items, + TotalItems = (int)totalCount + }; + } + + private async Task OnRowClickAsync(TableRowClickEventArgs args) + { + await SelectAsync(args.Item); + } + + private Task SelectAsync(SelectListItem? item) + { + if (item == null) + { + return Task.CompletedTask; + } + + MudDialog.Close(DialogResult.Ok(item)); + return Task.CompletedTask; + } + + private void CancelAsync() + { + MudDialog.Cancel(); + } +} diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Saas.Blazor/Extensions/ServiceCollectionExtensions.cs b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Saas.Blazor/Extensions/ServiceCollectionExtensions.cs new file mode 100644 index 000000000..18a820d87 --- /dev/null +++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Saas.Blazor/Extensions/ServiceCollectionExtensions.cs @@ -0,0 +1,13 @@ +using Elsa.Studio.Extensions; +using LINGYUN.Abp.ElsaNext.Studio.Saas.Blazor.Handlers; +using Microsoft.Extensions.DependencyInjection; + +namespace LINGYUN.Abp.ElsaNext.Studio.Saas.Blazor.Extensions; + +public static class ServiceCollectionExtensions +{ + public static IServiceCollection AddSaasUIHintHandlers(this IServiceCollection services) + { + return services.AddUIHintHandler(); + } +} diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Saas.Blazor/FodyWeavers.xml b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Saas.Blazor/FodyWeavers.xml new file mode 100644 index 000000000..5d6962159 --- /dev/null +++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Saas.Blazor/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Saas.Blazor/FodyWeavers.xsd b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Saas.Blazor/FodyWeavers.xsd new file mode 100644 index 000000000..3f3946e28 --- /dev/null +++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Saas.Blazor/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Saas.Blazor/Handlers/TenantPickerHandler.cs b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Saas.Blazor/Handlers/TenantPickerHandler.cs new file mode 100644 index 000000000..e3859ec2d --- /dev/null +++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Saas.Blazor/Handlers/TenantPickerHandler.cs @@ -0,0 +1,25 @@ +using Elsa.Studio; +using Elsa.Studio.Contracts; +using Elsa.Studio.Models; +using LINGYUN.Abp.ElsaNext.Studio.Saas.Blazor.Components; +using LINGYUN.Abp.ElsaNext.UIHints; +using Microsoft.AspNetCore.Components; + +namespace LINGYUN.Abp.ElsaNext.Studio.Saas.Blazor.Handlers; + +public class TenantPickerHandler : IUIHintHandler +{ + public bool GetSupportsUIHint(string uiHint) => uiHint is AbpElsaUIHints.TenantPicker; + + public string UISyntax => WellKnownSyntaxNames.Object; + + public RenderFragment DisplayInputEditor(DisplayInputEditorContext context) + { + return builder => + { + builder.OpenComponent(0, typeof(TenantPicker)); + builder.AddAttribute(1, nameof(TenantPicker.EditorContext), context); + builder.CloseComponent(); + }; + } +} diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Saas.Blazor/LINGYUN.Abp.ElsaNext.Studio.Saas.Blazor.csproj b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Saas.Blazor/LINGYUN.Abp.ElsaNext.Studio.Saas.Blazor.csproj new file mode 100644 index 000000000..e973fa786 --- /dev/null +++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Saas.Blazor/LINGYUN.Abp.ElsaNext.Studio.Saas.Blazor.csproj @@ -0,0 +1,20 @@ + + + + + + + net10.0 + LINGYUN.Abp.ElsaNext.Studio.Saas.Blazor + LINGYUN.Abp.ElsaNext.Studio.Saas.Blazor + false + false + false + + + + + + + + diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Saas.Blazor/_Imports.razor b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Saas.Blazor/_Imports.razor new file mode 100644 index 000000000..1f6d130e9 --- /dev/null +++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Saas.Blazor/_Imports.razor @@ -0,0 +1,5 @@ +@using Microsoft.AspNetCore.Components.Web +@using Elsa.Studio.Components +@using Elsa.Studio.Localization +@using MudBlazor +@using MudExtensions \ No newline at end of file diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext/LINGYUN/Abp/ElsaNext/UIHints/AbpElsaUIHints.cs b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext/LINGYUN/Abp/ElsaNext/UIHints/AbpElsaUIHints.cs new file mode 100644 index 000000000..34004c52e --- /dev/null +++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext/LINGYUN/Abp/ElsaNext/UIHints/AbpElsaUIHints.cs @@ -0,0 +1,7 @@ +namespace LINGYUN.Abp.ElsaNext.UIHints; + +public static class AbpElsaUIHints +{ + public const string TenantPicker = "tenant-picker"; + public const string UserPicker = "user-picker"; +}