From 5900f7cff1918b3c20d1d0e9e6c9a43d754a8abd Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Thu, 14 Mar 2024 14:55:06 +0100 Subject: [PATCH] Improve data display in workflow viewer 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. --- .../Components/DataPanel.razor | 64 +++++++++++++------ .../Components/ActivityDetailsTab.razor.cs | 23 +++++-- .../Components/ActivityExecutionsTab.razor | 24 +++---- .../Components/ActivityExecutionsTab.razor.cs | 11 ++++ .../Components/WorkflowInstanceDesigner.razor | 4 +- .../WorkflowInstanceDesigner.razor.cs | 18 ++++-- .../WorkflowInstanceWorkspace.razor | 2 +- 7 files changed, 96 insertions(+), 50 deletions(-) diff --git a/src/framework/Elsa.Studio.Shared/Components/DataPanel.razor b/src/framework/Elsa.Studio.Shared/Components/DataPanel.razor index 14b4ffb8..885d704b 100644 --- a/src/framework/Elsa.Studio.Shared/Components/DataPanel.razor +++ b/src/framework/Elsa.Studio.Shared/Components/DataPanel.razor @@ -4,26 +4,39 @@ @{ - 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()) { - - @item.Key - - - - - @if (!string.IsNullOrWhiteSpace(item.Value.Link)) - { - @item.Value.Text - } - else - { - @item.Value.Text - } - - + @foreach (var item in data) + { + + @item.Key + + + + + @if (!string.IsNullOrWhiteSpace(item.Value.Link)) + { + @item.Value.Text + } + else + { + @item.Value.Text + } + + + } + } + else + { + if (ShowNoDataAlert) + { + @NoDataMessage + } } @@ -42,8 +55,19 @@ [Parameter] public bool HideEmptyValues { get; set; } - [Inject] - private IClipboard Clipboard { get; set; } = default!; + /// + /// If true, a message will be displayed when there is no data. + /// + [Parameter] + public bool ShowNoDataAlert { get; set; } + + /// + /// The message to display when there is no data. + /// + [Parameter] + public string NoDataMessage { get; set; } = "No data available."; + + [Inject] private IClipboard Clipboard { get; set; } = default!; private async Task OnCopyClicked(string value) { diff --git a/src/modules/Elsa.Studio.Workflows/Components/WorkflowInstanceViewer/Components/ActivityDetailsTab.razor.cs b/src/modules/Elsa.Studio.Workflows/Components/WorkflowInstanceViewer/Components/ActivityDetailsTab.razor.cs index 2bd3cb5c..9a1519b7 100644 --- a/src/modules/Elsa.Studio.Workflows/Components/WorkflowInstanceViewer/Components/ActivityDetailsTab.razor.cs +++ b/src/modules/Elsa.Studio.Workflows/Components/WorkflowInstanceViewer/Components/ActivityDetailsTab.razor.cs @@ -41,9 +41,14 @@ public record ActivityExecutionRecordTableRow(int Number, ActivityExecutionRecor private ActivityExecutionRecord? LastActivityExecution => ActivityExecutions.LastOrDefault(); - private IEnumerable Items => - ActivityExecutions.Select((x, i) => new ActivityExecutionRecordTableRow(i + 1, x)); - + private IEnumerable Items + { + get + { + return ActivityExecutions.Select((x, i) => new ActivityExecutionRecordTableRow(i + 1, x)); + } + } + private ActivityExecutionRecord? SelectedItem { get; set; } = default!; private IDictionary ActivityInfo { get; set; } = new Dictionary(); @@ -55,16 +60,24 @@ public record ActivityExecutionRecordTableRow(int Number, ActivityExecutionRecor private IDictionary SelectedOutcomesData { get; set; } = new Dictionary(); private IDictionary SelectedOutputData { get; set; } = new Dictionary(); + /// + /// Refreshes the component. + /// + public void Refresh() + { + CreateDataModels(); + } + /// protected override void OnParametersSet() { - SelectedItem = null; - CreateDataModels(); } /// protected override void OnInitialized() { + SelectedItem = null; + CreateDataModels(); } private void CreateDataModels() diff --git a/src/modules/Elsa.Studio.Workflows/Components/WorkflowInstanceViewer/Components/ActivityExecutionsTab.razor b/src/modules/Elsa.Studio.Workflows/Components/WorkflowInstanceViewer/Components/ActivityExecutionsTab.razor index 80a89454..2b1b0354 100644 --- a/src/modules/Elsa.Studio.Workflows/Components/WorkflowInstanceViewer/Components/ActivityExecutionsTab.razor +++ b/src/modules/Elsa.Studio.Workflows/Components/WorkflowInstanceViewer/Components/ActivityExecutionsTab.razor @@ -37,30 +37,22 @@ -
- @if (SelectedActivityState.Any()) - { + @if (SelectedItem != null) + { +
State - +
- } - - @if (SelectedOutcomesData.Any()) - {
Outcomes - +
- } - - @if (SelectedOutputData.Any()) - {
Output - +
- } -
+
+ } \ No newline at end of file diff --git a/src/modules/Elsa.Studio.Workflows/Components/WorkflowInstanceViewer/Components/ActivityExecutionsTab.razor.cs b/src/modules/Elsa.Studio.Workflows/Components/WorkflowInstanceViewer/Components/ActivityExecutionsTab.razor.cs index 97d46e70..c3edf476 100644 --- a/src/modules/Elsa.Studio.Workflows/Components/WorkflowInstanceViewer/Components/ActivityExecutionsTab.razor.cs +++ b/src/modules/Elsa.Studio.Workflows/Components/WorkflowInstanceViewer/Components/ActivityExecutionsTab.razor.cs @@ -41,6 +41,17 @@ public record ActivityExecutionRecordTableRow(int Number, ActivityExecutionRecor private IDictionary SelectedActivityState { get; set; } = new Dictionary(); private IDictionary SelectedOutcomesData { get; set; } = new Dictionary(); private IDictionary SelectedOutputData { get; set; } = new Dictionary(); + + /// + /// Refreshes the component. + /// + public void Refresh() + { + SelectedItem = null; + SelectedActivityState = new Dictionary(); + SelectedOutcomesData = new Dictionary(); + SelectedOutputData = new Dictionary(); + } private void CreateSelectedItemDataModels(ActivityExecutionRecord? record) { diff --git a/src/modules/Elsa.Studio.Workflows/Components/WorkflowInstanceViewer/Components/WorkflowInstanceDesigner.razor b/src/modules/Elsa.Studio.Workflows/Components/WorkflowInstanceViewer/Components/WorkflowInstanceDesigner.razor index 5c581efe..5fdf359a 100644 --- a/src/modules/Elsa.Studio.Workflows/Components/WorkflowInstanceViewer/Components/WorkflowInstanceDesigner.razor +++ b/src/modules/Elsa.Studio.Workflows/Components/WorkflowInstanceViewer/Components/WorkflowInstanceDesigner.razor @@ -33,11 +33,11 @@ @if (SelectedActivity != null) { - + - + } diff --git a/src/modules/Elsa.Studio.Workflows/Components/WorkflowInstanceViewer/Components/WorkflowInstanceDesigner.razor.cs b/src/modules/Elsa.Studio.Workflows/Components/WorkflowInstanceViewer/Components/WorkflowInstanceDesigner.razor.cs index 08642575..7afc605e 100644 --- a/src/modules/Elsa.Studio.Workflows/Components/WorkflowInstanceViewer/Components/WorkflowInstanceDesigner.razor.cs +++ b/src/modules/Elsa.Studio.Workflows/Components/WorkflowInstanceViewer/Components/WorkflowInstanceDesigner.razor.cs @@ -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 _activityNodeLookup = new Dictionary(); private readonly IDictionary> _activityExecutionRecordsLookup = new Dictionary>(); @@ -65,12 +67,13 @@ public partial class WorkflowInstanceDesigner : IAsyncDisposable /// The activity selected callback. /// [Parameter] - public Func? ActivitySelected { get; set; } + public EventCallback ActivitySelected { get; set; } /// /// An event that is invoked when a workflow definition is edited. /// - [Parameter] public EventCallback EditWorkflowDefinition { get; set; } + [Parameter] + public EventCallback EditWorkflowDefinition { get; set; } /// /// Gets or sets the current selected sub-workflow. @@ -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> GetActivityExecutionRecordsAsync(string activityNodeId) @@ -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) @@ -289,7 +295,7 @@ private Task OnEditClicked() } } - var editWorkflowDefinition = this.EditWorkflowDefinition; + var editWorkflowDefinition = EditWorkflowDefinition; if (editWorkflowDefinition.HasDelegate) return editWorkflowDefinition.InvokeAsync(definitionId); diff --git a/src/modules/Elsa.Studio.Workflows/Components/WorkflowInstanceViewer/Components/WorkflowInstanceWorkspace.razor b/src/modules/Elsa.Studio.Workflows/Components/WorkflowInstanceViewer/Components/WorkflowInstanceWorkspace.razor index bbc33509..f5404d53 100644 --- a/src/modules/Elsa.Studio.Workflows/Components/WorkflowInstanceViewer/Components/WorkflowInstanceWorkspace.razor +++ b/src/modules/Elsa.Studio.Workflows/Components/WorkflowInstanceViewer/Components/WorkflowInstanceWorkspace.razor @@ -23,7 +23,7 @@ WorkflowInstance="workflowInstance" WorkflowDefinition="definition" PathChanged="OnPathChanged" - ActivitySelected="ActivitySelected" + ActivitySelected="@ActivitySelected" SelectedWorkflowExecutionLogRecord="SelectedWorkflowExecutionLogRecord" EditWorkflowDefinition="EditWorkflowDefinition" />