elsa-workflows / elsa-workflows/elsa-core

Activity description not displayed when Activity created using IActivityTypeProvider

Open
#894 5 comments 1 reaction 0 assignees View on GitHub
triaged workflow tooling
Dominant language
C#
Stars
7.9k
Forks
1.5k
Avg merge
15h 22m
Merged PRs (30d)
114

Description

Connected with my question in #875.

I've finished writing my first shot at creating `Activity` using `IActivityTypeProvider`, code provided below.
It displays in designer and executes OK :).
The only problem I still have is that the Activity description, `Test activity description`, is not displayed in the designer.

![NoActivityDescription](https://user-images.githubusercontent.com/7658839/115697225-aa594900-a363-11eb-97af-b863c304939c.png)

Could you please help if I did something wrong, or....?
In addition if you see anything in my solution that I should not be doing, please shout :)

Thank you.

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Elsa;
using Elsa.ActivityResults;
using Elsa.Design;
using Elsa.Exceptions;
using Elsa.Expressions;
using Elsa.Metadata;
using Elsa.Services;
using Elsa.Services.Models;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

namespace Test
{
public interface IDictionaryActivity : IActivity
{
public IDictionary Properties { get; }
}

public class TestActivity : Activity, IDictionaryActivity
{
public IDictionary Properties { get; } = new Dictionary();

private readonly ILogger _logger;

public TestActivity(ILogger logger)
{
_logger = logger;
_logger.LogInformation("Test activity constructor");
}

protected override async ValueTask OnExecuteAsync(ActivityExecutionContext context)
{
_logger.LogInformation("Test activity OnExecuteAsync");
_logger.LogDebug(GetPropertyString("FirstProperty"));
_logger.LogDebug(GetPropertyString("SecondProperty"));
_logger.LogDebug(GetPropertyString("ThirdProperty"));
_logger.LogDebug(GetPropertyString("FourthProperty"));
return Done();
}

private string GetPropertyString(string name)
{
object ret;
if (!Properties.TryGetValue(name, out ret))
ret = "missing";
return $"{name} = {(ret == null ? "null" : ret.ToString())}";
}
}

public class TestActivityTypeProvider : IActivityTypeProvider
{
public ValueTask> GetActivityTypesAsync(CancellationToken cancellationToken = default)
{
return new(new ActivityType[] { CreateTestActivityType() });
}

private ActivityType CreateTestActivityType()
{
List properties = new List();
properties.Add(
new ActivityPropertyDescriptor(
"FirstProperty",
typeof(string), // property type
ActivityPropertyUIHints.Dropdown, // property UI hint
"First Property Label",
"First Property description and a very long one",
new[] { "value1", "value2", "value3" }, // possible property values
null, // cathegory
"value2", // default value
SyntaxNames.Literal, // default syntax
new[] { SyntaxNames.JavaScript, SyntaxNames.Liquid }) // allowed syntaxes
);
properties.Add(
new ActivityPropertyDescriptor(
"SecondProperty",
typeof(HashSet), // property type
ActivityPropertyUIHints.CheckList, // property UI hint
"First Property Label",
"First Property description and a very long one",
new[] { "value9", "value8", "value7" }, // possible property values
null, // cathegory
"value8", // default value
SyntaxNames.Json, // default syntax
new[] { SyntaxNames.Json, SyntaxNames.JavaScript, SyntaxNames.Liquid }) // allowed syntaxes
);
properties.Add(
new ActivityPropertyDescriptor(
"ThirdProperty",
typeof(string), // property type
ActivityPropertyUIHints.Dropdown, // property UI hint
"Third Property Label",
"Third Property description and a very long one",
new[] { new SelectListItem("name1", "value1"), new SelectListItem("name2", "value2"), new SelectListItem("name3", "value3") }, // possible property values
null, // cathegory
"value3", // default value
SyntaxNames.Literal, // default syntax
new[] { SyntaxNames.JavaScript, SyntaxNames.Liquid }) // allowed syntaxes
);
properties.Add(
new ActivityPropertyDescriptor(
"FourthProperty",
typeof(string[]), // property type
ActivityPropertyUIHints.CheckList, // property UI hint
"Fourth Property Label",
"Fourth Property description and a very long one",
new[] { new SelectListItem("name9", "value9"), new SelectListItem("name8", "value8"), new SelectListItem("name7", "value7") }, // possible property values
null, // cathegory
"value9", // default value
SyntaxNames.Json, // default syntax
new[] { SyntaxNames.Json, SyntaxNames.JavaScript, SyntaxNames.Liquid }) // allowed syntaxes
);

var descriptor = new ActivityDescriptor
{
Type = typeof(TestActivity).FullName,
Category = "Test",
Traits = ActivityTraits.Action,
DisplayName = "Test Activity",
Outcomes = new[] { OutcomeNames.Done, OutcomeNames.False },
Properties = properties.ToArray()
};

Type activityType = typeof(TestActivity);
return new ActivityType
{
TypeName = descriptor.Type,
Type = activityType,
Description = "Test activity description",
DisplayName = descriptor.DisplayName,
Describe = () => descriptor,
ActivateAsync = async context =>
{
return await ActivateActivityAsync(context, activityType);
},
CanExecuteAsync = async context =>
{
var instance = await ActivateActivityAsync(context, activityType);
return await instance.CanExecuteAsync(context);
},
ExecuteAsync = async context =>
{
var instance = await ActivateActivityAsync(context, activityType);
return await instance.ExecuteAsync(context);
},
ResumeAsync = async context =>
{
var instance = await ActivateActivityAsync(context, activityType);
return await instance.ResumeAsync(context);
}
};
}

private async Task ActivateActivityAsync(ActivityExecutionContext context, Type type)
{
var activity = (IDictionaryActivity)ActivatorUtilities.GetServiceOrCreateInstance(context.ServiceProvider, type);
activity.Data = context.GetData();
activity.Id = context.ActivityId;

await SetActivityPropertiesAsync(activity, context);

return activity;
}

private async ValueTask SetActivityPropertiesAsync(IDictionaryActivity activity, ActivityExecutionContext activityExecutionContext)
{
var providers = activityExecutionContext.WorkflowExecutionContext.WorkflowBlueprint.ActivityPropertyProviders.GetProviders(activity.Id);

if (providers == null)
return;

foreach (var provider in providers)
{
try
{
var value = await provider.Value.GetValueAsync(activityExecutionContext, activityExecutionContext.CancellationToken);
activity.Properties[provider.Key] = value;
}
catch (Exception e)
{
throw new CannotSetActivityPropertyValueException($@"An exception was thrown whilst setting '{activity?.GetType().Name}.{provider.Key}'. See the inner exception for further details.", e);
}
}
}
}
}

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.