diff --git a/src/dashboard/Elsa.Dashboard/Areas/Elsa/Views/Shared/_Layout.cshtml b/src/dashboard/Elsa.Dashboard/Areas/Elsa/Views/Shared/_Layout.cshtml
index a646004be..7486f6474 100644
--- a/src/dashboard/Elsa.Dashboard/Areas/Elsa/Views/Shared/_Layout.cshtml
+++ b/src/dashboard/Elsa.Dashboard/Areas/Elsa/Views/Shared/_Layout.cshtml
@@ -32,7 +32,7 @@
-
+
@await RenderSectionAsync("HeadScripts", false)
diff --git a/src/dashboard/Elsa.Dashboard/Areas/Elsa/Views/_ViewImports.cshtml b/src/dashboard/Elsa.Dashboard/Areas/Elsa/Views/_ViewImports.cshtml
index 6d892d13c..da7508a62 100644
--- a/src/dashboard/Elsa.Dashboard/Areas/Elsa/Views/_ViewImports.cshtml
+++ b/src/dashboard/Elsa.Dashboard/Areas/Elsa/Views/_ViewImports.cshtml
@@ -2,3 +2,4 @@
@using Elsa.Dashboard.Areas.Elsa.ViewModels
@addTagHelper *, GravatarHelper.AspNetCore
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
+@addTagHelper *, Elsa.WorkflowDesigner
diff --git a/src/dashboard/Elsa.Dashboard/Elsa.Dashboard.csproj b/src/dashboard/Elsa.Dashboard/Elsa.Dashboard.csproj
index 1ecf6b207..d11fe57cc 100644
--- a/src/dashboard/Elsa.Dashboard/Elsa.Dashboard.csproj
+++ b/src/dashboard/Elsa.Dashboard/Elsa.Dashboard.csproj
@@ -19,6 +19,7 @@
+
@@ -26,20 +27,17 @@
-
-
+
+
+
-
- ..\..\..\..\..\..\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.extensions.fileproviders.physical\2.2.0\lib\netstandard2.0\Microsoft.Extensions.FileProviders.Physical.dll
-
-
-
-
- <_ContentIncludedByDefault Remove="wwwroot\assets\css\argon-dashboard.css" />
- <_ContentIncludedByDefault Remove="wwwroot\assets\css\argon-dashboard.css.map" />
- <_ContentIncludedByDefault Remove="wwwroot\assets\css\argon-dashboard.min.css" />
+ <_ContentIncludedByDefault Remove="wwwroot\assets\css\argon-dashboard.css" />
+ <_ContentIncludedByDefault Remove="wwwroot\assets\css\argon-dashboard.css.map" />
+ <_ContentIncludedByDefault Remove="wwwroot\assets\css\argon-dashboard.min.css" />
+ <_ContentIncludedByDefault Remove="Views\Shared\Components\WorkflowDesigner\Default.cshtml" />
+ <_ContentIncludedByDefault Remove="Views\_ViewImports.cshtml" />
diff --git a/src/dashboard/Elsa.Dashboard/Extensions/ActivityDefinitionListExtensions.cs b/src/dashboard/Elsa.Dashboard/Extensions/ActivityDefinitionListExtensions.cs
new file mode 100644
index 000000000..98ba4ae3b
--- /dev/null
+++ b/src/dashboard/Elsa.Dashboard/Extensions/ActivityDefinitionListExtensions.cs
@@ -0,0 +1,33 @@
+using System;
+using Elsa.Dashboard.Options;
+using Elsa.Services.Models;
+using Elsa.WorkflowDesigner;
+using Microsoft.Extensions.DependencyInjection;
+using Scrutor;
+
+namespace Elsa.Dashboard.Extensions
+{
+ public static class ActivityDefinitionListExtensions
+ {
+ public static ActivityDefinitionList Add
(this ActivityDefinitionList list) where T : IActivity
+ {
+ return list.Add(ActivityDescriber.Describe());
+ }
+
+ public static ActivityDefinitionList Discover(this ActivityDefinitionList list, Action selector)
+ {
+ var typeSourceSelector = new TypeSourceSelector();
+ selector(typeSourceSelector);
+
+ var serviceCollection = new ServiceCollection();
+ typeSourceSelector.Populate(serviceCollection, RegistrationStrategy.Replace(ReplacementBehavior.All));
+
+ foreach (var service in serviceCollection)
+ {
+ list.Add(ActivityDescriber.Describe(service.ImplementationType));
+ }
+
+ return list;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/dashboard/Elsa.Dashboard/Options/ActivityDefinitionList.cs b/src/dashboard/Elsa.Dashboard/Options/ActivityDefinitionList.cs
new file mode 100644
index 000000000..c9bcaf944
--- /dev/null
+++ b/src/dashboard/Elsa.Dashboard/Options/ActivityDefinitionList.cs
@@ -0,0 +1,29 @@
+using System.Collections;
+using System.Collections.Generic;
+using Elsa.WorkflowDesigner.Models;
+
+namespace Elsa.Dashboard.Options
+{
+ public class ActivityDefinitionList : IEnumerable
+ {
+ public ActivityDefinitionList()
+ {
+ Items = new Dictionary();
+ }
+
+ private IDictionary Items { get; }
+
+ public ActivityDefinitionList Add(ActivityDefinition item)
+ {
+ Items[item.Type] = item;
+ return this;
+ }
+
+ public IEnumerator GetEnumerator() => Items.Values.GetEnumerator();
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/dashboard/Elsa.Dashboard/Options/ElsaDashboardOptions.cs b/src/dashboard/Elsa.Dashboard/Options/ElsaDashboardOptions.cs
index 1d49d1b6b..9da2ca879 100644
--- a/src/dashboard/Elsa.Dashboard/Options/ElsaDashboardOptions.cs
+++ b/src/dashboard/Elsa.Dashboard/Options/ElsaDashboardOptions.cs
@@ -4,6 +4,13 @@ namespace Elsa.Dashboard.Options
{
public class ElsaDashboardOptions
{
+ public ElsaDashboardOptions()
+ {
+ Scripts = new List();
+ ActivityDefinitions = new ActivityDefinitionList();
+ }
+
public IList Scripts { get; set; }
+ public ActivityDefinitionList ActivityDefinitions { get; set; }
}
}
\ No newline at end of file
diff --git a/src/dashboard/Elsa.Dashboard/Theme/argon-dashboard/assets/img/brand/blue.png b/src/dashboard/Elsa.Dashboard/Theme/argon-dashboard/assets/img/brand/blue.png
deleted file mode 100644
index 88f515f1d..000000000
Binary files a/src/dashboard/Elsa.Dashboard/Theme/argon-dashboard/assets/img/brand/blue.png and /dev/null differ
diff --git a/src/dashboard/Elsa.Dashboard/Theme/argon-dashboard/assets/img/brand/favicon-16x16.png b/src/dashboard/Elsa.Dashboard/Theme/argon-dashboard/assets/img/brand/favicon-16x16.png
new file mode 100644
index 000000000..8d6de2988
Binary files /dev/null and b/src/dashboard/Elsa.Dashboard/Theme/argon-dashboard/assets/img/brand/favicon-16x16.png differ
diff --git a/src/dashboard/Elsa.Dashboard/Theme/argon-dashboard/assets/img/brand/favicon.ico b/src/dashboard/Elsa.Dashboard/Theme/argon-dashboard/assets/img/brand/favicon.ico
new file mode 100644
index 000000000..ce861ecff
Binary files /dev/null and b/src/dashboard/Elsa.Dashboard/Theme/argon-dashboard/assets/img/brand/favicon.ico differ
diff --git a/src/dashboard/Elsa.Dashboard/Theme/argon-dashboard/assets/img/brand/favicon.png b/src/dashboard/Elsa.Dashboard/Theme/argon-dashboard/assets/img/brand/favicon.png
index 53997a067..dfa8b3a2c 100644
Binary files a/src/dashboard/Elsa.Dashboard/Theme/argon-dashboard/assets/img/brand/favicon.png and b/src/dashboard/Elsa.Dashboard/Theme/argon-dashboard/assets/img/brand/favicon.png differ
diff --git a/src/dashboard/Elsa.Dashboard/Theme/argon-dashboard/assets/img/brand/white.png b/src/dashboard/Elsa.Dashboard/Theme/argon-dashboard/assets/img/brand/white.png
deleted file mode 100644
index df2708f39..000000000
Binary files a/src/dashboard/Elsa.Dashboard/Theme/argon-dashboard/assets/img/brand/white.png and /dev/null differ
diff --git a/src/dashboard/Elsa.WorkflowDesigner/ActivityDescriber.cs b/src/dashboard/Elsa.WorkflowDesigner/ActivityDescriber.cs
new file mode 100644
index 000000000..c88cfa153
--- /dev/null
+++ b/src/dashboard/Elsa.WorkflowDesigner/ActivityDescriber.cs
@@ -0,0 +1,97 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using Elsa.Attributes;
+using Elsa.Expressions;
+using Elsa.Services.Models;
+using Elsa.WorkflowDesigner.Models;
+using Humanizer;
+
+namespace Elsa.WorkflowDesigner
+{
+ public static class ActivityDescriber
+ {
+ public static ActivityDefinition Describe() where T : IActivity
+ {
+ return Describe(typeof(T));
+ }
+
+ public static ActivityDefinition Describe(Type activityType)
+ {
+ var activityDefinitionAttribute = activityType.GetCustomAttribute();
+ var activityDesignerAttribute = activityType.GetCustomAttribute();
+ var typeName = activityDefinitionAttribute?.Type ?? activityType.Name;
+
+ var displayName =
+ activityDefinitionAttribute?.DisplayName ??
+ activityType.Name.Humanize(LetterCasing.Title);
+
+ var description = activityDefinitionAttribute?.Description;
+ var category = activityDefinitionAttribute?.Category ?? "Miscellaneous";
+ var designerDescription = activityDesignerAttribute?.Description;
+ var designerOutcomes = activityDesignerAttribute?.Outcomes ?? new[] { OutcomeNames.Done };
+ var properties = DescribeProperties(activityType);
+
+ return new ActivityDefinition
+ {
+ Type = typeName.Camelize(),
+ DisplayName = displayName,
+ Description = description,
+ Category = category,
+ Properties = properties.ToArray(),
+ Designer = new ActivityDesignerSettings
+ {
+ Description = designerDescription,
+ Outcomes = designerOutcomes
+ }
+ };
+ }
+
+ private static IEnumerable DescribeProperties(Type activityType)
+ {
+ var properties = activityType.GetProperties();
+
+ foreach (var propertyInfo in properties)
+ {
+ var activityProperty = propertyInfo.GetCustomAttribute();
+
+ if (activityProperty == null)
+ yield break;
+
+ yield return new ActivityPropertyDescriptor
+ {
+ Name = (activityProperty.Name ?? propertyInfo.Name).Camelize(),
+ Label = activityProperty.Label ?? propertyInfo.Name.Humanize(LetterCasing.Title),
+ Type = (activityProperty.Type ?? DeterminePropertyType(propertyInfo)).Camelize(),
+ Hint = activityProperty.Hint,
+ Options = GetPropertyTypeOptions(propertyInfo)
+ };
+ }
+ }
+
+ private static object GetPropertyTypeOptions(PropertyInfo propertyInfo)
+ {
+ var optionsAttribute = propertyInfo.GetCustomAttribute();
+
+ return optionsAttribute?.GetOptions() ?? new object();
+ }
+
+ private static string DeterminePropertyType(PropertyInfo propertyInfo)
+ {
+ var type = propertyInfo.PropertyType;
+
+ if (typeof(IWorkflowExpression).IsAssignableFrom(type))
+ return ActivityPropertyTypes.Expression;
+
+ if (type == typeof(bool) || type == typeof(bool?))
+ return ActivityPropertyTypes.Boolean;
+
+ if (typeof(IEnumerable).IsAssignableFrom(type))
+ return ActivityPropertyTypes.List;
+
+ return ActivityPropertyTypes.Text;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/dashboard/Elsa.WorkflowDesigner/Elsa.WorkflowDesigner.csproj b/src/dashboard/Elsa.WorkflowDesigner/Elsa.WorkflowDesigner.csproj
new file mode 100644
index 000000000..2f155cdba
--- /dev/null
+++ b/src/dashboard/Elsa.WorkflowDesigner/Elsa.WorkflowDesigner.csproj
@@ -0,0 +1,25 @@
+
+
+
+ netstandard2.0
+ latest
+ 1.0.0
+ Sipke Schoorstra
+ Elsa is a set of workflowing libraries and tools to enable super-fast workflowing capabilities in any .NET Core application.
+ 2019
+ https://github.com/elsa-workflows/elsa-core
+ https://github.com/elsa-workflows/elsa-core
+ GitHub
+ elsa, workflows
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/dashboard/Elsa.WorkflowDesigner/Models/ActivityDefinition.cs b/src/dashboard/Elsa.WorkflowDesigner/Models/ActivityDefinition.cs
new file mode 100644
index 000000000..a50dd5e02
--- /dev/null
+++ b/src/dashboard/Elsa.WorkflowDesigner/Models/ActivityDefinition.cs
@@ -0,0 +1,17 @@
+namespace Elsa.WorkflowDesigner.Models
+{
+ public class ActivityDefinition
+ {
+ public ActivityDefinition()
+ {
+ Properties = new ActivityPropertyDescriptor[0];
+ }
+
+ public string Type { get; set; }
+ public string DisplayName { get; set; }
+ public string Description { get; set; }
+ public string Category { get; set; }
+ public ActivityPropertyDescriptor[] Properties { get; set; }
+ public ActivityDesignerSettings Designer { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/dashboard/Elsa.WorkflowDesigner/Models/ActivityDesignerSettings.cs b/src/dashboard/Elsa.WorkflowDesigner/Models/ActivityDesignerSettings.cs
new file mode 100644
index 000000000..09fe0a954
--- /dev/null
+++ b/src/dashboard/Elsa.WorkflowDesigner/Models/ActivityDesignerSettings.cs
@@ -0,0 +1,8 @@
+namespace Elsa.WorkflowDesigner.Models
+{
+ public class ActivityDesignerSettings
+ {
+ public object Description { get; set; }
+ public object Outcomes { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/dashboard/Elsa.WorkflowDesigner/Models/ActivityPropertyDescriptor.cs b/src/dashboard/Elsa.WorkflowDesigner/Models/ActivityPropertyDescriptor.cs
new file mode 100644
index 000000000..dbce67b82
--- /dev/null
+++ b/src/dashboard/Elsa.WorkflowDesigner/Models/ActivityPropertyDescriptor.cs
@@ -0,0 +1,11 @@
+namespace Elsa.WorkflowDesigner.Models
+{
+ public class ActivityPropertyDescriptor
+ {
+ public string Name { get; set; }
+ public string Type { get; set; }
+ public string Label { get; set; }
+ public string Hint { get; set; }
+ public object Options { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/dashboard/Elsa.WorkflowDesigner/Models/ActivityPropertyTypes.cs b/src/dashboard/Elsa.WorkflowDesigner/Models/ActivityPropertyTypes.cs
new file mode 100644
index 000000000..1c3a1058e
--- /dev/null
+++ b/src/dashboard/Elsa.WorkflowDesigner/Models/ActivityPropertyTypes.cs
@@ -0,0 +1,11 @@
+namespace Elsa.WorkflowDesigner.Models
+{
+ public static class ActivityPropertyTypes
+ {
+ public const string Text = "text";
+ public const string Boolean = "boolean";
+ public const string Expression = "expression";
+ public const string List = "list";
+ public const string Select = "select";
+ }
+}
\ No newline at end of file
diff --git a/src/dashboard/Elsa.WorkflowDesigner/Models/WorkflowExpressionOptions.cs b/src/dashboard/Elsa.WorkflowDesigner/Models/WorkflowExpressionOptions.cs
new file mode 100644
index 000000000..e541e6223
--- /dev/null
+++ b/src/dashboard/Elsa.WorkflowDesigner/Models/WorkflowExpressionOptions.cs
@@ -0,0 +1,7 @@
+namespace Elsa.WorkflowDesigner.Models
+{
+ public class WorkflowExpressionOptions
+ {
+ public bool Multiline { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/dashboard/Elsa.WorkflowDesigner/ViewComponents/WorkflowDesignerViewComponent.cs b/src/dashboard/Elsa.WorkflowDesigner/ViewComponents/WorkflowDesignerViewComponent.cs
new file mode 100644
index 000000000..c2f4b67ac
--- /dev/null
+++ b/src/dashboard/Elsa.WorkflowDesigner/ViewComponents/WorkflowDesignerViewComponent.cs
@@ -0,0 +1,32 @@
+using Elsa.WorkflowDesigner.Models;
+using Elsa.WorkflowDesigner.ViewModels;
+using Microsoft.AspNetCore.Mvc;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Serialization;
+
+namespace Elsa.WorkflowDesigner.ViewComponents
+{
+ public class WorkflowDesignerViewComponent : ViewComponent
+ {
+ public IViewComponentResult Invoke(ActivityDefinition[] activityDefinitions)
+ {
+ var model = new WorkflowDesignerViewComponentModel
+ {
+ ActivityDefinitionsJson = GetActivityDefinitionOptions(activityDefinitions)
+ };
+
+ return View(model);
+ }
+
+ private string GetActivityDefinitionOptions(ActivityDefinition[] activityDefinitions)
+ {
+ var definitions = activityDefinitions ?? new ActivityDefinition[0];
+ var settings = new JsonSerializerSettings
+ {
+ ContractResolver = new CamelCasePropertyNamesContractResolver(),
+ NullValueHandling = NullValueHandling.Ignore
+ };
+ return JsonConvert.SerializeObject(definitions, settings);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/dashboard/Elsa.WorkflowDesigner/ViewModels/WorkflowDesignerViewComponentModel.cs b/src/dashboard/Elsa.WorkflowDesigner/ViewModels/WorkflowDesignerViewComponentModel.cs
new file mode 100644
index 000000000..d44b897f4
--- /dev/null
+++ b/src/dashboard/Elsa.WorkflowDesigner/ViewModels/WorkflowDesignerViewComponentModel.cs
@@ -0,0 +1,7 @@
+namespace Elsa.WorkflowDesigner.ViewModels
+{
+ public class WorkflowDesignerViewComponentModel
+ {
+ public string ActivityDefinitionsJson { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/dashboard/Elsa.WorkflowDesigner/Views/Shared/Components/WorkflowDesigner/Default.cshtml b/src/dashboard/Elsa.WorkflowDesigner/Views/Shared/Components/WorkflowDesigner/Default.cshtml
new file mode 100644
index 000000000..0136beb44
--- /dev/null
+++ b/src/dashboard/Elsa.WorkflowDesigner/Views/Shared/Components/WorkflowDesigner/Default.cshtml
@@ -0,0 +1,3 @@
+@model Elsa.WorkflowDesigner.ViewModels.WorkflowDesignerViewComponentModel
+
+
\ No newline at end of file
diff --git a/src/dashboard/Elsa.WorkflowDesigner/Views/_ViewImports.cshtml b/src/dashboard/Elsa.WorkflowDesigner/Views/_ViewImports.cshtml
new file mode 100644
index 000000000..b66377318
--- /dev/null
+++ b/src/dashboard/Elsa.WorkflowDesigner/Views/_ViewImports.cshtml
@@ -0,0 +1,2 @@
+@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
+@addTagHelper *, Elsa.Dashboard