Add support for mixed-cased JSON keys
This commit is contained in:
parent
b9defca7bd
commit
b5e882efc0
|
|
@ -12,7 +12,9 @@ public static class DictionaryExtensions
|
|||
/// </summary>
|
||||
public static T? TryGetValue<T>(this IDictionary<string, object> dictionary, string key, Func<T>? defaultValue = default, JsonSerializerOptions? serializerOptions = default)
|
||||
{
|
||||
if (dictionary.TryGetValue(key, out var value) && value is not JsonElement { ValueKind: JsonValueKind.Undefined })
|
||||
var caseInsensitiveDictionary = new Dictionary<string, object>(dictionary, StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
if (caseInsensitiveDictionary.TryGetValue(key, out var value) && value is not JsonElement { ValueKind: JsonValueKind.Undefined })
|
||||
{
|
||||
var convertedValue = value.ConvertTo<T>(new ObjectConverterOptions(serializerOptions));
|
||||
|
||||
|
|
@ -33,7 +35,9 @@ public static class DictionaryExtensions
|
|||
/// </summary>
|
||||
public static object? TryGetValue(this IDictionary<string, object> dictionary, string key, Func<object>? defaultValue = default)
|
||||
{
|
||||
if (dictionary.TryGetValue(key, out var value) && value is not JsonElement { ValueKind: JsonValueKind.Undefined })
|
||||
var caseInsensitiveDictionary = new Dictionary<string, object>(dictionary, StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
if (caseInsensitiveDictionary.TryGetValue(key, out var value) && value is not JsonElement { ValueKind: JsonValueKind.Undefined })
|
||||
return value;
|
||||
|
||||
if (defaultValue == null)
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ export class DefaultActivityTemplate {
|
|||
const activity: Activity = nodeMap[activityId];
|
||||
const ports = portProvider.getOutboundPorts({activityDescriptor, activity});
|
||||
const embeddedPorts = ports.filter(x => x.type == PortType.Embedded && x.isBrowsable !== false);
|
||||
const canStartWorkflow = activity?.customProperties?.CanStartWorkflow ?? activity?.canStartWorkflow ?? false;
|
||||
const canStartWorkflow: boolean = activity?.customProperties?.canStartWorkflow ?? activity?.customProperties?.CanStartWorkflow ?? activity?.canStartWorkflow ?? false;
|
||||
const icon = this.icon;
|
||||
const hasIcon = !!icon;
|
||||
const textColor = canStartWorkflow ? 'tw-text-white' : 'tw-text-gray-700';
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@ export class ActivityPropertiesEditor {
|
|||
const activity: Activity = this.activity;
|
||||
const inputElement = e.target as HTMLInputElement;
|
||||
|
||||
activity.customProperties.CanStartWorkflow = inputElement.checked;
|
||||
activity.customProperties.canStartWorkflow = inputElement.checked;
|
||||
|
||||
this.updateActivity();
|
||||
}
|
||||
|
|
@ -299,7 +299,7 @@ export class ActivityPropertiesEditor {
|
|||
const {activity} = this.renderContext;
|
||||
const activityId = activity.id;
|
||||
const displayText: string = activity.metadata?.displayText ?? '';
|
||||
const canStartWorkflow: boolean = activity.customProperties?.CanStartWorkflow ?? activity.canStartWorkflow ?? false;
|
||||
const canStartWorkflow: boolean = activity.customProperties?.canStartWorkflow ?? activity?.customProperties?.CanStartWorkflow ?? activity.canStartWorkflow ?? false;
|
||||
const key = `${activityId}`;
|
||||
|
||||
return <div key={key}>
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@ namespace Elsa.Extensions;
|
|||
/// </summary>
|
||||
public static class ActivityPropertyExtensions
|
||||
{
|
||||
private const string CanStartWorkflowPropertyName = "CanStartWorkflow";
|
||||
private const string RunAsynchronouslyPropertyName = "RunAsynchronously";
|
||||
private const string SourcePropertyName = "Source";
|
||||
private static readonly string[] CanStartWorkflowPropertyName = {"canStartWorkflow", "CanStartWorkflow", };
|
||||
private static readonly string[] RunAsynchronouslyPropertyName = {"runAsynchronously", "RunAsynchronously" };
|
||||
private static readonly string[] SourcePropertyName = {"source", "Source"};
|
||||
|
||||
/// <summary>
|
||||
/// Gets a flag indicating whether this activity can be used for starting a workflow.
|
||||
|
|
@ -21,7 +21,7 @@ public static class ActivityPropertyExtensions
|
|||
/// <summary>
|
||||
/// Sets a flag indicating whether this activity can be used for starting a workflow.
|
||||
/// </summary>
|
||||
public static void SetCanStartWorkflow(this IActivity activity, bool value) => activity.CustomProperties[CanStartWorkflowPropertyName] = value;
|
||||
public static void SetCanStartWorkflow(this IActivity activity, bool value) => activity.CustomProperties[CanStartWorkflowPropertyName[0]] = value;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a flag indicating if this activity should execute synchronously or asynchronously.
|
||||
|
|
@ -35,7 +35,7 @@ public static class ActivityPropertyExtensions
|
|||
/// By default, activities with an <see cref="Workflows.Core.Models.ActivityKind"/> of <see cref="Workflows.Core.Models.ActivityKind.Action"/>, <see cref="Workflows.Core.Models.ActivityKind.Task"/> or <see cref="Workflows.Core.Models.ActivityKind.Trigger"/>
|
||||
/// will execute synchronously, while activities of the <see cref="Workflows.Core.Models.ActivityKind.Job"/> kind will execute asynchronously.
|
||||
/// </summary>
|
||||
public static void SetRunAsynchronously(this IActivity activity, bool value) => activity.CustomProperties[RunAsynchronouslyPropertyName] = value;
|
||||
public static void SetRunAsynchronously(this IActivity activity, bool value) => activity.CustomProperties[RunAsynchronouslyPropertyName[0]] = value;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the source file and line number where this activity was instantiated, if any.
|
||||
|
|
@ -45,7 +45,7 @@ public static class ActivityPropertyExtensions
|
|||
/// <summary>
|
||||
/// Sets the source file and line number where this activity was instantiated, if any.
|
||||
/// </summary>
|
||||
public static void SetSource(this IActivity activity, string value) => activity.CustomProperties[SourcePropertyName] = value;
|
||||
public static void SetSource(this IActivity activity, string value) => activity.CustomProperties[SourcePropertyName[0]] = value;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the source file and line number where this activity was instantiated, if any.
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ namespace Elsa.Extensions;
|
|||
public static class DictionaryExtensions
|
||||
{
|
||||
public static bool TryGetValue<T>(this IDictionary<string, object> dictionary, string key, out T value) => dictionary.TryGetValue<string, T>(key, out value);
|
||||
public static bool TryGetValue<T>(this IDictionary<string, object> dictionary, IEnumerable<string> keys, out T value) => dictionary.TryGetValue<string, T>(keys, out value);
|
||||
public static bool TryGetValue<T>(this IDictionary<object, object> dictionary, string key, out T value) => dictionary.TryGetValue<object, T>(key, out value);
|
||||
|
||||
public static bool TryGetValue<TKey, T>(this IDictionary<TKey, object> dictionary, TKey key, out T value)
|
||||
|
|
@ -19,6 +20,21 @@ public static class DictionaryExtensions
|
|||
value = ConvertValue<T>(item);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool TryGetValue<TKey, T>(this IDictionary<TKey, object> dictionary, IEnumerable<TKey> keys, out T value)
|
||||
{
|
||||
foreach (var key in keys)
|
||||
{
|
||||
if (dictionary.TryGetValue(key, out var item))
|
||||
{
|
||||
value = ConvertValue<T>(item);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
value = default!;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static T? GetValue<TKey, T>(this IDictionary<TKey, T> dictionary, TKey key) => ConvertValue<T>(dictionary[key]);
|
||||
public static T? GetValue<T>(this IDictionary<string, object> dictionary, string key) => ConvertValue<T>(dictionary[key]);
|
||||
|
|
@ -26,6 +42,7 @@ public static class DictionaryExtensions
|
|||
public static T? GetValueOrDefault<TKey, T>(this IDictionary<TKey, object> dictionary, TKey key, Func<T?> defaultValueFactory) => TryGetValue<TKey, T>(dictionary, key, out var value) ? value : defaultValueFactory();
|
||||
public static T? GetValueOrDefault<TKey, T>(this IDictionary<TKey, object> dictionary, TKey key) => GetValueOrDefault<TKey, T>(dictionary, key, () => default);
|
||||
public static T? GetValueOrDefault<T>(this IDictionary<string, object> dictionary, string key, Func<T?> defaultValueFactory) => TryGetValue<T>(dictionary, key, out var value) ? value : defaultValueFactory();
|
||||
public static T? GetValueOrDefault<T>(this IDictionary<string, object> dictionary, IEnumerable<string> keys, Func<T?> defaultValueFactory) => TryGetValue<T>(dictionary, keys, out var value) ? value : defaultValueFactory();
|
||||
public static T? GetValueOrDefault<T>(this IDictionary<string, object> dictionary, string key) => GetValueOrDefault<T>(dictionary, key, () => default);
|
||||
public static object? GetValueOrDefault(this IDictionary<string, object> dictionary, string key) => GetValueOrDefault<object>(dictionary, key, () => default);
|
||||
|
||||
|
|
|
|||
|
|
@ -16,21 +16,29 @@ public class ActivityFactory : IActivityFactory
|
|||
var canStartWorkflow = GetBoolean(context.Element, "canStartWorkflow");
|
||||
var runAsynchronously = GetBoolean(context.Element, "runAsynchronously");
|
||||
var activity = (IActivity)context.Element.Deserialize(type, context.SerializerOptions)!;
|
||||
|
||||
|
||||
activity.SetCanStartWorkflow(canStartWorkflow);
|
||||
activity.SetRunAsynchronously(runAsynchronously);
|
||||
|
||||
|
||||
return activity;
|
||||
}
|
||||
|
||||
|
||||
private static bool GetBoolean(JsonElement element, string propertyName)
|
||||
{
|
||||
if (element.TryGetProperty("customProperties", out var customPropertyElement))
|
||||
var propertyNames = new[] { propertyName.Camelize(), propertyName.Pascalize() };
|
||||
|
||||
foreach (var name in propertyNames)
|
||||
{
|
||||
if(customPropertyElement.TryGetProperty(propertyName.Pascalize(), out var canStartWorkflowElement))
|
||||
return canStartWorkflowElement.GetBoolean();
|
||||
if (element.TryGetProperty("customProperties", out var customPropertyElement))
|
||||
{
|
||||
if (customPropertyElement.TryGetProperty(name, out var canStartWorkflowElement))
|
||||
return canStartWorkflowElement.GetBoolean();
|
||||
}
|
||||
|
||||
if (element.TryGetProperty(propertyName.Camelize(), out var property) && property.GetBoolean())
|
||||
return true;
|
||||
}
|
||||
|
||||
return element.TryGetProperty(propertyName.Camelize(), out var property) && property.GetBoolean();
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue