41 changed files with 490 additions and 58 deletions
@ -1,6 +1,6 @@ |
|||
namespace LINGYUN.Abp.IM.Messages |
|||
{ |
|||
public enum MessageSourceTye |
|||
public enum MessageSourceType |
|||
{ |
|||
User = 0, |
|||
System = 10, |
|||
@ -1,3 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait /> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -0,0 +1,16 @@ |
|||
using Elsa.Services; |
|||
using Volo.Abp.BlobStoring; |
|||
using Volo.Abp.MultiTenancy; |
|||
|
|||
namespace LINGYUN.Abp.Elsa.Activities.BlobStoring; |
|||
|
|||
public abstract class BlobActivity : Activity |
|||
{ |
|||
protected ICurrentTenant CurrentTenant; |
|||
protected IBlobContainer<ElsaBlobContainer> BlobContainer; |
|||
|
|||
protected BlobActivity(IBlobContainer<ElsaBlobContainer> blobContainer) |
|||
{ |
|||
BlobContainer = blobContainer; |
|||
} |
|||
} |
|||
@ -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,17 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\configureawait.props" /> |
|||
<Import Project="..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard2.1</TargetFramework> |
|||
<RootNamespace /> |
|||
<Nullable>enable</Nullable> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\common\LINGYUN.Abp.IM\LINGYUN.Abp.IM.csproj" /> |
|||
<ProjectReference Include="..\LINGYUN.Abp.Elsa\LINGYUN.Abp.Elsa.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,11 @@ |
|||
using LINGYUN.Abp.IM; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace LINGYUN.Abp.Elsa.Activities.IM; |
|||
|
|||
[DependsOn( |
|||
typeof(AbpElsaModule), |
|||
typeof(AbpIMModule))] |
|||
public class AbpElsaActivitiesIMModule : AbpModule |
|||
{ |
|||
} |
|||
@ -0,0 +1,90 @@ |
|||
using Elsa.ActivityResults; |
|||
using Elsa.Attributes; |
|||
using Elsa.Services; |
|||
using Elsa.Services.Models; |
|||
using LINGYUN.Abp.IM.Messages; |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Timing; |
|||
|
|||
namespace LINGYUN.Abp.Elsa.Activities.IM; |
|||
|
|||
[Action(Category = "Message", Description = "Send an message.")] |
|||
public class SendMessage : Activity |
|||
{ |
|||
private readonly IClock _clock; |
|||
private readonly IMessageSender _messageSender; |
|||
|
|||
[ActivityInput(Hint = "The message content.")] |
|||
public string Content { get; set; } //TODO: Other message type
|
|||
|
|||
[ActivityInput(Hint = "Source user identity.")] |
|||
public Guid FormUser { get; set; } |
|||
|
|||
[ActivityInput(Hint = "Source user name.")] |
|||
public string? FormUserName { get; set; } |
|||
|
|||
[ActivityInput( |
|||
Hint = "Receiving user identity.", |
|||
UIHint = "If the value is not empty, it is a user message")] |
|||
public Guid? To { get; set; } |
|||
|
|||
[ActivityInput( |
|||
Hint = "Receiving group identity.", |
|||
UIHint = "If the value is not empty, it is a group message")] |
|||
public string? GroupId { get; set; } |
|||
|
|||
[ActivityOutput] |
|||
public string? MessageId { get; set; } |
|||
|
|||
public SendMessage( |
|||
IClock clock, |
|||
IMessageSender messageSender) |
|||
{ |
|||
_clock = clock; |
|||
_messageSender = messageSender; |
|||
} |
|||
|
|||
|
|||
protected async override ValueTask<IActivityExecutionResult> OnExecuteAsync(ActivityExecutionContext context) |
|||
{ |
|||
ChatMessage? chatMessage = null; |
|||
var tenantId = context.GetTenantId(); |
|||
|
|||
if (!GroupId.IsNullOrWhiteSpace()) |
|||
{ |
|||
chatMessage = ChatMessage.Group( |
|||
FormUser, |
|||
FormUserName, |
|||
GroupId, |
|||
Content, |
|||
_clock, |
|||
false, |
|||
MessageType.Text, |
|||
MessageSourceTye.User, |
|||
tenantId); |
|||
} |
|||
else if (To.HasValue) |
|||
{ |
|||
chatMessage = ChatMessage.User( |
|||
FormUser, |
|||
FormUserName, |
|||
To.Value, |
|||
Content, |
|||
_clock, |
|||
false, |
|||
MessageType.Text, |
|||
MessageSourceTye.User, |
|||
tenantId); |
|||
} |
|||
|
|||
if (chatMessage != null) |
|||
{ |
|||
MessageId = await _messageSender.SendMessageAsync(chatMessage); |
|||
|
|||
return Done(); |
|||
} |
|||
|
|||
return Suspend(); |
|||
} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
using Elsa.Attributes; |
|||
using Elsa.Options; |
|||
using Elsa.Services.Startup; |
|||
using Microsoft.Extensions.Configuration; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
|
|||
namespace LINGYUN.Abp.Elsa.Activities.IM; |
|||
|
|||
[Feature("IM")] |
|||
public class Startup : StartupBase |
|||
{ |
|||
public override void ConfigureElsa(ElsaOptionsBuilder elsa, IConfiguration configuration) |
|||
{ |
|||
elsa.AddIMActivities(); |
|||
} |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
using Elsa.Options; |
|||
using LINGYUN.Abp.Elsa.Activities.IM; |
|||
|
|||
namespace Microsoft.Extensions.DependencyInjection; |
|||
|
|||
public static class IMServiceCollectionExtensions |
|||
{ |
|||
public static ElsaOptionsBuilder AddIMActivities(this ElsaOptionsBuilder options) |
|||
{ |
|||
options |
|||
.AddActivity<SendMessage>(); |
|||
|
|||
return options; |
|||
} |
|||
} |
|||
@ -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,17 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\configureawait.props" /> |
|||
<Import Project="..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard2.1</TargetFramework> |
|||
<RootNamespace /> |
|||
<Nullable>enable</Nullable> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\common\LINGYUN.Abp.Notifications\LINGYUN.Abp.Notifications.csproj" /> |
|||
<ProjectReference Include="..\LINGYUN.Abp.Elsa\LINGYUN.Abp.Elsa.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,11 @@ |
|||
using LINGYUN.Abp.Notifications; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace LINGYUN.Abp.Elsa.Activities.Notifications; |
|||
|
|||
[DependsOn( |
|||
typeof(AbpElsaModule), |
|||
typeof(AbpNotificationModule))] |
|||
public class AbpElsaActivitiesNotificationsModule : AbpModule |
|||
{ |
|||
} |
|||
@ -0,0 +1,82 @@ |
|||
using Elsa.ActivityResults; |
|||
using Elsa.Attributes; |
|||
using Elsa.Design; |
|||
using Elsa.Expressions; |
|||
using Elsa.Providers.WorkflowStorage; |
|||
using Elsa.Services; |
|||
using Elsa.Services.Models; |
|||
using LINGYUN.Abp.Notifications; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace LINGYUN.Abp.Elsa.Activities.Notifications; |
|||
|
|||
[Action(Category = "Notification", Description = "Send an notification.")] |
|||
public class SendNotification : Activity |
|||
{ |
|||
private readonly INotificationSender _notificationSender; |
|||
|
|||
[ActivityInput(Hint = "The name of the registered notification.", SupportedSyntaxes = new[] { SyntaxNames.JavaScript, SyntaxNames.Liquid })] |
|||
public string NotificationName { get; set; } |
|||
|
|||
[ActivityInput( |
|||
Hint = "Notifications pass data or template content.", |
|||
UIHint = ActivityInputUIHints.MultiLine, |
|||
SupportedSyntaxes = new[] { SyntaxNames.JavaScript, SyntaxNames.Liquid }, |
|||
DefaultWorkflowStorageProvider = TransientWorkflowStorageProvider.ProviderName |
|||
)] |
|||
public object NotificationData { get; set; } |
|||
|
|||
[ActivityInput( |
|||
Hint = "The recipients user id list.", |
|||
UIHint = ActivityInputUIHints.MultiText, |
|||
DefaultSyntax = SyntaxNames.Json, |
|||
SupportedSyntaxes = new[] { SyntaxNames.Json, SyntaxNames.JavaScript })] |
|||
public ICollection<Guid> To { get; set; } = new List<Guid>(); |
|||
|
|||
[ActivityInput(Hint = "Notifications severity.", SupportedSyntaxes = new[] { SyntaxNames.JavaScript, SyntaxNames.Liquid })] |
|||
public NotificationSeverity Severity { get; set; } = NotificationSeverity.Info; |
|||
|
|||
[ActivityOutput] |
|||
public string? NotificationId { get; set; } |
|||
|
|||
public SendNotification( |
|||
INotificationSender notificationSender) |
|||
{ |
|||
_notificationSender = notificationSender; |
|||
} |
|||
|
|||
|
|||
protected async override ValueTask<IActivityExecutionResult> OnExecuteAsync(ActivityExecutionContext context) |
|||
{ |
|||
var tenantId = context.GetTenantId(); |
|||
switch (NotificationData) |
|||
{ |
|||
case NotificationData data: |
|||
NotificationId = await _notificationSender.SendNofiterAsync( |
|||
NotificationName, |
|||
data, |
|||
GetUserIdentifiers(), |
|||
tenantId, |
|||
Severity); |
|||
return Done(); |
|||
case NotificationTemplate template: |
|||
NotificationId = await _notificationSender.SendNofiterAsync( |
|||
NotificationName, |
|||
template, |
|||
GetUserIdentifiers(), |
|||
tenantId, |
|||
Severity); |
|||
return Done(); |
|||
} |
|||
|
|||
return Suspend(); |
|||
} |
|||
|
|||
private IEnumerable<UserIdentifier> GetUserIdentifiers() |
|||
{ |
|||
return To.Select(to => new UserIdentifier(to, to.ToString())); |
|||
} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
using Elsa.Attributes; |
|||
using Elsa.Options; |
|||
using Elsa.Services.Startup; |
|||
using Microsoft.Extensions.Configuration; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
|
|||
namespace LINGYUN.Abp.Elsa.Activities.Notifications; |
|||
|
|||
[Feature("Notification")] |
|||
public class Startup : StartupBase |
|||
{ |
|||
public override void ConfigureElsa(ElsaOptionsBuilder elsa, IConfiguration configuration) |
|||
{ |
|||
elsa.AddNotificationActivities(); |
|||
} |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
using Elsa.Options; |
|||
using LINGYUN.Abp.Elsa.Activities.Notifications; |
|||
|
|||
namespace Microsoft.Extensions.DependencyInjection; |
|||
|
|||
public static class NotificationServiceCollectionExtensions |
|||
{ |
|||
public static ElsaOptionsBuilder AddNotificationActivities(this ElsaOptionsBuilder options) |
|||
{ |
|||
options |
|||
.AddActivity<SendNotification>(); |
|||
|
|||
return options; |
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -1,3 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait /> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -0,0 +1,17 @@ |
|||
using System; |
|||
|
|||
namespace Elsa.Models; |
|||
|
|||
public static class WorkflowInstanceExtensions |
|||
{ |
|||
public static Guid? GetTenantId(this WorkflowInstance instance) |
|||
{ |
|||
var tenantId = instance.TenantId; |
|||
if (!tenantId.IsNullOrWhiteSpace() && |
|||
Guid.TryParse(tenantId, out var id)) |
|||
{ |
|||
return id; |
|||
} |
|||
return null; |
|||
} |
|||
} |
|||
@ -0,0 +1,12 @@ |
|||
using Elsa.Models; |
|||
using System; |
|||
|
|||
namespace Elsa.Services.Models; |
|||
|
|||
public static class ActivityExecutionContextExtensions |
|||
{ |
|||
public static Guid? GetTenantId(this ActivityExecutionContext context) |
|||
{ |
|||
return context.WorkflowInstance.GetTenantId(); |
|||
} |
|||
} |
|||
@ -1,3 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait /> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -0,0 +1,52 @@ |
|||
using Elsa.Models; |
|||
using Elsa.Services; |
|||
using Elsa.Services.Models; |
|||
using Elsa.Services.Workflows; |
|||
using Elsa.Services.WorkflowStorage; |
|||
using MediatR; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Logging; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.MultiTenancy; |
|||
|
|||
namespace LINGYUN.Abp.Elsa; |
|||
|
|||
public class AbpWorkflowRunner : WorkflowRunner |
|||
{ |
|||
private readonly ICurrentTenant _currentTenant; |
|||
public AbpWorkflowRunner( |
|||
ICurrentTenant currentTenant, |
|||
IWorkflowContextManager workflowContextManager, |
|||
IMediator mediator, |
|||
IServiceScopeFactory serviceScopeFactory, |
|||
IGetsStartActivities startingActivitiesProvider, |
|||
IWorkflowStorageService workflowStorageService, |
|||
ILogger<WorkflowRunner> logger) |
|||
: base( |
|||
workflowContextManager, |
|||
mediator, |
|||
serviceScopeFactory, |
|||
startingActivitiesProvider, |
|||
workflowStorageService, |
|||
logger) |
|||
{ |
|||
_currentTenant = currentTenant; |
|||
} |
|||
|
|||
protected async override Task<RunWorkflowResult> RunWorkflowInternalAsync( |
|||
WorkflowExecutionContext workflowExecutionContext, |
|||
string? activityId = null, |
|||
CancellationToken cancellationToken = default) |
|||
{ |
|||
var tenantId = workflowExecutionContext.WorkflowInstance.GetTenantId(); |
|||
|
|||
using (_currentTenant.Change(tenantId)) |
|||
{ |
|||
return await base.RunWorkflowInternalAsync( |
|||
workflowExecutionContext, |
|||
activityId, |
|||
cancellationToken); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue