Skip to content

Commit

Permalink
Add Persistence strategy at Workflow / Activity Level (#136)
Browse files Browse the repository at this point in the history
* Add Persistence strategy at Workflow / Activity Level

* remove using about removed Contracts

* refactor and renaming to LogPersistenceMode

* Refactor PersistenceTab and update project references

Updated various aspects of the PersistenceTab class and its functionality to improve code quality and readability. Simplified the handling of persistence configurations and simplified the use of properties. Transitioned project reference for Elsa.Api.Client from package reference to direct project reference for better development experience in Elsa.Studio.Core.

* rename GetSelectComponent2 to GetSelectComponent

* Consolidate project files and update Elsa.Api.Client package

This commit consolidates various project properties files into a single Directory.Build.props file, simplifying the project file structure and reducing duplication. The version of the Elsa.Api.Client package reference is updated and the package is now being directly referenced instead of via a project reference. JetBrains.Annotations usage has been removed as well.

* Update package version in GitHub workflows

The version of the package in the GitHub workflows has been updated from 3.1.0 to 3.2.0. This was done to ensure consistency with the project's latest release and standards.

* Refactor code for readability in Settings.razor

The code in Settings.razor has been cleaned up with extraneous spaces removed and alignment of attributes fixed. This modification enhances code readability and maintainability in the workflow properties' settings section.

* Refactor code formatting in Settings.razor.cs

Adjusted the code formatting to improve readability in Settings.razor.cs. The modifications mainly include adding extra line breaks and removing unnecessary white space. No functionality was changed in this commit.

---------

Co-authored-by: Jérémie DEVILLARD <[email protected]>
Co-authored-by: Sipke Schoorstra <[email protected]>
  • Loading branch information
3 people authored Mar 30, 2024
1 parent 0a3b6c0 commit 145dfbb
Show file tree
Hide file tree
Showing 13 changed files with 298 additions and 30 deletions.
4 changes: 2 additions & 2 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@
<PackageVersion Include="ShortGuid" Version="2.0.1" />
<PackageVersion Include="ThrottleDebounce" Version="2.0.0" />
<PackageVersion Include="BlazorMonaco" Version="3.1.0" />
<PackageVersion Include="Elsa.Api.Client" Version="3.1.0-preview.1210" />
<PackageVersion Include="Elsa.Api.Client" Version="3.2.0-preview.1331" />
<PackageVersion Include="Refit" Version="7.0.0" />
<PackageVersion Include="Refit.HttpClientFactory" Version="7.0.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net6.0' or '$(TargetFramework)' == 'net7.0'">
<ItemGroup Condition="'$(TargetFramework)' == 'net7.0'">
<PackageVersion Include="Microsoft.AspNetCore.Components" Version="7.0.16" />
<PackageVersion Include="Microsoft.AspNetCore.Components.Authorization" Version="7.0.16" />
<PackageVersion Include="Microsoft.AspNetCore.Components.CustomElements" Version="7.0.16" />
Expand Down
5 changes: 4 additions & 1 deletion Elsa.Studio.sln
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@


Microsoft Visual Studio Solution File, Format Version 12.00
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{875A7E2E-4B7C-4AF0-A71E-3980B73AF363}"
ProjectSection(SolutionItems) = preProject
src\Directory.Build.props = src\Directory.Build.props
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "solution", "solution", "{C5E5655F-9B0D-4A93-9D0D-58216E8DE9C1}"
ProjectSection(SolutionItems) = preProject
Expand Down
20 changes: 20 additions & 0 deletions src/Directory.Build.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<Project>

<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))" />

<PropertyGroup Label="TargetFrameworks">
<TargetFrameworks>net7.0;net8.0</TargetFrameworks>
</PropertyGroup>

<ItemGroup Label="Files">
<None Include="..\..\..\icon.png" Pack="true" PackagePath="\" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="ConfigureAwait.Fody" PrivateAssets="All" />
<PackageReference Include="Fody" PrivateAssets="All" />
<PackageReference Include="JetBrains.Annotations" PrivateAssets="All" />
<PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
using Elsa.Studio.Core.BlazorServer.HostedServices;
using Elsa.Studio.Extensions;
using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection;

namespace Elsa.Studio.Core.BlazorServer.Extensions;

/// <summary>
/// Contains extension methods for the <see cref="IServiceCollection"/> interface.
/// </summary>
[PublicAPI]
public static class ServiceCollectionExtensions
{
/// <summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
using Elsa.Studio.Extensions;
using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection;

namespace Elsa.Studio.Core.BlazorWasm.Extensions;

/// <summary>
/// Contains extension methods for the <see cref="IServiceCollection"/> interface.
/// </summary>
[PublicAPI]
public static class ServiceCollectionExtensions
{
/// <summary>
Expand Down
6 changes: 3 additions & 3 deletions src/framework/Elsa.Studio.Core/Elsa.Studio.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@
<PackageReference Include="ThrottleDebounce"/>
</ItemGroup>

<!-- <ItemGroup Label="Elsa">-->
<!-- <ProjectReference Include="..\..\..\..\..\elsa-core\main\src\clients\Elsa.Api.Client\Elsa.Api.Client.csproj"/>-->
<!-- </ItemGroup>-->
<!-- <ItemGroup Label="Elsa">-->
<!-- <ProjectReference Include="..\..\..\..\..\elsa-core\main\src\clients\Elsa.Api.Client\Elsa.Api.Client.csproj"/>-->
<!-- </ItemGroup>-->

<ItemGroup Label="Elsa">
<PackageReference Include="Elsa.Api.Client"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,13 @@
using Elsa.Studio.Contracts;
using Elsa.Studio.Options;
using Elsa.Studio.Services;
using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection;

namespace Elsa.Studio.Extensions;

/// <summary>
/// Contains extension methods for the <see cref="IServiceCollection"/> interface.
/// </summary>
[PublicAPI]
public static class ServiceCollectionExtensions
{
/// <summary>
Expand Down
3 changes: 0 additions & 3 deletions src/framework/Elsa.Studio.Shared/ToolVersion.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
using JetBrains.Annotations;

namespace Elsa.Studio;

/// <summary>
/// Represents the version of the tool.
/// </summary>
[PublicAPI]
public static class ToolVersion
{
/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,13 @@
</MudTabPanel>
}

<MudTabPanel Text="Persistence">
<ScrollableWell MaxHeight="VisiblePaneHeight">
<PersistenceTab WorkflowDefinition="WorkflowDefinition" Activity="@Activity" ActivityDescriptor="@ActivityDescriptor" OnActivityUpdated="OnActivityUpdated" />
</ScrollableWell>
</MudTabPanel>


<MudTabPanel Text="Info">
@if (ActivityDescriptor != null)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
@using Elsa.Api.Client.Resources.ActivityDescriptors.Models
@using Elsa.Api.Client.Resources.WorkflowDefinitions.Enums
@using Variant = MudBlazor.Variant
@inherits StudioComponentBase


@{

RenderFragment GetSelectComponent(String propertyName, IDictionary<string, LogPersistenceMode> properties) =>
@<MudSelect Label="@propertyName"
T="LogPersistenceMode"
Variant="@MudBlazor.Variant.Outlined"
Value="@GetProperty(propertyName,properties)"
ValueChanged="@((value) => SetProperty(propertyName,properties,value))"
ToStringFunc="@(x=> x.ToString())"
ReadOnly="IsReadOnly"
SelectedValuesChanged="(values)=>OnBindingChanged()">
@foreach (LogPersistenceMode item in Enum.GetValues(typeof(LogPersistenceMode)))
{
<MudSelectItem Value="@item"></MudSelectItem>
}
</MudSelect>
;

}
<div class="pa-4">
<MudForm ReadOnly="IsReadOnly">
<MudStack Spacing="6">
<MudText Typo="Typo.overline">Default configuration</MudText>
<MudSelect Label="Default Configuration"
T=LogPersistenceMode
Variant="@MudBlazor.Variant.Outlined"
Value="@_persistenceConfiguration.Default"
ValueChanged="@(async (bindingOption) => _persistenceConfiguration.Default = bindingOption)"
ToStringFunc="@(x=> x.ToString())"
ReadOnly="IsReadOnly"
SelectedValuesChanged="(values)=>OnBindingChanged()">
@foreach (LogPersistenceMode item in Enum.GetValues(typeof(LogPersistenceMode)))
{
<MudSelectItem Value="@item"></MudSelectItem>
}

</MudSelect>
<MudDivider />
<MudText Typo="Typo.overline">Input Properties</MudText>
@if(!InputDescriptors.Any())
{
<Well>
<MudAlert Severity="Severity.Normal" Variant="Variant.Text">This activity does not have any input properties.</MudAlert>
</Well>
}
@foreach(var input in InputDescriptors)
{
@GetSelectComponent(input.Name, _persistenceConfiguration.Inputs);
}

<MudDivider />
<MudText Typo="Typo.overline">Output Properties</MudText>
@if (!OutputDescriptors.Any())
{
<Well>
<MudAlert Severity="Severity.Normal" Variant="Variant.Text">This activity does not have any output properties.</MudAlert>
</Well>
}
@foreach (var output in OutputDescriptors)
{
@GetSelectComponent(output.Name, _persistenceConfiguration.Outputs);
}
</MudStack>
</MudForm>

<MudOverlay Visible="@IsReadOnly" Absolute="true" />
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
using Elsa.Api.Client.Extensions;
using Elsa.Api.Client.Resources.ActivityDescriptors.Models;
using Elsa.Api.Client.Resources.WorkflowDefinitions.Enums;
using Elsa.Api.Client.Resources.WorkflowDefinitions.Models;
using Elsa.Studio.Workflows.UI.Contracts;
using Humanizer;
using Microsoft.AspNetCore.Components;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;

namespace Elsa.Studio.Workflows.Components.WorkflowDefinitionEditor.Components.ActivityProperties.Tabs;

/// <summary>
/// Represents the persistence tab.
/// </summary>
public partial class PersistenceTab
{
/// An event raised when the activity is updated.
[Parameter] public Func<JsonObject, Task>? OnActivityUpdated { get; set; }
/// <summary>
/// Gets or sets the workflow definition.
/// </summary>
[Parameter]
public WorkflowDefinition? WorkflowDefinition { get; set; }
/// <summary>
/// Gets or sets the activity to edit.
/// </summary>
[Parameter]
public JsonObject? Activity { get; set; }
/// <summary>
/// The workspace.
/// </summary>
[CascadingParameter] public IWorkspace? Workspace { get; set; }
/// <summary>
/// Gets or sets the activity descriptor.
/// </summary>
[Parameter]
public ActivityDescriptor? ActivityDescriptor { get; set; }

private ICollection<InputDescriptor> InputDescriptors { get; set; } = new List<InputDescriptor>();
private ICollection<OutputDescriptor> OutputDescriptors { get; set; } = new List<OutputDescriptor>();
private bool IsReadOnly => Workspace?.IsReadOnly == true;
private PersistenceActivityConfiguration _persistenceConfiguration = new();
private JsonSerializerOptions _serializerOptions = default!;
private const string LogPersistenceModeKey = "logPersistenceMode";

/// <inheritdoc />
protected override void OnInitialized()
{
_persistenceConfiguration = new PersistenceActivityConfiguration();
_serializerOptions = new System.Text.Json.JsonSerializerOptions()
{
PropertyNameCaseInsensitive = true,
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
};
_serializerOptions.Converters.Add(new JsonStringEnumConverter());

base.OnInitialized();
}

/// <inheritdoc />
protected override void OnParametersSet()
{
if (Activity == null || ActivityDescriptor == null)
return;

InputDescriptors = ActivityDescriptor.Inputs.ToList();
OutputDescriptors = ActivityDescriptor.Outputs.ToList();

SetPersistenceProperties();
}

private void SetPersistenceProperties()
{
var customProperties = Activity?.GetProperty("customProperties");
if (customProperties == null)
{
customProperties = new JsonObject(new List<KeyValuePair<string, JsonNode?>>());
Activity?.SetProperty(customProperties, "customProperties");
}

var persistence = ((JsonObject)customProperties).GetProperty<PersistenceActivityConfiguration>(_serializerOptions, LogPersistenceModeKey) ?? new PersistenceActivityConfiguration();

_persistenceConfiguration = persistence;
var props = _persistenceConfiguration.SerializeToNode(_serializerOptions);
Activity?.SetProperty(props, "customProperties", LogPersistenceModeKey);
}

private async Task OnBindingChanged()
{
var props = _persistenceConfiguration.SerializeToNode(_serializerOptions);
Activity?.SetProperty(props, "customProperties", LogPersistenceModeKey);

await RaiseActivityUpdated();
}

private LogPersistenceMode GetProperty(string propertyName, IDictionary<string,LogPersistenceMode> properties)
{
var prop = propertyName.Camelize();
if (properties.All(o => o.Key != prop))
properties[prop] = LogPersistenceMode.Default;
return properties[prop];
}
private void SetProperty(string propertyName, IDictionary<string, LogPersistenceMode> properties, LogPersistenceMode value)
{
var prop = propertyName.Camelize();
properties[prop] = value;
}
private async Task RaiseActivityUpdated()
{
if (OnActivityUpdated != null)
await OnActivityUpdated(Activity!);
}
}

/// <summary>
/// Defines the Persistence Strategy Configuration for an activity
/// </summary>
public class PersistenceActivityConfiguration
{
/// <summary>
/// Default Configuration Strategy for the activity
/// </summary>
public LogPersistenceMode Default { get; set; } = LogPersistenceMode.Default;

/// <summary>
/// Define Configuration Strategy for each Input properties
/// </summary>
public IDictionary<string, LogPersistenceMode> Inputs { get; set; } = new Dictionary<string, LogPersistenceMode>();

/// <summary>
/// Define Configuration Strategy for each Output properties
/// </summary>
public IDictionary<string, LogPersistenceMode> Outputs { get; set; } = new Dictionary<string, LogPersistenceMode>();
}

Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
@using Elsa.Api.Client.Resources.WorkflowDefinitions.Enums
@using Variant = MudBlazor.Variant
@using Elsa.Api.Client.Resources.WorkflowActivationStrategies.Models
@using Elsa.Api.Client.Resources.IncidentStrategies.Models
Expand Down Expand Up @@ -36,14 +37,26 @@
<MudSelectItem T="IncidentStrategyDescriptor" Value="@strategy">@(strategy?.DisplayName ?? "Default")</MudSelectItem>
}
</MudSelect>
<MudSelect
Label="Log Persistence Mode"
T="LogPersistenceMode?"
Variant="@Variant.Outlined"
Value="@_selectedLogPersistenceMode"
ValueChanged="@OnLogPersistenceModeChanged"
ReadOnly="IsReadOnly">
@foreach (LogPersistenceMode item in Enum.GetValues(typeof(LogPersistenceMode)))
{
<MudSelectItem Value="@((LogPersistenceMode?)item)">@item</MudSelectItem>
}
</MudSelect>
<MudField Variant="Variant.Text" HelperText="Allow this workflow to be used as an activity." Margin="Margin.None">
<MudCheckBox
T="bool?"
Label="Usable as activity"
Checked="@(WorkflowDefinition.Options.UsableAsActivity == true)"
CheckedChanged="@OnUsableAsActivityCheckChanged"
Dense=" true"
ReadOnly=" IsReadOnly"/>
Dense="true"
ReadOnly="IsReadOnly"/>
</MudField>
@if (WorkflowDefinition.Options.UsableAsActivity == true)
{
Expand All @@ -54,7 +67,7 @@
Dense="@true"
Checked="@(WorkflowDefinition.Options.AutoUpdateConsumingWorkflows)"
CheckedChanged="@OnAutoUpdateConsumingWorkflowsCheckChanged"
ReadOnly=" IsReadOnly"/>
ReadOnly="IsReadOnly"/>
</MudField>
<MudTextField
T="string"
Expand Down
Loading

0 comments on commit 145dfbb

Please sign in to comment.