- {options.map((option, index) => {
+ {items.map((item, index) => {
const inputId = `${fieldId}_${index}`;
- const optionIsString = typeof(option) == 'string';
- const value = optionIsString ? option : option.value;
- const text = optionIsString ? option : option.text;
+ const optionIsString = typeof(item) == 'string';
+ const value = optionIsString ? item : item.value;
+ const text = optionIsString ? item : item.text;
const isSelected = values.findIndex(x => x == value) >= 0;
return (
@@ -74,3 +84,5 @@ export class ElsaCheckListProperty {
);
}
}
+
+Tunnel.injectProps(ElsaCheckListProperty, ['serverUrl']);
\ No newline at end of file
diff --git a/src/designer/elsa-workflows-studio/src/components/editors/properties/elsa-dropdown-property/elsa-dropdown-property.tsx b/src/designer/elsa-workflows-studio/src/components/editors/properties/elsa-dropdown-property/elsa-dropdown-property.tsx
index dc5ffcd12..483b4b9a1 100644
--- a/src/designer/elsa-workflows-studio/src/components/editors/properties/elsa-dropdown-property/elsa-dropdown-property.tsx
+++ b/src/designer/elsa-workflows-studio/src/components/editors/properties/elsa-dropdown-property/elsa-dropdown-property.tsx
@@ -2,6 +2,7 @@ import {Component, h, Prop, State} from '@stencil/core';
import {ActivityDefinitionProperty, ActivityPropertyDescriptor, RuntimeSelectListItemsProviderSettings, SelectListItem, SyntaxNames} from "../../../../models";
import Tunnel from "../../../../data/workflow-editor";
import {createElsaClient} from "../../../../services/elsa-client";
+import {getSelectListItems} from "../../../../utils/select-list-items";
@Component({
tag: 'elsa-dropdown-property',
@@ -33,22 +34,7 @@ export class ElsaDropdownProperty {
}
async componentWillRender(){
- const propertyDescriptor = this.propertyDescriptor;
- const options = propertyDescriptor.options;
- let items = [];
-
- if (!!options.runtimeSelectListItemsProviderType) {
- items = await this.fetchRuntimeItems(options);
- } else {
- items = options as Array
|| [];
- }
-
- this.items = items;
- }
-
- async fetchRuntimeItems(options: RuntimeSelectListItemsProviderSettings): Promise>{
- const elsaClient = createElsaClient(this.serverUrl);
- return await elsaClient.designerApi.runtimeSelectItemsApi.get(options.runtimeSelectListItemsProviderType, options.context || {});
+ this.items = await getSelectListItems(this.serverUrl, this.propertyDescriptor);
}
render() {
diff --git a/src/designer/elsa-workflows-studio/src/components/editors/properties/elsa-multi-text-property/elsa-multi-text-property.tsx b/src/designer/elsa-workflows-studio/src/components/editors/properties/elsa-multi-text-property/elsa-multi-text-property.tsx
index 93797514a..564f11c54 100644
--- a/src/designer/elsa-workflows-studio/src/components/editors/properties/elsa-multi-text-property/elsa-multi-text-property.tsx
+++ b/src/designer/elsa-workflows-studio/src/components/editors/properties/elsa-multi-text-property/elsa-multi-text-property.tsx
@@ -1,6 +1,8 @@
import {Component, h, Prop, State} from '@stencil/core';
-import {ActivityDefinitionProperty, ActivityPropertyDescriptor, SyntaxNames, MultiTextDefinition} from "../../../../models";
+import {ActivityDefinitionProperty, ActivityPropertyDescriptor, SyntaxNames, SelectListItem} from "../../../../models";
import {parseJson} from "../../../../utils/utils";
+import Tunnel from "../../../../data/workflow-editor";
+import {getSelectListItems} from "../../../../utils/select-list-items";
@Component({
tag: 'elsa-multi-text-property',
@@ -11,15 +13,20 @@ export class ElsaMultiTextProperty {
@Prop() propertyDescriptor: ActivityPropertyDescriptor;
@Prop() propertyModel: ActivityDefinitionProperty;
+ @Prop({mutable: true}) serverUrl: string;
@State() currentValue?: string;
+ items: any[];
+
async componentWillLoad() {
this.currentValue = this.propertyModel.expressions[SyntaxNames.Json] || '[]';
}
- onValueChanged(newValue: Array) {
+ onValueChanged(newValue: Array) {
const newValues = newValue.map(dropdown => {
if (typeof dropdown === 'string') return dropdown;
+ if (typeof dropdown === 'number') return dropdown.toString();
+ if (typeof dropdown === 'boolean') return dropdown.toString();
return dropdown.value;
})
@@ -32,13 +39,17 @@ export class ElsaMultiTextProperty {
this.currentValue = e.detail;
}
- createKeyValueOptions(options: Array) {
+ createKeyValueOptions(options: Array) {
if (options === null)
return options;
return options.map(option => typeof option === 'string' ? { text: option, value: option } : option);
}
+ async componentWillRender(){
+ this.items = await getSelectListItems(this.serverUrl, this.propertyDescriptor);
+ }
+
render() {
const propertyDescriptor = this.propertyDescriptor;
const propertyModel = this.propertyModel;
@@ -46,9 +57,9 @@ export class ElsaMultiTextProperty {
const fieldId = propertyName;
const fieldName = propertyName;
const values = parseJson(this.currentValue);
- propertyDescriptor.options = propertyDescriptor.options || null;
+ const items = this.items;
const valueType = propertyDescriptor.options !== null ? 'dropdown' : 'multi-text';
- const propertyOptions = this.createKeyValueOptions(propertyDescriptor.options);
+ const propertyOptions = this.createKeyValueOptions(items);
const elsaInputTags = valueType === 'multi-text' ?
this.onValueChanged(e.detail)} /> :
@@ -65,3 +76,5 @@ export class ElsaMultiTextProperty {
)
}
}
+
+Tunnel.injectProps(ElsaMultiTextProperty, ['serverUrl']);
diff --git a/src/designer/elsa-workflows-studio/src/models/domain.ts b/src/designer/elsa-workflows-studio/src/models/domain.ts
index a0d36f9eb..16a1ec370 100644
--- a/src/designer/elsa-workflows-studio/src/models/domain.ts
+++ b/src/designer/elsa-workflows-studio/src/models/domain.ts
@@ -168,11 +168,6 @@ export interface ConnectionDefinitionMapped {
outcome: string;
}
-export interface MultiTextDefinition {
- text: string;
- value: string;
-}
-
export interface ActivityDefinitionProperty {
name: string;
syntax?: string;
diff --git a/src/designer/elsa-workflows-studio/src/utils/select-list-items.ts b/src/designer/elsa-workflows-studio/src/utils/select-list-items.ts
new file mode 100644
index 000000000..3d87cd470
--- /dev/null
+++ b/src/designer/elsa-workflows-studio/src/utils/select-list-items.ts
@@ -0,0 +1,20 @@
+import {ActivityPropertyDescriptor, RuntimeSelectListItemsProviderSettings, SelectListItem} from "../models";
+import {createElsaClient, ElsaClient} from "../services/elsa-client";
+
+async function fetchRuntimeItems(serverUrl: string, options: RuntimeSelectListItemsProviderSettings): Promise> {
+ const elsaClient = createElsaClient(serverUrl);
+ return await elsaClient.designerApi.runtimeSelectItemsApi.get(options.runtimeSelectListItemsProviderType, options.context || {});
+}
+
+export async function getSelectListItems(serverUrl: string, propertyDescriptor: ActivityPropertyDescriptor): Promise> {
+ const options = propertyDescriptor.options;
+ let items = [];
+
+ if (!!options.runtimeSelectListItemsProviderType) {
+ items = await fetchRuntimeItems(serverUrl, options);
+ } else {
+ items = options as Array || [];
+ }
+
+ return items || [];
+}
\ No newline at end of file
diff --git a/src/samples/server/Elsa.Samples.Server.Host/Activities/VehicleActivity.cs b/src/samples/server/Elsa.Samples.Server.Host/Activities/VehicleActivity.cs
index a49d845cb..f401a0e42 100644
--- a/src/samples/server/Elsa.Samples.Server.Host/Activities/VehicleActivity.cs
+++ b/src/samples/server/Elsa.Samples.Server.Host/Activities/VehicleActivity.cs
@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading;
@@ -15,6 +16,13 @@ namespace Elsa.Samples.Server.Host.Activities
[Action]
public class VehicleActivity : Activity, IActivityPropertyOptionsProvider, IRuntimeSelectListItemsProvider
{
+ private Random _random;
+
+ public VehicleActivity()
+ {
+ _random = new Random();
+ }
+
[ActivityProperty(
UIHint = ActivityPropertyUIHints.Dropdown,
OptionsProvider = typeof(VehicleActivity),
@@ -23,15 +31,18 @@ namespace Elsa.Samples.Server.Host.Activities
)]
public string? Brand { get; set; }
- public object GetOptions(PropertyInfo property) => new RuntimeSelectListItemsProviderSettings(GetType());
+ public object GetOptions(PropertyInfo property) => new RuntimeSelectListItemsProviderSettings(GetType(), new VehicleContext(_random.Next(100)));
public ValueTask> GetItemsAsync(object? context, CancellationToken cancellationToken = default)
{
- var brands = new[] { "BMW", "Peugot", "Tesla" };
+ var vehicleContext = (VehicleContext) context!;
+ var brands = new[] { "BMW", "Peugot", "Tesla", vehicleContext.RandomNumber.ToString() };
var items = brands.Select(x => new SelectListItem(x)).ToList();
return new ValueTask>(items);
}
protected override IActivityExecutionResult OnExecute() => Done(Brand);
}
+
+ public record VehicleContext(int RandomNumber);
}
\ No newline at end of file
diff --git a/src/server/Elsa.Server.Api/Endpoints/Designer/RuntimeSelectListItems/Get.cs b/src/server/Elsa.Server.Api/Endpoints/Designer/RuntimeSelectListItems/Get.cs
index 9839b5dcb..a5de8651d 100644
--- a/src/server/Elsa.Server.Api/Endpoints/Designer/RuntimeSelectListItems/Get.cs
+++ b/src/server/Elsa.Server.Api/Endpoints/Designer/RuntimeSelectListItems/Get.cs
@@ -3,9 +3,11 @@ using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Elsa.Design;
+using Elsa.Serialization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
+using Newtonsoft.Json;
using Swashbuckle.AspNetCore.Annotations;
namespace Elsa.Server.Api.Endpoints.Designer.RuntimeSelectListItems
@@ -17,10 +19,12 @@ namespace Elsa.Server.Api.Endpoints.Designer.RuntimeSelectListItems
public class Get : Controller
{
private readonly IServiceProvider _serviceProvider;
+ private readonly IContentSerializer _contentSerializer;
- public Get(IServiceProvider serviceProvider)
+ public Get(IServiceProvider serviceProvider, IContentSerializer contentSerializer)
{
_serviceProvider = serviceProvider;
+ _contentSerializer = contentSerializer;
}
[HttpPost]
@@ -31,13 +35,23 @@ namespace Elsa.Server.Api.Endpoints.Designer.RuntimeSelectListItems
OperationId = "Designer.RuntimeSelectListItems.Get",
Tags = new[] { "Designer.RuntimeSelectListItems" })
]
- public async Task Handle(string providerTypeName, object? context = default, CancellationToken cancellationToken = default)
+ public async Task Handle([FromBody]RuntimeSelectListItemsContextHolder model, CancellationToken cancellationToken = default)
{
- var type = Type.GetType(providerTypeName)!;
- var provider = (IRuntimeSelectListItemsProvider)ActivatorUtilities.GetServiceOrCreateInstance(_serviceProvider, type);
+ var type = Type.GetType(model.ProviderTypeName)!;
+ var provider = (IRuntimeSelectListItemsProvider) ActivatorUtilities.GetServiceOrCreateInstance(_serviceProvider, type);
+ var context = model?.Context;
var items = (await provider.GetItemsAsync(context, cancellationToken)).ToList();
+ var serializerSettings = _contentSerializer.GetSettings();
- return Ok(items);
+ return Json(items, serializerSettings);
}
}
+
+ public record RuntimeSelectListItemsContextHolder
+ {
+ [FromRoute] public string ProviderTypeName { get; set; } = default!;
+
+ [JsonProperty(TypeNameHandling = TypeNameHandling.All)]
+ public object? Context { get; set; }
+ };
}
\ No newline at end of file