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

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


The following commit(s) were added to refs/heads/refactor_designer by this push:
     new bfad822cda feature: full support for states in the refactored state 
machine designer (#6169)
bfad822cda is described below

commit bfad822cda8636b4d48a962504e197cefea4e391
Author: Xiangkun Yin <[email protected]>
AuthorDate: Fri Jan 5 21:46:56 2024 +0800

    feature: full support for states in the refactored state machine designer 
(#6169)
---
 .../seata-saga-statemachine-designer/src/Editor.js |   2 +
 .../src/layout/behavior/AttachCatchBehavior.js     |  42 ++++
 .../src/layout/behavior/index.js                   |   3 +
 .../src/modeling/SagaExporter.js                   |  34 ++-
 .../src/modeling/SagaFactory.js                    |  20 ++
 .../src/modeling/SagaImporter.js                   |  35 ++-
 .../src/modeling/SagaRules.js                      |  78 +++++-
 .../provider/PropertiesProvider.js                 |   4 +-
 .../provider/properties/StateProps.js              |   2 +
 .../src/providers/PaletteProvider.js               |  12 +-
 .../src/render/PathMap.js                          |  42 ++++
 .../src/render/Renderer.js                         | 276 +++++++++++++++++++--
 .../src/spec/{TaskState.js => Catch.js}            |  21 +-
 .../src/spec/{TaskState.js => Choice.js}           |  31 ++-
 .../src/spec/{ServiceTask.js => ChoiceEntry.js}    |  23 +-
 .../src/spec/{TaskState.js => Compensation.js}     |  16 +-
 .../spec/{TaskState.js => CompensationTrigger.js}  |  19 +-
 .../src/spec/{ServiceTask.js => ExceptionMatch.js} |  27 +-
 .../src/spec/{TaskState.js => Fail.js}             |  17 +-
 .../src/spec/{TaskState.js => ScriptTask.js}       |  14 +-
 .../src/spec/ServiceTask.js                        |   5 -
 .../src/spec/{TaskState.js => SubStateMachine.js}  |  13 +-
 .../src/spec/{TaskState.js => Succeed.js}          |  18 +-
 .../src/spec/TaskState.js                          |  25 ++
 .../src/utils/index.js                             |   6 +-
 25 files changed, 664 insertions(+), 121 deletions(-)

diff --git a/saga/seata-saga-statemachine-designer/src/Editor.js 
b/saga/seata-saga-statemachine-designer/src/Editor.js
index ab282ee6e9..fc03ffc486 100644
--- a/saga/seata-saga-statemachine-designer/src/Editor.js
+++ b/saga/seata-saga-statemachine-designer/src/Editor.js
@@ -20,6 +20,7 @@ import { innerSVG } from 'tiny-svg';
 import Diagram from 'diagram-js';
 
 import AlignElementsModule from 'diagram-js/lib/features/align-elements';
+import AttachSupport from 'diagram-js/lib/features/attach-support';
 import AutoScrollModule from 'diagram-js/lib/features/auto-scroll';
 import BendpointsModule from 'diagram-js/lib/features/bendpoints';
 import ConnectModule from 'diagram-js/lib/features/connect';
@@ -79,6 +80,7 @@ Editor.prototype.modules = [
 
   // Built-in modules
   AlignElementsModule,
+  AttachSupport,
   AutoScrollModule,
   BendpointsModule,
   ConnectModule,
diff --git 
a/saga/seata-saga-statemachine-designer/src/layout/behavior/AttachCatchBehavior.js
 
b/saga/seata-saga-statemachine-designer/src/layout/behavior/AttachCatchBehavior.js
new file mode 100644
index 0000000000..d9b9b1d8a7
--- /dev/null
+++ 
b/saga/seata-saga-statemachine-designer/src/layout/behavior/AttachCatchBehavior.js
@@ -0,0 +1,42 @@
+/*
+ *  Copyright 1999-2019 Seata.io Group.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+import inherits from 'inherits-browser';
+
+import CommandInterceptor from 'diagram-js/lib/command/CommandInterceptor';
+import { is } from '../../utils';
+
+const LOW_PRIORITY = 500;
+
+function shouldUpdate(shape, host) {
+  return is(shape, 'Catch') && host;
+}
+
+export default function AttachEventBehavior(injector) {
+  injector.invoke(CommandInterceptor, this);
+  this.postExecuted('element.updateAttachment', LOW_PRIORITY, ({ context }) => 
{
+    const { shape, oldHost, newHost } = context;
+
+    if (shouldUpdate(shape, newHost)) {
+      delete oldHost?.businessObject.Catch;
+      newHost.businessObject.Catch = shape.businessObject;
+    }
+  });
+}
+
+inherits(AttachEventBehavior, CommandInterceptor);
+
+AttachEventBehavior.$inject = ['injector'];
diff --git a/saga/seata-saga-statemachine-designer/src/layout/behavior/index.js 
b/saga/seata-saga-statemachine-designer/src/layout/behavior/index.js
index fad1764dab..e0f716184f 100644
--- a/saga/seata-saga-statemachine-designer/src/layout/behavior/index.js
+++ b/saga/seata-saga-statemachine-designer/src/layout/behavior/index.js
@@ -14,16 +14,19 @@
  *  limitations under the License.
  */
 
+import AttachCatchBehavior from './AttachCatchBehavior';
 import LayoutConnectionBehavior from './LayoutConnectionBehavior';
 import ReplaceConnectionBehavior from './ReplaceConnectionBehavior';
 import LayoutUpdateBehavior from './LayoutUpdateBehavior';
 
 export default {
   __init__: [
+    'attachCatchBehavior',
     'layoutConnectionBehavior',
     'replaceConnectionBehavior',
     'layoutUpdateBehavior',
   ],
+  attachCatchBehavior: ['type', AttachCatchBehavior],
   layoutConnectionBehavior: ['type', LayoutConnectionBehavior],
   replaceConnectionBehavior: ['type', ReplaceConnectionBehavior],
   layoutUpdateBehavior: ['type', LayoutUpdateBehavior],
diff --git a/saga/seata-saga-statemachine-designer/src/modeling/SagaExporter.js 
b/saga/seata-saga-statemachine-designer/src/modeling/SagaExporter.js
index 67fc1b6a6a..92112c6dd2 100644
--- a/saga/seata-saga-statemachine-designer/src/modeling/SagaExporter.js
+++ b/saga/seata-saga-statemachine-designer/src/modeling/SagaExporter.js
@@ -54,12 +54,36 @@ SagaExporter.prototype.parseEdge = function (definitions, 
edge) {
     }
   } else {
     const stateRef = definitions.States[source];
-    stateRef.Next = target;
-
-    if (stateRef.edge === undefined) {
-      stateRef.edge = {};
+    switch (businessObject.Type) {
+      case 'ChoiceEntry':
+        if (!stateRef.Choices) {
+          stateRef.Choices = [];
+        }
+        stateRef.Choices.push({
+          Expression: businessObject.Expression,
+          Next: target,
+        });
+        if (businessObject.Default) {
+          stateRef.Default = target;
+        }
+        stateRef.edge = assign(stateRef.edge || {}, { [target]: elementJson });
+        break;
+      case 'ExceptionMatch':
+        stateRef.Catch.push({
+          Exceptions: businessObject.Exceptions,
+          Next: target,
+        });
+        stateRef.catch = assign(stateRef.catch || {}, { edge: { [target]: 
elementJson } });
+        break;
+      case 'Compensation':
+        stateRef.CompensateState = target;
+        stateRef.edge = assign(stateRef.edge || {}, { [target]: elementJson });
+        break;
+      case 'Transition':
+      default:
+        stateRef.Next = target;
+        stateRef.edge = assign(stateRef.edge || {}, { [target]: elementJson });
     }
-    assign(stateRef.edge, { [target]: elementJson });
   }
 };
 
diff --git a/saga/seata-saga-statemachine-designer/src/modeling/SagaFactory.js 
b/saga/seata-saga-statemachine-designer/src/modeling/SagaFactory.js
index 9e7adb73a9..7456bc54df 100644
--- a/saga/seata-saga-statemachine-designer/src/modeling/SagaFactory.js
+++ b/saga/seata-saga-statemachine-designer/src/modeling/SagaFactory.js
@@ -18,6 +18,16 @@ import Transition from '../spec/Transition';
 import StateMachine from '../spec/StateMachine';
 import ServiceTask from '../spec/ServiceTask';
 import StartState from '../spec/StartState';
+import ScriptTask from '../spec/ScriptTask';
+import Choice from '../spec/Choice';
+import ChoiceEntry from '../spec/ChoiceEntry';
+import Succeed from '../spec/Succeed';
+import Fail from '../spec/Fail';
+import Catch from '../spec/Catch';
+import ExceptionMatch from '../spec/ExceptionMatch';
+import CompensationTrigger from '../spec/CompensationTrigger';
+import SubStateMachine from '../spec/SubStateMachine';
+import Compensation from '../spec/Compensation';
 
 export default function SagaFactory() {
   const typeToSpec = new Map();
@@ -25,6 +35,16 @@ export default function SagaFactory() {
   typeToSpec.set('StartState', StartState);
   typeToSpec.set('StateMachine', StateMachine);
   typeToSpec.set('ServiceTask', ServiceTask);
+  typeToSpec.set('ScriptTask', ScriptTask);
+  typeToSpec.set('Choice', Choice);
+  typeToSpec.set('ChoiceEntry', ChoiceEntry);
+  typeToSpec.set('Succeed', Succeed);
+  typeToSpec.set('Fail', Fail);
+  typeToSpec.set('Catch', Catch);
+  typeToSpec.set('ExceptionMatch', ExceptionMatch);
+  typeToSpec.set('CompensationTrigger', CompensationTrigger);
+  typeToSpec.set('SubStateMachine', SubStateMachine);
+  typeToSpec.set('Compensation', Compensation);
   this.typeToSpec = typeToSpec;
 }
 
diff --git a/saga/seata-saga-statemachine-designer/src/modeling/SagaImporter.js 
b/saga/seata-saga-statemachine-designer/src/modeling/SagaImporter.js
index e0fb570348..6cd3708adc 100644
--- a/saga/seata-saga-statemachine-designer/src/modeling/SagaImporter.js
+++ b/saga/seata-saga-statemachine-designer/src/modeling/SagaImporter.js
@@ -46,12 +46,14 @@ export default function SagaImporter(
   canvas,
   elementFactory,
   elementRegistry,
+  modeling,
 ) {
   this.sagaFactory = sagaFactory;
   this.eventBus = eventBus;
   this.canvas = canvas;
   this.elementRegistry = elementRegistry;
   this.elementFactory = elementFactory;
+  this.modeling = modeling;
 }
 
 SagaImporter.$inject = [
@@ -60,6 +62,7 @@ SagaImporter.$inject = [
   'canvas',
   'elementFactory',
   'elementRegistry',
+  'modeling',
 ];
 
 SagaImporter.prototype.import = function (definitions) {
@@ -74,18 +77,33 @@ SagaImporter.prototype.import = function (definitions) {
     this.root(root);
 
     // Add start state
-    const start = this.sagaFactory.create('StartState');
+    let start = this.sagaFactory.create('StartState');
     start.importJson(definitions);
-    this.add(start);
+    start = this.add(start);
 
     const edges = [];
+    const catches = [];
     forEach(definitions.States, (semantic) => {
       const state = this.sagaFactory.create(semantic.Type);
       state.importJson(semantic);
-      this.add(state);
+      const host = this.add(state);
       if (semantic.edge) {
         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.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) });
+      }
     });
 
     // Add start edge
@@ -100,6 +118,15 @@ SagaImporter.prototype.import = function (definitions) {
       transition.importJson(semantic);
       this.add(transition);
     });
+
+    forEach(catches, (oneCatch) => {
+      const { source, edges: exceptionMatches } = oneCatch;
+      forEach(exceptionMatches, (semantic) => {
+        const exceptionMatch = this.sagaFactory.create(semantic.Type);
+        exceptionMatch.importJson(semantic);
+        this.add(exceptionMatch, { source });
+      });
+    });
   } catch (e) {
     error = e;
     console.error(error);
@@ -142,7 +169,7 @@ SagaImporter.prototype.add = function (semantic, attrs = 
{}) {
   } else if (style.Type === 'Edge') {
     waypoints = collectWaypoints(style);
 
-    source = this.getSource(semantic) || attrs.source;
+    source = attrs.source || this.getSource(semantic);
     target = this.getTarget(semantic);
     semantic.style.source = source;
     semantic.style.target = target;
diff --git a/saga/seata-saga-statemachine-designer/src/modeling/SagaRules.js 
b/saga/seata-saga-statemachine-designer/src/modeling/SagaRules.js
index 8abfba154f..5a90516342 100644
--- a/saga/seata-saga-statemachine-designer/src/modeling/SagaRules.js
+++ b/saga/seata-saga-statemachine-designer/src/modeling/SagaRules.js
@@ -17,6 +17,8 @@
 import inherits from 'inherits-browser';
 
 import RuleProvider from 'diagram-js/lib/features/rules/RuleProvider';
+import { getOrientation } from 'diagram-js/lib/layout/LayoutUtil';
+import { is } from '../utils';
 
 export default function SagaRules(injector) {
   injector.invoke(RuleProvider, this);
@@ -34,17 +36,89 @@ function canConnect(source, target) {
   if (target.parent !== source.parent || source === target) {
     return false;
   }
+
+  if (is(source, 'Task') && is(target, 'Task') && 
target.businessObject.IsForCompensation) {
+    return { type: 'Compensation' };
+  }
+
+  if (is(source, 'Choice')) {
+    return { type: 'ChoiceEntry' };
+  }
+
+  if (is(source, 'Catch')) {
+    return { type: 'ExceptionMatch' };
+  }
+
   return { type: 'Transition' };
 }
 
-SagaRules.prototype.canConnect = canConnect;
+function canCreate(shapes, target) {
+  let shapeList = shapes;
+  if (!Array.isArray(shapes)) {
+    shapeList = [shapes];
+  }
+
+  const invalid = shapeList.map((shape) => {
+    if (is(shape, 'Catch')) {
+      return false;
+    }
+
+    if (!target) {
+      return true;
+    }
+
+    return target.parent === shape.target;
+  }).filter((valid) => !valid).length;
+
+  return !invalid;
+}
+
+function canAttach(shapes, target, position) {
+  if (Array.isArray(shapes)) {
+    if (shapes.length > 1) {
+      return false;
+    }
+  }
+  const shape = shapes[0] || shapes;
+
+  if (is(shape, 'Catch')) {
+    if (position && getOrientation(position, target, -15) === 'intersect') {
+      return false;
+    }
+
+    if (is(target, 'Task')) {
+      return 'attach';
+    }
+  }
+
+  return false;
+}
+
+function canMove(shapes, target, position) {
+  const shapeSet = new Set(shapes);
+  // Exclude all catches with parents included
+  const filtered = shapes.filter((shape) => !(is(shape, 'Catch') && 
shapeSet.has(shape.parent)));
+  return !target || canAttach(filtered, target, position) || 
canCreate(filtered, target);
+}
 
 SagaRules.prototype.init = function () {
   this.addRule('shape.create', (context) => {
     const { target } = context;
     const { shape } = context;
 
-    return target.parent === shape.target;
+    return canCreate(shape, target);
+  });
+
+  this.addRule('shape.attach', (context) => {
+    const { shape, target, position } = context;
+
+    return canAttach(shape, target, position);
+  });
+
+  this.addRule('elements.move', (context) => {
+    const { shapes, target, position } = context;
+
+    return canMove(shapes, target, position);
   });
 
   this.addRule('connection.create', (context) => {
diff --git 
a/saga/seata-saga-statemachine-designer/src/properties-panel/provider/PropertiesProvider.js
 
b/saga/seata-saga-statemachine-designer/src/properties-panel/provider/PropertiesProvider.js
index e40f634d8b..3aaf2a22c0 100644
--- 
a/saga/seata-saga-statemachine-designer/src/properties-panel/provider/PropertiesProvider.js
+++ 
b/saga/seata-saga-statemachine-designer/src/properties-panel/provider/PropertiesProvider.js
@@ -33,7 +33,7 @@ function GeneralGroup(element) {
     entries.push(...VersionProps({ element }));
   }
 
-  if (is(element, 'Connection') || is(element, 'StartState')) {
+  if (is(element, 'Connection') || is(element, 'StartState') || is(element, 
'Catch')) {
     return null;
   }
 
@@ -51,7 +51,7 @@ function JsonGroup(element) {
     ...StyleProps({ element }),
   ];
 
-  if (is(element, 'Connection') || is(element, 'StartState')) {
+  if (is(element, 'Transition') || is(element, 'Compensation') || is(element, 
'StartState') || is(element, 'Catch')) {
     entries.splice(0, 1);
   }
 
diff --git 
a/saga/seata-saga-statemachine-designer/src/properties-panel/provider/properties/StateProps.js
 
b/saga/seata-saga-statemachine-designer/src/properties-panel/provider/properties/StateProps.js
index 44bdcd4c53..57c3e7f9eb 100644
--- 
a/saga/seata-saga-statemachine-designer/src/properties-panel/provider/properties/StateProps.js
+++ 
b/saga/seata-saga-statemachine-designer/src/properties-panel/provider/properties/StateProps.js
@@ -39,6 +39,8 @@ function State(props) {
       const value = assign({}, e.businessObject);
       // Exclude style
       delete value.style;
+      // Exclude Catch for Task
+      delete value.Catch;
       return JSON.stringify(value, null, 2);
     },
     validate: (value) => {
diff --git 
a/saga/seata-saga-statemachine-designer/src/providers/PaletteProvider.js 
b/saga/seata-saga-statemachine-designer/src/providers/PaletteProvider.js
index 071946746e..e673c6f312 100644
--- a/saga/seata-saga-statemachine-designer/src/providers/PaletteProvider.js
+++ b/saga/seata-saga-statemachine-designer/src/providers/PaletteProvider.js
@@ -17,6 +17,16 @@
 import { assign } from 'min-dash';
 import ServiceTask from '../spec/ServiceTask';
 import StartState from '../spec/StartState';
+import ScriptTask from '../spec/ScriptTask';
+import Choice from '../spec/Choice';
+import Succeed from '../spec/Succeed';
+import Fail from '../spec/Fail';
+import Catch from '../spec/Catch';
+import CompensationTrigger from '../spec/CompensationTrigger';
+import SubStateMachine from '../spec/SubStateMachine';
+
+const SPEC_LIST = [StartState, ServiceTask, ScriptTask, SubStateMachine, 
Choice, Succeed, Fail,
+  Catch, CompensationTrigger];
 
 /**
  * A palette provider.
@@ -75,7 +85,7 @@ PaletteProvider.prototype.getPaletteEntries = function () {
       separator: true,
     },
   };
-  [StartState, ServiceTask].forEach((Spec) => {
+  SPEC_LIST.forEach((Spec) => {
     const type = Spec.prototype.Type;
     entries[`create-${type}`] = createAction(type, 'state', 
Spec.prototype.THUMBNAIL_CLASS, `Create ${type}`);
   });
diff --git a/saga/seata-saga-statemachine-designer/src/render/PathMap.js 
b/saga/seata-saga-statemachine-designer/src/render/PathMap.js
index 281de6c29d..a74013b95f 100644
--- a/saga/seata-saga-statemachine-designer/src/render/PathMap.js
+++ b/saga/seata-saga-statemachine-designer/src/render/PathMap.js
@@ -127,6 +127,48 @@ export default function PathMap() {
       heightElements: [],
       widthElements: [],
     },
+    MARKER_SUB_PROCESS: {
+      d: 'm{mx},{my} m 7,2 l 0,10 m -5,-5 l 10,0',
+      height: 10,
+      width: 10,
+      heightElements: [],
+      widthElements: [],
+    },
+    TASK_TYPE_SCRIPT: {
+      d: 'm {mx},{my} c 9.966553,-6.27276 -8.000926,-7.91932 2.968968,-14.938 
l -8.802728,0 '
+        + 'c -10.969894,7.01868 6.997585,8.66524 -2.968967,14.938 z '
+        + 'm -7,-12 l 5,0 '
+        + 'm -4.5,3 l 4.5,0 '
+        + 'm -3,3 l 5,0'
+        + 'm -4,3 l 5,0',
+      height: 15,
+      width: 12.6,
+      heightElements: [6, 14],
+      widthElements: [10.5, 21],
+    },
+    GATEWAY_EXCLUSIVE: {
+      d: 'm {mx},{my} {e.x0},{e.y0} {e.x1},{e.y0} {e.x2},0 {e.x4},{e.y2} '
+        + '{e.x4},{e.y1} {e.x2},0 {e.x1},{e.y3} {e.x0},{e.y3} '
+        + '{e.x3},0 {e.x5},{e.y1} {e.x5},{e.y2} {e.x3},0 z',
+      height: 17.5,
+      width: 17.5,
+      heightElements: [8.5, 6.5312, -6.5312, -8.5],
+      widthElements: [6.5, -6.5, 3, -3, 5, -5],
+    },
+    EVENT_ERROR: {
+      d: 'm {mx},{my} {e.x0},-{e.y0} {e.x1},-{e.y1} {e.x2},{e.y2} 
{e.x3},-{e.y3} -{e.x4},{e.y4} -{e.x5},-{e.y5} z',
+      height: 36,
+      width: 36,
+      heightElements: [0.023, 8.737, 8.151, 16.564, 10.591, 8.714],
+      widthElements: [0.085, 6.672, 6.97, 4.273, 5.337, 6.636],
+    },
+    EVENT_COMPENSATION: {
+      d: 'm {mx},{my} {e.x0},-{e.y0} 0,{e.y1} z m {e.x1},-{e.y2} 
{e.x2},-{e.y3} 0,{e.y1} -{e.x2},-{e.y3} z',
+      height: 36,
+      width: 36,
+      heightElements: [6.5, 13, 0.4, 6.1],
+      widthElements: [9, 9.3, 8.7],
+    },
   };
 
   this.getRawPath = function getRawPath(pathId) {
diff --git a/saga/seata-saga-statemachine-designer/src/render/Renderer.js 
b/saga/seata-saga-statemachine-designer/src/render/Renderer.js
index 6fb53d7e15..c5d0d9bc21 100644
--- a/saga/seata-saga-statemachine-designer/src/render/Renderer.js
+++ b/saga/seata-saga-statemachine-designer/src/render/Renderer.js
@@ -25,6 +25,7 @@ import { append as svgAppend, attr as svgAttr, create as 
svgCreate } from 'tiny-
 import BaseRenderer from 'diagram-js/lib/draw/BaseRenderer';
 
 import { createLine } from 'diagram-js/lib/util/RenderUtil';
+import { translate } from 'diagram-js/lib/util/SvgTransformUtil';
 
 const BLACK = 'hsl(225, 10%, 15%)';
 const TASK_BORDER_RADIUS = 10;
@@ -64,6 +65,16 @@ export default function Renderer(config, eventBus, pathMap, 
styles, textRenderer
   const defaultStrokeColor = (config && config.defaultStrokeColor) || BLACK;
   const defaultLabelColor = (config && config.defaultLabelColor);
 
+  function shapeStyle(attrs) {
+    return styles.computeStyle(attrs, {
+      strokeLinecap: 'round',
+      strokeLinejoin: 'round',
+      stroke: BLACK,
+      strokeWidth: 2,
+      fill: 'white',
+    });
+  }
+
   function addMarker(id, options) {
     const attrs = assign({
       strokeWidth: 1,
@@ -116,15 +127,32 @@ export default function Renderer(config, eventBus, 
pathMap, styles, textRenderer
     const end = svgCreate('path');
     svgAttr(end, { d: 'M 1 5 L 11 10 L 1 15 Z' });
 
-    addMarker(id, {
-      element: end,
-      attrs: {
-        fill: stroke,
-        stroke: 'none',
-      },
-      ref: { x: 11, y: 10 },
-      scale: 1,
-    });
+    if (type === 'connection-end') {
+      addMarker(id, {
+        element: end,
+        attrs: {
+          fill: stroke,
+          stroke: 'none',
+        },
+        ref: { x: 11, y: 10 },
+        scale: 1,
+      });
+    }
+
+    if (type === 'default-choice-marker') {
+      const defaultChoiceMarker = svgCreate('path', {
+        d: 'M 6 4 L 10 16',
+        ...shapeStyle({
+          stroke,
+        }),
+      });
+
+      addMarker(id, {
+        element: defaultChoiceMarker,
+        ref: { x: 0, y: 10 },
+        scale: 1,
+      });
+    }
   }
 
   function marker(type, fill, stroke) {
@@ -146,13 +174,7 @@ export default function Renderer(config, eventBus, 
pathMap, styles, textRenderer
 
     offset = offset || 0;
 
-    attrs = computeStyle(attrs, {
-      strokeLinecap: 'round',
-      strokeLinejoin: 'round',
-      stroke: BLACK,
-      strokeWidth: 2,
-      fill: 'white',
-    });
+    attrs = shapeStyle(attrs);
 
     if (attrs.fill === 'none') {
       delete attrs.fillOpacity;
@@ -243,6 +265,33 @@ export default function Renderer(config, eventBus, 
pathMap, styles, textRenderer
     return path;
   }
 
+  function drawDiamond(parentGfx, width, height, attrs) {
+    const x2 = width / 2;
+    const y2 = height / 2;
+
+    const points = [
+      { x: x2, y: 0 },
+      { x: width, y: y2 },
+      { x: x2, y: height },
+      { x: 0, y: y2 },
+    ];
+
+    const pointsString = points.map((point) => {
+      return `${point.x},${point.y}`;
+    }).join(' ');
+
+    attrs = shapeStyle(attrs);
+
+    const polygon = svgCreate('polygon', {
+      ...attrs,
+      points: pointsString,
+    });
+
+    svgAppend(parentGfx, polygon);
+
+    return polygon;
+  }
+
   function drawLine(p, waypoints, attrs) {
     attrs = computeStyle(attrs, ['no-fill'], {
       stroke: BLACK,
@@ -270,7 +319,7 @@ export default function Renderer(config, eventBus, pathMap, 
styles, textRenderer
   function attachTaskMarkers(p, element, taskMarkers) {
     const obj = getSemantic(element);
 
-    const sub = taskMarkers && taskMarkers.indexOf('SubStateMachine') !== -1;
+    const sub = taskMarkers && taskMarkers.indexOf('SubStateMachineMarker') 
!== -1;
     let position;
 
     if (sub) {
@@ -318,13 +367,49 @@ export default function Renderer(config, eventBus, 
pathMap, styles, textRenderer
 
       return drawLine(p, element.waypoints, attrs);
     },
+    ChoiceEntry(p, element) {
+      const fill = getFillColor(element, defaultFillColor);
+      const stroke = getStrokeColor(element, defaultStrokeColor);
+      const attrs = {
+        stroke,
+        strokeWidth: 1,
+        strokeLinecap: 'round',
+        strokeLinejoin: 'round',
+        markerEnd: marker('connection-end', fill, stroke),
+      };
+
+      const path = drawLine(p, element.waypoints, attrs);
+
+      if (getSemantic(element).Default) {
+        svgAttr(path, {
+          markerStart: marker('default-choice-marker', fill, stroke),
+        });
+      }
+
+      return path;
+    },
+    ExceptionMatch(p, element) {
+      return renderer('Transition')(p, element);
+    },
+    Compensation(p, element) {
+      const stroke = getStrokeColor(element, defaultStrokeColor);
+      const attrs = {
+        stroke,
+        strokeWidth: 1,
+        strokeLinecap: 'round',
+        strokeLinejoin: 'round',
+        strokeDasharray: '10, 11',
+      };
+
+      return drawLine(p, element.waypoints, attrs);
+    },
     StartState(parentGfx, element) {
       return drawCircle(parentGfx, element.width, element.height, {
         fill: getFillColor(element, defaultFillColor),
         stroke: getStrokeColor(element, defaultStrokeColor),
       });
     },
-    Task(parentGfx, element) {
+    Task(parentGfx, element, additionalMarkers) {
       const attrs = {
         fill: getFillColor(element, defaultFillColor),
         stroke: getStrokeColor(element, defaultStrokeColor),
@@ -334,7 +419,7 @@ export default function Renderer(config, eventBus, pathMap, 
styles, textRenderer
       const rect = drawRect(parentGfx, element.width, element.height, 
TASK_BORDER_RADIUS, attrs);
 
       renderEmbeddedLabel(parentGfx, element, 'center-middle');
-      attachTaskMarkers(parentGfx, element);
+      attachTaskMarkers(parentGfx, element, additionalMarkers);
 
       return rect;
     },
@@ -380,6 +465,50 @@ export default function Renderer(config, eventBus, 
pathMap, styles, textRenderer
 
       return task;
     },
+    ScriptTask(parentGfx, element) {
+      const task = renderer('Task')(parentGfx, element);
+      const pathData = pathMap.getScaledPath('TASK_TYPE_SCRIPT', {
+        abspos: {
+          x: 15,
+          y: 20,
+        },
+      });
+
+      /* script path */ drawPath(parentGfx, pathData, {
+        strokeWidth: 1,
+        stroke: getStrokeColor(element, defaultStrokeColor),
+      });
+
+      return task;
+    },
+    SubStateMachine(parentGfx, element) {
+      return renderer('Task')(parentGfx, element, ['SubStateMachineMarker']);
+    },
+    SubStateMachineMarker(parentGfx, element) {
+      const markerRect = drawRect(parentGfx, 14, 14, 0, {
+        strokeWidth: 1,
+        fill: getFillColor(element, defaultFillColor),
+        stroke: getStrokeColor(element, defaultStrokeColor),
+      });
+
+      translate(markerRect, element.width / 2 - 7.5, element.height - 20);
+
+      const markerPath = pathMap.getScaledPath('MARKER_SUB_PROCESS', {
+        xScaleFactor: 1.5,
+        yScaleFactor: 1.5,
+        containerWidth: element.width,
+        containerHeight: element.height,
+        position: {
+          mx: (element.width / 2 - 7.5) / element.width,
+          my: (element.height - 20) / element.height,
+        },
+      });
+
+      drawMarker('sub-process', parentGfx, markerPath, {
+        fill: getFillColor(element, defaultFillColor),
+        stroke: getStrokeColor(element, defaultStrokeColor),
+      });
+    },
     LoopMarker(parentGfx, element, position) {
       const markerPath = pathMap.getScaledPath('MARKER_LOOP', {
         xScaleFactor: 1,
@@ -417,6 +546,115 @@ export default function Renderer(config, eventBus, 
pathMap, styles, textRenderer
         stroke: getStrokeColor(element, defaultStrokeColor),
       });
     },
+    Gateway(parentGfx, element) {
+      return drawDiamond(parentGfx, element.width, element.height, {
+        fill: getFillColor(element, defaultFillColor),
+        fillOpacity: DEFAULT_FILL_OPACITY,
+        stroke: getStrokeColor(element, defaultStrokeColor),
+      });
+    },
+    Choice(parentGfx, element) {
+      const diamond = renderer('Gateway')(parentGfx, element);
+
+      const pathData = pathMap.getScaledPath('GATEWAY_EXCLUSIVE', {
+        xScaleFactor: 0.4,
+        yScaleFactor: 0.4,
+        containerWidth: element.width,
+        containerHeight: element.height,
+        position: {
+          mx: 0.32,
+          my: 0.3,
+        },
+      });
+
+      drawPath(parentGfx, pathData, {
+        strokeWidth: 1,
+        fill: getStrokeColor(element, defaultStrokeColor),
+        stroke: getStrokeColor(element, defaultStrokeColor),
+      });
+
+      return diamond;
+    },
+    Succeed(parentGfx, element) {
+      return drawCircle(parentGfx, element.width, element.height, {
+        strokeWidth: 4,
+        fill: getFillColor(element, defaultFillColor),
+        stroke: getStrokeColor(element, defaultStrokeColor),
+      });
+    },
+    Error(parentGfx, element, fill) {
+      const pathData = pathMap.getScaledPath('EVENT_ERROR', {
+        xScaleFactor: 1.1,
+        yScaleFactor: 1.1,
+        containerWidth: element.width,
+        containerHeight: element.height,
+        position: {
+          mx: 0.2,
+          my: 0.722,
+        },
+      });
+      return drawPath(parentGfx, pathData, {
+        strokeWidth: 1,
+        fill: fill ? getStrokeColor(element, defaultStrokeColor) : 'none',
+        stroke: getStrokeColor(element, defaultStrokeColor),
+      });
+    },
+    Fail(parentGfx, element) {
+      const circle = handlers.Succeed(parentGfx, element);
+      renderer('Error')(parentGfx, element, true);
+      return circle;
+    },
+    Event(parentGfx, element) {
+      const attrs = {
+        strokeWidth: 1.5,
+        fill: getFillColor(element, defaultFillColor),
+        stroke: getStrokeColor(element, defaultStrokeColor),
+      };
+
+      // apply fillOpacity
+      const outerAttrs = {
+        ...attrs,
+        fillOpacity: 1,
+      };
+
+      // apply no-fill
+      const innerAttrs = {
+        ...attrs,
+        fill: 'none',
+      };
+
+      const outer = drawCircle(parentGfx, element.width, element.height, 
outerAttrs);
+      drawCircle(parentGfx, element.width, element.height, 3, innerAttrs);
+      return outer;
+    },
+    Catch(parentGfx, element) {
+      const outer = renderer('Event')(parentGfx, element);
+      renderer('Error')(parentGfx, element);
+
+      return outer;
+    },
+    CompensationTrigger(parentGfx, element) {
+      const outer = renderer('Event')(parentGfx, element);
+      const pathData = pathMap.getScaledPath('EVENT_COMPENSATION', {
+        xScaleFactor: 1,
+        yScaleFactor: 1,
+        containerWidth: element.width,
+        containerHeight: element.height,
+        position: {
+          mx: 0.22,
+          my: 0.5,
+        },
+      });
+
+      const fill = 'none';
+
+      drawPath(parentGfx, pathData, {
+        strokeWidth: 1,
+        fill,
+        stroke: getStrokeColor(element, defaultStrokeColor),
+      });
+      return outer;
+    },
   };
   function drawShape(parent, element) {
     const h = handlers[element.type];
diff --git a/saga/seata-saga-statemachine-designer/src/spec/TaskState.js 
b/saga/seata-saga-statemachine-designer/src/spec/Catch.js
similarity index 71%
copy from saga/seata-saga-statemachine-designer/src/spec/TaskState.js
copy to saga/seata-saga-statemachine-designer/src/spec/Catch.js
index 47ab79b3c8..e32432b950 100644
--- a/saga/seata-saga-statemachine-designer/src/spec/TaskState.js
+++ b/saga/seata-saga-statemachine-designer/src/spec/Catch.js
@@ -14,14 +14,17 @@
  *  limitations under the License.
  */
 
-import State from './State';
+import Node from './style/Node';
+
+export default class Catch extends Node {
 
-export default class TaskState extends State {
-  constructor() {
-    super();
-    this.Input = [{}];
-    this.Output = {};
-    this.Status = {};
-    this.Retry = [];
-  }
 }
+
+Catch.prototype.Type = 'Catch';
+
+Catch.prototype.THUMBNAIL_CLASS = 'bpmn-icon-intermediate-event-catch-error';
+
+Catch.prototype.DEFAULT_SIZE = {
+  width: 36,
+  height: 36,
+};
diff --git a/saga/seata-saga-statemachine-designer/src/spec/TaskState.js 
b/saga/seata-saga-statemachine-designer/src/spec/Choice.js
similarity index 52%
copy from saga/seata-saga-statemachine-designer/src/spec/TaskState.js
copy to saga/seata-saga-statemachine-designer/src/spec/Choice.js
index 47ab79b3c8..810c3b1d90 100644
--- a/saga/seata-saga-statemachine-designer/src/spec/TaskState.js
+++ b/saga/seata-saga-statemachine-designer/src/spec/Choice.js
@@ -16,12 +16,29 @@
 
 import State from './State';
 
-export default class TaskState extends State {
-  constructor() {
-    super();
-    this.Input = [{}];
-    this.Output = {};
-    this.Status = {};
-    this.Retry = [];
+export default class Choice extends State {
+  importJson(json) {
+    super.importJson(json);
+    if (json.edge) {
+      this.Choices.forEach((choice) => {
+        if (json.edge[choice.Next]) {
+          json.edge[choice.Next].Expression = choice.Expression;
+        }
+      });
+      if (json.edge[this.Default]) {
+        json.edge[this.Default].Default = true;
+      }
+    }
+    delete this.Choices;
+    delete this.Default;
   }
 }
+
+Choice.prototype.Type = 'Choice';
+
+Choice.prototype.THUMBNAIL_CLASS = 'bpmn-icon-gateway-xor';
+
+Choice.prototype.DEFAULT_SIZE = {
+  width: 50,
+  height: 50,
+};
diff --git a/saga/seata-saga-statemachine-designer/src/spec/ServiceTask.js 
b/saga/seata-saga-statemachine-designer/src/spec/ChoiceEntry.js
similarity index 63%
copy from saga/seata-saga-statemachine-designer/src/spec/ServiceTask.js
copy to saga/seata-saga-statemachine-designer/src/spec/ChoiceEntry.js
index 9ac9a2d447..5440988ada 100644
--- a/saga/seata-saga-statemachine-designer/src/spec/ServiceTask.js
+++ b/saga/seata-saga-statemachine-designer/src/spec/ChoiceEntry.js
@@ -14,21 +14,22 @@
  *  limitations under the License.
  */
 
-import TaskState from './TaskState';
+import Transition from './Transition';
 
-export default class ServiceTask extends TaskState {
+export default class ChoiceEntry extends Transition {
   constructor() {
     super();
-    this.ServiceName = '';
-    this.ServiceMethod = '';
+    this.Expression = '';
+    this.Default = false;
   }
-}
 
-ServiceTask.prototype.Type = 'ServiceTask';
+  importJson(json) {
+    super.importJson(json);
+    this.Expression = json.Expression;
+    this.Default = json.Default;
+  }
+}
 
-ServiceTask.prototype.THUMBNAIL_CLASS = 'bpmn-icon-service-task';
+ChoiceEntry.prototype.Type = 'ChoiceEntry';
 
-ServiceTask.prototype.DEFAULT_SIZE = {
-  width: 100,
-  height: 80,
-};
+ChoiceEntry.prototype.THUMBNAIL_CLASS = 'bpmn-icon-connection';
diff --git a/saga/seata-saga-statemachine-designer/src/spec/TaskState.js 
b/saga/seata-saga-statemachine-designer/src/spec/Compensation.js
similarity index 74%
copy from saga/seata-saga-statemachine-designer/src/spec/TaskState.js
copy to saga/seata-saga-statemachine-designer/src/spec/Compensation.js
index 47ab79b3c8..c496c18249 100644
--- a/saga/seata-saga-statemachine-designer/src/spec/TaskState.js
+++ b/saga/seata-saga-statemachine-designer/src/spec/Compensation.js
@@ -14,14 +14,12 @@
  *  limitations under the License.
  */
 
-import State from './State';
+import Transition from './Transition';
+
+export default class Compensation extends Transition {
 
-export default class TaskState extends State {
-  constructor() {
-    super();
-    this.Input = [{}];
-    this.Output = {};
-    this.Status = {};
-    this.Retry = [];
-  }
 }
+
+Compensation.prototype.Type = 'Compensation';
+
+Compensation.prototype.THUMBNAIL_CLASS = 'bpmn-icon-connection-multi';
diff --git a/saga/seata-saga-statemachine-designer/src/spec/TaskState.js 
b/saga/seata-saga-statemachine-designer/src/spec/CompensationTrigger.js
similarity index 68%
copy from saga/seata-saga-statemachine-designer/src/spec/TaskState.js
copy to saga/seata-saga-statemachine-designer/src/spec/CompensationTrigger.js
index 47ab79b3c8..4a023564fd 100644
--- a/saga/seata-saga-statemachine-designer/src/spec/TaskState.js
+++ b/saga/seata-saga-statemachine-designer/src/spec/CompensationTrigger.js
@@ -16,12 +16,15 @@
 
 import State from './State';
 
-export default class TaskState extends State {
-  constructor() {
-    super();
-    this.Input = [{}];
-    this.Output = {};
-    this.Status = {};
-    this.Retry = [];
-  }
+export default class CompensationTrigger extends State {
+
 }
+
+CompensationTrigger.prototype.Type = 'CompensationTrigger';
+
+CompensationTrigger.prototype.THUMBNAIL_CLASS = 
'bpmn-icon-intermediate-event-catch-compensation';
+
+CompensationTrigger.prototype.DEFAULT_SIZE = {
+  width: 36,
+  height: 36,
+};
diff --git a/saga/seata-saga-statemachine-designer/src/spec/ServiceTask.js 
b/saga/seata-saga-statemachine-designer/src/spec/ExceptionMatch.js
similarity index 58%
copy from saga/seata-saga-statemachine-designer/src/spec/ServiceTask.js
copy to saga/seata-saga-statemachine-designer/src/spec/ExceptionMatch.js
index 9ac9a2d447..72f7097b58 100644
--- a/saga/seata-saga-statemachine-designer/src/spec/ServiceTask.js
+++ b/saga/seata-saga-statemachine-designer/src/spec/ExceptionMatch.js
@@ -14,21 +14,26 @@
  *  limitations under the License.
  */
 
-import TaskState from './TaskState';
+import Transition from './Transition';
 
-export default class ServiceTask extends TaskState {
+export default class ExceptionMatch extends Transition {
   constructor() {
     super();
-    this.ServiceName = '';
-    this.ServiceMethod = '';
+    this.Exceptions = [];
+  }
+
+  importJson(json) {
+    super.importJson(json);
+    this.Exceptions = json.Exceptions;
   }
-}
 
-ServiceTask.prototype.Type = 'ServiceTask';
+  exportJson() {
+    const json = super.exportJson();
+    json.style.source = this.style.source.host.businessObject.Name;
+    return json;
+  }
+}
 
-ServiceTask.prototype.THUMBNAIL_CLASS = 'bpmn-icon-service-task';
+ExceptionMatch.prototype.Type = 'ExceptionMatch';
 
-ServiceTask.prototype.DEFAULT_SIZE = {
-  width: 100,
-  height: 80,
-};
+ExceptionMatch.prototype.THUMBNAIL_CLASS = 'bpmn-icon-connection';
diff --git a/saga/seata-saga-statemachine-designer/src/spec/TaskState.js 
b/saga/seata-saga-statemachine-designer/src/spec/Fail.js
similarity index 73%
copy from saga/seata-saga-statemachine-designer/src/spec/TaskState.js
copy to saga/seata-saga-statemachine-designer/src/spec/Fail.js
index 47ab79b3c8..d10fa518ab 100644
--- a/saga/seata-saga-statemachine-designer/src/spec/TaskState.js
+++ b/saga/seata-saga-statemachine-designer/src/spec/Fail.js
@@ -16,12 +16,19 @@
 
 import State from './State';
 
-export default class TaskState extends State {
+export default class Fail extends State {
   constructor() {
     super();
-    this.Input = [{}];
-    this.Output = {};
-    this.Status = {};
-    this.Retry = [];
+    this.ErrorCode = '';
+    this.Message = '';
   }
 }
+
+Fail.prototype.Type = 'Fail';
+
+Fail.prototype.THUMBNAIL_CLASS = 'bpmn-icon-end-event-error';
+
+Fail.prototype.DEFAULT_SIZE = {
+  width: 36,
+  height: 36,
+};
diff --git a/saga/seata-saga-statemachine-designer/src/spec/TaskState.js 
b/saga/seata-saga-statemachine-designer/src/spec/ScriptTask.js
similarity index 71%
copy from saga/seata-saga-statemachine-designer/src/spec/TaskState.js
copy to saga/seata-saga-statemachine-designer/src/spec/ScriptTask.js
index 47ab79b3c8..094f749c9c 100644
--- a/saga/seata-saga-statemachine-designer/src/spec/TaskState.js
+++ b/saga/seata-saga-statemachine-designer/src/spec/ScriptTask.js
@@ -14,14 +14,16 @@
  *  limitations under the License.
  */
 
-import State from './State';
+import TaskState from './TaskState';
 
-export default class TaskState extends State {
+export default class ScriptTask extends TaskState {
   constructor() {
     super();
-    this.Input = [{}];
-    this.Output = {};
-    this.Status = {};
-    this.Retry = [];
+    this.ScriptType = 'groovy';
+    this.ScriptContent = '';
   }
 }
+
+ScriptTask.prototype.Type = 'ScriptTask';
+
+ScriptTask.prototype.THUMBNAIL_CLASS = 'bpmn-icon-script-task';
diff --git a/saga/seata-saga-statemachine-designer/src/spec/ServiceTask.js 
b/saga/seata-saga-statemachine-designer/src/spec/ServiceTask.js
index 9ac9a2d447..000b1b3feb 100644
--- a/saga/seata-saga-statemachine-designer/src/spec/ServiceTask.js
+++ b/saga/seata-saga-statemachine-designer/src/spec/ServiceTask.js
@@ -27,8 +27,3 @@ export default class ServiceTask extends TaskState {
 ServiceTask.prototype.Type = 'ServiceTask';
 
 ServiceTask.prototype.THUMBNAIL_CLASS = 'bpmn-icon-service-task';
-
-ServiceTask.prototype.DEFAULT_SIZE = {
-  width: 100,
-  height: 80,
-};
diff --git a/saga/seata-saga-statemachine-designer/src/spec/TaskState.js 
b/saga/seata-saga-statemachine-designer/src/spec/SubStateMachine.js
similarity index 71%
copy from saga/seata-saga-statemachine-designer/src/spec/TaskState.js
copy to saga/seata-saga-statemachine-designer/src/spec/SubStateMachine.js
index 47ab79b3c8..6dcd611487 100644
--- a/saga/seata-saga-statemachine-designer/src/spec/TaskState.js
+++ b/saga/seata-saga-statemachine-designer/src/spec/SubStateMachine.js
@@ -14,14 +14,15 @@
  *  limitations under the License.
  */
 
-import State from './State';
+import TaskState from './TaskState';
 
-export default class TaskState extends State {
+export default class SubStateMachine extends TaskState {
   constructor() {
     super();
-    this.Input = [{}];
-    this.Output = {};
-    this.Status = {};
-    this.Retry = [];
+    this.StateMachineName = '';
   }
 }
+
+SubStateMachine.prototype.Type = 'SubStateMachine';
+
+SubStateMachine.prototype.THUMBNAIL_CLASS = 'bpmn-icon-subprocess-collapsed';
diff --git a/saga/seata-saga-statemachine-designer/src/spec/TaskState.js 
b/saga/seata-saga-statemachine-designer/src/spec/Succeed.js
similarity index 75%
copy from saga/seata-saga-statemachine-designer/src/spec/TaskState.js
copy to saga/seata-saga-statemachine-designer/src/spec/Succeed.js
index 47ab79b3c8..9ae46f34cd 100644
--- a/saga/seata-saga-statemachine-designer/src/spec/TaskState.js
+++ b/saga/seata-saga-statemachine-designer/src/spec/Succeed.js
@@ -16,12 +16,14 @@
 
 import State from './State';
 
-export default class TaskState extends State {
-  constructor() {
-    super();
-    this.Input = [{}];
-    this.Output = {};
-    this.Status = {};
-    this.Retry = [];
-  }
+export default class Succeed extends State {
 }
+
+Succeed.prototype.Type = 'Succeed';
+
+Succeed.prototype.THUMBNAIL_CLASS = 'bpmn-icon-end-event-none';
+
+Succeed.prototype.DEFAULT_SIZE = {
+  width: 36,
+  height: 36,
+};
diff --git a/saga/seata-saga-statemachine-designer/src/spec/TaskState.js 
b/saga/seata-saga-statemachine-designer/src/spec/TaskState.js
index 47ab79b3c8..70b1f45638 100644
--- a/saga/seata-saga-statemachine-designer/src/spec/TaskState.js
+++ b/saga/seata-saga-statemachine-designer/src/spec/TaskState.js
@@ -19,9 +19,34 @@ import State from './State';
 export default class TaskState extends State {
   constructor() {
     super();
+    this.IsForCompensation = false;
     this.Input = [{}];
     this.Output = {};
     this.Status = {};
     this.Retry = [];
   }
+
+  importJson(json) {
+    super.importJson(json);
+    delete this.catch;
+  }
+
+  exportJson() {
+    const json = super.exportJson();
+    const { Catch } = json;
+    if (Catch) {
+      json.catch = json.Catch.exportJson();
+      json.Catch = [];
+    }
+
+    if (this.CompensateState) {
+      json.CompensateState = this.CompensateState.Name;
+    }
+    return json;
+  }
 }
+
+TaskState.prototype.DEFAULT_SIZE = {
+  width: 100,
+  height: 80,
+};
diff --git a/saga/seata-saga-statemachine-designer/src/utils/index.js 
b/saga/seata-saga-statemachine-designer/src/utils/index.js
index 91b12d590b..83007488b5 100644
--- a/saga/seata-saga-statemachine-designer/src/utils/index.js
+++ b/saga/seata-saga-statemachine-designer/src/utils/index.js
@@ -60,12 +60,12 @@ export function setProperties(businessObject, properties, 
override) {
 export function is(element, target) {
   const type = element?.businessObject?.Type || element?.Type || element;
 
-  if (target === 'State') {
-    return type === 'ServiceTask';
+  if (target === 'Task') {
+    return type === 'ServiceTask' || type === 'ScriptTask' || type === 
'SubStateMachine';
   }
 
   if (target === 'Connection') {
-    return type === 'Transition';
+    return type === 'Transition' || type === 'ChoiceEntry' || type === 
'ExceptionMatch' || type === 'Compensation';
   }
 
   return type === target;


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


Reply via email to