From bfecd95989c4c48e1200f056f03e4d26e23853fb Mon Sep 17 00:00:00 2001 From: Julian Purse Date: Wed, 2 Oct 2024 13:15:51 +0200 Subject: [PATCH 1/3] enhance graph to indicate flow --- CHANGELOG.md | 1 + nflow-explorer/src/component/StateGraph.jsx | 45 ++++++++++++++++--- nflow-explorer/src/component/StateGraph.scss | 3 ++ .../WorkflowInstanceDetailsPage.tsx | 2 +- 4 files changed, 43 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d4f2bce8d..6493f7462 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ - Support Azure AD authentication in Explorer (see nflow-explorer/src/config.js for configuration options) - Improve REST API error response handling - Sort state variables by name + - indicate workflow states used in graph and show active state in graph - Use ReactJS 18.x, material UI 5.x - Replace Create React App -build by Vite - `nflow-engine` diff --git a/nflow-explorer/src/component/StateGraph.jsx b/nflow-explorer/src/component/StateGraph.jsx index d68ca4091..140c50fd9 100644 --- a/nflow-explorer/src/component/StateGraph.jsx +++ b/nflow-explorer/src/component/StateGraph.jsx @@ -20,22 +20,53 @@ import './StateGraph.scss'; // - zoom and pan state graph // TODO move to service.ts? -function createGraph(definition) { +function createGraph(props) { const g = new dagreD3.graphlib.Graph().setGraph({}); - const states = definition.states; + const states = props.definition.states; // create nodes for (let state of states) { g.setNode(state.id, {label: state.id, class: `node-${state.type}`}); // Round the corners of the nodes const node = g.node(state.id); node.rx = node.ry = 5; + + //if instance is provided, highlight with the .active + // + if (props.instance && props.instance.state === state.id) { + node.class += ' current-state'; + + } + + } + + function hasNavigatedState(fromState, toState, instance) { + //reverse iterate through the actions, + //when we have two actions in sequence that match the from state and the to state we return true + const actions = instance.actions; + + for (let i = 0; i < actions.length - 1; i++) { + // Check if the current action state matches the toState (since it's reversed) + if (actions[i].state === toState && actions[i + 1].state === fromState) { + return true; + } + } + if(actions[0].state == fromState && toState == instance.state){ + //this is the final state where there is no action showing + return true; + } + + return false; } // create edges between nodes for (let state of states) { for (let transition of state.transitions || []) { + var hasNavigated = false; + if (props.instance) { + hasNavigated = hasNavigatedState(state.id, transition, props.instance); + } g.setEdge(state.id, transition, { - class: 'edge-normal', + class: 'edge-normal' + (hasNavigated ? ' active' : ''), curve: d3.curveBasis, arrowhead: 'normal' }); @@ -46,8 +77,8 @@ function createGraph(definition) { curve: d3.curveBasis, arrowhead: 'normal' }); - } else if (definition.onError) { - g.setEdge(state.id, definition.onError, { + } else if (props.definition.onError) { + g.setEdge(state.id, props.definition.onError, { class: 'edge-error', curve: d3.curveBasis, arrowhead: 'normal' @@ -84,8 +115,8 @@ function render(g, selector) { function StateGraph(props) { useEffect(() => { - console.info('StateGraph', props.definition); - const g = createGraph(props.definition); + console.info('StateGraph', props); + const g = createGraph(props); render(g, 'svg#stategraph'); return () => { // Remove svg element which is created in render(), since it is not managed by React diff --git a/nflow-explorer/src/component/StateGraph.scss b/nflow-explorer/src/component/StateGraph.scss index 7a8fbdc98..7a72388d2 100644 --- a/nflow-explorer/src/component/StateGraph.scss +++ b/nflow-explorer/src/component/StateGraph.scss @@ -132,6 +132,7 @@ .edge-error.active, .edge-failure.active .edge-unexpected { stroke-width: 2px; + stroke: red; } .edge-normal.selected, @@ -166,6 +167,8 @@ /* */ g.current-state > g > g > text { text-decoration: underline; + fill: red; + font-weight: bold; } /* diff --git a/nflow-explorer/src/workflow-instance/WorkflowInstanceDetailsPage.tsx b/nflow-explorer/src/workflow-instance/WorkflowInstanceDetailsPage.tsx index aaabbd706..5aca10566 100644 --- a/nflow-explorer/src/workflow-instance/WorkflowInstanceDetailsPage.tsx +++ b/nflow-explorer/src/workflow-instance/WorkflowInstanceDetailsPage.tsx @@ -161,7 +161,7 @@ const InstanceSummary = ({ - + From 41c6e71f30533cbfe6671935010bbf47d3de0e69 Mon Sep 17 00:00:00 2001 From: Julian Purse Date: Thu, 3 Oct 2024 12:10:06 +0200 Subject: [PATCH 2/3] change to blue --- nflow-explorer/src/component/StateGraph.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nflow-explorer/src/component/StateGraph.scss b/nflow-explorer/src/component/StateGraph.scss index 7a72388d2..c7a5b898f 100644 --- a/nflow-explorer/src/component/StateGraph.scss +++ b/nflow-explorer/src/component/StateGraph.scss @@ -132,7 +132,7 @@ .edge-error.active, .edge-failure.active .edge-unexpected { stroke-width: 2px; - stroke: red; + stroke: blue; } .edge-normal.selected, From defe3c1bdbaf2f6afe70959e0e94a07313f23b7c Mon Sep 17 00:00:00 2001 From: Julian Purse Date: Thu, 3 Oct 2024 12:43:46 +0200 Subject: [PATCH 3/3] update current state colour also to blue --- nflow-explorer/src/component/StateGraph.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nflow-explorer/src/component/StateGraph.scss b/nflow-explorer/src/component/StateGraph.scss index c7a5b898f..6929d9602 100644 --- a/nflow-explorer/src/component/StateGraph.scss +++ b/nflow-explorer/src/component/StateGraph.scss @@ -167,7 +167,7 @@ /* */ g.current-state > g > g > text { text-decoration: underline; - fill: red; + fill: blue; font-weight: bold; }