Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save sfmskywalker/3553c05e3a8bc588bc85173d7f69b7f2 to your computer and use it in GitHub Desktop.
Save sfmskywalker/3553c05e3a8bc588bc85173d7f69b7f2 to your computer and use it in GitHub Desktop.
Building Workflow Driven .NET Applications With Elsa 2 - Part 7
using System;
using System.Threading;
using System.Threading.Tasks;
using Elsa.Scripting.JavaScript.Events;
using Elsa.Scripting.JavaScript.Messages;
using MediatR;
using Microsoft.AspNetCore.StaticFiles;
namespace DocumentManagement.Workflows.Scripting.JavaScript
{
/// <summary>
/// Registers custom JS functions.
/// </summary>
public class ConfigureJavaScriptEngineWithCustomFunctions : INotificationHandler<EvaluatingJavaScriptExpression>
{
private readonly IContentTypeProvider _contentTypeProvider;
public ConfigureJavaScriptEngineWithCustomFunctions(IContentTypeProvider contentTypeProvider)
{
_contentTypeProvider = contentTypeProvider;
}
public Task Handle(EvaluatingJavaScriptExpression notification, CancellationToken cancellationToken)
{
var engine = notification.Engine;
engine.SetValue("contentTypeFromFileName", (Func<string, string>) GetContentType);
return Task.CompletedTask;
}
private string GetContentType(string fileName) => _contentTypeProvider.TryGetContentType(fileName, out var contentType) ? contentType : "application/octet-stream";
}
}
using System;
using System.Threading;
using System.Threading.Tasks;
using Elsa.Scripting.JavaScript.Events;
using Elsa.Scripting.JavaScript.Messages;
using MediatR;
using Microsoft.AspNetCore.StaticFiles;
namespace DocumentManagement.Workflows.Scripting.JavaScript
{
/// <summary>
/// Registers custom JS functions and type definitions.
/// </summary>
public class ConfigureJavaScriptEngineWithCustomFunctions : INotificationHandler<EvaluatingJavaScriptExpression>, INotificationHandler<RenderingTypeScriptDefinitions>
{
private readonly IContentTypeProvider _contentTypeProvider;
public ConfigureJavaScriptEngineWithCustomFunctions(IContentTypeProvider contentTypeProvider)
{
_contentTypeProvider = contentTypeProvider;
}
public Task Handle(EvaluatingJavaScriptExpression notification, CancellationToken cancellationToken)
{
var engine = notification.Engine;
engine.SetValue("contentTypeFromFileName", (Func<string, string>) GetContentType);
return Task.CompletedTask;
}
public Task Handle(RenderingTypeScriptDefinitions notification, CancellationToken cancellationToken)
{
var output = notification.Output;
output.AppendLine("declare function contentTypeFromFileName(fileName: string): string");
return Task.CompletedTask;
}
private string GetContentType(string fileName) => _contentTypeProvider.TryGetContentType(fileName, out var contentType) ? contentType : "application/octet-stream";
}
}
using System;
using System.Collections.Generic;
using DocumentManagement.Workflows.Activities;
using Elsa.Scripting.JavaScript.Services;
namespace DocumentManagement.Workflows.Scripting.JavaScript
{
/// <summary>
/// Register .NET types for which we want to include with JS intellisense.
/// </summary>
public class CustomTypeDefinitionProvider : TypeDefinitionProvider
{
public override IEnumerable<Type> CollectTypes(TypeDefinitionContext context)
{
yield return typeof(DocumentFile);
}
}
}
using System.Threading;
using System.Threading.Tasks;
using Elsa.Activities.Http.Events;
using MediatR;
using Microsoft.AspNetCore.Http;
namespace DocumentManagement.Web.Handlers
{
/// <summary>
/// Responds to the Accept or Reject signal when the user clicks either option from the email.
/// </summary>
public class DisplaySignalReceivedPage : INotificationHandler<HttpTriggeredSignal>
{
private readonly IHttpContextAccessor _httpContextAccessor;
public DisplaySignalReceivedPage(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public Task Handle(HttpTriggeredSignal notification, CancellationToken cancellationToken)
{
var affectedWorkflows = notification.AffectedWorkflows;
// Exit if no workflows were affected.
if (affectedWorkflows.Count == 0)
return Task.CompletedTask;
var signalName = notification.SignalModel.Name;
var response = _httpContextAccessor.HttpContext!.Response;
// Redirect to the appropriate page.
switch (signalName)
{
case "Approve":
response.Redirect("/leave-request-approved");
break;
case "Reject":
response.Redirect("/leave-request-denied");
break;
}
return Task.CompletedTask;
}
}
}
using System.Threading;
using System.Threading.Tasks;
using Elsa.Activities.Http.Events;
using MediatR;
using Microsoft.AspNetCore.Http;
namespace DocumentManagement.Web.Handlers
{
/// <summary>
/// Responds to the Accept or Reject signal when the user clicks either option from the email.
/// </summary>
public class DisplaySignalReceivedPage : INotificationHandler<HttpTriggeredSignal>
{
private readonly IHttpContextAccessor _httpContextAccessor;
public DisplaySignalReceivedPage(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public Task Handle(HttpTriggeredSignal notification, CancellationToken cancellationToken)
{
var affectedWorkflows = notification.AffectedWorkflows;
// Exit if no workflows were affected.
if (affectedWorkflows.Count == 0)
return Task.CompletedTask;
var signalName = notification.SignalModel.Name;
var response = _httpContextAccessor.HttpContext!.Response;
// Redirect to the appropriate page.
switch (signalName)
{
case "Approve":
response.Redirect("/leave-request-approved");
break;
case "Reject":
response.Redirect("/leave-request-denied");
break;
case "Valid":
response.Redirect("/identity-confirmed");
break;
case "Fake":
response.Redirect("/identity-theft-confirmed");
break;
}
return Task.CompletedTask;
}
}
}
const fileName = input.Document.FileName;
const contentType = contentTypeFromFileName(fileName);
const attachment = new EmailAttachment(input.FileStream, fileName, contentType);
return attachment;
<p>Please review attached leave request.</p>
<a href="{{ "Approve" | signal_url }}">Appove</a> or <a href="{{ "Reject" | signal_url }}">Reject</a>
@page "/leave-request-approved"
@{
ViewData["Title"] = "Leave Request Approved";
}
<div>
<h1 class="display-4">Leave Request Approved</h1>
<p>We will let the happy employee know. Thank you!</p>
</div>
@page "/leave-request-denied"
@{
ViewData["Title"] = "Leave Request Denied";
}
<div>
<h1 class="display-4">Leave Request Denied</h1>
<p>We will let the lazy employee know there's no time for that. Thank you!</p>
</div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment