Add icons and reorganize activity categories

This commit is contained in:
Sipke Schoorstra 2023-01-03 20:28:57 +01:00
parent cbbac57e6f
commit ebf693b33b
23 changed files with 136 additions and 10 deletions

View file

@ -0,0 +1,9 @@
import {FunctionalComponent, h} from '@stencil/core';
import {ActivityIconSettings, getActivityIconCssClass} from "./models";
export const BreakIcon: FunctionalComponent<ActivityIconSettings> = (settings) => (
<svg class={getActivityIconCssClass(settings)} width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z"/>
<path d="M9 11l-4 4l4 4m-4 -4h11a4 4 0 0 0 0 -8h-1"/>
</svg>
);

View file

@ -0,0 +1,8 @@
import {FunctionalComponent, h} from '@stencil/core';
import {ActivityIconSettings, getActivityIconCssClass} from "./models";
export const CompleteIcon: FunctionalComponent<ActivityIconSettings> = (settings) => (
<svg class={getActivityIconCssClass(settings)} width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z"/> <circle cx="12" cy="12" r="9" /> <path d="M9 12l2 2l4 -4" />
</svg>
);

View file

@ -0,0 +1,8 @@
import {FunctionalComponent, h} from '@stencil/core';
import {ActivityIconSettings, getActivityIconCssClass} from "./models";
export const FaultIcon: FunctionalComponent<ActivityIconSettings> = (settings) => (
<svg class={getActivityIconCssClass(settings)} width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
);

View file

@ -0,0 +1,8 @@
import {FunctionalComponent, h} from '@stencil/core';
import {ActivityIconSettings, getActivityIconCssClass} from "./models";
export const FinishIcon: FunctionalComponent<ActivityIconSettings> = (settings) => (
<svg class={getActivityIconCssClass(settings)} width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"/>
</svg>
);

View file

@ -0,0 +1,11 @@
import {FunctionalComponent, h} from '@stencil/core';
import {ActivityIconSettings, getActivityIconCssClass} from "./models";
export const ForIcon: FunctionalComponent<ActivityIconSettings> = (settings) => (
<svg class={getActivityIconCssClass(settings)} width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z"/>
<path d="M4 12v-3a3 3 0 0 1 3 -3h13m-3 -3l3 3l-3 3"/>
<path d="M20 12v3a3 3 0 0 1 -3 3h-13m3 3l-3-3l3-3"/>
<path d="M11 11l1 -1v4"/>
</svg>
);

View file

@ -0,0 +1,13 @@
import {FunctionalComponent, h} from '@stencil/core';
import {ActivityIconSettings, getActivityIconCssClass} from "./models";
export const ForkIcon: FunctionalComponent<ActivityIconSettings> = (settings) => (
<svg class={getActivityIconCssClass(settings)} width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z"/>
<circle cx="12" cy="18" r="2"/>
<circle cx="7" cy="6" r="2"/>
<circle cx="17" cy="6" r="2"/>
<path d="M7 8v2a2 2 0 0 0 2 2h6a2 2 0 0 0 2 -2v-2"/>
<line x1="12" y1="12" x2="12" y2="16"/>
</svg>
);

View file

@ -0,0 +1,8 @@
import {FunctionalComponent, h} from '@stencil/core';
import {ActivityIconSettings, getActivityIconCssClass} from "./models";
export const SetNameIcon: FunctionalComponent<ActivityIconSettings> = (settings) => (
<svg class={getActivityIconCssClass(settings)} width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z"/> <line x1="11" y1="5" x2="17" y2="5" /> <line x1="7" y1="19" x2="13" y2="19" /> <line x1="14" y1="5" x2="10" y2="19" />
</svg>
);

View file

@ -0,0 +1,8 @@
import {FunctionalComponent, h} from '@stencil/core';
import {ActivityIconSettings, getActivityIconCssClass} from "./models";
export const SetVariableIcon: FunctionalComponent<ActivityIconSettings> = (settings) => (
<svg class={getActivityIconCssClass(settings)} width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z"/> <path d="M4 20h4l10.5 -10.5a1.5 1.5 0 0 0 -4 -4l-10.5 10.5v4" /> <line x1="13.5" y1="6.5" x2="17.5" y2="10.5" />
</svg>
);

View file

@ -0,0 +1,8 @@
import {FunctionalComponent, h} from '@stencil/core';
import {ActivityIconSettings, getActivityIconCssClass} from "./models";
export const StartIcon: FunctionalComponent<ActivityIconSettings> = (settings) => (
<svg class={getActivityIconCssClass(settings)} width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="10" />
</svg>
);

View file

@ -0,0 +1,14 @@
import {FunctionalComponent, h} from '@stencil/core';
import {ActivityIconSettings, getActivityIconCssClass} from "./models";
export const StartAtIcon: FunctionalComponent<ActivityIconSettings> = (settings) => (
<svg class={getActivityIconCssClass(settings)} width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z"/>
<rect x="4" y="5" width="16" height="16" rx="2"/>
<line x1="16" y1="3" x2="16" y2="7"/>
<line x1="8" y1="3" x2="8" y2="7"/>
<line x1="4" y1="11" x2="20" y2="11"/>
<line x1="11" y1="15" x2="12" y2="15"/>
<line x1="12" y1="15" x2="12" y2="18"/>
</svg>
);

View file

@ -0,0 +1,8 @@
import {FunctionalComponent, h} from '@stencil/core';
import {ActivityIconSettings, getActivityIconCssClass} from "./models";
export const WhileIcon: FunctionalComponent<ActivityIconSettings> = (settings) => (
<svg class={getActivityIconCssClass(settings)} width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z"/> <path d="M4 12v-3a3 3 0 0 1 3 -3h13m-3 -3l3 3l-3 3" /> <path d="M20 12v3a3 3 0 0 1 -3 3h-13m3 3l-3-3l3-3" />
</svg>
);

View file

@ -80,7 +80,7 @@ export class DefaultActivityTemplate {
{this.renderIcon(icon)}
</div>
<div class="flex items-center">
<div class="m-3">
<div class={displayTypeIsPicker ? `m-2` : 'm-3'}>
<span class={`${textColor}`}>{displayText}</span>
<div>
{this.renderPorts(activity, embeddedPorts)}

View file

@ -52,7 +52,7 @@ export class ToolboxActivities {
buildModel = (): any => {
const browsableDescriptors = descriptorsStore.activityDescriptors.filter(x => x.isBrowsable);
const categorizedActivitiesLookup = groupBy(browsableDescriptors, x => x.category);
const categories = Object.keys(categorizedActivitiesLookup);
const categories = Object.keys(categorizedActivitiesLookup).sort((a, b) => a.localeCompare(b));
const renderedActivities: Map<string, string> = new Map<string, string>();
// Group activities by category

View file

@ -14,6 +14,16 @@ import {
HttpEndpointIcon, HttpResponseIcon, HttpRequestIcon,
CorrelateIcon
} from "../components/icons/activities";
import {ForIcon} from "../components/icons/activities/for";
import {FinishIcon} from "../components/icons/activities/finish";
import {FaultIcon} from "../components/icons/activities/fault";
import {SetNameIcon} from "../components/icons/activities/set-name";
import {SetVariableIcon} from "../components/icons/activities/set-variable";
import {StartIcon} from "../components/icons/activities/start";
import {StartAtIcon} from "../components/icons/activities/startat";
import {BreakIcon} from "../components/icons/activities/break";
import {ForkIcon} from "../components/icons/activities/fork";
import {CompleteIcon} from "../components/icons/activities/complete";
export type ActivityType = string;
export type ActivityIconProducer = (ActivityIconSettings?) => any;
@ -24,16 +34,20 @@ export class ActivityIconRegistry {
private iconMap: Map<ActivityType, ActivityIconProducer> = new Map<ActivityType, ActivityIconProducer>();
constructor() {
this.add('Elsa.WriteLine', settings => <WriteLineIcon size={settings?.size}/>);
this.add('Elsa.WriteLine', settings => <WriteLineIcon size={settings?.size}/>);
this.add('Elsa.ReadLine', settings => <ReadLineIcon size={settings?.size}/>);
this.add('Elsa.If', settings => <IfIcon size={settings?.size}/>);
this.add('Elsa.Flowchart', settings => <FlowchartIcon size={settings?.size}/>);
this.add('Elsa.Fork', settings => <ForkIcon size={settings?.size}/>);
this.add('Elsa.HttpEndpoint', settings => <HttpEndpointIcon size={settings?.size}/>);
this.add('Elsa.WriteHttpResponse', settings => <HttpResponseIcon size={settings?.size}/>);
this.add('Elsa.ForEach', settings => <ForEachIcon size={settings?.size}/>);
this.add('Elsa.For', settings => <ForIcon size={settings?.size}/>);
this.add('Elsa.While', settings => <ForIcon size={settings?.size}/>);
this.add('Elsa.Break', settings => <BreakIcon size={settings?.size}/>);
this.add('Elsa.Delay', settings => <DelayIcon size={settings?.size}/>);
this.add('Elsa.Timer', settings => <TimerIcon size={settings?.size}/>);
this.add('Elsa.StartAt', settings => <StartAtIcon size={settings?.size}/>);
this.add('Elsa.FlowDecision', settings => <FlowDecisionIcon size={settings?.size}/>);
this.add('Elsa.Event', settings => <EventIcon size={settings?.size}/>);
this.add('Elsa.RunJavaScript', settings => <RunJavaScriptIcon size={settings?.size}/>);
@ -41,6 +55,12 @@ export class ActivityIconRegistry {
this.add('Elsa.FlowNode', settings => <FlowNodeIcon size={settings?.size}/>);
this.add('Elsa.SendHttpRequest', settings => <HttpRequestIcon size={settings?.size}/>);
this.add("Elsa.Correlate", settings => <CorrelateIcon size={settings?.size}/>)
this.add("Elsa.Start", settings => <StartIcon size={settings?.size}/>)
this.add("Elsa.Finish", settings => <FinishIcon size={settings?.size}/>)
this.add('Elsa.Fault', settings => <FaultIcon size={settings?.size}/>);
this.add('Elsa.Complete', settings => <CompleteIcon size={settings?.size}/>);
this.add('Elsa.SetName', settings => <SetNameIcon size={settings?.size}/>);
this.add('Elsa.SetVariable', settings => <SetVariableIcon size={settings?.size}/>);
}
public add(activityType: ActivityType, icon: ActivityIconProducer) {

View file

@ -8,7 +8,7 @@ namespace Elsa.Workflows.Core.Activities;
/// <summary>
/// Mark the workflow as finished.
/// </summary>
[Activity("Elsa", "Control Flow", "Mark the workflow as finished.")]
[Activity("Elsa", "Primitives", "Mark the workflow as finished.")]
public class Finish : ActivityBase
{
/// <inheritdoc />

View file

@ -12,7 +12,7 @@ namespace Elsa.Workflows.Core.Activities;
/// <summary>
/// Iterate over a sequence of steps between a start and an end number.
/// </summary>
[Activity("Elsa", "Control Flow", "Iterate over a sequence of steps between a start and an end number.")]
[Activity("Elsa", "Primitives", "Iterate over a sequence of steps between a start and an end number.")]
public class For : ActivityBase
{
private const string CurrentStepProperty = "CurrentStep";

View file

@ -12,7 +12,7 @@ namespace Elsa.Workflows.Core.Activities;
/// <summary>
/// Iterate over a set of values.
/// </summary>
[Activity("Elsa", "Control Flow", "Iterate over a set of values.")]
[Activity("Elsa", "Primitives", "Iterate over a set of values.")]
public class ForEach : ActivityBase
{
private const string CurrentIndexProperty = "CurrentIndex";

View file

@ -1,3 +1,4 @@
using System.ComponentModel;
using System.Runtime.CompilerServices;
using Elsa.Expressions.Models;
using Elsa.Workflows.Core.Attributes;
@ -8,6 +9,7 @@ namespace Elsa.Workflows.Core.Activities;
/// <summary>
/// Represents an inline code activity that can be used to execute arbitrary .NET code from a workflow.
/// </summary>
[Browsable(false)]
[Activity("Elsa", "Primitives", "Evaluate a Boolean condition to determine which path to execute next.")]
public class Inline : Activity
{

View file

@ -8,7 +8,7 @@ namespace Elsa.Workflows.Core.Activities;
/// This activity is instantiated in case a workflow references an activity type that could not be found.
/// </summary>
[Browsable(false)]
[Activity("Elsa", "Workflows", "A placeholder activity that will be used in case a workflow definition references an activity type that cannot be found.")]
[Activity("Elsa", "System", "A placeholder activity that will be used in case a workflow definition references an activity type that cannot be found.")]
public class NotFoundActivity : Activity
{
/// <inheritdoc />

View file

@ -11,7 +11,7 @@ namespace Elsa.Workflows.Core.Activities;
/// Schedule an activity for each item in parallel.
/// </summary>
/// <typeparam name="T"></typeparam>
[Activity("Elsa", "Control Flow", "Schedule an activity for each item in parallel.")]
[Activity("Elsa", "Primitives", "Schedule an activity for each item in parallel.")]
public class ParallelForEach<T> : Activity
{
private const string CollectedCountProperty = nameof(CollectedCountProperty);

View file

@ -13,6 +13,7 @@ namespace Elsa.Workflows.Core.Activities;
/// Execute a set of activities in sequence.
/// </summary>
[Category("Workflows")]
[Browsable(false)]
[Activity("Elsa", "Workflows", "Execute a set of activities in sequence.")]
public class Sequence : Container
{

View file

@ -8,7 +8,7 @@ namespace Elsa.Workflows.Core.Activities;
/// <summary>
/// Sets a property on the workflow execution context with the specified name value.
/// </summary>
[Activity("Elsa", "Workflows", "Set the name of the workflow instance to a specified value.")]
[Activity("Elsa", "Primitives", "Set the name of the workflow instance to a specified value.")]
public class SetName : Activity
{
/// <summary>

View file

@ -8,7 +8,7 @@ namespace Elsa.Workflows.Core.Activities;
/// <summary>
/// Mark the workflow as finished.
/// </summary>
[Activity("Elsa", "Control Flow", "A milestone activity with no behavior other than marking a milestone.", Kind = ActivityKind.Action)]
[Activity("Elsa", "Primitives", "A milestone activity with no behavior other than marking a milestone.", Kind = ActivityKind.Action)]
public class Start : Activity
{
/// <inheritdoc />