This is an automated email from the ASF dual-hosted git repository.

ptyin pushed a commit to branch 2.x
in repository https://gitbox.apache.org/repos/asf/incubator-seata.git


The following commit(s) were added to refs/heads/2.x by this push:
     new a0b2d9b78d feature: support autolayout in seata-statemachine-designer 
(#6415)
a0b2d9b78d is described below

commit a0b2d9b78dd09011fe7b540e8bd73af48bf3873e
Author: Durgesh Kadwe <[email protected]>
AuthorDate: Sat Mar 16 07:21:34 2024 +0530

    feature: support autolayout in seata-statemachine-designer (#6415)
    
    * issue: Resolve issue related to autolayout in seata-statemachine-designer
    
    * Delete all/.factorypath
    
    * Delete console/.factorypath
    
    * Delete integration/motan/.factorypath
    
    * Delete saga/seata-saga-statemachine-designer/package-lock.json
    
    * Delete 
seata-spring-autoconfigure/seata-spring-autoconfigure-client/.factorypath
    
    * Delete 
seata-spring-autoconfigure/seata-spring-autoconfigure-core/.factorypath
    
    * Delete 
seata-spring-autoconfigure/seata-spring-autoconfigure-server/.factorypath
    
    * Delete seata-spring-boot-starter/.factorypath
    
    * Delete saga/seata-saga-statemachine-designer/src/modeling/SagaExporter.js
    
    * Update Edge.js
    
    * Update SagaImporter.js
    
    * Update Node.js
    
    * removed debugger and console.log from SagaImporter.js
    
    * Added SagaExporter.js file
    
    * Revert "Delete saga/seata-saga-statemachine-designer/package-lock.json"
    
    This reverts commit 4e8f56ef7a64738c5fa251bfac4cff7822f2a20e.
    
    * fix eslint problems and revert package-lock.json
    
    * remove extra space lines
    
    * Added literal constant and optimize the code
    
    * fix eslint problems
    
    * use 'is' to substitute conditions
    
    * register 2.x.md
    
    * register 2.x.md
    
    ---------
    
    Co-authored-by: Durgesh.Kadwe <[email protected]>
    Co-authored-by: ptyin <[email protected]>
---
 changes/en-us/2.x.md                               |   2 +
 changes/zh-cn/2.x.md                               |   2 +
 .../.eslintrc.json                                 |   3 +-
 .../src/modeling/SagaImporter.js                   | 115 +++++-
 .../src/spec/style/Node.js                         | 393 +++++++++++++++++++++
 .../src/utils/index.js                             |   8 +
 6 files changed, 508 insertions(+), 15 deletions(-)

diff --git a/changes/en-us/2.x.md b/changes/en-us/2.x.md
index d7b8ff8ad9..60602ebc53 100644
--- a/changes/en-us/2.x.md
+++ b/changes/en-us/2.x.md
@@ -8,6 +8,7 @@ Add changes here for all PR submitted to the 2.x branch.
 - [[#6169](https://github.com/apache/incubator-seata/pull/6169)] full support 
for states in the refactored state machine designer
 - [[#6230](https://github.com/apache/incubator-seata/pull/6230)] RocketMQ 
transaction are supported
 - [[#6326](https://github.com/apache/incubator-seata/pull/6326)] support raft 
node metadata sync
+- [[#6415](https://github.com/apache/incubator-seata/pull/6415)] support 
autolayout in seata-statemachine-designer
 
 ### bugfix:
 - [[#6090](https://github.com/apache/incubator-seata/pull/6090)] fix the TCC 
aspect exception handling process, do not wrapping the internal call exceptions
@@ -164,5 +165,6 @@ Thanks to these contributors for their code commits. Please 
report an unintended
 - [saberyjs](https://github.com/SABERYJS)
 - [gggyd123](https://github.com/gggyd123)
 - [jonasHanhan](https://github.com/jonasHanhan)
+- [Code-breaker1998](https://github.com/Code-breaker1998)
 
 Also, we receive many valuable issues, questions and advices from our 
community. Thanks for you all.
diff --git a/changes/zh-cn/2.x.md b/changes/zh-cn/2.x.md
index 78a45a9b8e..0720041568 100644
--- a/changes/zh-cn/2.x.md
+++ b/changes/zh-cn/2.x.md
@@ -8,6 +8,7 @@
 - [[#6169](https://github.com/apache/incubator-seata/pull/6169)] 支持新版本状态机设计器
 - [[#6230](https://github.com/apache/incubator-seata/pull/6230)] 支持RocketMQ消息事务
 - [[#6326](https://github.com/apache/incubator-seata/pull/6326)] 
支持raft节点间的元数据同步
+- [[#6415](https://github.com/apache/incubator-seata/pull/6415)] 支持 Saga 
设计器的自动布局
 
 ### bugfix:
 - [[#6090](https://github.com/apache/incubator-seata/pull/6090)] 
修复tcc切面异常处理过程,不对内部调用异常做包装处理,直接向外抛出
@@ -166,5 +167,6 @@
 - [saberyjs](https://github.com/SABERYJS)
 - [gggyd123](https://github.com/gggyd123)
 - [jonasHanhan](https://github.com/jonasHanhan)
+- [Code-breaker1998](https://github.com/Code-breaker1998)
 
 同时,我们收到了社区反馈的很多有价值的issue和建议,非常感谢大家。
diff --git a/saga/seata-saga-statemachine-designer/.eslintrc.json 
b/saga/seata-saga-statemachine-designer/.eslintrc.json
index 8720470c67..e7a4bad512 100644
--- a/saga/seata-saga-statemachine-designer/.eslintrc.json
+++ b/saga/seata-saga-statemachine-designer/.eslintrc.json
@@ -25,6 +25,7 @@
     "react/no-deprecated": 0,
     "react/react-in-jsx-scope": 0,
     "react/jsx-no-bind": 0,
-    "no-underscore-dangle": 0
+    "no-underscore-dangle": 0,
+    "no-restricted-syntax": 0
   }
 }
diff --git a/saga/seata-saga-statemachine-designer/src/modeling/SagaImporter.js 
b/saga/seata-saga-statemachine-designer/src/modeling/SagaImporter.js
index 4234136edf..a97c0d88a7 100644
--- a/saga/seata-saga-statemachine-designer/src/modeling/SagaImporter.js
+++ b/saga/seata-saga-statemachine-designer/src/modeling/SagaImporter.js
@@ -41,6 +41,49 @@ function collectWaypoints(edge) {
   return null;
 }
 
+function addArrayList(definitions) {
+  const adjList = new Map();
+  forEach(definitions.States, (semantic) => {
+    // Initialize an array to store values for the key
+    adjList.set(semantic, []);
+
+    if (semantic.Next || semantic.CompensateState || semantic.Choices) {
+      const options = [];
+
+      if (semantic.Next) {
+        options.push(semantic.Next);
+      }
+
+      if (semantic.CompensateState) {
+        options.push(semantic.CompensateState);
+      }
+
+      if (semantic.Choices) {
+        semantic.Choices.forEach((option) => options.push(option.Next));
+      }
+
+      const existingValues = adjList.get(semantic);
+      options.forEach((next) => {
+        existingValues.push(definitions.States[next]);
+      });
+      adjList.set(semantic, existingValues);
+    }
+  });
+  return adjList;
+}
+
+function addCatchList(definitions, nodes) {
+  const adjList = new Map();
+  adjList.set(nodes, []);
+  nodes.Catch.forEach((option) => {
+    const { Next } = option;
+    const existingValues = adjList.get(nodes);
+    existingValues.push(definitions.States[Next]);
+    adjList.set(nodes, existingValues);
+  });
+  return adjList;
+}
+
 export default function SagaImporter(
   sagaFactory,
   eventBus,
@@ -76,38 +119,77 @@ SagaImporter.prototype.import = function (definitions) {
     const root = this.sagaFactory.create('StateMachine');
     root.importJson(definitions);
     this.root(root);
-
     // Add start state
     let start = this.sagaFactory.create('StartState');
+    let stateArrayList = new Map();
     start.importJson(definitions);
+    let begin = start;
     start = this.add(start);
-
     const edges = [];
     const catches = [];
     forEach(definitions.States, (semantic) => {
       const state = this.sagaFactory.create(semantic.Type);
-      state.importJson(semantic);
+
+      if (semantic.style === undefined) {
+        stateArrayList = addArrayList(definitions);
+        state.importStates(definitions, semantic, begin, stateArrayList);
+      } else {
+        state.importJson(semantic);
+        begin = state;
+      }
       const host = this.add(state);
-      if (semantic.edge) {
+
+      if (semantic.edge === undefined) {
+        state.importEdges(definitions, semantic);
+        if (semantic.edge) {
+          edges.push(...Object.values(semantic.edge));
+        }
+      } else {
         edges.push(...Object.values(semantic.edge));
       }
-      if (semantic.catch) {
-        const node = this.sagaFactory.create('Catch');
-        node.importJson(semantic.catch);
-        const source = this.add(node);
+
+      if (semantic.Catch) {
+        let source;
+        if (semantic.catch === undefined) {
+          const node = this.sagaFactory.create('Catch');
+          const catchList = addCatchList(definitions, semantic);
+          node.addCatch(definitions, semantic, catchList, stateArrayList);
+          source = this.add(node);
+        } else {
+          const node = this.sagaFactory.create('Catch');
+          node.importJson(semantic.catch);
+          source = this.add(node);
+        }
+
+        if (semantic.catch.edge === undefined) {
+          state.importCatchesEdges(definitions, semantic);
+        }
         if (semantic.catch.edge) {
           semantic.Catch.forEach((exceptionMatch) => {
             if (semantic.catch.edge[exceptionMatch.Next]) {
               semantic.catch.edge[exceptionMatch.Next].Exceptions = 
exceptionMatch.Exceptions;
             }
           });
+
+          this.modeling.updateAttachment(source, host);
+          catches.push({
+            source,
+            edges: Object.values(semantic.catch.edge),
+          });
         }
-        this.modeling.updateAttachment(source, host);
-        catches.push({ source, edges: Object.values(semantic.catch.edge) });
       }
     });
 
-    // Add start edge
+    if ((definitions.edge === undefined) && (definitions.States)) {
+      start = this.sagaFactory.create('StartState');
+      definitions.edge = {};
+      start.importJsonEdges(definitions);
+      if (definitions.edge) {
+        const startEdge = this.sagaFactory.create('Transition');
+        startEdge.importJson(definitions.edge);
+        this.add(startEdge, { source: start });
+      }
+    }
     if (definitions.edge) {
       const startEdge = this.sagaFactory.create('Transition');
       startEdge.importJson(definitions.edge);
@@ -121,7 +203,10 @@ SagaImporter.prototype.import = function (definitions) {
     });
 
     forEach(catches, (oneCatch) => {
-      const { source, edges: exceptionMatches } = oneCatch;
+      const {
+        source,
+        edges: exceptionMatches,
+      } = oneCatch;
       forEach(exceptionMatches, (semantic) => {
         const exceptionMatch = this.sagaFactory.create(semantic.Type);
         exceptionMatch.importJson(semantic);
@@ -133,7 +218,10 @@ SagaImporter.prototype.import = function (definitions) {
     console.error(error);
   }
 
-  this.eventBus.fire('import.done', { error, warnings });
+  this.eventBus.fire('import.done', {
+    error,
+    warnings,
+  });
 };
 
 SagaImporter.prototype.root = function (semantic) {
@@ -181,7 +269,6 @@ SagaImporter.prototype.add = function (semantic, attrs = 
{}) {
         target,
         waypoints,
       });
-      // console.log(elementDefinition);
 
       element = elementFactory.createConnection(elementDefinition);
 
diff --git a/saga/seata-saga-statemachine-designer/src/spec/style/Node.js 
b/saga/seata-saga-statemachine-designer/src/spec/style/Node.js
index dc06861bb1..b872a16fda 100644
--- a/saga/seata-saga-statemachine-designer/src/spec/style/Node.js
+++ b/saga/seata-saga-statemachine-designer/src/spec/style/Node.js
@@ -18,15 +18,408 @@
 import { assign } from 'min-dash';
 import BaseSpec from '../BaseSpec';
 import NodeStyle from './NodeStyle';
+import { is } from '../../utils/index';
 // import THUMBNAIL from '../icons/bpmn-icon-service-task.svg';
 
+const OFFSET_X = 36; const OFFSET_Y = 18; const OFFSET_TARGET_X = 20;
+const DEFAULT_X = 200; const DEFAULT_Y = 200; const OFFSET_TARGET_Y = 40;
+const DEFAULT_WIDTH = 100; const DEFAULT_HEIGHT = 80;
+
 export default class Node extends BaseSpec {
   style = new NodeStyle();
 
   importJson(json) {
+    if (json.style === undefined) {
+      json.style = {};
+      json.style.bounds = {
+        x: DEFAULT_X,
+        y: DEFAULT_Y,
+        width: OFFSET_X,
+        height: OFFSET_X,
+      };
+    }
     assign(this.style.bounds, json.style.bounds);
   }
 
+  isElementPresent(visited, target) {
+    for (const element of visited) {
+      if (element[0] === target[0] && element[1] === target[1]) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  addWaypoints(
+    source,
+    target,
+    definitions,
+    type,
+    targetWidth,
+    targetHeight,
+    sourceWidth,
+    sourceHeight,
+  ) {
+    const sourceX = definitions.States[source].style.bounds.x;
+    const sourceY = definitions.States[source].style.bounds.y;
+    const targetX = definitions.States[target].style.bounds.x;
+    const targetY = definitions.States[target].style.bounds.y;
+    let waypoints1 = [];
+    if (type === 'Transition') {
+      waypoints1 = [{
+        x: sourceX + sourceWidth,
+        y: sourceY + (sourceHeight / 2),
+      }, {
+        x: targetX - OFFSET_TARGET_X,
+        y: targetY + (targetHeight / 2),
+      }, {
+        x: targetX,
+        y: targetY + (targetHeight / 2),
+      }];
+    } else if (type === 'Compensation') {
+      waypoints1 = [{
+        x: sourceX + (sourceWidth / 2),
+        y: sourceY + sourceHeight,
+      }, {
+        x: targetX + (targetWidth / 2),
+        y: targetY - OFFSET_TARGET_X,
+      }, {
+        x: targetX + (targetWidth / 2),
+        y: targetY,
+      }];
+    } else if (sourceX === targetX) {
+      waypoints1 = [{
+        x: sourceX + (sourceWidth / 2),
+        y: sourceY + sourceHeight,
+      }, {
+        x: targetX + (targetWidth / 2),
+        y: targetY - OFFSET_TARGET_X,
+      }, {
+        x: targetX + (targetWidth / 2),
+        y: targetY,
+      }];
+    } else if (sourceY === targetY) {
+      waypoints1 = [{
+        x: sourceX + sourceWidth,
+        y: sourceY + (sourceHeight / 2),
+      }, {
+        x: targetX - OFFSET_TARGET_X,
+        y: targetY + (targetHeight / 2),
+      }, {
+        x: targetX,
+        y: targetY + (targetHeight / 2),
+      }];
+    }
+
+    return {
+      style: {
+        waypoints: waypoints1,
+        source,
+        target,
+      },
+      Type: type,
+    };
+  }
+
+  importEdges(definitions, startState) {
+    if (startState.Next) {
+      this.addEdge(startState.Name, startState.Next, definitions, 
'Transition', startState);
+    }
+
+    if (startState.CompensateState) {
+      this.addEdge(startState.Name, startState.CompensateState, definitions, 
'Compensation', startState);
+    }
+
+    if (startState.Choices) {
+      for (const option of startState.Choices) {
+        this.addEdge(startState.Name, option.Next, definitions, 'ChoiceEntry', 
startState);
+      }
+    }
+
+    this.importJson(startState);
+  }
+
+  addEdge(source, target, definitions, type, startState) {
+    const sourceWidth = this.calculateWidth(definitions.States[source]);
+    const sourceHeight = this.calculateHeight(definitions.States[source]);
+    const targetWidth = this.calculateWidth(definitions.States[target]);
+    const targetHeight = this.calculateHeight(definitions.States[target]);
+
+    const elementJson = this.addWaypoints(
+      source,
+      target,
+      definitions,
+      type,
+      targetWidth,
+      targetHeight,
+      sourceWidth,
+      sourceHeight,
+    );
+    startState.edge = Object.assign(startState.edge || {}, { [target]: 
elementJson });
+  }
+
+  calculateWidth(state) {
+    if (is(state, 'Task')) {
+      return 100;
+    }
+    if (is(state, 'Event')) {
+      return 36;
+    }
+    if (is(state, 'Choice')) {
+      return 50;
+    }
+    return 100;
+  }
+
+  calculateHeight(state) {
+    if (is(state, 'Task')) {
+      return 80;
+    }
+    if (is(state, 'Event')) {
+      return 36;
+    }
+    if (is(state, 'Choice')) {
+      return 50;
+    }
+    return 80;
+  }
+
+  importJsonEdges(json) {
+    if (json.States) {
+      const targetX = json.States[json.StartState].style.bounds.x;
+      const targetY = json.States[json.StartState].style.bounds.y;
+      json.edge = {
+        style: {
+          waypoints: [{
+            x: DEFAULT_X + OFFSET_X,
+            y: DEFAULT_X + OFFSET_Y,
+          }, {
+            x: targetX - OFFSET_TARGET_X,
+            y: targetY + OFFSET_TARGET_Y,
+          }, {
+            x: targetX,
+            y: targetY + OFFSET_TARGET_Y,
+          }],
+          target: json.StartState,
+        },
+        Type: 'Transition',
+      };
+    }
+    this.importJson(json);
+  }
+
+  importCatchesEdges(definitions, startState) {
+    const catchEdges = startState.Catch;
+    for (const option of catchEdges) {
+      const sourceX = definitions.States[startState.Name].catch.style.bounds.x;
+      const sourceY = definitions.States[startState.Name].catch.style.bounds.y;
+      const targetX = definitions.States[option.Next].style.bounds.x;
+      const targetY = definitions.States[option.Next].style.bounds.y;
+      let waypoints1 = [];
+      if (is(option.Next, 'Task')) {
+        waypoints1 = [{
+          x: sourceX + OFFSET_Y,
+          y: sourceY,
+        }, {
+          x: targetX + DEFAULT_WIDTH / 2,
+          y: targetY + DEFAULT_WIDTH,
+        }, {
+          x: targetX + DEFAULT_WIDTH / 2,
+          y: (targetY + DEFAULT_WIDTH) - OFFSET_TARGET_X,
+        }];
+      } else {
+        waypoints1 = [{
+          x: sourceX + OFFSET_Y,
+          y: sourceY,
+        }, {
+          x: targetX + OFFSET_Y,
+          y: (targetY + OFFSET_X) + OFFSET_TARGET_X,
+        }, {
+          x: targetX + OFFSET_Y,
+          y: targetY + OFFSET_X,
+        }];
+      }
+      startState.catch.edge = assign(startState.catch.edge || {}, {
+        [option.Next]: {
+          style: {
+            waypoints: waypoints1,
+            source: startState.Name,
+            target: option.Next,
+          },
+          Type: 'ExceptionMatch',
+        },
+      });
+    }
+    this.importJson(startState.catch);
+  }
+
+  addCatch(definitions, node, catchList, adjList) {
+    node.catch = {};
+    if (node.Catch) {
+      const {
+        style: {
+          bounds: {
+            x,
+            y,
+          },
+        },
+      } = node;
+      const newX = x;
+      const newY = y;
+      node.catch.style = {};
+      node.catch.style.bounds = {
+        x: newX + DEFAULT_WIDTH / 2,
+        y: newY - OFFSET_TARGET_X,
+        width: OFFSET_X,
+        height: OFFSET_X,
+      };
+    }
+    this.importJson(node.catch);
+
+    let prev = node.catch;
+    let width1;
+    let height1;
+    catchList.get(node).forEach((semantic) => {
+      if (is(semantic, 'Task')) {
+        width1 = DEFAULT_WIDTH;
+        height1 = DEFAULT_HEIGHT;
+      } else {
+        width1 = OFFSET_X;
+        height1 = OFFSET_X;
+      }
+      semantic.style = {};
+      semantic.style.bounds = {
+        x: prev.style.bounds.x - DEFAULT_WIDTH / 2,
+        y: prev.style.bounds.y - DEFAULT_WIDTH,
+        width: width1,
+        height: height1,
+      };
+      prev = semantic;
+
+      this.importStates(definitions, semantic, null, adjList);
+    });
+  }
+
+  importStates(definitions, startState, begin, adjList) {
+    const visited = [];
+    const queue = [];
+    if (begin !== null) {
+      if (startState.style === undefined) {
+        startState.style = {};
+        if (startState.style.bounds === undefined) {
+          startState.style.bounds = {
+            x: begin.style.bounds.x + 150, // Adjust x-coordinate
+            y: begin.style.bounds.y, // Adjust y-coordinate
+            width: DEFAULT_WIDTH,
+            height: DEFAULT_HEIGHT,
+          };
+        }
+      }
+      this.importJson(startState);
+    }
+    queue.push(startState);
+
+    function setBounds(neighbor, x, y, width1, height1) {
+      if (neighbor.style.bounds === undefined) {
+        neighbor.style.bounds = {
+          x, // Adjust x-coordinate
+          y, // Adjust y-coordinate
+          width: width1,
+          height: height1,
+        };
+        visited.push([x, y]);
+      }
+    }
+
+    while (queue.length) {
+      const currentState = queue.shift();
+
+      adjList.get(currentState).forEach((neighbor) => {
+        if (neighbor.style === undefined) {
+          neighbor.style = {};
+          if (is(neighbor, 'End')) {
+            const target = [];
+            target.push(currentState.style.bounds.x + 150, 
currentState.style.bounds.y);
+            if (this.isElementPresent(visited, target)) {
+              setBounds(
+                neighbor,
+                currentState.style.bounds.x + 150,
+                currentState.style.bounds.y,
+                OFFSET_X,
+                OFFSET_X,
+              );
+            } else {
+              setBounds(
+                neighbor,
+                currentState.style.bounds.x,
+                currentState.style.bounds.y + 150,
+                OFFSET_X,
+                OFFSET_X,
+              );
+            }
+          }
+
+          if (is(neighbor, 'Task') && !neighbor.IsForCompensation) {
+            const target = [];
+            target.push(currentState.style.bounds.x + 150, 
currentState.style.bounds.y);
+            if (this.isElementPresent(visited, target)) {
+              setBounds(
+                neighbor,
+                currentState.style.bounds.x + 150,
+                currentState.style.bounds.y,
+                DEFAULT_WIDTH,
+                DEFAULT_HEIGHT,
+              );
+            } else {
+              setBounds(
+                neighbor,
+                currentState.style.bounds.x,
+                currentState.style.bounds.y + 150,
+                DEFAULT_WIDTH,
+                DEFAULT_HEIGHT,
+              );
+            }
+
+            const { Name } = neighbor;
+            queue.push(definitions.States[Name]);
+          } else if (is(neighbor, 'Task') && neighbor.IsForCompensation) {
+            const target = [];
+            target.push(currentState.style.bounds.x, 
currentState.style.bounds.y + 150);
+            if (this.isElementPresent(visited, target)) {
+              setBounds(
+                neighbor,
+                currentState.style.bounds.x,
+                currentState.style.bounds.y + 150,
+                DEFAULT_WIDTH,
+                DEFAULT_HEIGHT,
+              );
+            }
+          } else if (is(neighbor, 'CompensationTrigger')) {
+            setBounds(
+              neighbor,
+              currentState.style.bounds.x,
+              currentState.style.bounds.y - 150,
+              OFFSET_X,
+              OFFSET_X,
+            );
+            const { Name } = neighbor;
+            queue.push(definitions.States[Name]);
+          } else if (is(neighbor, 'Choice')) {
+            setBounds(
+              neighbor,
+              currentState.style.bounds.x + 150,
+              currentState.style.bounds.y,
+              50,
+              50,
+            );
+            const { Name } = neighbor;
+            queue.push(definitions.States[Name]);
+          }
+        }
+      });
+    }
+  }
+
   exportJson() {
     return assign({}, { style: this.style });
   }
diff --git a/saga/seata-saga-statemachine-designer/src/utils/index.js 
b/saga/seata-saga-statemachine-designer/src/utils/index.js
index 72054ca1c5..cb5fb3f572 100644
--- a/saga/seata-saga-statemachine-designer/src/utils/index.js
+++ b/saga/seata-saga-statemachine-designer/src/utils/index.js
@@ -61,6 +61,14 @@ export function setProperties(businessObject, properties, 
override) {
 export function is(element, target) {
   const type = element?.businessObject?.Type || element?.Type || element;
 
+  if (target === 'Event') {
+    return type === 'StartState' || type === 'CompensationTrigger' || type === 
'Catch' || type === 'Fail' || type === 'Succeed';
+  }
+
+  if (target === 'End') {
+    return type === 'Fail' || type === 'Succeed';
+  }
+
   if (target === 'Task') {
     return type === 'ServiceTask' || type === 'ScriptTask' || type === 
'SubStateMachine';
   }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to