diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Blazor/Localization/Resources/ElsaStudioBlazor/en.json b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Blazor/Localization/Resources/ElsaStudioBlazor/en.json index e2962ece2..48535886a 100644 --- a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Blazor/Localization/Resources/ElsaStudioBlazor/en.json +++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Blazor/Localization/Resources/ElsaStudioBlazor/en.json @@ -5,6 +5,7 @@ "Menu:WorkflowDefinitions": "Workflow Definitions", "Menu:WorkflowInstances": "Workflow Instances", "Menu:Settings": "Settings", + "Select": "Select", "14 days": "14 days", "180 days": "180 days", "30 days": "30 days", diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Blazor/Localization/Resources/ElsaStudioBlazor/zh-Hans.json b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Blazor/Localization/Resources/ElsaStudioBlazor/zh-Hans.json index 70fd190c2..7ae90f140 100644 --- a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Blazor/Localization/Resources/ElsaStudioBlazor/zh-Hans.json +++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Blazor/Localization/Resources/ElsaStudioBlazor/zh-Hans.json @@ -5,6 +5,7 @@ "Menu:WorkflowDefinitions": "工作流定义", "Menu:WorkflowInstances": "工作流实例", "Menu:Settings": "设置", + "Select": "选择", "180 days": "180 天", "30 days": "30 天", "7 days": "7 天", diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Notifications.Blazor/Components/NotificationPicker.razor b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Notifications.Blazor/Components/NotificationPicker.razor index d9f1d106f..c6dda794c 100644 --- a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Notifications.Blazor/Components/NotificationPicker.razor +++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Notifications.Blazor/Components/NotificationPicker.razor @@ -1,4 +1,4 @@ -@using Elsa.Api.Client.Shared.UIHints.DropDown +@using LINGYUN.Abp.ElsaNext.Studio.Blazor.Components @inject ILocalizer Localizer @inherits StudioComponentBase @@ -6,25 +6,18 @@ var inputDescriptor = EditorContext.InputDescriptor; var displayName = inputDescriptor.DisplayName; var description = inputDescriptor.Description; - var selectedValue = GetSelectedValue(); } - - + \ No newline at end of file diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Notifications.Blazor/Components/NotificationPicker.razor.cs b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Notifications.Blazor/Components/NotificationPicker.razor.cs index f6f35044c..db12314b4 100644 --- a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Notifications.Blazor/Components/NotificationPicker.razor.cs +++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Notifications.Blazor/Components/NotificationPicker.razor.cs @@ -1,54 +1,110 @@ using Elsa.Api.Client.Shared.UIHints.DropDown; using Elsa.Studio.Models; +using LINGYUN.Abp.ElsaNext.Studio.Blazor.Components; using LINGYUN.Abp.Notifications; using Microsoft.AspNetCore.Components; using Microsoft.Extensions.Localization; -using System.Collections.Generic; -using System.Linq; +using MudBlazor; using System.Threading.Tasks; namespace LINGYUN.Abp.ElsaNext.Studio.Notifications.Blazor.Components; public partial class NotificationPicker { - private ICollection _items = []; - private IReadOnlyList _notifications = []; + private SelectListItem? _selectedItem; [Parameter] public DisplayInputEditorContext EditorContext { get; set; } = null!; + [Inject] protected IDialogService DialogService { get; set; } = null!; [Inject] private IStringLocalizerFactory StringLocalizerFactory { get; set; } = null!; [Inject] private INotificationDefinitionManager NotificationDefinitionManager { get; set; } = null!; - private SelectListItem? GetSelectedValue() + protected async override Task OnInitializedAsync() { - var value = EditorContext.GetLiteralValueOrDefault(); - return _items.FirstOrDefault(x => x.Value == value); - } + var selectedItem = await ResolveSelectedItemAsync(); - private void OnSearch(string? filter) - { - _items = _notifications - .WhereIf(!string.IsNullOrWhiteSpace(filter), x => x.Text.Contains(filter!)) - .Take(10) - .ToList(); + if (selectedItem != null) + { + await InvokeAsync(() => _selectedItem = selectedItem); + } } - private async Task OnValueChanged(SelectListItem? value) + private async Task ResolveSelectedItemAsync() { - await EditorContext.UpdateValueOrLiteralExpressionAsync(value?.Value ?? ""); + var value = EditorContext.GetLiteralValueOrDefault(); + + if (string.IsNullOrWhiteSpace(value)) + { + return null; + } + + var notificationDefine = await NotificationDefinitionManager.GetOrNullAsync(value); + if (notificationDefine != null) + { + return new SelectListItem(notificationDefine.DisplayName.Localize(StringLocalizerFactory), notificationDefine.Name); + } + + return new SelectListItem(value, value); } - protected async override Task OnInitializedAsync() + private async Task OpenSelectDialogAsync() { - var notifications = await NotificationDefinitionManager.GetNotificationsAsync(); + if (EditorContext.IsReadOnly) + { + return; + } - _notifications = notifications - .Select(notification => - new SelectListItem( - notification.DisplayName.Localize(StringLocalizerFactory), notification.Name)) - .OrderBy(x => x.Text) - .ToList(); + 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 + }; - _items = _notifications.Take(10).ToList(); + 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); + }); } } diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Notifications.Blazor/Components/NotificationSelectDialog.razor b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Notifications.Blazor/Components/NotificationSelectDialog.razor new file mode 100644 index 000000000..bd87ddcbb --- /dev/null +++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Studio.Notifications.Blazor/Components/NotificationSelectDialog.razor @@ -0,0 +1,155 @@ +@using System.Threading +@using Elsa.Api.Client.Shared.UIHints.DropDown +@using LINGYUN.Abp.Notifications +@using Microsoft.Extensions.Localization +@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] private IStringLocalizerFactory StringLocalizerFactory { get; set; } = null!; + [Inject] private INotificationDefinitionManager NotificationDefinitionManager { 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 notifications = await NotificationDefinitionManager.GetNotificationsAsync(); + + var items = notifications + .Select(notification => new SelectListItem( + notification.DisplayName.Localize(StringLocalizerFactory), + notification.Name)) + .WhereIf(!string.IsNullOrWhiteSpace(filter), x => x.Text.Contains(filter!) || x.Value.Contains(filter!)) + .OrderBy(x => x.Text) + .Skip(state.Page * state.PageSize) + .Take(state.PageSize) + .ToList(); + + return new TableData + { + Items = items, + TotalItems = notifications.Count, + }; + } + + 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/LINGYUN/Abp/ElsaNext/UIHints/AbpElsaUIHints.cs b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext/LINGYUN/Abp/ElsaNext/UIHints/AbpElsaUIHints.cs index 34004c52e..bb7999e3f 100644 --- 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 @@ -1,7 +1,8 @@ -namespace LINGYUN.Abp.ElsaNext.UIHints; +namespace LINGYUN.Abp.ElsaNext.UIHints; public static class AbpElsaUIHints { public const string TenantPicker = "tenant-picker"; public const string UserPicker = "user-picker"; + public const string UserPickerMultiple = "user-picker-multiple"; }