41 changed files with 490 additions and 58 deletions
@ -1,6 +1,6 @@ |
|||||
namespace LINGYUN.Abp.IM.Messages |
namespace LINGYUN.Abp.IM.Messages |
||||
{ |
{ |
||||
public enum MessageSourceTye |
public enum MessageSourceType |
||||
{ |
{ |
||||
User = 0, |
User = 0, |
||||
System = 10, |
System = 10, |
||||
@ -1,3 +1,3 @@ |
|||||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
<ConfigureAwait /> |
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
</Weavers> |
</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"> |
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
<ConfigureAwait /> |
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
</Weavers> |
</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"> |
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
<ConfigureAwait /> |
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
</Weavers> |
</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