Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Diagnostics;
using System.Globalization;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.RegularExpressions;
using Altinn.App.Core.Models;
using Altinn.App.Core.Models.Expressions;
Expand All @@ -16,7 +17,7 @@
/// <summary>
/// Shortcut for evaluating a boolean expression on a given property on a <see cref="Models.Layout.Components.Base.BaseComponent" />
/// </summary>
[Obsolete("Use ComponentContext.IsHidden or ComponentContext.EvaluateExpression instead")]

Check warning on line 20 in src/Altinn.App.Core/Internal/Expressions/ExpressionEvaluator.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Do not forget to remove this deprecated code someday.

See more on https://sonarcloud.io/project/issues?id=Altinn_app-lib-dotnet&issues=AZ5oQ4XX6-HW161ULzz4&open=AZ5oQ4XX6-HW161ULzz4&pullRequest=1769
public static async Task<bool> EvaluateBooleanExpression(
LayoutEvaluatorState state,
ComponentContext context,
Expand Down Expand Up @@ -131,6 +132,7 @@
ExpressionFunction.minus => Minus(args),
ExpressionFunction.multiply => Multiply(args),
ExpressionFunction.divide => Divide(args),
ExpressionFunction.list => List(args),
ExpressionFunction.INVALID => throw new ExpressionEvaluatorTypeErrorException(
$"Function {expr.Args.FirstOrDefault()} not implemented in backend {expr}"
),
Expand Down Expand Up @@ -747,7 +749,7 @@
}

var all = true;
foreach (var arg in args)

Check warning on line 752 in src/Altinn.App.Core/Internal/Expressions/ExpressionEvaluator.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Loops should be simplified using the "Where" LINQ method

See more on https://sonarcloud.io/project/issues?id=Altinn_app-lib-dotnet&issues=AZ5oQ4XX6-HW161ULzz5&open=AZ5oQ4XX6-HW161ULzz5&pullRequest=1769
{
// the LINQ All() method would short-circuit and not evaluate all args, so we do it manually to ensure exceptions are thrown correctly
if (!PrepareBooleanArg(arg))
Expand Down Expand Up @@ -789,7 +791,7 @@
}

bool any = false;
foreach (var arg in args)

Check warning on line 794 in src/Altinn.App.Core/Internal/Expressions/ExpressionEvaluator.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Loops should be simplified using the "Where" LINQ method

See more on https://sonarcloud.io/project/issues?id=Altinn_app-lib-dotnet&issues=AZ5oQ4XX6-HW161ULzz6&open=AZ5oQ4XX6-HW161ULzz6&pullRequest=1769
{
// the LINQ Any() method would short-circuit and not evaluate all args, so we do it manually to ensure exceptions are thrown correctly
if (PrepareBooleanArg(arg))
Expand Down Expand Up @@ -997,6 +999,11 @@
return positionalArguments[index.Value];
}

private static JsonArray List(ExpressionValue[] args)
{
return new JsonArray(args.Select(a => JsonSerializer.SerializeToNode(a)).ToArray());
}

/// <summary>
/// Performs arithmetic operation using decimal precision to avoid floating point precision issues.
/// Converts doubles to decimal, performs the operation, and converts back to double.
Expand Down
93 changes: 63 additions & 30 deletions src/Altinn.App.Core/Internal/Expressions/ExpressionValue.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using System.Collections;

Check failure on line 1 in src/Altinn.App.Core/Internal/Expressions/ExpressionValue.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

Using directive is unnecessary. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0005)

Check failure on line 1 in src/Altinn.App.Core/Internal/Expressions/ExpressionValue.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

Using directive is unnecessary. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0005)

Check failure on line 1 in src/Altinn.App.Core/Internal/Expressions/ExpressionValue.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

Using directive is unnecessary. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0005)

Check failure on line 1 in src/Altinn.App.Core/Internal/Expressions/ExpressionValue.cs

View workflow job for this annotation

GitHub Actions / Run dotnet build and test (macos-latest)

Using directive is unnecessary. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0005)

Check failure on line 1 in src/Altinn.App.Core/Internal/Expressions/ExpressionValue.cs

View workflow job for this annotation

GitHub Actions / Run dotnet build and test (macos-latest)

Using directive is unnecessary. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0005)

Check warning on line 1 in src/Altinn.App.Core/Internal/Expressions/ExpressionValue.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Using directive is unnecessary.

See more on https://sonarcloud.io/project/issues?id=Altinn_app-lib-dotnet&issues=AZ6BvPim-3CBvFhL9u0D&open=AZ6BvPim-3CBvFhL9u0D&pullRequest=1769
using System.Diagnostics;
using System.Globalization;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;

namespace Altinn.App.Core.Internal.Expressions;
Expand All @@ -18,8 +20,8 @@
// double is a value type where nullable takes extra space, and we only read it when it should be set
private readonly double _numberValue = 0;

// private readonly Dictionary<string, ExpressionValue>? _objectValue = null;

Check warning on line 23 in src/Altinn.App.Core/Internal/Expressions/ExpressionValue.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this commented out code.

See more on https://sonarcloud.io/project/issues?id=Altinn_app-lib-dotnet&issues=AZ5oQ4TR6-HW161ULzzq&open=AZ5oQ4TR6-HW161ULzzq&pullRequest=1769
// private readonly ExpressionValue[]? _arrayValue = null;
private readonly JsonArray? _arrayValue = null;

/// <summary>
/// Constructor for NULL value (structs require a public parameterless constructor)
Expand All @@ -27,7 +29,7 @@
public ExpressionValue()
: this(JsonValueKind.Null) { }

private ExpressionValue(JsonValueKind valueKind)

Check warning on line 32 in src/Altinn.App.Core/Internal/Expressions/ExpressionValue.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

All 'ExpressionValue' method overloads should be adjacent.

See more on https://sonarcloud.io/project/issues?id=Altinn_app-lib-dotnet&issues=AZ5oQ4TR6-HW161ULzzz&open=AZ5oQ4TR6-HW161ULzzz&pullRequest=1769
{
ValueKind = valueKind;
}
Expand Down Expand Up @@ -84,16 +86,17 @@
}

// private ExpressionValue(Dictionary<string, ExpressionValue>? value)
// {

Check warning on line 89 in src/Altinn.App.Core/Internal/Expressions/ExpressionValue.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this commented out code.

See more on https://sonarcloud.io/project/issues?id=Altinn_app-lib-dotnet&issues=AZ5oQ4TR6-HW161ULzzr&open=AZ5oQ4TR6-HW161ULzzr&pullRequest=1769
// _valueKind = value is null ? JsonValueKind.Null : JsonValueKind.Object;
// _objectValue = value;
// }

// private ExpressionValue(ExpressionValue[]? value)
// {
// _valueKind = value is null ? JsonValueKind.Null : JsonValueKind.Array;
// _arrayValue = value;
// }
/// <summary>Constructor for array value</summary>
public ExpressionValue(JsonArray value)
{
ValueKind = JsonValueKind.Array;
_arrayValue = value;
}

/// <summary>
/// Convert a nullable boolean to ExpressionValue
Expand All @@ -113,12 +116,12 @@
// /// <summary>
// /// Convert a Dictionary to ExpressionValue
// /// </summary>
// public static implicit operator ExpressionValue(Dictionary<string, ExpressionValue>? value) => new(value);

Check warning on line 119 in src/Altinn.App.Core/Internal/Expressions/ExpressionValue.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this commented out code.

See more on https://sonarcloud.io/project/issues?id=Altinn_app-lib-dotnet&issues=AZ5oQ4TR6-HW161ULzzs&open=AZ5oQ4TR6-HW161ULzzs&pullRequest=1769
//
// /// <summary>
// /// Convert an array to ExpressionValue
// /// </summary>
// public static implicit operator ExpressionValue(ExpressionValue[]? value) => new(value);

/// <summary>
/// Convert an array to ExpressionValue
/// </summary>
public static implicit operator ExpressionValue(JsonArray value) => new(value);

/// <summary>
/// Convert any of the supported CLR types to an expressionTypeUnion
Expand Down Expand Up @@ -172,10 +175,32 @@
'"'
) // Trim quotes to match the string representation
,
JsonArray jsonArrayValue => jsonArrayValue,
_ => ToJsonArrayOrNull(value),
};
}

private static ExpressionValue ToJsonArrayOrNull(object? value)
{
var node = JsonSerializer.SerializeToNode(value);
return node switch
{
JsonArray jsonArray => jsonArray,
_ => Null,
};
}

private static object? JsonElementToObject(JsonElement jsonElement) =>
jsonElement.ValueKind switch
{
JsonValueKind.True => true,
JsonValueKind.False => false,
JsonValueKind.String => jsonElement.GetString(),
JsonValueKind.Number => jsonElement.GetDouble(),
JsonValueKind.Array => jsonElement.EnumerateArray().Select(JsonElementToObject).ToArray(),
_ => null,
};

/// <summary>
/// Convert the value to the relevant CLR type
/// </summary>
Expand All @@ -190,7 +215,7 @@
JsonValueKind.String => String,
JsonValueKind.Number => Number,
// JsonValueKind.Object => Object,
// JsonValueKind.Array => Array,
JsonValueKind.Array => Array,
_ => throw new InvalidOperationException("Invalid value kind"),
};

Expand All @@ -215,7 +240,7 @@
/// <summary>
/// Get the value as a string (or throw if it isn't a string ValueKind)
/// </summary>
public string String =>

Check warning on line 243 in src/Altinn.App.Core/Internal/Expressions/ExpressionValue.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Identifier 'String' contains type name

See more on https://sonarcloud.io/project/issues?id=Altinn_app-lib-dotnet&issues=AZ5oQ4TR6-HW161ULzz3&open=AZ5oQ4TR6-HW161ULzz3&pullRequest=1769
ValueKind switch
{
JsonValueKind.String => _stringValue ?? throw new UnreachableException("Not a string"),
Expand All @@ -238,21 +263,22 @@

// public Dictionary<string, ExpressionValue> Object =>
// _valueKind switch
// {

Check warning on line 266 in src/Altinn.App.Core/Internal/Expressions/ExpressionValue.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this commented out code.

See more on https://sonarcloud.io/project/issues?id=Altinn_app-lib-dotnet&issues=AZ5oQ4TR6-HW161ULzzt&open=AZ5oQ4TR6-HW161ULzzt&pullRequest=1769
// JsonValueKind.Object => _objectValue ?? throw new UnreachableException($"{this} is not an object"),
// _ => throw new InvalidCastException(
// $"The .Object property can't be used on an expression value that represent a {_valueKind}"
// ),
// };
//
// public ExpressionValue[] Array =>
// _valueKind switch
// {
// JsonValueKind.Array => _arrayValue ?? throw new UnreachableException($"{this} is not an array"),
// _ => throw new InvalidCastException(
// $"The .Array property can't be used on an expression value that represent a {_valueKind}"
// ),
// };

/// <summary>Get the value as an array (or throw if it isn't an array ValueKind)</summary>
public JsonArray Array =>
ValueKind switch
{
JsonValueKind.Array => _arrayValue ?? throw new UnreachableException($"{this} is not an array"),
_ => throw new InvalidCastException(
$"The .Array property can't be used on an expression value that represent a {ValueKind}"
),
};

/// <summary>
/// Get the value as it would be serialized to JSON
Expand All @@ -263,12 +289,12 @@
JsonValueKind.Null => "null",
JsonValueKind.Undefined => "undefined",
JsonValueKind.True => "true",
JsonValueKind.False => "false",

Check warning on line 292 in src/Altinn.App.Core/Internal/Expressions/ExpressionValue.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define a constant instead of using this literal 'false' 7 times.

See more on https://sonarcloud.io/project/issues?id=Altinn_app-lib-dotnet&issues=AZ5oQ4TR6-HW161ULzz0&open=AZ5oQ4TR6-HW161ULzz0&pullRequest=1769
JsonValueKind.String => JsonSerializer.Serialize(String, _unsafeSerializerOptionsForSerializingDates),
JsonValueKind.Number => Number.ToString(CultureInfo.InvariantCulture),
// JsonValueKind.Object => JsonSerializer.Serialize(Object),
// JsonValueKind.Array => JsonSerializer.Serialize(Array),
_ => throw new InvalidOperationException($"Invalid value kind {ValueKind}"),

Check failure on line 297 in src/Altinn.App.Core/Internal/Expressions/ExpressionValue.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this 'throw' expression.

See more on https://sonarcloud.io/project/issues?id=Altinn_app-lib-dotnet&issues=AZ5oQ4TR6-HW161ULzz1&open=AZ5oQ4TR6-HW161ULzz1&pullRequest=1769
};

/// <summary>
Expand Down Expand Up @@ -326,7 +352,7 @@
{
throw new NotImplementedException("Equals is not used for ExpressionValue");
// First compare value kinds
// if (_valueKind != other._valueKind)

Check warning on line 355 in src/Altinn.App.Core/Internal/Expressions/ExpressionValue.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this commented out code.

See more on https://sonarcloud.io/project/issues?id=Altinn_app-lib-dotnet&issues=AZ5oQ4TR6-HW161ULzzu&open=AZ5oQ4TR6-HW161ULzzu&pullRequest=1769
// return false;

// // Then compare actual values based on the kind
Expand Down Expand Up @@ -355,7 +381,7 @@
{
throw new NotImplementedException("GetHashCode is not implemented for ExpressionValue");
// return ValueKind switch
// {

Check warning on line 384 in src/Altinn.App.Core/Internal/Expressions/ExpressionValue.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this commented out code.

See more on https://sonarcloud.io/project/issues?id=Altinn_app-lib-dotnet&issues=AZ5oQ4TR6-HW161ULzzv&open=AZ5oQ4TR6-HW161ULzzv&pullRequest=1769
// JsonValueKind.Null => 0,
// JsonValueKind.True => 1,
// JsonValueKind.False => 0,
Expand Down Expand Up @@ -472,7 +498,7 @@
/// <param name="result">The result (null or default if unsuccessful), but note that null might also be a valid result</param>
/// <param name="type">The type to convert to</param>
/// <returns>Whether the conversion was successful</returns>
public bool TryDeserialize(Type type, out object? result)

Check failure on line 501 in src/Altinn.App.Core/Internal/Expressions/ExpressionValue.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this method to reduce its Cognitive Complexity from 28 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=Altinn_app-lib-dotnet&issues=AZ5oQ4TR6-HW161ULzz2&open=AZ5oQ4TR6-HW161ULzz2&pullRequest=1769
{
// Value types can be Nullable<T>, so assign underlyingType accordingly
Type underlyingType;
Expand Down Expand Up @@ -589,7 +615,7 @@

private static bool IsSupportedNumericType(Type type)
{
// TODO: consider supporting enums as numeric types as well, but currently we

Check warning on line 618 in src/Altinn.App.Core/Internal/Expressions/ExpressionValue.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Complete the task associated to this 'TODO' comment.

See more on https://sonarcloud.io/project/issues?id=Altinn_app-lib-dotnet&issues=AZ5oQ4TR6-HW161ULzzy&open=AZ5oQ4TR6-HW161ULzzy&pullRequest=1769
// don't use C# enums in datamodels, so it isn't very urgent.
return type == typeof(double)
|| type == typeof(int)
Expand Down Expand Up @@ -621,18 +647,25 @@
JsonTokenType.Number => reader.GetDouble(),
JsonTokenType.Null => ExpressionValue.Null,
// JsonTokenType.StartObject => ReadObject(ref reader),
// JsonTokenType.StartArray => ReadArray(ref reader),
JsonTokenType.StartArray => ReadArray(ref reader, options),
_ => throw new JsonException(),
};
}

// private ExpressionValue ReadArray(ref Utf8JsonReader reader)
// {
// throw new NotImplementedException();
// }
//
private static ExpressionValue ReadArray(ref Utf8JsonReader reader, JsonSerializerOptions options)
{
if (reader.TokenType != JsonTokenType.StartArray)
{
throw new JsonException("Expected StartArray token.");
}
var values =
JsonSerializer.Deserialize<JsonArray>(ref reader, options)
?? throw new JsonException("Expected EndArray token.");
return new ExpressionValue(values);
}

// private ExpressionValue ReadObject(ref Utf8JsonReader reader)
// {

Check warning on line 668 in src/Altinn.App.Core/Internal/Expressions/ExpressionValue.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this commented out code.

See more on https://sonarcloud.io/project/issues?id=Altinn_app-lib-dotnet&issues=AZ5oQ4TR6-HW161ULzzw&open=AZ5oQ4TR6-HW161ULzzw&pullRequest=1769
// throw new NotImplementedException();
// }

Expand All @@ -658,11 +691,11 @@
writer.WriteNumberValue(value.Number);
break;
// case JsonValueKind.Object:
// JsonSerializer.Serialize(writer, value.Object, options);

Check warning on line 694 in src/Altinn.App.Core/Internal/Expressions/ExpressionValue.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this commented out code.

See more on https://sonarcloud.io/project/issues?id=Altinn_app-lib-dotnet&issues=AZ5oQ4TR6-HW161ULzzx&open=AZ5oQ4TR6-HW161ULzzx&pullRequest=1769
// break;
// case JsonValueKind.Array:
// JsonSerializer.Serialize(writer, value.Array, options);
// break;
case JsonValueKind.Array:
JsonSerializer.Serialize(writer, value.Array, options);
break;
default:
throw new JsonException();
}
Expand Down
3 changes: 3 additions & 0 deletions src/Altinn.App.Core/Models/Expressions/ExpressionFunction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -225,4 +225,7 @@ public enum ExpressionFunction
/// Divide numbers. Must be numeric values.
/// </summary>
divide,

/// <summary>Create a list from the arguments.</summary>
list,
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public ExpressionTestCaseRoot() { }
public string? Name { get; set; }

[JsonPropertyName("expression")]
public Expression Expression { get; set; }
public Expression? Expression { get; set; }

[JsonPropertyName("context")]
public ComponentContextForTestSpec? Context { get; set; }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Text.Json;
using Altinn.App.Core.Internal.Expressions;
using Altinn.App.Core.Internal.Texts;
using Altinn.App.Core.Models.Expressions;
using Altinn.App.Core.Models.Layout;
using Altinn.App.Core.Tests.LayoutExpressions.TestUtilities;
using Altinn.App.Core.Tests.TestUtils;
Expand Down Expand Up @@ -93,7 +94,7 @@ private async Task RunTestCase(string testName, string folder)
{
await ExpressionEvaluator.EvaluateExpression(
state,
test.Expression,
(Expression)test.Expression!,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these should be test.Expression.Value

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, fixed!

await test.GetContextOrNull(state)
);
};
Expand All @@ -107,7 +108,7 @@ await test.GetContextOrNull(state)

var result = await ExpressionEvaluator.EvaluateExpression(
state,
test.Expression,
(Expression)test.Expression!,
await test.GetContextOrNull(state)!
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,11 @@ public async Task Divide_Theory(string testName, ExpressionTestCaseRoot.TestCase
[SharedTest("round")]
public async Task Round_Theory(string testName, string folder) => await RunTestCase(testName, folder);

[Theory]
[SharedTestCases("list")]
public async Task List_Theory(string testName, ExpressionTestCaseRoot.TestCaseItem testCaseItem) =>
await RunTestCase(testName, new ExpressionTestCaseRoot(testCaseItem));

private static async Task<ExpressionTestCaseRoot> LoadTestCase(string file, string folder)
{
ExpressionTestCaseRoot testCase = new();
Expand Down Expand Up @@ -395,17 +400,20 @@ private async Task RunTestCase(string testName, ExpressionTestCaseRoot test)

test.ParsingException.Should().BeNull("Loading of test failed");

await RunTestCaseItem(
new ExpressionTestCaseRoot.TestCaseItem()
{
Expects = test.Expects,
Expression = test.Expression,
ExpectsFailure = test.ExpectsFailure,
},
state,
context,
positionalArguments
);
if (test.Expression != null)
{
await RunTestCaseItem(
new ExpressionTestCaseRoot.TestCaseItem()
{
Expects = test.Expects,
Expression = (Expression)test.Expression,
ExpectsFailure = test.ExpectsFailure,
},
state,
context,
positionalArguments
);
}

if (test.TestCases != null)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Text.Json;
using Altinn.App.Core.Internal.Expressions;
using Altinn.App.Core.Internal.Texts;
using Altinn.App.Core.Models.Expressions;
using Altinn.App.Core.Models.Layout;
using Altinn.App.Core.Tests.LayoutExpressions.TestUtilities;
using Altinn.App.Core.Tests.TestUtils;
Expand Down Expand Up @@ -59,7 +60,11 @@ public async Task Simple_Theory(string testName, string folder)
var state = dataAccessor.GetLayoutEvaluatorState();
Assert.NotNull(state);

await ExpressionEvaluator.EvaluateExpression(state, test.Expression, await test.GetContextOrNull(state));
await ExpressionEvaluator.EvaluateExpression(
state,
(Expression)test.Expression!,
await test.GetContextOrNull(state)
);
};
(await act.Should().ThrowAsync<Exception>()).WithMessage(testCase.ExpectsFailure + "*");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"name": "Lookup a list",
"layouts": {
"Page1": {
"$schema": "https://altinncdn.no/schemas/json/layout/layout.schema.v1.json",
"data": {
"layout": [
{
"id": "some-component",
"type": "Checkboxes",
"dataModelBindings": {
"simpleBinding": "chosenValues"
},
"options": [
{
"value": "a",
"label": "id_KZuKMBAE5eel"
},
{
"value": "b",
"label": "id_Erk5v6GSNDu6"
},
{
"value": "c",
"label": "id_6S71AQBlLcPX"
}
]
}
]
}
}
},
"dataModel": {
"chosenValues": ["a", "c"]
},
"expression": ["component", "some-component"],
"expects": ["a", "c"]
}

This file was deleted.

Loading
Loading