6 changed files with 250 additions and 43 deletions
@ -1,54 +1,110 @@ |
|||||
using Elsa.Api.Client.Shared.UIHints.DropDown; |
using Elsa.Api.Client.Shared.UIHints.DropDown; |
||||
using Elsa.Studio.Models; |
using Elsa.Studio.Models; |
||||
|
using LINGYUN.Abp.ElsaNext.Studio.Blazor.Components; |
||||
using LINGYUN.Abp.Notifications; |
using LINGYUN.Abp.Notifications; |
||||
using Microsoft.AspNetCore.Components; |
using Microsoft.AspNetCore.Components; |
||||
using Microsoft.Extensions.Localization; |
using Microsoft.Extensions.Localization; |
||||
using System.Collections.Generic; |
using MudBlazor; |
||||
using System.Linq; |
|
||||
using System.Threading.Tasks; |
using System.Threading.Tasks; |
||||
|
|
||||
namespace LINGYUN.Abp.ElsaNext.Studio.Notifications.Blazor.Components; |
namespace LINGYUN.Abp.ElsaNext.Studio.Notifications.Blazor.Components; |
||||
|
|
||||
public partial class NotificationPicker |
public partial class NotificationPicker |
||||
{ |
{ |
||||
private ICollection<SelectListItem> _items = []; |
private SelectListItem? _selectedItem; |
||||
private IReadOnlyList<SelectListItem> _notifications = []; |
|
||||
|
|
||||
[Parameter] public DisplayInputEditorContext EditorContext { get; set; } = null!; |
[Parameter] public DisplayInputEditorContext EditorContext { get; set; } = null!; |
||||
|
|
||||
|
[Inject] protected IDialogService DialogService { get; set; } = null!; |
||||
[Inject] private IStringLocalizerFactory StringLocalizerFactory { get; set; } = null!; |
[Inject] private IStringLocalizerFactory StringLocalizerFactory { get; set; } = null!; |
||||
[Inject] private INotificationDefinitionManager NotificationDefinitionManager { get; set; } = null!; |
[Inject] private INotificationDefinitionManager NotificationDefinitionManager { get; set; } = null!; |
||||
|
|
||||
private SelectListItem? GetSelectedValue() |
protected async override Task OnInitializedAsync() |
||||
{ |
{ |
||||
var value = EditorContext.GetLiteralValueOrDefault(); |
var selectedItem = await ResolveSelectedItemAsync(); |
||||
return _items.FirstOrDefault(x => x.Value == value); |
|
||||
} |
|
||||
|
|
||||
private void OnSearch(string? filter) |
if (selectedItem != null) |
||||
{ |
{ |
||||
_items = _notifications |
await InvokeAsync(() => _selectedItem = selectedItem); |
||||
.WhereIf(!string.IsNullOrWhiteSpace(filter), x => x.Text.Contains(filter!)) |
} |
||||
.Take(10) |
|
||||
.ToList(); |
|
||||
} |
} |
||||
|
|
||||
private async Task OnValueChanged(SelectListItem? value) |
private async Task<SelectListItem?> 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 |
var inputDescriptor = EditorContext.InputDescriptor; |
||||
.Select(notification => |
var parameters = new DialogParameters<NotificationSelectDialog> |
||||
new SelectListItem( |
{ |
||||
notification.DisplayName.Localize(StringLocalizerFactory), notification.Name)) |
{ x => x.Title, Localizer[inputDescriptor.DisplayName ?? inputDescriptor.Name] }, |
||||
.OrderBy(x => x.Text) |
{ x => x.SelectedValue, _selectedItem?.Value } |
||||
.ToList(); |
}; |
||||
|
var options = new DialogOptions |
||||
|
{ |
||||
|
CloseOnEscapeKey = true, |
||||
|
FullWidth = true, |
||||
|
MaxWidth = MaxWidth.Medium |
||||
|
}; |
||||
|
|
||||
_items = _notifications.Take(10).ToList(); |
var dialog = await DialogService.ShowAsync<NotificationSelectDialog>(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); |
||||
|
}); |
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -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 |
||||
|
|
||||
|
<MudDialog> |
||||
|
<TitleContent> |
||||
|
<MudText Typo="Typo.h6">@Title</MudText> |
||||
|
</TitleContent> |
||||
|
<DialogContent> |
||||
|
<MudStack Spacing="3"> |
||||
|
<MudTextField T="string" |
||||
|
Value="_searchText" |
||||
|
ValueChanged="OnSearchTextChangedAsync" |
||||
|
Immediate="true" |
||||
|
Placeholder="@Localizer["Search"]" |
||||
|
Adornment="Adornment.Start" |
||||
|
AdornmentIcon="@Icons.Material.Filled.Search" |
||||
|
Variant="Variant.Outlined" |
||||
|
Margin="Margin.Dense" /> |
||||
|
|
||||
|
<MudTable T="SelectListItem" |
||||
|
@ref="_table" |
||||
|
ServerData="LoadTenantsAsync" |
||||
|
Dense="true" |
||||
|
Hover="true" |
||||
|
Breakpoint="Breakpoint.None" |
||||
|
OnRowClick="OnRowClickAsync"> |
||||
|
<HeaderContent> |
||||
|
<MudTh>@Localizer["Name"]</MudTh> |
||||
|
<MudTh Style="text-align:right" /> |
||||
|
</HeaderContent> |
||||
|
<RowTemplate> |
||||
|
<MudTd DataLabel="@Localizer["Name"]">@context.Text</MudTd> |
||||
|
<MudTd DataLabel="" Style="text-align:right"> |
||||
|
@if (context.Value == SelectedValue) |
||||
|
{ |
||||
|
<MudIcon Icon="@Icons.Material.Filled.Check" Color="Color.Success" Size="Size.Small" /> |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
<MudButton Size="Size.Small" Variant="Variant.Text" Color="Color.Primary" OnClick="@(() => SelectAsync(context))"> |
||||
|
@Localizer["Select"] |
||||
|
</MudButton> |
||||
|
} |
||||
|
</MudTd> |
||||
|
</RowTemplate> |
||||
|
<PagerContent> |
||||
|
<MudTablePager |
||||
|
PageSizeOptions="new int[] { 10, 25, 50, 100 }"/> |
||||
|
</PagerContent> |
||||
|
<NoRecordsContent> |
||||
|
<MudText Typo="Typo.body2">@Localizer["No results found"]</MudText> |
||||
|
</NoRecordsContent> |
||||
|
</MudTable> |
||||
|
</MudStack> |
||||
|
</DialogContent> |
||||
|
<DialogActions> |
||||
|
<MudButton Variant="Variant.Text" OnClick="CancelAsync">@Localizer["Cancel"]</MudButton> |
||||
|
</DialogActions> |
||||
|
</MudDialog> |
||||
|
|
||||
|
@code { |
||||
|
private const int DebounceIntervalMilliseconds = 350; |
||||
|
|
||||
|
private MudTable<SelectListItem>? _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<TableData<SelectListItem>> 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<SelectListItem> |
||||
|
{ |
||||
|
Items = items, |
||||
|
TotalItems = notifications.Count, |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
private async Task OnRowClickAsync(TableRowClickEventArgs<SelectListItem> 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(); |
||||
|
} |
||||
|
} |
||||
@ -1,7 +1,8 @@ |
|||||
namespace LINGYUN.Abp.ElsaNext.UIHints; |
namespace LINGYUN.Abp.ElsaNext.UIHints; |
||||
|
|
||||
public static class AbpElsaUIHints |
public static class AbpElsaUIHints |
||||
{ |
{ |
||||
public const string TenantPicker = "tenant-picker"; |
public const string TenantPicker = "tenant-picker"; |
||||
public const string UserPicker = "user-picker"; |
public const string UserPicker = "user-picker"; |
||||
|
public const string UserPickerMultiple = "user-picker-multiple"; |
||||
} |
} |
||||
|
|||||
Loading…
Reference in new issue