Skip to content

Commit 9f9c8d4

Browse files
committed
fix(Dashboard): Multiple fixes and improvements
Signed-off-by: Charles d'Avernas <charles.davernas@neuroglia.io>
1 parent dd5177e commit 9f9c8d4

File tree

29 files changed

+403
-146
lines changed

29 files changed

+403
-146
lines changed

src/api/Synapse.Api.Application/Synapse.Api.Application.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<NeutralLanguage>en</NeutralLanguage>
88
<GenerateDocumentationFile>True</GenerateDocumentationFile>
99
<VersionPrefix>1.0.0</VersionPrefix>
10-
<VersionSuffix>alpha5.3</VersionSuffix>
10+
<VersionSuffix>alpha5.7</VersionSuffix>
1111
<AssemblyVersion>$(VersionPrefix)</AssemblyVersion>
1212
<FileVersion>$(VersionPrefix)</FileVersion>
1313
<Authors>The Synapse Authors</Authors>

src/api/Synapse.Api.Client.Core/Synapse.Api.Client.Core.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<NeutralLanguage>en</NeutralLanguage>
88
<GenerateDocumentationFile>True</GenerateDocumentationFile>
99
<VersionPrefix>1.0.0</VersionPrefix>
10-
<VersionSuffix>alpha5.3</VersionSuffix>
10+
<VersionSuffix>alpha5.7</VersionSuffix>
1111
<AssemblyVersion>$(VersionPrefix)</AssemblyVersion>
1212
<FileVersion>$(VersionPrefix)</FileVersion>
1313
<Authors>The Synapse Authors</Authors>

src/api/Synapse.Api.Client.Http/Synapse.Api.Client.Http.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<NeutralLanguage>en</NeutralLanguage>
88
<GenerateDocumentationFile>True</GenerateDocumentationFile>
99
<VersionPrefix>1.0.0</VersionPrefix>
10-
<VersionSuffix>alpha5.3</VersionSuffix>
10+
<VersionSuffix>alpha5.7</VersionSuffix>
1111
<AssemblyVersion>$(VersionPrefix)</AssemblyVersion>
1212
<FileVersion>$(VersionPrefix)</FileVersion>
1313
<Authors>The Synapse Authors</Authors>

src/api/Synapse.Api.Http/Synapse.Api.Http.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<OutputType>Library</OutputType>
99
<GenerateDocumentationFile>True</GenerateDocumentationFile>
1010
<VersionPrefix>1.0.0</VersionPrefix>
11-
<VersionSuffix>alpha5.3</VersionSuffix>
11+
<VersionSuffix>alpha5.7</VersionSuffix>
1212
<AssemblyVersion>$(VersionPrefix)</AssemblyVersion>
1313
<FileVersion>$(VersionPrefix)</FileVersion>
1414
<Authors>The Synapse Authors</Authors>

src/api/Synapse.Api.Server/Synapse.Api.Server.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<NeutralLanguage>en</NeutralLanguage>
88
<GenerateDocumentationFile>True</GenerateDocumentationFile>
99
<VersionPrefix>1.0.0</VersionPrefix>
10-
<VersionSuffix>alpha5.3</VersionSuffix>
10+
<VersionSuffix>alpha5.7</VersionSuffix>
1111
<AssemblyVersion>$(VersionPrefix)</AssemblyVersion>
1212
<FileVersion>$(VersionPrefix)</FileVersion>
1313
<Authors>The Synapse Authors</Authors>

src/cli/Synapse.Cli/Synapse.Cli.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<NeutralLanguage>en</NeutralLanguage>
99
<GenerateDocumentationFile>True</GenerateDocumentationFile>
1010
<VersionPrefix>1.0.0</VersionPrefix>
11-
<VersionSuffix>alpha5.3</VersionSuffix>
11+
<VersionSuffix>alpha5.7</VersionSuffix>
1212
<AssemblyVersion>$(VersionPrefix)</AssemblyVersion>
1313
<FileVersion>$(VersionPrefix)</FileVersion>
1414
<Authors>The Synapse Authors</Authors>

src/core/Synapse.Core.Infrastructure.Containers.Docker/Synapse.Core.Infrastructure.Containers.Docker.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<NeutralLanguage>en</NeutralLanguage>
88
<GenerateDocumentationFile>True</GenerateDocumentationFile>
99
<VersionPrefix>1.0.0</VersionPrefix>
10-
<VersionSuffix>alpha5.3</VersionSuffix>
10+
<VersionSuffix>alpha5.7</VersionSuffix>
1111
<AssemblyVersion>$(VersionPrefix)</AssemblyVersion>
1212
<FileVersion>$(VersionPrefix)</FileVersion>
1313
<Authors>The Synapse Authors</Authors>

src/core/Synapse.Core.Infrastructure.Containers.Kubernetes/Synapse.Core.Infrastructure.Containers.Kubernetes.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<NeutralLanguage>en</NeutralLanguage>
88
<GenerateDocumentationFile>True</GenerateDocumentationFile>
99
<VersionPrefix>1.0.0</VersionPrefix>
10-
<VersionSuffix>alpha5.3</VersionSuffix>
10+
<VersionSuffix>alpha5.7</VersionSuffix>
1111
<AssemblyVersion>$(VersionPrefix)</AssemblyVersion>
1212
<FileVersion>$(VersionPrefix)</FileVersion>
1313
<Authors>The Synapse Authors</Authors>

src/core/Synapse.Core.Infrastructure/Synapse.Core.Infrastructure.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<NeutralLanguage>en</NeutralLanguage>
88
<GenerateDocumentationFile>True</GenerateDocumentationFile>
99
<VersionPrefix>1.0.0</VersionPrefix>
10-
<VersionSuffix>alpha5.3</VersionSuffix>
10+
<VersionSuffix>alpha5.7</VersionSuffix>
1111
<AssemblyVersion>$(VersionPrefix)</AssemblyVersion>
1212
<FileVersion>$(VersionPrefix)</FileVersion>
1313
<Authors>The Synapse Authors</Authors>

src/core/Synapse.Core/Synapse.Core.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<NeutralLanguage>en</NeutralLanguage>
88
<GenerateDocumentationFile>True</GenerateDocumentationFile>
99
<VersionPrefix>1.0.0</VersionPrefix>
10-
<VersionSuffix>alpha5.3</VersionSuffix>
10+
<VersionSuffix>alpha5.7</VersionSuffix>
1111
<AssemblyVersion>$(VersionPrefix)</AssemblyVersion>
1212
<FileVersion>$(VersionPrefix)</FileVersion>
1313
<Authors>The Synapse Authors</Authors>

src/correlator/Synapse.Correlator/Synapse.Correlator.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<NeutralLanguage>en</NeutralLanguage>
99
<GenerateDocumentationFile>True</GenerateDocumentationFile>
1010
<VersionPrefix>1.0.0</VersionPrefix>
11-
<VersionSuffix>alpha5.3</VersionSuffix>
11+
<VersionSuffix>alpha5.7</VersionSuffix>
1212
<AssemblyVersion>$(VersionPrefix)</AssemblyVersion>
1313
<FileVersion>$(VersionPrefix)</FileVersion>
1414
<Authors>The Synapse Authors</Authors>
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
@*
2+
Copyright © 2024-Present The Synapse Authors
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*@
16+
17+
@using Json.Schema
18+
@using Neuroglia.Data.Infrastructure.ResourceOriented.Properties
19+
@using ServerlessWorkflow.Sdk
20+
@using ServerlessWorkflow.Sdk.Models
21+
@using System.Xml.Schema
22+
@using Synapse.Core.Infrastructure.Services
23+
@using System.Text.Json.Nodes
24+
@namespace Synapse.Dashboard.Components
25+
@inject MonacoInterop MonacoInterop
26+
@inject IExternalResourceProvider ExternalResourceProvider
27+
@inject IJsonSerializer JsonSerializer
28+
@inject IXmlSerializer XmlSerializer
29+
30+
<Tabs>
31+
@if(schema != null)
32+
{
33+
<Tab Title="Form" Active="true">
34+
<Content>
35+
<div class="pt-3">
36+
<DynamicForm Schema="schema" OnValueChanged="value => OnValueChanged(value)" />
37+
</div>
38+
</Content>
39+
</Tab>
40+
}
41+
<Tab Title="Text">
42+
<Content>
43+
<div class="pt-3">
44+
<MonacoEditor OnTextChanged="OnTextChanged" ModelName="@modelName" Document="input" />
45+
</div>
46+
</Content>
47+
</Tab>
48+
</Tabs>
49+
50+
<div class="text-center">
51+
<Button Outline="true" Color="ButtonColor.Primary" class="m-auto mt-3 w-100" @onclick="async _ => await OnStartAsync()">
52+
<Icon Name="IconName.Play" />
53+
Start
54+
</Button>
55+
</div>
56+
57+
@code {
58+
59+
WorkflowDefinition? workflowDefinition;
60+
JsonSchema? schema;
61+
string payload = string.Empty;
62+
string modelName = string.Empty;
63+
EquatableDictionary<string, object>? input;
64+
65+
[Parameter] public WorkflowDefinition? WorkflowDefinition { get; set; }
66+
[Parameter] public EquatableDictionary<string, object>? Input { get; set; }
67+
[Parameter] public EventCallback<string> OnCreate { get; set; }
68+
[Parameter] public EventCallback<ProblemDetails> OnProblem { get; set; }
69+
70+
void OnValueChanged(object? value)
71+
{
72+
payload = value == null ? string.Empty : JsonSerializer.SerializeToText(value);
73+
}
74+
75+
void OnTextChanged(string value)
76+
{
77+
payload = value;
78+
}
79+
80+
protected override async Task OnParametersSetAsync()
81+
{
82+
await base.OnParametersSetAsync();
83+
if (input != Input) input = Input;
84+
if (workflowDefinition != WorkflowDefinition)
85+
{
86+
workflowDefinition = WorkflowDefinition;
87+
await LoadSchemaAsync();
88+
}
89+
if (WorkflowDefinition?.Input?.Schema?.Document != null)
90+
{
91+
modelName = WorkflowDefinition.Document.Name + "-" + WorkflowDefinition.Document.Version;
92+
await MonacoInterop.AddValidationSchemaAsync(JsonSerializer.SerializeToText(WorkflowDefinition.Input.Schema.Document), $"https://synapse.io/schemas/{modelName}.json", $"{modelName}*").ConfigureAwait(false);
93+
}
94+
}
95+
96+
async Task OnStartAsync()
97+
{
98+
if (schema != null)
99+
{
100+
var node = string.IsNullOrWhiteSpace(payload) ? null : JsonSerializer.Deserialize<JsonNode>(payload);
101+
var evaluationOptions = new EvaluationOptions()
102+
{
103+
OutputFormat = OutputFormat.List
104+
};
105+
var evaluationResult = schema.Evaluate(node, evaluationOptions);
106+
if (!evaluationResult.IsValid)
107+
{
108+
var errors = evaluationResult.Details.Where(d => d.Errors != null).SelectMany(d => d.Errors!).GroupBy(e => e.Key).Select(e => new KeyValuePair<string, string[]>(e.Key, e.Select(e => e.Value).ToArray())).ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
109+
var problemDetails = new ProblemDetails(ErrorTypes.Invalid, ProblemTitles.ValidationFailed, ErrorStatus.Validation, "Workflow instance input validation failed", errors: errors);
110+
if (OnProblem.HasDelegate) await OnProblem.InvokeAsync(problemDetails);
111+
return;
112+
}
113+
}
114+
if (OnCreate.HasDelegate) await OnCreate.InvokeAsync(payload);
115+
}
116+
117+
async Task LoadSchemaAsync()
118+
{
119+
var schemaDefinition = WorkflowDefinition?.Input?.Schema;
120+
if (schemaDefinition == null) return;
121+
if (schemaDefinition.Resource == null)
122+
{
123+
switch (schemaDefinition.Format)
124+
{
125+
case SchemaFormat.Avro:
126+
schema = Avro.Schema.Parse(JsonSerializer.SerializeToText(schemaDefinition.Document)).ToJsonSchema();
127+
break;
128+
case SchemaFormat.Json:
129+
schema = JsonSchema.FromText(JsonSerializer.SerializeToText(schemaDefinition.Document));
130+
break;
131+
case SchemaFormat.Xml:
132+
var xml = XmlSerializer.SerializeToText(schemaDefinition.Document);
133+
var stringReader = new StringReader(xml);
134+
schema = XmlSchema.Read(stringReader, null)!.ToJsonSchema();
135+
break;
136+
default:
137+
throw new NotSupportedException($"The specified schema format '{schemaDefinition.Format}' is not supported");
138+
}
139+
}
140+
else
141+
{
142+
using var stream = await ExternalResourceProvider.ReadAsync(schemaDefinition.Resource).ConfigureAwait(false);
143+
using var streamReader = new StreamReader(stream);
144+
schema = schemaDefinition.Format switch
145+
{
146+
SchemaFormat.Avro => Avro.Schema.Parse(await streamReader.ReadToEndAsync()).ToJsonSchema(),
147+
SchemaFormat.Json => await JsonSchema.FromStream(stream).ConfigureAwait(false),
148+
SchemaFormat.Xml => XmlSchema.Read(stream, null)!.ToJsonSchema(),
149+
_ => throw new NotSupportedException($"The specified schema format '{schemaDefinition.Format}' is not supported"),
150+
};
151+
}
152+
}
153+
154+
}

src/dashboard/Synapse.Dashboard/Components/DynamicForm/DynamicForm.razor

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,13 @@
2828
case SchemaValueType.Null:
2929
break;
3030
case SchemaValueType.Array:
31-
31+
var itemsSchema = schema.GetItems();
32+
if (itemsSchema != null)
33+
{
34+
<div class="border border-muted rounded p-3">
35+
<DynamicFormArray Schema="Schema" OnValueChanged="async value => await OnValueChangedAsync(value)" />
36+
</div>
37+
}
3238
break;
3339
case SchemaValueType.Object:
3440
var properties = schema.GetProperties() ?? new Dictionary<string, JsonSchema>();
@@ -65,7 +71,7 @@
6571
/// <summary>
6672
/// Gets/sets the handler to call whenever the form's value changes
6773
/// </summary>
68-
[Parameter] public EventCallback<object?> OnValueChanged{ get; set; }
74+
[Parameter] public EventCallback<object?> OnValueChanged { get; set; }
6975

7076
/// <inheritdoc/>
7177
protected override async Task OnInitializedAsync()
@@ -84,6 +90,12 @@
8490
if (this.Schema != null && this.Schema != this.schema) this.Store.SetSchema(this.Schema);
8591
}
8692

93+
async Task OnValueChangedAsync(object? value)
94+
{
95+
this.Store.SetValue(value);
96+
await this.OnValueChanged.InvokeAsync(currentValue);
97+
}
98+
8799
async Task OnValueChangedAsync(string name, object? value)
88100
{
89101
this.Store.SetPropertyValue(name, value);
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
@using Json.Schema
2+
@namespace Synapse.Dashboard
3+
4+
@if(schema != null)
5+
{
6+
if (itemsSchema != null)
7+
{
8+
@foreach (var form in forms.OrderBy(kvp => kvp.Key))
9+
{
10+
<div @key="@form.Key">
11+
@form.Value
12+
<Button Outline="true" Color="ButtonColor.Danger" Class="w-100" @onclick="@(() => OnRemoveItemAsync(form.Key))">
13+
<Icon Name="IconName.Dash" />
14+
Remove
15+
</Button>
16+
<hr />
17+
</div>
18+
}
19+
<Button Outline="true" Color="ButtonColor.Success" Class="w-100" @onclick="OnAddItemAsync">
20+
<Icon Name="IconName.Plus" />
21+
Add
22+
</Button>
23+
}
24+
}
25+
26+
@code {
27+
28+
JsonSchema? schema;
29+
JsonSchema? itemsSchema;
30+
Dictionary<int, RenderFragment> forms = [];
31+
Dictionary<int, object> items = [];
32+
33+
/// <summary>
34+
/// Gets/sets the form field's schema
35+
/// </summary>
36+
[Parameter] public JsonSchema Schema { get; set; } = null!;
37+
38+
/// <summary>
39+
/// Gets/sets the handler to call whenever the field's value changes
40+
/// </summary>
41+
[Parameter] public EventCallback<object?> OnValueChanged { get; set; }
42+
43+
/// <inheritdoc/>
44+
protected override void OnParametersSet()
45+
{
46+
base.OnParametersSet();
47+
if (schema != Schema)
48+
{
49+
schema = Schema;
50+
itemsSchema = schema.GetItems();
51+
}
52+
}
53+
54+
async Task OnAddItemAsync()
55+
{
56+
var key = forms.Count < 1 ? 0 : forms.Max(kvp => kvp.Key) + 1;
57+
forms[key] = CreateDynamicForm(key);
58+
items[key] = new { };
59+
await OnValueChanged.InvokeAsync(items.Values);
60+
}
61+
62+
async Task OnItemChangedAsync(int key, object value)
63+
{
64+
items[key] = value;
65+
await this.OnValueChanged.InvokeAsync(items.Values);
66+
}
67+
68+
async Task OnRemoveItemAsync(int key)
69+
{
70+
var form = forms[key];
71+
forms.Remove(key);
72+
items.Remove(key);
73+
await this.OnValueChanged.InvokeAsync(items.Values);
74+
}
75+
76+
RenderFragment CreateDynamicForm(int key) => builder =>
77+
{
78+
builder.OpenComponent<DynamicForm>(0);
79+
builder.AddAttribute(1, "Schema", itemsSchema);
80+
builder.AddAttribute(2, "OnValueChanged", EventCallback.Factory.Create<object>(this, value => OnItemChangedAsync(key, value)));
81+
builder.CloseComponent();
82+
};
83+
84+
}

src/dashboard/Synapse.Dashboard/Components/DynamicForm/DynamicFormField.razor

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@
2020
@switch (schema.GetJsonType())
2121
{
2222
case SchemaValueType.Array:
23-
23+
<div class="border border-muted rounded p-3">
24+
<DynamicFormArray Schema="Schema" OnValueChanged="async e => await OnValueChanged.InvokeAsync(e)" />
25+
</div>
2426
break;
2527
case SchemaValueType.Object:
2628
<div class="border border-muted rounded p-3">

0 commit comments

Comments
 (0)