22 changed files with 637 additions and 0 deletions
@ -0,0 +1,17 @@ |
|||||
|
using LINGYUN.Abp.ElsaNext.Studio.Blazor; |
||||
|
using LINGYUN.Abp.ElsaNext.Studio.Webhooks.Blazor.Extensions; |
||||
|
using LINGYUN.Abp.ElsaNext.Webhooks; |
||||
|
using Volo.Abp.Modularity; |
||||
|
|
||||
|
namespace LINGYUN.Abp.ElsaNext.Studio.Webhooks.Blazor; |
||||
|
|
||||
|
[DependsOn( |
||||
|
typeof(AbpElsaNextWebhooksModule), |
||||
|
typeof(AbpElsaNextStudioBlazorModule))] |
||||
|
public class AbpElsaNextStudioWebhooksBlazorModule : AbpModule |
||||
|
{ |
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
context.Services.AddWebhooksUIHintHandlers(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,130 @@ |
|||||
|
@using Elsa.Api.Client.Shared.UIHints.DropDown |
||||
|
@using Elsa.Studio.Models |
||||
|
@using LINGYUN.Abp.ElsaNext.Studio.Blazor.Components |
||||
|
@using LINGYUN.Abp.Webhooks |
||||
|
@using Microsoft.Extensions.Localization |
||||
|
@inject ILocalizer Localizer |
||||
|
|
||||
|
@inherits StudioComponentBase |
||||
|
@{ |
||||
|
var inputDescriptor = EditorContext.InputDescriptor; |
||||
|
var displayName = inputDescriptor.DisplayName; |
||||
|
var description = inputDescriptor.Description; |
||||
|
} |
||||
|
|
||||
|
<ExpressionInput EditorContext="@EditorContext"> |
||||
|
<ChildContent> |
||||
|
<MudTextFieldEx Value="@(_selectedItem?.Text ?? string.Empty)" |
||||
|
Label="@Localizer[displayName]" |
||||
|
HelperText="@Localizer[description]" |
||||
|
Variant="Variant.Outlined" |
||||
|
Margin="Margin.Dense" |
||||
|
ReadOnly="true" |
||||
|
Disabled="EditorContext.IsReadOnly" |
||||
|
OnFieldClick="@(_ => OpenSelectDialogAsync())" |
||||
|
AdornmentIcons="GetAdornmentIcons()" /> |
||||
|
</ChildContent> |
||||
|
</ExpressionInput> |
||||
|
|
||||
|
@code { |
||||
|
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 IWebhookDefinitionManager WebhookDefinitionManager { get; set; } = null!; |
||||
|
|
||||
|
protected async override Task OnInitializedAsync() |
||||
|
{ |
||||
|
var selectedItem = await ResolveSelectedItemAsync(); |
||||
|
|
||||
|
if (selectedItem != null) |
||||
|
{ |
||||
|
await InvokeAsync(() => _selectedItem = selectedItem); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private async Task<SelectListItem?> ResolveSelectedItemAsync() |
||||
|
{ |
||||
|
var value = EditorContext.GetLiteralValueOrDefault(); |
||||
|
|
||||
|
if (string.IsNullOrWhiteSpace(value)) |
||||
|
{ |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
var webhookDefine = await WebhookDefinitionManager.GetOrNullAsync(value); |
||||
|
if (webhookDefine != null) |
||||
|
{ |
||||
|
return new SelectListItem( |
||||
|
webhookDefine.DisplayName != null |
||||
|
? webhookDefine.DisplayName.Localize(StringLocalizerFactory) |
||||
|
: webhookDefine.Name, |
||||
|
webhookDefine.Name); |
||||
|
} |
||||
|
|
||||
|
return new SelectListItem(value, value); |
||||
|
} |
||||
|
|
||||
|
private async Task OpenSelectDialogAsync() |
||||
|
{ |
||||
|
if (EditorContext.IsReadOnly) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
var inputDescriptor = EditorContext.InputDescriptor; |
||||
|
var parameters = new DialogParameters<WebhookSelectDialog> |
||||
|
{ |
||||
|
{ 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<WebhookSelectDialog>(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,156 @@ |
|||||
|
@using System.Threading |
||||
|
@using Elsa.Api.Client.Shared.UIHints.DropDown |
||||
|
@using LINGYUN.Abp.Webhooks |
||||
|
@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 IWebhookDefinitionManager WebhookDefinitionManager { 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 webhooks = await WebhookDefinitionManager.GetWebhooksAsync(); |
||||
|
|
||||
|
var items = webhooks |
||||
|
.Select(webhook => new SelectListItem( |
||||
|
webhook.DisplayName != null |
||||
|
? webhook.DisplayName.Localize(StringLocalizerFactory) |
||||
|
: webhook.Name, |
||||
|
webhook.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 = webhooks.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(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,13 @@ |
|||||
|
using Elsa.Studio.Extensions; |
||||
|
using LINGYUN.Abp.ElsaNext.Studio.Webhooks.Blazor.Handlers; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
|
||||
|
namespace LINGYUN.Abp.ElsaNext.Studio.Webhooks.Blazor.Extensions; |
||||
|
|
||||
|
public static class ServiceCollectionExtensions |
||||
|
{ |
||||
|
public static IServiceCollection AddWebhooksUIHintHandlers(this IServiceCollection services) |
||||
|
{ |
||||
|
return services.AddUIHintHandler<WebhookPickerHandler>(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
|
</Weavers> |
||||
@ -0,0 +1,30 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
||||
|
<xs:element name="Weavers"> |
||||
|
<xs:complexType> |
||||
|
<xs:all> |
||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
||||
|
<xs:complexType> |
||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:all> |
||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:schema> |
||||
@ -0,0 +1,25 @@ |
|||||
|
using Elsa.Studio; |
||||
|
using Elsa.Studio.Contracts; |
||||
|
using Elsa.Studio.Models; |
||||
|
using LINGYUN.Abp.ElsaNext.Studio.Webhooks.Blazor.Components; |
||||
|
using LINGYUN.Abp.ElsaNext.Webhooks.UIHints; |
||||
|
using Microsoft.AspNetCore.Components; |
||||
|
|
||||
|
namespace LINGYUN.Abp.ElsaNext.Studio.Webhooks.Blazor.Handlers; |
||||
|
|
||||
|
public class WebhookPickerHandler : IUIHintHandler |
||||
|
{ |
||||
|
public bool GetSupportsUIHint(string uiHint) => uiHint is WebhooksUIHints.WebhookPicker; |
||||
|
|
||||
|
public string UISyntax => WellKnownSyntaxNames.Object; |
||||
|
|
||||
|
public RenderFragment DisplayInputEditor(DisplayInputEditorContext context) |
||||
|
{ |
||||
|
return builder => |
||||
|
{ |
||||
|
builder.OpenComponent(0, typeof(WebhookPicker)); |
||||
|
builder.AddAttribute(1, nameof(WebhookPicker.EditorContext), context); |
||||
|
builder.CloseComponent(); |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,20 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk.Razor"> |
||||
|
|
||||
|
<Import Project="..\..\..\..\configureawait.props" /> |
||||
|
<Import Project="..\..\..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>net10.0</TargetFramework> |
||||
|
<AssemblyName>LINGYUN.Abp.ElsaNext.Studio.Webhooks.Blazor</AssemblyName> |
||||
|
<PackageId>LINGYUN.Abp.ElsaNext.Studio.Webhooks.Blazor</PackageId> |
||||
|
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> |
||||
|
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> |
||||
|
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\LINGYUN.Abp.ElsaNext.Webhooks\LINGYUN.Abp.ElsaNext.Webhooks.csproj" /> |
||||
|
<ProjectReference Include="..\LINGYUN.Abp.ElsaNext.Studio.Blazor\LINGYUN.Abp.ElsaNext.Studio.Blazor.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,5 @@ |
|||||
|
@using Microsoft.AspNetCore.Components.Web |
||||
|
@using Elsa.Studio.Components |
||||
|
@using Elsa.Studio.Localization |
||||
|
@using MudBlazor |
||||
|
@using MudExtensions |
||||
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
|
</Weavers> |
||||
@ -0,0 +1,30 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
||||
|
<xs:element name="Weavers"> |
||||
|
<xs:complexType> |
||||
|
<xs:all> |
||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
||||
|
<xs:complexType> |
||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:all> |
||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:schema> |
||||
@ -0,0 +1,26 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\..\..\configureawait.props" /> |
||||
|
<Import Project="..\..\..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>net10.0</TargetFramework> |
||||
|
<AssemblyName>LINGYUN.Abp.ElsaNext.Webhooks</AssemblyName> |
||||
|
<PackageId>LINGYUN.Abp.ElsaNext.Webhooks</PackageId> |
||||
|
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> |
||||
|
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> |
||||
|
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<Content Remove="LINGYUN\Abp\ElsaNext\Webhooks\Localization\**\*.json" /> |
||||
|
<EmbeddedResource Include="LINGYUN\Abp\ElsaNext\Webhooks\Localization\**\*.json" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\..\webhooks\LINGYUN.Abp.Webhooks\LINGYUN.Abp.Webhooks.csproj" /> |
||||
|
<ProjectReference Include="..\LINGYUN.Abp.ElsaNext\LINGYUN.Abp.ElsaNext.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,38 @@ |
|||||
|
using Elsa.Features.Services; |
||||
|
using LINGYUN.Abp.ElsaNext.Localization; |
||||
|
using LINGYUN.Abp.ElsaNext.Webhooks.Extensions; |
||||
|
using LINGYUN.Abp.Webhooks; |
||||
|
using Volo.Abp.Localization; |
||||
|
using Volo.Abp.Modularity; |
||||
|
using Volo.Abp.VirtualFileSystem; |
||||
|
|
||||
|
namespace LINGYUN.Abp.ElsaNext.Webhooks; |
||||
|
|
||||
|
[DependsOn( |
||||
|
typeof(AbpWebhooksModule), |
||||
|
typeof(AbpElsaNextModule))] |
||||
|
public class AbpElsaNextWebhooksModule : AbpModule |
||||
|
{ |
||||
|
public override void PreConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
PreConfigure<IModule>(elsa => |
||||
|
{ |
||||
|
elsa.UseAbpWebhooks(); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
Configure<AbpVirtualFileSystemOptions>(options => |
||||
|
{ |
||||
|
options.FileSets.AddEmbedded<AbpElsaNextWebhooksModule>(); |
||||
|
}); |
||||
|
|
||||
|
Configure<AbpLocalizationOptions>(options => |
||||
|
{ |
||||
|
options.Resources |
||||
|
.Get<ElsaNextResource>() |
||||
|
.AddVirtualJson("/LINGYUN/Abp/ElsaNext/Webhooks/Localization/Resources"); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,60 @@ |
|||||
|
using Elsa.Extensions; |
||||
|
using Elsa.Workflows; |
||||
|
using Elsa.Workflows.Attributes; |
||||
|
using Elsa.Workflows.Models; |
||||
|
using Elsa.Workflows.UIHints; |
||||
|
using LINGYUN.Abp.ElsaNext.Webhooks.UIHints; |
||||
|
using LINGYUN.Abp.Webhooks; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace LINGYUN.Abp.ElsaNext.Webhooks.Activities; |
||||
|
|
||||
|
[Activity("Elsa", "Webhooks", "Send webhooks to subscriptions.", Kind = ActivityKind.Task)] |
||||
|
public class PublishWebhook : CodeActivity |
||||
|
{ |
||||
|
[Input( |
||||
|
Description = "Unique name of the webhook.", |
||||
|
UIHint = WebhooksUIHints.WebhookPicker)] |
||||
|
public Input<string> WebhookName { get; set; } = default!; |
||||
|
|
||||
|
[Input(Description = "Data to send.")] |
||||
|
public Input<object> WebhookData { get; set; } = default!; |
||||
|
|
||||
|
[Input(Description = "If true, It sends the exact same data as the parameter to clients.")] |
||||
|
public Input<bool?> SendExactSameData { get; set; } = default!; |
||||
|
|
||||
|
[Input(Description = "If true, webhook will only contain given headers. If false given headers will be added to predefined headers in subscription.")] |
||||
|
public Input<bool?> UseOnlyGivenHeaders { get; set; } = default!; |
||||
|
|
||||
|
[Input( |
||||
|
Description = "That headers will be sent with the webhook.", |
||||
|
UIHint = InputUIHints.Dictionary)] |
||||
|
public Input<Dictionary<string, string>> Headers { get; set; } = default!; |
||||
|
|
||||
|
protected async override ValueTask ExecuteAsync(ActivityExecutionContext context) |
||||
|
{ |
||||
|
var webhookPublisher = context.GetRequiredService<IWebhookPublisher>(); |
||||
|
|
||||
|
var webhookName = WebhookName.Get(context); |
||||
|
var webhookData = WebhookData.Get(context); |
||||
|
var sendExactSameData = SendExactSameData.GetOrDefault(context) ?? true; |
||||
|
WebhookHeader? webhookHeader = null; |
||||
|
var headers = Headers.GetOrDefault(context); |
||||
|
if (headers != null) |
||||
|
{ |
||||
|
var useOnlyGivenHeaders = UseOnlyGivenHeaders.GetOrDefault(context) ?? false; |
||||
|
webhookHeader = new WebhookHeader |
||||
|
{ |
||||
|
UseOnlyGivenHeaders = useOnlyGivenHeaders, |
||||
|
Headers = headers, |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
await webhookPublisher.PublishAsync( |
||||
|
webhookName, |
||||
|
webhookData, |
||||
|
sendExactSameData, |
||||
|
webhookHeader); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
using Elsa.Features.Services; |
||||
|
using LINGYUN.Abp.ElsaNext.Webhooks.Features; |
||||
|
using System; |
||||
|
|
||||
|
namespace LINGYUN.Abp.ElsaNext.Webhooks.Extensions; |
||||
|
|
||||
|
public static class ModuleExtensions |
||||
|
{ |
||||
|
public static IModule UseAbpWebhooks(this IModule configuration, Action<WebhooksFeature>? configure = null) |
||||
|
{ |
||||
|
configuration.Configure(configure); |
||||
|
return configuration; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
using Elsa.Extensions; |
||||
|
using Elsa.Features.Abstractions; |
||||
|
using Elsa.Features.Services; |
||||
|
|
||||
|
namespace LINGYUN.Abp.ElsaNext.Webhooks.Features; |
||||
|
|
||||
|
public class WebhooksFeature : FeatureBase |
||||
|
{ |
||||
|
public WebhooksFeature(IModule module) : base(module) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public override void Configure() |
||||
|
{ |
||||
|
Module.AddActivitiesFrom<WebhooksFeature>(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
{ |
||||
|
"culture": "en", |
||||
|
"texts": { |
||||
|
"Webhooks": "Webhooks", |
||||
|
"Publish Webhook": "Publish Webhook", |
||||
|
"Send webhooks to subscriptions.": "Send webhooks to subscriptions.", |
||||
|
"Data to send.": "Data to send.", |
||||
|
"If true, It sends the exact same data as the parameter to clients.": "If true, It sends the exact same data as the parameter to clients.", |
||||
|
"If true, webhook will only contain given headers. If false given headers will be added to predefined headers in subscription.": "If true, webhook will only contain given headers. If false given headers will be added to predefined headers in subscription.", |
||||
|
"That headers will be sent with the webhook.": "That headers will be sent with the webhook." |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
{ |
||||
|
"culture": "zh-Hans", |
||||
|
"texts": { |
||||
|
"Webhooks": "Webhooks", |
||||
|
"Publish Webhook": "发布Webhook", |
||||
|
"Send webhooks to subscriptions.": "向订阅方发布Webhook。", |
||||
|
"Data to send.": "要发送的数据。", |
||||
|
"If true, It sends the exact same data as the parameter to clients.": "如果为True,它会向客户端发送与参数完全相同的数据。", |
||||
|
"If true, webhook will only contain given headers. If false given headers will be added to predefined headers in subscription.": "如果为True,webhook 将仅包含指定的标头。如果为False,则在订阅中预定义的标头将添加给定的标头。", |
||||
|
"That headers will be sent with the webhook.": "将随 webhook 一起发送的请求头。" |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,6 @@ |
|||||
|
namespace LINGYUN.Abp.ElsaNext.Webhooks.UIHints; |
||||
|
|
||||
|
public static class WebhooksUIHints |
||||
|
{ |
||||
|
public const string WebhookPicker = "webhook-picker"; |
||||
|
} |
||||
Loading…
Reference in new issue