Skip to content

Commit

Permalink
Improve data display in workflow viewer
Browse files Browse the repository at this point in the history
Condensed the code for displaying activity state, outcomes, and output data in the workflow instance viewer. Added no-data alerts and revamped refresh mechanisms to enhance user interaction and provide informative feedback when data is missing.
  • Loading branch information
sfmskywalker committed Mar 14, 2024
1 parent af83ebe commit 5900f7c
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 50 deletions.
64 changes: 44 additions & 20 deletions src/framework/Elsa.Studio.Shared/Components/DataPanel.razor
Expand Up @@ -4,26 +4,39 @@
<MudSimpleTable Outlined="true" Striped="false" Dense="true" Elevation="0" Bordered="false">
<tbody>
@{
var data = HideEmptyValues ? Data.Where(x => !string.IsNullOrWhiteSpace(x.Value.Text)) : Data;
var data = (HideEmptyValues
? Data.Where(x => !string.IsNullOrWhiteSpace(x.Value.Text))
: Data)
.ToDictionary(x => x.Key, x => x.Value);
}
@foreach (var item in data)
@if (data.Any())
{
<tr>
<td style="width: 200px;">@item.Key</td>
<td style="width: 50px;">
<MudIconButton Icon="@Icons.Material.Outlined.ContentCopy" Size="Size.Small" Title="Copy" OnClick="@(() => OnCopyClicked(item.Value.Text!))" Disabled="@(string.IsNullOrWhiteSpace(item.Value.Text))"/>
</td>
<td>
@if (!string.IsNullOrWhiteSpace(item.Value.Link))
{
<MudLink Href="@item.Value.Link">@item.Value.Text</MudLink>
}
else
{
<span>@item.Value.Text</span>
}
</td>
</tr>
@foreach (var item in data)
{
<tr>
<td style="width: 200px;">@item.Key</td>
<td style="width: 50px;">
<MudIconButton Icon="@Icons.Material.Outlined.ContentCopy" Size="Size.Small" Title="Copy" OnClick="@(() => OnCopyClicked(item.Value.Text!))" Disabled="@(string.IsNullOrWhiteSpace(item.Value.Text))"/>
</td>
<td>
@if (!string.IsNullOrWhiteSpace(item.Value.Link))
{
<MudLink Href="@item.Value.Link">@item.Value.Text</MudLink>
}
else
{
<span>@item.Value.Text</span>
}
</td>
</tr>
}
}
else
{
if (ShowNoDataAlert)
{
<MudAlert Severity="Severity.Normal" Dense="true" Variant="Variant.Text">@NoDataMessage</MudAlert>
}
}
</tbody>
</MudSimpleTable>
Expand All @@ -42,8 +55,19 @@
[Parameter]
public bool HideEmptyValues { get; set; }

[Inject]
private IClipboard Clipboard { get; set; } = default!;
/// <summary>
/// If true, a message will be displayed when there is no data.
/// </summary>
[Parameter]
public bool ShowNoDataAlert { get; set; }

/// <summary>
/// The message to display when there is no data.
/// </summary>
[Parameter]
public string NoDataMessage { get; set; } = "No data available.";

[Inject] private IClipboard Clipboard { get; set; } = default!;

private async Task OnCopyClicked(string value)
{
Expand Down
Expand Up @@ -41,9 +41,14 @@ public record ActivityExecutionRecordTableRow(int Number, ActivityExecutionRecor

private ActivityExecutionRecord? LastActivityExecution => ActivityExecutions.LastOrDefault();

private IEnumerable<ActivityExecutionRecordTableRow> Items =>
ActivityExecutions.Select((x, i) => new ActivityExecutionRecordTableRow(i + 1, x));

private IEnumerable<ActivityExecutionRecordTableRow> Items
{
get
{
return ActivityExecutions.Select((x, i) => new ActivityExecutionRecordTableRow(i + 1, x));
}
}

private ActivityExecutionRecord? SelectedItem { get; set; } = default!;

private IDictionary<string, DataPanelItem> ActivityInfo { get; set; } = new Dictionary<string, DataPanelItem>();
Expand All @@ -55,16 +60,24 @@ public record ActivityExecutionRecordTableRow(int Number, ActivityExecutionRecor
private IDictionary<string, string?> SelectedOutcomesData { get; set; } = new Dictionary<string, string?>();
private IDictionary<string, string?> SelectedOutputData { get; set; } = new Dictionary<string, string?>();

/// <summary>
/// Refreshes the component.
/// </summary>
public void Refresh()
{
CreateDataModels();
}

/// <inheritdoc />
protected override void OnParametersSet()
{
SelectedItem = null;
CreateDataModels();
}

/// <inheritdoc />
protected override void OnInitialized()
{
SelectedItem = null;
CreateDataModels();
}

private void CreateDataModels()
Expand Down
Expand Up @@ -37,30 +37,22 @@
</PagerContent>
</MudTable>

<div>
@if (SelectedActivityState.Any())
{
@if (SelectedItem != null)
{
<div>
<div>
<MudText Typo="Typo.overline" GutterBottom="true" Align="Align.Left">State</MudText>
<DataPanel Data="@SelectedActivityState" HideEmptyValues="false"/>
<DataPanel Data="@SelectedActivityState" HideEmptyValues="false" ShowNoDataAlert="true" NoDataMessage="No state associated with this execution."/>
</div>
}

@if (SelectedOutcomesData.Any())
{
<div>
<MudText Typo="Typo.overline" GutterBottom="true" Align="Align.Left">Outcomes</MudText>
<DataPanel Data="@SelectedOutcomesData" HideEmptyValues="true"/>
<DataPanel Data="@SelectedOutcomesData" HideEmptyValues="true" ShowNoDataAlert="true" NoDataMessage="No outcomes associated with this execution."/>
</div>
}

@if (SelectedOutputData.Any())
{
<div>
<MudText Typo="Typo.overline" GutterBottom="true" Align="Align.Left">Output</MudText>
<DataPanel Data="@SelectedOutputData" HideEmptyValues="false"/>
<DataPanel Data="@SelectedOutputData" HideEmptyValues="false" ShowNoDataAlert="true" NoDataMessage="No output associated with this execution."/>
</div>
}
</div>
</div>
}
</MudStack>
</ScrollableWell>
Expand Up @@ -41,6 +41,17 @@ public record ActivityExecutionRecordTableRow(int Number, ActivityExecutionRecor
private IDictionary<string, DataPanelItem> SelectedActivityState { get; set; } = new Dictionary<string, DataPanelItem>();
private IDictionary<string, DataPanelItem> SelectedOutcomesData { get; set; } = new Dictionary<string, DataPanelItem>();
private IDictionary<string, DataPanelItem> SelectedOutputData { get; set; } = new Dictionary<string, DataPanelItem>();

/// <summary>
/// Refreshes the component.
/// </summary>
public void Refresh()
{
SelectedItem = null;
SelectedActivityState = new Dictionary<string, DataPanelItem>();
SelectedOutcomesData = new Dictionary<string, DataPanelItem>();
SelectedOutputData = new Dictionary<string, DataPanelItem>();
}

private void CreateSelectedItemDataModels(ActivityExecutionRecord? record)
{
Expand Down
Expand Up @@ -33,11 +33,11 @@
@if (SelectedActivity != null)
{
<MudTabPanel Text="Activity">
<ActivityDetailsTab Activity="@SelectedActivity" ActivityExecutions="SelectedActivityExecutions" VisiblePaneHeight="@_propertiesPaneHeight"/>
<ActivityDetailsTab @ref="_activityDetailsTab" Activity="@SelectedActivity" ActivityExecutions="SelectedActivityExecutions" VisiblePaneHeight="@_propertiesPaneHeight"/>
</MudTabPanel>

<MudTabPanel Text="Executions" BadgeData="@SelectedActivityExecutions.Count">
<ActivityExecutionsTab Activity="@SelectedActivity" ActivityExecutions="SelectedActivityExecutions" VisiblePaneHeight="@_propertiesPaneHeight"/>
<ActivityExecutionsTab @ref="_activityExecutionsTab" Activity="@SelectedActivity" ActivityExecutions="SelectedActivityExecutions" VisiblePaneHeight="@_propertiesPaneHeight"/>
</MudTabPanel>
}

Expand Down
Expand Up @@ -31,6 +31,8 @@ public partial class WorkflowInstanceDesigner : IAsyncDisposable
private WorkflowInstance _workflowInstance = default!;
private RadzenSplitterPane _activityPropertiesPane = default!;
private DiagramDesignerWrapper _designer = default!;
private ActivityDetailsTab? _activityDetailsTab = default!;
private ActivityExecutionsTab? _activityExecutionsTab = default!;
private int _propertiesPaneHeight = 300;
private IDictionary<string, ActivityNode> _activityNodeLookup = new Dictionary<string, ActivityNode>();
private readonly IDictionary<string, ICollection<ActivityExecutionRecord>> _activityExecutionRecordsLookup = new Dictionary<string, ICollection<ActivityExecutionRecord>>();
Expand Down Expand Up @@ -65,12 +67,13 @@ public partial class WorkflowInstanceDesigner : IAsyncDisposable
/// The activity selected callback.
/// </summary>
[Parameter]
public Func<JsonObject, Task>? ActivitySelected { get; set; }
public EventCallback<JsonObject> ActivitySelected { get; set; }

/// <summary>
/// An event that is invoked when a workflow definition is edited.
/// </summary>
[Parameter] public EventCallback<string> EditWorkflowDefinition { get; set; }
[Parameter]
public EventCallback<string> EditWorkflowDefinition { get; set; }

/// <summary>
/// Gets or sets the current selected sub-workflow.
Expand Down Expand Up @@ -223,8 +226,9 @@ private async Task HandleActivitySelectedAsync(JsonObject activity)
SelectedActivity = activity;
ActivityDescriptor = ActivityRegistry.Find(activity!.GetTypeName(), activity!.GetVersion());
SelectedActivityExecutions = await GetActivityExecutionRecordsAsync(activityNodeId);

StateHasChanged();
_activityDetailsTab?.Refresh();
_activityExecutionsTab?.Refresh();
}

private async Task<ICollection<ActivityExecutionRecord>> GetActivityExecutionRecordsAsync(string activityNodeId)
Expand Down Expand Up @@ -262,8 +266,10 @@ private async Task OnActivitySelected(JsonObject activity)
SelectedWorkflowExecutionLogRecord = null;
await HandleActivitySelectedAsync(activity);

if (ActivitySelected != null)
await ActivitySelected(activity);
var activitySelected = ActivitySelected;

if (activitySelected.HasDelegate)
await activitySelected.InvokeAsync(activity);
}

private async Task OnResize(RadzenSplitterResizeEventArgs arg)
Expand All @@ -289,7 +295,7 @@ private Task OnEditClicked()
}
}

var editWorkflowDefinition = this.EditWorkflowDefinition;
var editWorkflowDefinition = EditWorkflowDefinition;

if (editWorkflowDefinition.HasDelegate)
return editWorkflowDefinition.InvokeAsync(definitionId);
Expand Down
Expand Up @@ -23,7 +23,7 @@
WorkflowInstance="workflowInstance"
WorkflowDefinition="definition"
PathChanged="OnPathChanged"
ActivitySelected="ActivitySelected"
ActivitySelected="@ActivitySelected"
SelectedWorkflowExecutionLogRecord="SelectedWorkflowExecutionLogRecord"
EditWorkflowDefinition="EditWorkflowDefinition"
/>
Expand Down

0 comments on commit 5900f7c

Please sign in to comment.