chore(project): 添加项目配置文件和忽略规则
- 添加 Babel 配置文件支持 ES6+ 语法转换 - 添加 ESLint 忽略规则和配置文件 - 添加 Git 忽略规则文件 - 添加 Travis CI 配置文件 - 添加 1.4.2 版本变更日志文件 - 添加 Helm 图表辅助模板文件 - 添加 Helm 忽略规则文件
This commit is contained in:
42
saga/seata-saga-statemachine-designer/.babelrc
Normal file
42
saga/seata-saga-statemachine-designer/.babelrc
Normal file
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"presets": [
|
||||
[
|
||||
"@babel/preset-env",
|
||||
{
|
||||
"modules": false,
|
||||
"useBuiltIns": "usage",
|
||||
"corejs": "core-js@3",
|
||||
}
|
||||
],
|
||||
"@babel/preset-react"
|
||||
],
|
||||
"plugins": [
|
||||
"@babel/plugin-transform-runtime",
|
||||
[
|
||||
"@babel/plugin-proposal-class-properties",
|
||||
{
|
||||
"loose": true
|
||||
}
|
||||
],
|
||||
[
|
||||
"module-resolver",
|
||||
{
|
||||
"alias": {
|
||||
"@common": "./ggeditor/common",
|
||||
"@components": "./ggeditor/components",
|
||||
"@helpers": "./ggeditor/helpers",
|
||||
"@utils": "./ggeditor/utils",
|
||||
"@gg-editor-core": "./ggeditor/gg-editor-core"
|
||||
}
|
||||
}
|
||||
],
|
||||
[
|
||||
"transform-inline-environment-variables",
|
||||
{
|
||||
"include": [
|
||||
"GG_EDITOR_VERSION"
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
4
saga/seata-saga-statemachine-designer/.eslintignore
Normal file
4
saga/seata-saga-statemachine-designer/.eslintignore
Normal file
@@ -0,0 +1,4 @@
|
||||
es
|
||||
cjs
|
||||
dist
|
||||
scripts
|
||||
26
saga/seata-saga-statemachine-designer/.eslintrc.json
Normal file
26
saga/seata-saga-statemachine-designer/.eslintrc.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"env": {
|
||||
"browser": true
|
||||
},
|
||||
"parser": "babel-eslint",
|
||||
"extends": "airbnb",
|
||||
"rules": {
|
||||
"arrow-body-style": 0,
|
||||
"class-methods-use-this": 0,
|
||||
"func-names": 0,
|
||||
"import/extensions": 0,
|
||||
"import/no-extraneous-dependencies": 0,
|
||||
"import/no-unresolved": 0,
|
||||
"jsx-a11y/anchor-is-valid":0,
|
||||
"jsx-a11y/no-static-element-interactions": 0,
|
||||
"no-param-reassign": 0,
|
||||
"no-plusplus": 0,
|
||||
"object-curly-newline": 0,
|
||||
"react/destructuring-assignment": 0,
|
||||
"react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }],
|
||||
"react/no-multi-comp": 0,
|
||||
"react/prefer-stateless-function": 0,
|
||||
"react/prop-types": 0,
|
||||
"react/sort-comp": 0
|
||||
}
|
||||
}
|
||||
4
saga/seata-saga-statemachine-designer/.gitignore
vendored
Normal file
4
saga/seata-saga-statemachine-designer/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
es
|
||||
cjs
|
||||
dist
|
||||
node_modules
|
||||
13
saga/seata-saga-statemachine-designer/LICENSE
Normal file
13
saga/seata-saga-statemachine-designer/LICENSE
Normal file
@@ -0,0 +1,13 @@
|
||||
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.
|
||||
25
saga/seata-saga-statemachine-designer/README.md
Normal file
25
saga/seata-saga-statemachine-designer/README.md
Normal file
@@ -0,0 +1,25 @@
|
||||
English | [简体中文](README.zh-CN.md)
|
||||
|
||||
# Seata Saga StateMachine Designer
|
||||
|
||||
A visual graph Seata Saga StateMachine Designer based on [GGEditor](https://github.com/alibaba/GGEditor).
|
||||
|
||||
## run
|
||||
|
||||
```sh
|
||||
$ git clone https://github.com/seata/seata.git
|
||||
$ cd saga/seata-saga-statemachine-designer
|
||||
$ npm install
|
||||
$ npm start
|
||||
```
|
||||
|
||||
## build a package
|
||||
```sh
|
||||
$ cd saga/saga-statemachine-designer
|
||||
$ npm build
|
||||
```
|
||||
|
||||
copy 'index.html' and 'dist' directory to static html directory of web server
|
||||
|
||||
## Usage
|
||||
To understand the state types of the state machine, please see [document of Saga](http://seata.io/zh-cn/docs/user/saga.html). After using the designer to complete the design of the state machine, you can click the 'Json View' button on the toolbar to switch to the Json view, and save the Json to the project of your own application. Although the Json generated by the designer is different from the standard Json of the Saga state machine (because the json generated by the designer has layout information), the state machine can be directly loaded and it will be converted into the Json of the Saga state machine standard.
|
||||
25
saga/seata-saga-statemachine-designer/README.zh-CN.md
Normal file
25
saga/seata-saga-statemachine-designer/README.zh-CN.md
Normal file
@@ -0,0 +1,25 @@
|
||||
[English](README.md) | 简体中文
|
||||
|
||||
# Seata Saga StateMachine Designer
|
||||
|
||||
Seata Saga 状态机可视化图形设计器, 基于 [GGEditor](https://github.com/alibaba/GGEditor)
|
||||
|
||||
## 运行
|
||||
|
||||
```sh
|
||||
$ git clone https://github.com/seata/seata.git
|
||||
$ cd saga/seata-saga-statemachine-designer
|
||||
$ npm install
|
||||
$ npm start
|
||||
```
|
||||
|
||||
## 打包
|
||||
```sh
|
||||
$ cd saga/saga-statemachine-designer
|
||||
$ npm build
|
||||
```
|
||||
|
||||
然后将index.html和dist目录拷贝到web server的静态页面目录下
|
||||
|
||||
## 使用
|
||||
了解状态机的种状态类型,请看Saga的[文档](http://seata.io/zh-cn/docs/user/saga.html)。 通过设计器完成设计后可以点击工具栏的'Json View'按钮切换到Json视图,将Json拷贝保存到自己应用的工程里。虽然设计器生成的Json与Saga标准的Json有所差别(因为设计器生成的json带有布局信息),但状态机可以直接加载,它会将其转化成Saga状态机标准的Json。
|
||||
@@ -0,0 +1,13 @@
|
||||
const global = {
|
||||
trackable: process.env.NODE_ENV === 'production',
|
||||
version: process.env.GG_EDITOR_VERSION,
|
||||
};
|
||||
|
||||
export default {
|
||||
get(key) {
|
||||
return global[key];
|
||||
},
|
||||
set(key, value) {
|
||||
global[key] = value;
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,72 @@
|
||||
export const FLOW_CONTAINER = 'J_FlowContainer';
|
||||
export const MIND_CONTAINER = 'J_MindContainer';
|
||||
export const KONI_CONTAINER = 'J_KoniContainer';
|
||||
export const TOOLBAR_CONTAINER = 'J_ToolbarContainer';
|
||||
export const MINIMAP_CONTAINER = 'J_MinimapContainer';
|
||||
export const CONTEXT_MENU_CONTAINER = 'J_ContextMenuContainer';
|
||||
|
||||
export const FLOW_CLASS_NAME = 'Flow';
|
||||
export const MIND_CLASS_NAME = 'Mind';
|
||||
export const KONI_CLASS_NAME = 'Koni';
|
||||
|
||||
export const EVENT_BEFORE_ADD_PAGE = 'beforeAddPage';
|
||||
export const EVENT_AFTER_ADD_PAGE = 'afterAddPage';
|
||||
|
||||
export const STATUS_CANVAS_SELECTED = 'canvas-selected';
|
||||
export const STATUS_NODE_SELECTED = 'node-selected';
|
||||
export const STATUS_EDGE_SELECTED = 'edge-selected';
|
||||
export const STATUS_GROUP_SELECTED = 'group-selected';
|
||||
export const STATUS_MULTI_SELECTED = 'multi-selected';
|
||||
|
||||
export const GRAPH_MOUSE_REACT_EVENTS = {
|
||||
click: 'Click',
|
||||
contextmenu: 'ContextMenu',
|
||||
dblclick: 'DoubleClick',
|
||||
drag: 'Drag',
|
||||
dragend: 'DragEnd',
|
||||
dragenter: 'DragEnter',
|
||||
dragleave: 'DragLeave',
|
||||
dragstart: 'DragStart',
|
||||
drop: 'Drop',
|
||||
mousedown: 'MouseDown',
|
||||
mouseenter: 'MouseEnter',
|
||||
mouseleave: 'MouseLeave',
|
||||
mousemove: 'MouseMove',
|
||||
mouseup: 'MouseUp',
|
||||
};
|
||||
|
||||
export const GRAPH_OTHER_REACT_EVENTS = {
|
||||
afterchange: 'onAfterChange',
|
||||
afterchangesize: 'onAfterChangeSize',
|
||||
afterviewportchange: 'onAfterViewportChange',
|
||||
beforechange: 'onBeforeChange',
|
||||
beforechangesize: 'onBeforeChangeSize',
|
||||
beforeviewportchange: 'onBeforeViewportChange',
|
||||
keydown: 'onKeyDown',
|
||||
keyup: 'onKeyUp',
|
||||
mousewheel: 'onMouseWheel',
|
||||
};
|
||||
|
||||
export const PAGE_REACT_EVENTS = {
|
||||
afteritemactived: 'onAfterItemActived',
|
||||
afteriteminactivated: 'onAfterItemInactivated',
|
||||
afteritemselected: 'onAfterItemSelected',
|
||||
afteritemunactived: 'onAfterItemInactivated',
|
||||
afteritemunselected: 'onAfterItemUnselected',
|
||||
beforeitemactived: 'onBeforeItemActived',
|
||||
beforeiteminactivated: 'onBeforeItemInactivated',
|
||||
beforeitemselected: 'onBeforeItemSelected',
|
||||
beforeitemunactived: 'onBeforeItemInactivated',
|
||||
beforeitemunselected: 'onBeforeItemUnselected',
|
||||
keyUpEditLabel: 'onKeyUpEditLabel',
|
||||
};
|
||||
|
||||
export const EDITOR_REACT_EVENTS = {
|
||||
aftercommandexecute: 'onAfterCommandExecute',
|
||||
beforecommandexecute: 'onBeforeCommandExecute',
|
||||
};
|
||||
|
||||
export const GRAPH_MOUSE_EVENTS = Object.keys(GRAPH_MOUSE_REACT_EVENTS);
|
||||
export const GRAPH_OTHER_EVENTS = Object.keys(GRAPH_OTHER_REACT_EVENTS);
|
||||
export const PAGE_EVENTS = Object.keys(PAGE_REACT_EVENTS);
|
||||
export const EDITOR_EVENTS = Object.keys(EDITOR_REACT_EVENTS);
|
||||
@@ -0,0 +1,3 @@
|
||||
import React from 'react';
|
||||
|
||||
export default React.createContext({});
|
||||
@@ -0,0 +1,18 @@
|
||||
import React from 'react';
|
||||
import GGEditorContext from '@common/context/GGEditorContext';
|
||||
|
||||
export default function (WrappedComponent) {
|
||||
class InjectGGEditorContext extends React.Component {
|
||||
render() {
|
||||
const { forwardRef, ...rest } = this.props;
|
||||
|
||||
return (
|
||||
<GGEditorContext.Consumer>
|
||||
{context => <WrappedComponent ref={forwardRef} {...rest} {...context} />}
|
||||
</GGEditorContext.Consumer>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return React.forwardRef((props, ref) => <InjectGGEditorContext {...props} forwardRef={ref} />);
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
import React from 'react';
|
||||
|
||||
export default React.createContext({});
|
||||
@@ -0,0 +1,21 @@
|
||||
class PropsAPI {
|
||||
editor = null;
|
||||
|
||||
constructor(editor) {
|
||||
this.editor = editor;
|
||||
|
||||
['executeCommand'].forEach((key) => {
|
||||
this[key] = (...params) => this.editor[key](...params);
|
||||
});
|
||||
|
||||
['read', 'save', 'add', 'find', 'update', 'remove', 'getSelected'].forEach((key) => {
|
||||
this[key] = (...params) => this.currentPage[key](...params);
|
||||
});
|
||||
}
|
||||
|
||||
get currentPage() {
|
||||
return this.editor.getCurrentPage();
|
||||
}
|
||||
}
|
||||
|
||||
export default PropsAPI;
|
||||
@@ -0,0 +1,18 @@
|
||||
import React from 'react';
|
||||
import PropsAPIContext from '@common/context/PropsAPIContext';
|
||||
|
||||
export default function (WrappedComponent) {
|
||||
class InjectPropsAPI extends React.Component {
|
||||
render() {
|
||||
const { forwardRef, ...rest } = this.props;
|
||||
|
||||
return (
|
||||
<PropsAPIContext.Consumer>
|
||||
{propsAPI => <WrappedComponent ref={forwardRef} {...rest} propsAPI={propsAPI} />}
|
||||
</PropsAPIContext.Consumer>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return React.forwardRef((props, ref) => <InjectPropsAPI {...props} forwardRef={ref} />);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import GGEditorCore from '@gg-editor-core/bundle';
|
||||
import { EVENT_BEFORE_ADD_PAGE } from '@common/constants';
|
||||
import track from '@helpers/track';
|
||||
import { uniqueId } from '@utils';
|
||||
|
||||
export default class Editor extends GGEditorCore {
|
||||
constructor(options) {
|
||||
super(options);
|
||||
|
||||
this.id = uniqueId();
|
||||
|
||||
this.on(EVENT_BEFORE_ADD_PAGE, ({ className }) => {
|
||||
track({ c1: className });
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import React from 'react';
|
||||
|
||||
class Command extends React.Component {
|
||||
render() {
|
||||
const { name, children } = this.props;
|
||||
|
||||
return (
|
||||
<div className="command" data-command={name}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Command;
|
||||
@@ -0,0 +1,30 @@
|
||||
import React from 'react';
|
||||
|
||||
class Menu extends React.Component {
|
||||
static create = function (type) {
|
||||
return class TypedMenu extends Menu {
|
||||
constructor(props) {
|
||||
super(props, type);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
constructor(props, type) {
|
||||
super(props);
|
||||
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
render() {
|
||||
const { children } = this.props;
|
||||
const { type } = this;
|
||||
|
||||
return (
|
||||
<div className="menu" data-status={`${type}-selected`}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Menu;
|
||||
@@ -0,0 +1,44 @@
|
||||
import React from 'react';
|
||||
import { pick } from '@utils';
|
||||
import Editor from '@components/Base/Editor';
|
||||
import { CONTEXT_MENU_CONTAINER } from '@common/constants';
|
||||
import withGGEditorContext from '@common/context/GGEditorContext/withGGEditorContext';
|
||||
import Menu from './Menu';
|
||||
|
||||
class ContextMenu extends React.Component {
|
||||
contextMenu = null;
|
||||
|
||||
get containerId() {
|
||||
const { editor } = this.props;
|
||||
|
||||
return `${CONTEXT_MENU_CONTAINER}_${editor.id}`;
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { editor } = this.props;
|
||||
|
||||
this.contextMenu = new Editor.Contextmenu({
|
||||
container: this.containerId,
|
||||
});
|
||||
|
||||
editor.add(this.contextMenu);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { children } = this.props;
|
||||
|
||||
return (
|
||||
<div id={this.containerId} {...pick(this.props, ['style', 'className'])}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const NodeMenu = Menu.create('node');
|
||||
export const EdgeMenu = Menu.create('edge');
|
||||
export const GroupMenu = Menu.create('group');
|
||||
export const MultiMenu = Menu.create('multi');
|
||||
export const CanvasMenu = Menu.create('canvas');
|
||||
|
||||
export default withGGEditorContext(ContextMenu);
|
||||
@@ -0,0 +1,35 @@
|
||||
import React from 'react';
|
||||
import { pick } from '@utils';
|
||||
|
||||
class Panel extends React.Component {
|
||||
static create = function (type) {
|
||||
return class TypedPanel extends Panel {
|
||||
constructor(props) {
|
||||
super(props, type);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
constructor(props, type) {
|
||||
super(props);
|
||||
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
render() {
|
||||
const { status, children } = this.props;
|
||||
const { type } = this;
|
||||
|
||||
if (`${type}-selected` !== status) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div {...pick(this.props, ['style', 'className'])}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Panel;
|
||||
@@ -0,0 +1,58 @@
|
||||
import React from 'react';
|
||||
import { pick } from '@utils';
|
||||
import { STATUS_CANVAS_SELECTED } from '@common/constants';
|
||||
import withGGEditorContext from '@common/context/GGEditorContext/withGGEditorContext';
|
||||
import Panel from './Panel';
|
||||
|
||||
class DetailPanel extends React.Component {
|
||||
state = {
|
||||
status: '',
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.bindEvent();
|
||||
}
|
||||
|
||||
bindEvent() {
|
||||
const { onAfterAddPage } = this.props;
|
||||
|
||||
onAfterAddPage(({ page }) => {
|
||||
this.setState({
|
||||
status: STATUS_CANVAS_SELECTED,
|
||||
});
|
||||
|
||||
page.on('statuschange', ({ status }) => {
|
||||
this.setState({ status });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { children } = this.props;
|
||||
const { status } = this.state;
|
||||
|
||||
if (!status) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div {...pick(this.props, ['style', 'className'])}>
|
||||
{
|
||||
React.Children.toArray(children).map(child => React.cloneElement(child, {
|
||||
status,
|
||||
}))
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const NodePanel = Panel.create('node');
|
||||
export const EdgePanel = Panel.create('edge');
|
||||
export const GroupPanel = Panel.create('group');
|
||||
export const MultiPanel = Panel.create('multi');
|
||||
export const CanvasPanel = Panel.create('canvas');
|
||||
|
||||
export default withGGEditorContext(DetailPanel);
|
||||
@@ -0,0 +1,38 @@
|
||||
import Editor from '@components/Base/Editor';
|
||||
import {
|
||||
FLOW_CONTAINER,
|
||||
FLOW_CLASS_NAME,
|
||||
EVENT_BEFORE_ADD_PAGE,
|
||||
EVENT_AFTER_ADD_PAGE,
|
||||
} from '@common/constants';
|
||||
import Page from '@components/Page';
|
||||
import withGGEditorContext from '@common/context/GGEditorContext/withGGEditorContext';
|
||||
|
||||
class Flow extends Page {
|
||||
static defaultProps = {
|
||||
data: {
|
||||
nodes: [],
|
||||
edges: [],
|
||||
},
|
||||
};
|
||||
|
||||
get pageId() {
|
||||
const { editor } = this.props;
|
||||
|
||||
return `${FLOW_CONTAINER}_${editor.id}`;
|
||||
}
|
||||
|
||||
initPage() {
|
||||
const { editor } = this.props;
|
||||
|
||||
editor.emit(EVENT_BEFORE_ADD_PAGE, { className: FLOW_CLASS_NAME });
|
||||
|
||||
this.page = new Editor.Flow(this.config);
|
||||
|
||||
editor.add(this.page);
|
||||
|
||||
editor.emit(EVENT_AFTER_ADD_PAGE, { page: this.page });
|
||||
}
|
||||
}
|
||||
|
||||
export default withGGEditorContext(Flow);
|
||||
@@ -0,0 +1,85 @@
|
||||
import React from 'react';
|
||||
import Editor from '@components/Base/Editor';
|
||||
import {
|
||||
EDITOR_EVENTS,
|
||||
EDITOR_REACT_EVENTS,
|
||||
EVENT_BEFORE_ADD_PAGE,
|
||||
EVENT_AFTER_ADD_PAGE,
|
||||
} from '@common/constants';
|
||||
import { pick } from '@utils';
|
||||
import Global from '@common/Global';
|
||||
import GGEditorContext from '@common/context/GGEditorContext';
|
||||
import PropsAPIContext from '@common/context/PropsAPIContext';
|
||||
import PropsAPI from '@common/context/PropsAPIContext/propsAPI';
|
||||
|
||||
class GGEditor extends React.Component {
|
||||
static setTrackable(value) {
|
||||
Global.set('trackable', Boolean(value));
|
||||
}
|
||||
|
||||
editor = null;
|
||||
|
||||
get currentPage() {
|
||||
return this.editor.getCurrentPage();
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.init();
|
||||
this.bindEvent();
|
||||
}
|
||||
|
||||
addListener = (target, eventName, handler) => {
|
||||
if (typeof handler === 'function') target.on(eventName, handler);
|
||||
};
|
||||
|
||||
handleBeforeAddPage = (func) => {
|
||||
this.editor.on(EVENT_BEFORE_ADD_PAGE, func);
|
||||
};
|
||||
|
||||
handleAfterAddPage = (func) => {
|
||||
const { currentPage: page } = this;
|
||||
|
||||
if (page) {
|
||||
func({ page });
|
||||
return;
|
||||
}
|
||||
|
||||
this.editor.on(EVENT_AFTER_ADD_PAGE, func);
|
||||
};
|
||||
|
||||
init() {
|
||||
this.editor = new Editor();
|
||||
this.ggEditor = {
|
||||
editor: this.editor,
|
||||
onBeforeAddPage: this.handleBeforeAddPage,
|
||||
onAfterAddPage: this.handleAfterAddPage,
|
||||
};
|
||||
this.propsAPI = new PropsAPI(this.editor);
|
||||
}
|
||||
|
||||
bindEvent() {
|
||||
EDITOR_EVENTS.forEach((event) => {
|
||||
this.addListener(this.editor, [event], this.props[EDITOR_REACT_EVENTS[event]]);
|
||||
});
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.editor.destroy();
|
||||
}
|
||||
|
||||
render() {
|
||||
const { children } = this.props;
|
||||
|
||||
return (
|
||||
<GGEditorContext.Provider value={this.ggEditor}>
|
||||
<PropsAPIContext.Provider value={this.propsAPI}>
|
||||
<div {...pick(this.props, ['style', 'className'])}>{children}</div>
|
||||
</PropsAPIContext.Provider>
|
||||
</GGEditorContext.Provider>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default GGEditor;
|
||||
@@ -0,0 +1,43 @@
|
||||
import React from 'react';
|
||||
import withGGEditorContext from '@common/context/GGEditorContext/withGGEditorContext';
|
||||
|
||||
class Item extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.bindEvent();
|
||||
}
|
||||
|
||||
handleMouseDown = () => {
|
||||
const { type, size, shape, model } = this.props;
|
||||
|
||||
if (this.page) {
|
||||
this.page.beginAdd(type, {
|
||||
type,
|
||||
size,
|
||||
shape,
|
||||
...model,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
bindEvent() {
|
||||
const { onAfterAddPage } = this.props;
|
||||
|
||||
onAfterAddPage(({ page }) => {
|
||||
this.page = page;
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { src, shape, children } = this.props;
|
||||
|
||||
return (
|
||||
<div style={{ cursor: 'pointer' }} onMouseDown={this.handleMouseDown}>
|
||||
{src ? <img src={src} alt={shape} draggable={false} /> : children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withGGEditorContext(Item);
|
||||
@@ -0,0 +1,46 @@
|
||||
import React from 'react';
|
||||
import { pick } from '@utils';
|
||||
import withGGEditorContext from '@common/context/GGEditorContext/withGGEditorContext';
|
||||
import Item from './Item';
|
||||
|
||||
class ItemPanel extends React.Component {
|
||||
page = null;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.bindEvent();
|
||||
}
|
||||
|
||||
handleMouseUp = () => {
|
||||
this.page.cancelAdd();
|
||||
}
|
||||
|
||||
bindEvent() {
|
||||
const { onAfterAddPage } = this.props;
|
||||
|
||||
onAfterAddPage(({ page }) => {
|
||||
this.page = page;
|
||||
|
||||
document.addEventListener('mouseup', this.handleMouseUp);
|
||||
});
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
document.removeEventListener('mouseup', this.handleMouseUp);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { children } = this.props;
|
||||
|
||||
return (
|
||||
<div id={this.containerId} {...pick(this.props, ['style', 'className'])}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export { Item };
|
||||
|
||||
export default withGGEditorContext(ItemPanel);
|
||||
@@ -0,0 +1,38 @@
|
||||
import Editor from '@components/Base/Editor';
|
||||
import {
|
||||
KONI_CONTAINER,
|
||||
KONI_CLASS_NAME,
|
||||
EVENT_BEFORE_ADD_PAGE,
|
||||
EVENT_AFTER_ADD_PAGE,
|
||||
} from '@common/constants';
|
||||
import Page from '@components/Page';
|
||||
import withGGEditorContext from '@common/context/GGEditorContext/withGGEditorContext';
|
||||
|
||||
class Koni extends Page {
|
||||
static defaultProps = {
|
||||
data: {
|
||||
nodes: [],
|
||||
edges: [],
|
||||
},
|
||||
};
|
||||
|
||||
get pageId() {
|
||||
const { editor } = this.props;
|
||||
|
||||
return `${KONI_CONTAINER}_${editor.id}`;
|
||||
}
|
||||
|
||||
initPage() {
|
||||
const { editor } = this.props;
|
||||
|
||||
editor.emit(EVENT_BEFORE_ADD_PAGE, { className: KONI_CLASS_NAME });
|
||||
|
||||
this.page = new Editor.Koni(this.config);
|
||||
|
||||
editor.add(this.page);
|
||||
|
||||
editor.emit(EVENT_AFTER_ADD_PAGE, { page: this.page });
|
||||
}
|
||||
}
|
||||
|
||||
export default withGGEditorContext(Koni);
|
||||
@@ -0,0 +1,52 @@
|
||||
import Editor from '@components/Base/Editor';
|
||||
import {
|
||||
MIND_CONTAINER,
|
||||
MIND_CLASS_NAME,
|
||||
EVENT_BEFORE_ADD_PAGE,
|
||||
EVENT_AFTER_ADD_PAGE,
|
||||
} from '@common/constants';
|
||||
import Page from '@components/Page';
|
||||
import withGGEditorContext from '@common/context/GGEditorContext/withGGEditorContext';
|
||||
|
||||
class Mind extends Page {
|
||||
get pageId() {
|
||||
const { editor } = this.props;
|
||||
|
||||
return `${MIND_CONTAINER}_${editor.id}`;
|
||||
}
|
||||
|
||||
initPage() {
|
||||
const { editor } = this.props;
|
||||
|
||||
editor.emit(EVENT_BEFORE_ADD_PAGE, { className: MIND_CLASS_NAME });
|
||||
|
||||
this.page = new Editor.Mind(this.config);
|
||||
|
||||
editor.add(this.page);
|
||||
|
||||
editor.emit(EVENT_AFTER_ADD_PAGE, { page: this.page });
|
||||
}
|
||||
|
||||
bindEvent() {
|
||||
super.bindEvent();
|
||||
this.bindKeyUpEditLabel();
|
||||
}
|
||||
|
||||
bindKeyUpEditLabel() {
|
||||
const editLabel = this.page.get('labelTextArea');
|
||||
|
||||
editLabel.on('keyup', (e) => {
|
||||
e.stopPropagation();
|
||||
|
||||
const item = editLabel.focusItem;
|
||||
const text = editLabel.textContent;
|
||||
|
||||
this.page.emit('keyUpEditLabel', {
|
||||
item,
|
||||
text,
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default withGGEditorContext(Mind);
|
||||
@@ -0,0 +1,89 @@
|
||||
import React from 'react';
|
||||
import G6 from '@antv/g6';
|
||||
import { pick } from '@utils';
|
||||
import { MINIMAP_CONTAINER } from '@common/constants';
|
||||
import withGGEditorContext from '@common/context/GGEditorContext/withGGEditorContext';
|
||||
|
||||
require('@antv/g6/build/plugin.tool.minimap');
|
||||
|
||||
const { Minimap: G6Minimap } = G6.Components;
|
||||
|
||||
class Minimap extends React.Component {
|
||||
minimap = null;
|
||||
|
||||
get containerId() {
|
||||
const { editor } = this.props;
|
||||
|
||||
return `${MINIMAP_CONTAINER}_${editor.id}`;
|
||||
}
|
||||
|
||||
get currentPage() {
|
||||
const { editor } = this.props;
|
||||
|
||||
return editor.getCurrentPage();
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.bindEvent();
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.init();
|
||||
this.bindPage();
|
||||
}
|
||||
|
||||
init() {
|
||||
const {
|
||||
container = this.containerId,
|
||||
width,
|
||||
height,
|
||||
viewportWindowStyle,
|
||||
viewportBackStyle,
|
||||
} = this.props;
|
||||
|
||||
const { clientWidth, clientHeight } = document.getElementById(container);
|
||||
|
||||
this.minimap = new G6Minimap({
|
||||
container,
|
||||
width: width || clientWidth,
|
||||
height: height || clientHeight,
|
||||
viewportWindowStyle,
|
||||
viewportBackStyle,
|
||||
});
|
||||
|
||||
this.minimap.getGraph = () => this.currentPage.getGraph();
|
||||
}
|
||||
|
||||
bindPage() {
|
||||
if (!this.minimap || !this.currentPage) {
|
||||
return;
|
||||
}
|
||||
|
||||
const graph = this.currentPage.getGraph();
|
||||
|
||||
this.minimap.bindGraph(graph);
|
||||
this.minimap.debounceRender();
|
||||
}
|
||||
|
||||
bindEvent() {
|
||||
const { onAfterAddPage } = this.props;
|
||||
|
||||
onAfterAddPage(() => {
|
||||
this.bindPage();
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { container } = this.props;
|
||||
|
||||
if (container) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return <div id={this.containerId} {...pick(this.props, ['style', 'className'])} />;
|
||||
}
|
||||
}
|
||||
|
||||
export default withGGEditorContext(Minimap);
|
||||
@@ -0,0 +1,121 @@
|
||||
import React from 'react';
|
||||
import { pick, merge } from '@utils';
|
||||
import {
|
||||
GRAPH_MOUSE_EVENTS,
|
||||
GRAPH_OTHER_EVENTS,
|
||||
PAGE_EVENTS,
|
||||
GRAPH_MOUSE_REACT_EVENTS,
|
||||
GRAPH_OTHER_REACT_EVENTS,
|
||||
PAGE_REACT_EVENTS,
|
||||
} from '@common/constants';
|
||||
|
||||
class Page extends React.Component {
|
||||
page;
|
||||
|
||||
get pageId() {
|
||||
return '';
|
||||
}
|
||||
|
||||
config = {};
|
||||
|
||||
componentDidMount() {
|
||||
this.init();
|
||||
this.bindEvent();
|
||||
this.forceUpdate();
|
||||
}
|
||||
|
||||
shouldComponentUpdate(props) {
|
||||
const { data: newData } = props;
|
||||
const { data: oldData } = this.props;
|
||||
const { mode: newMode } = props.graph || {};
|
||||
const { mode: oldMode } = this.props.graph || {};
|
||||
|
||||
if (newMode !== oldMode) {
|
||||
this.page.changeMode(newMode);
|
||||
}
|
||||
|
||||
if (newData !== oldData) {
|
||||
// Remove the arrow after the connection point of the compensation type
|
||||
newData.edges.forEach((item) => {
|
||||
if (item.type === 'Compensation') {
|
||||
item.style = {
|
||||
...item.style,
|
||||
endArrow: false,
|
||||
};
|
||||
}
|
||||
});
|
||||
this.page.read(newData);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (props.className !== this.props.className) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
get graph() {
|
||||
return this.page.getGraph();
|
||||
}
|
||||
|
||||
initPage() { }
|
||||
|
||||
readData() {
|
||||
const { data } = this.config;
|
||||
|
||||
if (data) {
|
||||
this.page.read(data);
|
||||
}
|
||||
}
|
||||
|
||||
addListener = (target, eventName, handler) => {
|
||||
if (typeof handler === 'function') target.on(eventName, handler);
|
||||
};
|
||||
|
||||
init() {
|
||||
merge(this.config, this.props, {
|
||||
graph: {
|
||||
container: this.pageId,
|
||||
},
|
||||
});
|
||||
|
||||
this.initPage();
|
||||
this.readData();
|
||||
}
|
||||
|
||||
bindEvent() {
|
||||
const { addListener } = this;
|
||||
|
||||
GRAPH_MOUSE_EVENTS.forEach((event) => {
|
||||
const eventName = GRAPH_MOUSE_REACT_EVENTS[event];
|
||||
|
||||
addListener(this.graph, `${event}`, this.props[`on${eventName}`]);
|
||||
addListener(this.graph, `node:${event}`, this.props[`onNode${eventName}`]);
|
||||
addListener(this.graph, `edge:${event}`, this.props[`onEdge${eventName}`]);
|
||||
addListener(this.graph, `group:${event}`, this.props[`onGroup${eventName}`]);
|
||||
addListener(this.graph, `guide:${event}`, this.props[`onGuide${eventName}`]);
|
||||
addListener(this.graph, `anchor:${event}`, this.props[`onAnchor${eventName}`]);
|
||||
});
|
||||
|
||||
GRAPH_OTHER_EVENTS.forEach((event) => {
|
||||
addListener(this.graph, [event], this.props[GRAPH_OTHER_REACT_EVENTS[event]]);
|
||||
});
|
||||
|
||||
PAGE_EVENTS.forEach((event) => {
|
||||
addListener(this.page, [event], this.props[PAGE_REACT_EVENTS[event]]);
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { page, pageId } = this;
|
||||
const { children } = this.props;
|
||||
|
||||
return (
|
||||
<div id={pageId} {...pick(this.props, ['style', 'className'])}>
|
||||
{page ? children : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Page;
|
||||
@@ -0,0 +1,57 @@
|
||||
import React from 'react';
|
||||
import Editor from '@components/Base/Editor';
|
||||
import { upperFirst } from '@utils';
|
||||
import withGGEditorContext from '@common/context/GGEditorContext/withGGEditorContext';
|
||||
|
||||
class Register extends React.Component {
|
||||
static create = function (type) {
|
||||
class TypedRegister extends Register {
|
||||
constructor(props) {
|
||||
super(props, type);
|
||||
}
|
||||
}
|
||||
|
||||
return withGGEditorContext(TypedRegister);
|
||||
}
|
||||
|
||||
constructor(props, type) {
|
||||
super(props);
|
||||
|
||||
this.type = type;
|
||||
|
||||
this.bindEvent();
|
||||
}
|
||||
|
||||
bindEvent() {
|
||||
const { type } = this;
|
||||
const { onBeforeAddPage } = this.props;
|
||||
|
||||
onBeforeAddPage(({ className }) => {
|
||||
let host = Editor[className];
|
||||
let keys = ['name', 'config', 'extend'];
|
||||
|
||||
if (type === 'command') {
|
||||
host = Editor;
|
||||
}
|
||||
|
||||
if (type === 'behaviour') {
|
||||
keys = ['name', 'behaviour', 'dependences'];
|
||||
}
|
||||
|
||||
const args = keys.map(key => this.props[key]);
|
||||
|
||||
host[`register${upperFirst(type)}`](...args);
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export const RegisterNode = Register.create('node');
|
||||
export const RegisterEdge = Register.create('edge');
|
||||
export const RegisterGroup = Register.create('group');
|
||||
export const RegisterGuide = Register.create('guide');
|
||||
export const RegisterCommand = Register.create('command');
|
||||
export const RegisterBehaviour = Register.create('behaviour');
|
||||
@@ -0,0 +1,41 @@
|
||||
import React from 'react';
|
||||
import Editor from '@components/Base/Editor';
|
||||
import { pick } from '@utils';
|
||||
import { TOOLBAR_CONTAINER } from '@common/constants';
|
||||
import withGGEditorContext from '@common/context/GGEditorContext/withGGEditorContext';
|
||||
|
||||
class Toolbar extends React.Component {
|
||||
toolbar = null;
|
||||
|
||||
get containerId() {
|
||||
const { editor } = this.props;
|
||||
|
||||
return `${TOOLBAR_CONTAINER}_${editor.id}`;
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
const { editor, onAfterAddPage } = props;
|
||||
|
||||
onAfterAddPage(() => {
|
||||
this.toolbar = new Editor.Toolbar({
|
||||
container: this.containerId,
|
||||
});
|
||||
|
||||
editor.add(this.toolbar);
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { children } = this.props;
|
||||
|
||||
return (
|
||||
<div id={this.containerId} {...pick(this.props, ['style', 'className'])}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withGGEditorContext(Toolbar);
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,34 @@
|
||||
import Global from '@common/Global';
|
||||
import { toQueryString } from '@utils';
|
||||
|
||||
const BASE_URL = 'http://gm.mmstat.com/fsp.1.1';
|
||||
|
||||
const track = (options) => {
|
||||
const trackable = Global.get('trackable');
|
||||
const version = Global.get('version');
|
||||
|
||||
if (!trackable) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { location, navigator } = window;
|
||||
const image = new Image();
|
||||
const params = toQueryString({
|
||||
pid: 'ggeditor',
|
||||
code: '11',
|
||||
msg: 'syslog',
|
||||
page: `${location.protocol}//${location.host}${location.pathname}`,
|
||||
hash: location.hash,
|
||||
ua: navigator.userAgent,
|
||||
rel: version,
|
||||
...options,
|
||||
});
|
||||
|
||||
image.src = `${BASE_URL}?${params}`;
|
||||
};
|
||||
|
||||
export default (options) => {
|
||||
setTimeout(() => {
|
||||
track(options);
|
||||
}, 1000);
|
||||
};
|
||||
63
saga/seata-saga-statemachine-designer/ggeditor/index.js
Normal file
63
saga/seata-saga-statemachine-designer/ggeditor/index.js
Normal file
@@ -0,0 +1,63 @@
|
||||
import Flow from '@components/Flow';
|
||||
import Mind from '@components/Mind';
|
||||
import Koni from '@components/Koni';
|
||||
import {
|
||||
RegisterNode,
|
||||
RegisterEdge,
|
||||
RegisterGroup,
|
||||
RegisterGuide,
|
||||
RegisterCommand,
|
||||
RegisterBehaviour,
|
||||
} from '@components/Register';
|
||||
import Command from '@components/Command';
|
||||
import Minimap from '@components/Minimap';
|
||||
import ContextMenu, {
|
||||
NodeMenu,
|
||||
EdgeMenu,
|
||||
GroupMenu,
|
||||
MultiMenu,
|
||||
CanvasMenu,
|
||||
} from '@components/ContextMenu';
|
||||
import Toolbar from '@components/Toolbar';
|
||||
import ItemPanel, { Item } from '@components/ItemPanel';
|
||||
import DetailPanel, {
|
||||
NodePanel,
|
||||
EdgePanel,
|
||||
GroupPanel,
|
||||
MultiPanel,
|
||||
CanvasPanel,
|
||||
} from '@components/DetailPanel';
|
||||
import withPropsAPI from '@common/context/PropsAPIContext/withPropsAPI';
|
||||
import GGEditor from '@components/GGEditor';
|
||||
|
||||
export {
|
||||
Flow,
|
||||
Mind,
|
||||
Koni,
|
||||
RegisterNode,
|
||||
RegisterEdge,
|
||||
RegisterGroup,
|
||||
RegisterGuide,
|
||||
RegisterCommand,
|
||||
RegisterBehaviour,
|
||||
Command,
|
||||
Minimap,
|
||||
NodeMenu,
|
||||
EdgeMenu,
|
||||
GroupMenu,
|
||||
MultiMenu,
|
||||
CanvasMenu,
|
||||
ContextMenu,
|
||||
Toolbar,
|
||||
Item,
|
||||
ItemPanel,
|
||||
NodePanel,
|
||||
EdgePanel,
|
||||
GroupPanel,
|
||||
MultiPanel,
|
||||
CanvasPanel,
|
||||
DetailPanel,
|
||||
withPropsAPI,
|
||||
};
|
||||
|
||||
export default GGEditor;
|
||||
@@ -0,0 +1,14 @@
|
||||
import merge from 'lodash/merge';
|
||||
import pick from 'lodash/pick';
|
||||
import uniqueId from 'lodash/uniqueId';
|
||||
import upperFirst from 'lodash/upperFirst';
|
||||
|
||||
const toQueryString = obj => Object.keys(obj).map(key => `${encodeURIComponent(key)}=${encodeURIComponent(obj[key])}`).join('&');
|
||||
|
||||
export {
|
||||
merge,
|
||||
pick,
|
||||
toQueryString,
|
||||
uniqueId,
|
||||
upperFirst,
|
||||
};
|
||||
22
saga/seata-saga-statemachine-designer/index.html
Normal file
22
saga/seata-saga-statemachine-designer/index.html
Normal file
@@ -0,0 +1,22 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
<title>Seata Saga StateMachine Designer</title>
|
||||
<link rel="stylesheet" href="http://g.alicdn.com/code/lib/antd/3.16.1/antd.min.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script src="http://g.alicdn.com/code/lib/react/16.8.6/umd/react.production.min.js"></script>
|
||||
<script src="http://g.alicdn.com/code/lib/react-dom/16.8.6/umd/react-dom.production.min.js"></script>
|
||||
<script src="http://g.alicdn.com/code/lib/react-router-dom/5.0.0/react-router-dom.min.js"></script>
|
||||
<script src="http://g.alicdn.com/code/lib/moment.js/2.24.0/moment.min.js"></script>
|
||||
<script src="http://g.alicdn.com/code/lib/antd/3.16.1/antd.min.js"></script>
|
||||
<script src="./dist/bundle.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
10647
saga/seata-saga-statemachine-designer/package-lock.json
generated
Normal file
10647
saga/seata-saga-statemachine-designer/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
94
saga/seata-saga-statemachine-designer/package.json
Normal file
94
saga/seata-saga-statemachine-designer/package.json
Normal file
@@ -0,0 +1,94 @@
|
||||
{
|
||||
"name": "seata-saga-statemachine-designer",
|
||||
"version": "0.0.1",
|
||||
"description": "A visual graph designer for Seata Saga StateMachine based on GGEdior 2.0.4",
|
||||
"keywords": [
|
||||
"react",
|
||||
"graphics",
|
||||
"designer",
|
||||
"seata",
|
||||
"saga",
|
||||
"state machine"
|
||||
],
|
||||
"main": "cjs/index.js",
|
||||
"module": "es/index.js",
|
||||
"types": "typings/index.d.ts",
|
||||
"files": [
|
||||
"src",
|
||||
"es",
|
||||
"cjs",
|
||||
"dist",
|
||||
"*.md",
|
||||
"typings"
|
||||
],
|
||||
"scripts": {
|
||||
"start": "webpack-dev-server --config ./tools/webpack.config.dev.js --open",
|
||||
"build": "rimraf ./dist && webpack --config ./tools/webpack.config.prod.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/seata/seata.git"
|
||||
},
|
||||
"authors": [
|
||||
{
|
||||
"name": "陈龙",
|
||||
"email": "long_187@126.com"
|
||||
},
|
||||
{
|
||||
"name": "高力",
|
||||
"email": "3071730@qq.com"
|
||||
}
|
||||
],
|
||||
"license": "Apache License, Version 2.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/seata/seata/issues"
|
||||
},
|
||||
"homepage": "http://seata.io/",
|
||||
"peerDependencies": {
|
||||
"react": "^16.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@antv/g6": "^2.2.6",
|
||||
"codemirror": "^5.55.0",
|
||||
"core-js": "^3.6.5",
|
||||
"lodash": "^4.17.10",
|
||||
"react-codemirror": "^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.10.4",
|
||||
"@babel/core": "^7.10.4",
|
||||
"@babel/plugin-proposal-class-properties": "^7.10.4",
|
||||
"@babel/plugin-transform-modules-commonjs": "^7.10.4",
|
||||
"@babel/plugin-transform-runtime": "^7.10.4",
|
||||
"@babel/polyfill": "^7.10.4",
|
||||
"@babel/preset-env": "^7.10.4",
|
||||
"@babel/preset-react": "^7.10.4",
|
||||
"@babel/runtime": "^7.10.4",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"babel-loader": "^8.1.0",
|
||||
"babel-plugin-module-resolver": "^3.1.1",
|
||||
"babel-plugin-transform-inline-environment-variables": "^0.4.3",
|
||||
"cross-env": "^5.2.0",
|
||||
"css-loader": "^2.1.0",
|
||||
"cz-conventional-changelog": "^2.1.0",
|
||||
"eslint": "^5.11.1",
|
||||
"eslint-config-airbnb": "^17.1.0",
|
||||
"eslint-plugin-import": "^2.22.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.3.1",
|
||||
"eslint-plugin-react": "^7.20.3",
|
||||
"less": "^3.11.3",
|
||||
"less-loader": "^4.1.0",
|
||||
"postcss-loader": "^3.0.0",
|
||||
"postcss-preset-env": "^6.5.0",
|
||||
"rimraf": "^2.6.2",
|
||||
"style-loader": "^0.23.1",
|
||||
"webpack": "^4.43.0",
|
||||
"webpack-cli": "^3.3.12",
|
||||
"webpack-dev-server": "^3.11.0"
|
||||
},
|
||||
"config": {
|
||||
"commitizen": {
|
||||
"path": "./node_modules/cz-conventional-changelog"
|
||||
}
|
||||
}
|
||||
}
|
||||
125
saga/seata-saga-statemachine-designer/src/Flow/WorkSpace.js
Normal file
125
saga/seata-saga-statemachine-designer/src/Flow/WorkSpace.js
Normal file
@@ -0,0 +1,125 @@
|
||||
import React from 'react';
|
||||
import { withPropsAPI, Flow } from 'gg-editor';
|
||||
import styles from './index.less';
|
||||
import CodeMirror from 'react-codemirror';
|
||||
import 'codemirror/lib/codemirror.css'
|
||||
import 'codemirror/mode/javascript/javascript'
|
||||
|
||||
const nodeIndexes = {
|
||||
Start: 1,
|
||||
ServiceTask: 1,
|
||||
ScriptTask: 1,
|
||||
Compensation: 1,
|
||||
Choice: 1,
|
||||
Succeed: 1,
|
||||
Fail: 1,
|
||||
Catch: 1,
|
||||
CompensationTrigger: 1,
|
||||
SubStateMachine: 1
|
||||
}
|
||||
|
||||
class WorkSpaceBase extends React.Component {
|
||||
|
||||
toGGEditorData(dataMap) {
|
||||
const data = { nodes: [], edges: [] };
|
||||
Object.values(dataMap).map(value => {
|
||||
|
||||
if (value.type && value.type == 'node') {
|
||||
data.nodes[data.nodes.length] = value;
|
||||
}
|
||||
else if (value.source && value.target) {
|
||||
data.edges[data.edges.length] = value;
|
||||
}
|
||||
});
|
||||
return data;
|
||||
};
|
||||
|
||||
changeFlowData(param) {
|
||||
const { propsAPI, setFlowData } = this.props;
|
||||
const { executeCommand, update } = propsAPI;
|
||||
|
||||
if (param.action == 'add' && param.item.type == 'edge') {
|
||||
// Default polyline-round type @FIXME polyline-round has a bug
|
||||
if (param.item.target
|
||||
&& param.item.target.model
|
||||
&& param.item.source
|
||||
&& param.item.source.model) {
|
||||
executeCommand(() => {
|
||||
update(param.item, {
|
||||
shape: 'flow-polyline-round',
|
||||
});
|
||||
});
|
||||
}
|
||||
if (param.item.target && param.item.target.model && param.item.target.model.stateType == 'Compensation') {
|
||||
executeCommand(() => {
|
||||
update(param.item, {
|
||||
style: {
|
||||
lineDash: "4",
|
||||
},
|
||||
type: 'Compensation',
|
||||
});
|
||||
});
|
||||
}
|
||||
else if (param.item.source && param.item.source.model) {
|
||||
if (param.item.source.model.stateType == 'Choice') {
|
||||
const choiceLinePropsTemplate = {
|
||||
"Expression": "",
|
||||
"Default": false
|
||||
};
|
||||
executeCommand(() => {
|
||||
update(param.item, {
|
||||
stateProps: choiceLinePropsTemplate
|
||||
});
|
||||
});
|
||||
}
|
||||
else if (param.item.source.model.stateType == 'Catch') {
|
||||
const catchLinePropsTemplate = {
|
||||
"Exceptions": ["java.lang.Throwable"]
|
||||
};
|
||||
executeCommand(() => {
|
||||
update(param.item, {
|
||||
stateProps: catchLinePropsTemplate
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (param.action == 'add' && param.item.type == 'node' && param.item.model) {
|
||||
param.item.model.stateId = param.item.model.stateId + nodeIndexes[param.item.model.stateType]++;
|
||||
if (param.item.model.stateType == 'ServiceTask'
|
||||
|| param.item.model.stateType == 'Compensation'
|
||||
|| param.item.model.stateType == 'ScriptTask'
|
||||
|| param.item.model.stateType == 'SubStateMachine') {
|
||||
param.item.model.label = param.item.model.stateId;
|
||||
}
|
||||
if (param.item.model.stateType == 'SubStateMachine') {
|
||||
executeCommand(() => {
|
||||
update(param.item, {
|
||||
style: {
|
||||
lineWidth: 2,
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
param.item && setFlowData(this.toGGEditorData(param.item.dataMap));
|
||||
};
|
||||
|
||||
render() {
|
||||
const { showJson, flowData, setFlowData } = this.props;
|
||||
|
||||
return <>
|
||||
{showJson && <CodeMirror value={JSON.stringify(flowData, null, 2)} options={{
|
||||
lineNumbers: true,
|
||||
mode: 'javascript'
|
||||
}} onChange={(newValue) => {
|
||||
setFlowData(JSON.parse(newValue));
|
||||
}}></CodeMirror>}
|
||||
<Flow className={styles.flow + (showJson ? ' ' + styles.hidden : '')} data={flowData} onAfterChange={this.changeFlowData.bind(this)} />
|
||||
</>
|
||||
}
|
||||
}
|
||||
|
||||
export const WorkSpace = withPropsAPI(WorkSpaceBase)
|
||||
41
saga/seata-saga-statemachine-designer/src/Flow/index.js
Normal file
41
saga/seata-saga-statemachine-designer/src/Flow/index.js
Normal file
@@ -0,0 +1,41 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Row, Col } from 'antd';
|
||||
import GGEditor from 'gg-editor';
|
||||
import EditorMinimap from '../components/EditorMinimap';
|
||||
import { FlowContextMenu } from '../components/EditorContextMenu';
|
||||
import { FlowToolbar } from '../components/EditorToolbar';
|
||||
import { FlowItemPanel } from '../components/EditorItemPanel';
|
||||
import { FlowDetailPanel } from '../components/EditorDetailPanel';
|
||||
import styles from './index.less';
|
||||
import { WorkSpace } from './WorkSpace';
|
||||
|
||||
const FlowPage = () => {
|
||||
|
||||
const [showJson, setShowJson] = useState(false);
|
||||
const [flowData, setFlowData] = useState({});
|
||||
|
||||
return (
|
||||
<GGEditor className={styles.editor}>
|
||||
<Row type="flex" className={styles.editorHd}>
|
||||
<Col span={24}>
|
||||
<FlowToolbar setShowJson={setShowJson} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row type="flex" className={styles.editorBd}>
|
||||
<Col span={3} className={styles.editorSidebar}>
|
||||
<FlowItemPanel />
|
||||
</Col>
|
||||
<Col span={16} className={styles.editorContent}>
|
||||
<WorkSpace showJson={showJson} flowData={flowData} setFlowData={setFlowData} />
|
||||
</Col>
|
||||
<Col span={5} className={styles.editorSidebar}>
|
||||
<FlowDetailPanel />
|
||||
<EditorMinimap />
|
||||
</Col>
|
||||
</Row>
|
||||
<FlowContextMenu />
|
||||
</GGEditor>
|
||||
);
|
||||
};
|
||||
|
||||
export default FlowPage;
|
||||
57
saga/seata-saga-statemachine-designer/src/Flow/index.less
Normal file
57
saga/seata-saga-statemachine-designer/src/Flow/index.less
Normal file
@@ -0,0 +1,57 @@
|
||||
.editor {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.editorHd {
|
||||
padding: 8px;
|
||||
border: 1px solid #e6e9ed;
|
||||
}
|
||||
|
||||
.editorBd {
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.editorSidebar,
|
||||
.editorContent {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.editorSidebar {
|
||||
background: #fafafa;
|
||||
|
||||
&:first-child {
|
||||
border-right: 1px solid #e6e9ed;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-left: 1px solid #e6e9ed;
|
||||
}
|
||||
}
|
||||
|
||||
.flow,
|
||||
.mind,
|
||||
.koni {
|
||||
flex: 1;
|
||||
// https://github.com/philipwalton/flexbugs/issues/197#issuecomment-378908438
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
:global {
|
||||
.ReactCodeMirror {
|
||||
flex: 1;
|
||||
|
||||
.CodeMirror {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import { Icon } from 'antd';
|
||||
|
||||
const IconFont = Icon.createFromIconfontCN({
|
||||
scriptUrl: 'https://at.alicdn.com/t/font_1101588_01zniftxm9yp.js',
|
||||
});
|
||||
|
||||
export default IconFont;
|
||||
|
||||
export const IconFontExt = Icon.createFromIconfontCN({
|
||||
scriptUrl: 'https://at.alicdn.com/t/font_1529997_6nr9bramkvp.js',
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import React from 'react';
|
||||
import { NodeMenu, EdgeMenu, GroupMenu, MultiMenu, CanvasMenu, ContextMenu } from 'gg-editor';
|
||||
import MenuItem from './MenuItem';
|
||||
import styles from './index.less';
|
||||
|
||||
const FlowContextMenu = () => {
|
||||
return (
|
||||
<ContextMenu className={styles.contextMenu}>
|
||||
<NodeMenu>
|
||||
<MenuItem command="copy" />
|
||||
<MenuItem command="delete" />
|
||||
</NodeMenu>
|
||||
<EdgeMenu>
|
||||
<MenuItem command="delete" />
|
||||
</EdgeMenu>
|
||||
<GroupMenu>
|
||||
<MenuItem command="copy" />
|
||||
<MenuItem command="delete" />
|
||||
</GroupMenu>
|
||||
<MultiMenu>
|
||||
<MenuItem command="copy" />
|
||||
<MenuItem command="paste" />
|
||||
<MenuItem command="delete" />
|
||||
</MultiMenu>
|
||||
<CanvasMenu>
|
||||
<MenuItem command="undo" />
|
||||
<MenuItem command="redo" />
|
||||
<MenuItem command="pasteHere" icon="paste" text="Paste Here" />
|
||||
</CanvasMenu>
|
||||
</ContextMenu>
|
||||
);
|
||||
};
|
||||
|
||||
export default FlowContextMenu;
|
||||
@@ -0,0 +1,20 @@
|
||||
import React from 'react';
|
||||
import { Command } from 'gg-editor';
|
||||
import upperFirst from 'lodash/upperFirst';
|
||||
import IconFont from '../../common/IconFont';
|
||||
import styles from './index.less';
|
||||
|
||||
const MenuItem = (props) => {
|
||||
const { command, icon, text } = props;
|
||||
|
||||
return (
|
||||
<Command name={command}>
|
||||
<div className={styles.item}>
|
||||
<IconFont type={`icon-${icon || command}`} />
|
||||
<span>{text || upperFirst(command)}</span>
|
||||
</div>
|
||||
</Command>
|
||||
);
|
||||
};
|
||||
|
||||
export default MenuItem;
|
||||
@@ -0,0 +1,3 @@
|
||||
import FlowContextMenu from './FlowContextMenu';
|
||||
|
||||
export { FlowContextMenu };
|
||||
@@ -0,0 +1,39 @@
|
||||
.contextMenu {
|
||||
display: none;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
||||
|
||||
.item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 5px 12px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
user-select: none;
|
||||
|
||||
&:hover {
|
||||
background: #e6f7ff;
|
||||
}
|
||||
|
||||
i {
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
:global {
|
||||
.disable {
|
||||
:local {
|
||||
.item {
|
||||
color: rgba(0, 0, 0, 0.25);
|
||||
cursor: auto;
|
||||
|
||||
&:hover {
|
||||
background: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import { Card, Form, Input, Select, Button } from 'antd';
|
||||
import { withPropsAPI } from 'gg-editor';
|
||||
import upperFirst from 'lodash/upperFirst';
|
||||
|
||||
const { Item } = Form;
|
||||
const { Option } = Select;
|
||||
const { TextArea } = Input;
|
||||
|
||||
const inlineFormItemLayout = {
|
||||
labelCol: {
|
||||
sm: { span: 5 },
|
||||
},
|
||||
wrapperCol: {
|
||||
sm: { span: 19 },
|
||||
},
|
||||
};
|
||||
|
||||
let lastSelectedItem;
|
||||
|
||||
class DetailForm extends React.Component {
|
||||
get item() {
|
||||
const { propsAPI } = this.props;
|
||||
|
||||
return propsAPI.getSelected()[0] ? propsAPI.getSelected()[0] : lastSelectedItem;
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
// fix edit node details
|
||||
this.operationDetail();
|
||||
}
|
||||
|
||||
operationDetail = () => {
|
||||
const { propsAPI, form } = this.props;
|
||||
const currentPage = propsAPI.editor.getCurrentPage().getGraph();
|
||||
currentPage.on('node:click', (e) => {
|
||||
const { label, stateId, stateType, stateProps } = e.item.getModel();
|
||||
lastSelectedItem = e.item;
|
||||
form.setFieldsValue({ label, stateId, stateType, stateProps: JSON.stringify(stateProps, null, 2) });
|
||||
});
|
||||
currentPage.on('edge:click', (e) => {
|
||||
const { label = '', shape = 'flow-smooth', stateProps } = e.item.getModel();
|
||||
lastSelectedItem = e.item;
|
||||
form.setFieldsValue({ label, shape, stateProps: JSON.stringify(stateProps, null, 2) });
|
||||
});
|
||||
}
|
||||
|
||||
handleSubmit = (e) => {
|
||||
if (e && e.preventDefault) {
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
const { form, propsAPI } = this.props;
|
||||
const { executeCommand, update } = propsAPI;
|
||||
|
||||
setTimeout(() => {
|
||||
form.validateFieldsAndScroll((err, values) => {
|
||||
if (err) {
|
||||
return;
|
||||
}
|
||||
|
||||
const item = this.item;
|
||||
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (values.stateProps) {
|
||||
values.stateProps = JSON.parse(values.stateProps);
|
||||
}
|
||||
|
||||
lastSelectedItem = item;
|
||||
|
||||
executeCommand(() => {
|
||||
update(item, {
|
||||
...values,
|
||||
});
|
||||
});
|
||||
});
|
||||
}, 0);
|
||||
};
|
||||
|
||||
renderEdgeShapeSelect = () => {
|
||||
return (
|
||||
<Select onChange={this.handleSubmit}>
|
||||
<Option value="flow-smooth">Smooth</Option>
|
||||
<Option value="flow-polyline">Polyline</Option>
|
||||
<Option value="flow-polyline-round">Polyline Round</Option>
|
||||
</Select>
|
||||
);
|
||||
};
|
||||
|
||||
renderNodeDetail = () => {
|
||||
const { form } = this.props;
|
||||
const { label, stateId, stateType, stateProps } = this.item.getModel();
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Item label="Label" {...inlineFormItemLayout}>
|
||||
{form.getFieldDecorator('label', {
|
||||
initialValue: label,
|
||||
})(<Input onBlur={this.handleSubmit} />)}
|
||||
</Item>
|
||||
<Item label="Id" {...inlineFormItemLayout}>
|
||||
{form.getFieldDecorator('stateId', {
|
||||
initialValue: stateId,
|
||||
})(<Input onBlur={this.handleSubmit} />)}
|
||||
</Item>
|
||||
<Item label="Type" {...inlineFormItemLayout}>
|
||||
{form.getFieldDecorator('stateType', {
|
||||
initialValue: stateType,
|
||||
})(<Input readOnly={true} />)}
|
||||
</Item>
|
||||
<Item label="Props" {...inlineFormItemLayout}>
|
||||
{form.getFieldDecorator('stateProps', {
|
||||
initialValue: JSON.stringify(stateProps, null, 2),
|
||||
})(<TextArea onBlur={this.handleSubmit} rows={16} />)}
|
||||
</Item>
|
||||
<a target="_blank" style={{ float: 'right' }} href="http://seata.io/zh-cn/docs/user/saga.html">How to fill the properties?</a>
|
||||
</Fragment >
|
||||
);
|
||||
};
|
||||
|
||||
renderEdgeDetail = () => {
|
||||
const { form } = this.props;
|
||||
const { label = '', shape = 'flow-smooth', stateProps } = this.item.getModel();
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Item label="Label" {...inlineFormItemLayout}>
|
||||
{form.getFieldDecorator('label', {
|
||||
initialValue: label,
|
||||
})(<Input onBlur={this.handleSubmit} />)}
|
||||
</Item>
|
||||
<Item label="Shape" {...inlineFormItemLayout}>
|
||||
{form.getFieldDecorator('shape', {
|
||||
initialValue: shape,
|
||||
})(this.renderEdgeShapeSelect())}
|
||||
</Item>
|
||||
<Item label="Props" {...inlineFormItemLayout}>
|
||||
{form.getFieldDecorator('stateProps', {
|
||||
initialValue: JSON.stringify(stateProps, null, 2),
|
||||
})(<TextArea onBlur={this.handleSubmit} rows={16} />)}
|
||||
</Item>
|
||||
<a target="_blank" style={{ float: 'right' }} href="http://seata.io/zh-cn/docs/user/saga.html">How to fill the properties?</a>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
renderGroupDetail = () => {
|
||||
const { form } = this.props;
|
||||
const { label = 'New Group' } = this.item.getModel();
|
||||
|
||||
return (
|
||||
<Item label="Label" {...inlineFormItemLayout}>
|
||||
{form.getFieldDecorator('label', {
|
||||
initialValue: label,
|
||||
})(<Input onBlur={this.handleSubmit} />)}
|
||||
</Item>
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { type } = this.props;
|
||||
|
||||
if (!this.item) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Card type="inner" size="small" title={upperFirst(type)} bordered={false}>
|
||||
<Form onSubmit={this.handleSubmit}>
|
||||
{type === 'node' && this.renderNodeDetail()}
|
||||
{type === 'edge' && this.renderEdgeDetail()}
|
||||
{type === 'group' && this.renderGroupDetail()}
|
||||
</Form>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Form.create()(withPropsAPI(DetailForm));
|
||||
@@ -0,0 +1,29 @@
|
||||
import React from 'react';
|
||||
import { Card } from 'antd';
|
||||
import { NodePanel, EdgePanel, GroupPanel, MultiPanel, CanvasPanel, DetailPanel } from 'gg-editor';
|
||||
import DetailForm from './DetailForm';
|
||||
import styles from './index.less';
|
||||
|
||||
const FlowDetailPanel = () => {
|
||||
return (
|
||||
<DetailPanel className={styles.detailPanel}>
|
||||
<NodePanel>
|
||||
<DetailForm type="node" />
|
||||
</NodePanel>
|
||||
<EdgePanel>
|
||||
<DetailForm type="edge" />
|
||||
</EdgePanel>
|
||||
<GroupPanel>
|
||||
<DetailForm type="group" />
|
||||
</GroupPanel>
|
||||
<MultiPanel>
|
||||
<Card type="inner" size="small" title="Multi Select" bordered={false} />
|
||||
</MultiPanel>
|
||||
<CanvasPanel>
|
||||
<Card type="inner" size="small" title="Canvas" bordered={false} />
|
||||
</CanvasPanel>
|
||||
</DetailPanel>
|
||||
);
|
||||
};
|
||||
|
||||
export default FlowDetailPanel;
|
||||
@@ -0,0 +1,3 @@
|
||||
import FlowDetailPanel from './FlowDetailPanel';
|
||||
|
||||
export { FlowDetailPanel };
|
||||
@@ -0,0 +1,10 @@
|
||||
.detailPanel {
|
||||
flex: 1;
|
||||
background: #fafafa;
|
||||
|
||||
:global {
|
||||
.ant-card {
|
||||
background: #fafafa;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
import React from 'react';
|
||||
import { Card } from 'antd';
|
||||
import { ItemPanel, Item } from 'gg-editor';
|
||||
import styles from './index.less';
|
||||
|
||||
const startPropsTemplate = {
|
||||
"StateMachine": {
|
||||
"Name": "",
|
||||
"Comment": "",
|
||||
"Version": "0.0.1"
|
||||
}
|
||||
};
|
||||
const serviceTaskPropsTemplate = {
|
||||
"ServiceName": "",
|
||||
"ServiceMethod": "",
|
||||
"Input": [
|
||||
{}
|
||||
],
|
||||
"Output": {
|
||||
},
|
||||
"Status": {
|
||||
},
|
||||
"Retry": [
|
||||
]
|
||||
};
|
||||
const scriptTaskPropsTemplate = {
|
||||
"ScriptType": "groovy",
|
||||
"ScriptContent": "",
|
||||
"Input": [
|
||||
{}
|
||||
],
|
||||
"Output": {
|
||||
}
|
||||
};
|
||||
const compensationPropsTemplate = {
|
||||
"ServiceName": "",
|
||||
"ServiceMethod": "",
|
||||
"Input": [
|
||||
{}
|
||||
],
|
||||
"Output": {
|
||||
},
|
||||
"Status": {
|
||||
},
|
||||
"Retry": [
|
||||
]
|
||||
};
|
||||
const failPropsTemplate = {
|
||||
"ErrorCode": "",
|
||||
"Message": ""
|
||||
};
|
||||
const subStateMachinePropsTemplate = {
|
||||
"StateMachineName": "",
|
||||
"Input": [
|
||||
{}
|
||||
],
|
||||
"Output": {
|
||||
}
|
||||
}
|
||||
|
||||
const FlowItemPanel = () => {
|
||||
return (
|
||||
<ItemPanel className={styles.itemPanel}>
|
||||
<Card bordered={false}>
|
||||
<Item
|
||||
type="node"
|
||||
size="72*72"
|
||||
shape="flow-circle"
|
||||
model={{
|
||||
color: '#FA8C16',
|
||||
label: 'Start',
|
||||
stateId: 'Start',
|
||||
stateType: 'Start',
|
||||
stateProps: startPropsTemplate,
|
||||
}}
|
||||
src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iODAiIGhlaWdodD0iODAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPjxkZWZzPjxjaXJjbGUgaWQ9ImIiIGN4PSIzNiIgY3k9IjM2IiByPSIzNiIvPjxmaWx0ZXIgeD0iLTkuNyUiIHk9Ii02LjklIiB3aWR0aD0iMTE5LjQlIiBoZWlnaHQ9IjExOS40JSIgZmlsdGVyVW5pdHM9Im9iamVjdEJvdW5kaW5nQm94IiBpZD0iYSI+PGZlT2Zmc2V0IGR5PSIyIiBpbj0iU291cmNlQWxwaGEiIHJlc3VsdD0ic2hhZG93T2Zmc2V0T3V0ZXIxIi8+PGZlR2F1c3NpYW5CbHVyIHN0ZERldmlhdGlvbj0iMiIgaW49InNoYWRvd09mZnNldE91dGVyMSIgcmVzdWx0PSJzaGFkb3dCbHVyT3V0ZXIxIi8+PGZlQ29tcG9zaXRlIGluPSJzaGFkb3dCbHVyT3V0ZXIxIiBpbjI9IlNvdXJjZUFscGhhIiBvcGVyYXRvcj0ib3V0IiByZXN1bHQ9InNoYWRvd0JsdXJPdXRlcjEiLz48ZmVDb2xvck1hdHJpeCB2YWx1ZXM9IjAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAuMDQgMCIgaW49InNoYWRvd0JsdXJPdXRlcjEiLz48L2ZpbHRlcj48L2RlZnM+PGcgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSg0IDIpIj48dXNlIGZpbGw9IiMwMDAiIGZpbHRlcj0idXJsKCNhKSIgeGxpbms6aHJlZj0iI2IiLz48dXNlIGZpbGwtb3BhY2l0eT0iLjkyIiBmaWxsPSIjRkZGMkU4IiB4bGluazpocmVmPSIjYiIvPjxjaXJjbGUgc3Ryb2tlPSIjRkZDMDY5IiBjeD0iMzYiIGN5PSIzNiIgcj0iMzUuNSIvPjwvZz48dGV4dCBmb250LWZhbWlseT0iUGluZ0ZhbmdTQy1SZWd1bGFyLCBQaW5nRmFuZyBTQyIgZm9udC1zaXplPSIxMiIgZmlsbD0iIzAwMCIgZmlsbC1vcGFjaXR5PSIuNjUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDQgMikiPjx0c3BhbiB4PSIyMyIgeT0iNDEiPlN0YXJ0PC90c3Bhbj48L3RleHQ+PC9nPjwvc3ZnPg=="
|
||||
/>
|
||||
<Item
|
||||
type="node"
|
||||
size="110*48"
|
||||
shape="flow-rect"
|
||||
model={{
|
||||
color: '#1890FF',
|
||||
label: 'ServiceTask',
|
||||
stateId: 'ServiceTask',
|
||||
stateType: 'ServiceTask',
|
||||
stateProps: serviceTaskPropsTemplate,
|
||||
}}
|
||||
src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTE4IiBoZWlnaHQ9IjU2IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj48ZGVmcz48cmVjdCBpZD0iYiIgeD0iMCIgeT0iMCIgd2lkdGg9IjExMCIgaGVpZ2h0PSI0OCIgcng9IjQiLz48ZmlsdGVyIHg9Ii04LjglIiB5PSItMTAuNCUiIHdpZHRoPSIxMTcuNSUiIGhlaWdodD0iMTI5LjIlIiBmaWx0ZXJVbml0cz0ib2JqZWN0Qm91bmRpbmdCb3giIGlkPSJhIj48ZmVPZmZzZXQgZHk9IjIiIGluPSJTb3VyY2VBbHBoYSIgcmVzdWx0PSJzaGFkb3dPZmZzZXRPdXRlcjEiLz48ZmVHYXVzc2lhbkJsdXIgc3RkRGV2aWF0aW9uPSIyIiBpbj0ic2hhZG93T2Zmc2V0T3V0ZXIxIiByZXN1bHQ9InNoYWRvd0JsdXJPdXRlcjEiLz48ZmVDb21wb3NpdGUgaW49InNoYWRvd0JsdXJPdXRlcjEiIGluMj0iU291cmNlQWxwaGEiIG9wZXJhdG9yPSJvdXQiIHJlc3VsdD0ic2hhZG93Qmx1ck91dGVyMSIvPjxmZUNvbG9yTWF0cml4IHZhbHVlcz0iMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMC4wNCAwIiBpbj0ic2hhZG93Qmx1ck91dGVyMSIvPjwvZmlsdGVyPjwvZGVmcz48ZyBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDQgMikiPjx1c2UgZmlsbD0iIzAwMCIgZmlsdGVyPSJ1cmwoI2EpIiB4bGluazpocmVmPSIjYiIvPjx1c2UgZmlsbC1vcGFjaXR5PSIuOTIiIGZpbGw9IiNFNkY3RkYiIHhsaW5rOmhyZWY9IiNiIi8+PHJlY3Qgc3Ryb2tlPSIjMTg5MEZGIiB4PSIuNSIgeT0iLjUiIHdpZHRoPSIxMDkiIGhlaWdodD0iNDciIHJ4PSI0Ii8+PC9nPjx0ZXh0IGZvbnQtZmFtaWx5PSJQaW5nRmFuZ1NDLVJlZ3VsYXIsIFBpbmdGYW5nIFNDIiBmb250LXNpemU9IjEyIiBmaWxsPSIjMDAwIiBmaWxsLW9wYWNpdHk9Ii42NSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNCAyKSI+PHRzcGFuIHg9IjIxIiB5PSIyOSI+U2VydmljZVRhc2s8L3RzcGFuPjwvdGV4dD48L2c+PC9zdmc+"
|
||||
/>
|
||||
<Item
|
||||
type="node"
|
||||
size="110*48"
|
||||
shape="flow-rect"
|
||||
model={{
|
||||
color: '#13C2C2',
|
||||
label: 'ScriptTask',
|
||||
stateId: 'ScriptTask',
|
||||
stateType: 'ScriptTask',
|
||||
stateProps: scriptTaskPropsTemplate,
|
||||
}}
|
||||
src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTE4IiBoZWlnaHQ9IjU2IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj48ZGVmcz48cmVjdCBpZD0iYiIgeD0iMCIgeT0iMCIgd2lkdGg9IjExMCIgaGVpZ2h0PSI0OCIgcng9IjQiLz48ZmlsdGVyIHg9Ii04LjglIiB5PSItMTAuNCUiIHdpZHRoPSIxMTcuNSUiIGhlaWdodD0iMTI5LjIlIiBmaWx0ZXJVbml0cz0ib2JqZWN0Qm91bmRpbmdCb3giIGlkPSJhIj48ZmVPZmZzZXQgZHk9IjIiIGluPSJTb3VyY2VBbHBoYSIgcmVzdWx0PSJzaGFkb3dPZmZzZXRPdXRlcjEiLz48ZmVHYXVzc2lhbkJsdXIgc3RkRGV2aWF0aW9uPSIyIiBpbj0ic2hhZG93T2Zmc2V0T3V0ZXIxIiByZXN1bHQ9InNoYWRvd0JsdXJPdXRlcjEiLz48ZmVDb21wb3NpdGUgaW49InNoYWRvd0JsdXJPdXRlcjEiIGluMj0iU291cmNlQWxwaGEiIG9wZXJhdG9yPSJvdXQiIHJlc3VsdD0ic2hhZG93Qmx1ck91dGVyMSIvPjxmZUNvbG9yTWF0cml4IHZhbHVlcz0iMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMC4wNCAwIiBpbj0ic2hhZG93Qmx1ck91dGVyMSIvPjwvZmlsdGVyPjwvZGVmcz48ZyBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDQgMikiPjx1c2UgZmlsbD0iIzAwMCIgZmlsdGVyPSJ1cmwoI2EpIiB4bGluazpocmVmPSIjYiIvPjx1c2UgZmlsbC1vcGFjaXR5PSIuOTIiIGZpbGw9IiNFNkZGRkIiIHhsaW5rOmhyZWY9IiNiIi8+PHJlY3Qgc3Ryb2tlPSIjNUNEQkQzIiB4PSIuNSIgeT0iLjUiIHdpZHRoPSIxMDkiIGhlaWdodD0iNDciIHJ4PSI0Ii8+PC9nPjx0ZXh0IGZvbnQtZmFtaWx5PSJQaW5nRmFuZ1NDLVJlZ3VsYXIsIFBpbmdGYW5nIFNDIiBmb250LXNpemU9IjEyIiBmaWxsPSIjMDAwIiBmaWxsLW9wYWNpdHk9Ii42NSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNCAyKSI+PHRzcGFuIHg9IjI0IiB5PSIyOSI+U2NyaXB0VGFzazwvdHNwYW4+PC90ZXh0PjwvZz48L3N2Zz4="
|
||||
/>
|
||||
<Item
|
||||
type="node"
|
||||
size="80*72"
|
||||
shape="flow-rhombus"
|
||||
model={{
|
||||
color: '#13C2C2',
|
||||
label: 'Choice',
|
||||
stateId: 'Choice',
|
||||
stateType: 'Choice'
|
||||
}}
|
||||
src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iODYiIGhlaWdodD0iNzgiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPjxkZWZzPjxwYXRoIGQ9Ik00Mi42NyAxLjY3bDM0Ljk2NSAzMS4zNTJhNCA0IDAgMCAxIDAgNS45NTZMNDIuNjcgNzAuMzNhNCA0IDAgMCAxLTUuMzQgMEwyLjM2NSAzOC45NzhhNCA0IDAgMCAxIDAtNS45NTZMMzcuMzMgMS42N2E0IDQgMCAwIDEgNS4zNCAweiIgaWQ9ImIiLz48ZmlsdGVyIHg9Ii04LjglIiB5PSItNi45JSIgd2lkdGg9IjExNy41JSIgaGVpZ2h0PSIxMTkuNCUiIGZpbHRlclVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgaWQ9ImEiPjxmZU9mZnNldCBkeT0iMiIgaW49IlNvdXJjZUFscGhhIiByZXN1bHQ9InNoYWRvd09mZnNldE91dGVyMSIvPjxmZUdhdXNzaWFuQmx1ciBzdGREZXZpYXRpb249IjIiIGluPSJzaGFkb3dPZmZzZXRPdXRlcjEiIHJlc3VsdD0ic2hhZG93Qmx1ck91dGVyMSIvPjxmZUNvbXBvc2l0ZSBpbj0ic2hhZG93Qmx1ck91dGVyMSIgaW4yPSJTb3VyY2VBbHBoYSIgb3BlcmF0b3I9Im91dCIgcmVzdWx0PSJzaGFkb3dCbHVyT3V0ZXIxIi8+PGZlQ29sb3JNYXRyaXggdmFsdWVzPSIwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwLjA0IDAiIGluPSJzaGFkb3dCbHVyT3V0ZXIxIi8+PC9maWx0ZXI+PC9kZWZzPjxnIGZpbGw9Im5vbmUiIGZpbGwtcnVsZT0iZXZlbm9kZCI+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMyAxKSI+PHVzZSBmaWxsPSIjMDAwIiBmaWx0ZXI9InVybCgjYSkiIHhsaW5rOmhyZWY9IiNiIi8+PHVzZSBmaWxsLW9wYWNpdHk9Ii45MiIgZmlsbD0iI0U2RkZGQiIgeGxpbms6aHJlZj0iI2IiLz48cGF0aCBzdHJva2U9IiM1Q0RCRDMiIGQ9Ik00Mi4zMzcgMi4wNDJhMy41IDMuNSAwIDAgMC00LjY3NCAwTDIuNjk4IDMzLjM5NGEzLjUgMy41IDAgMCAwIDAgNS4yMTJsMzQuOTY1IDMxLjM1MmEzLjUgMy41IDAgMCAwIDQuNjc0IDBsMzQuOTY1LTMxLjM1MmEzLjUgMy41IDAgMCAwIDAtNS4yMTJMNDIuMzM3IDIuMDQyeiIvPjwvZz48dGV4dCBmb250LWZhbWlseT0iUGluZ0ZhbmdTQy1SZWd1bGFyLCBQaW5nRmFuZyBTQyIgZm9udC1zaXplPSIxMiIgZmlsbD0iIzAwMCIgZmlsbC1vcGFjaXR5PSIuNjUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDMgMSkiPjx0c3BhbiB4PSIyMSIgeT0iNDIiPkNob2ljZTwvdHNwYW4+PC90ZXh0PjwvZz48L3N2Zz4="
|
||||
/>
|
||||
<Item
|
||||
type="node"
|
||||
size="110*48"
|
||||
shape="flow-capsule"
|
||||
model={{
|
||||
color: '#722ED1',
|
||||
label: 'Compensation',
|
||||
stateId: 'Compensation',
|
||||
stateType: 'Compensation',
|
||||
stateProps: compensationPropsTemplate,
|
||||
}}
|
||||
src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTE4IiBoZWlnaHQ9IjU2IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj48ZGVmcz48cmVjdCBpZD0iYiIgeD0iMCIgeT0iMCIgd2lkdGg9IjExMCIgaGVpZ2h0PSI0OCIgcng9IjI0Ii8+PGZpbHRlciB4PSItOC44JSIgeT0iLTEwLjQlIiB3aWR0aD0iMTE3LjUlIiBoZWlnaHQ9IjEyOS4yJSIgZmlsdGVyVW5pdHM9Im9iamVjdEJvdW5kaW5nQm94IiBpZD0iYSI+PGZlT2Zmc2V0IGR5PSIyIiBpbj0iU291cmNlQWxwaGEiIHJlc3VsdD0ic2hhZG93T2Zmc2V0T3V0ZXIxIi8+PGZlR2F1c3NpYW5CbHVyIHN0ZERldmlhdGlvbj0iMiIgaW49InNoYWRvd09mZnNldE91dGVyMSIgcmVzdWx0PSJzaGFkb3dCbHVyT3V0ZXIxIi8+PGZlQ29tcG9zaXRlIGluPSJzaGFkb3dCbHVyT3V0ZXIxIiBpbjI9IlNvdXJjZUFscGhhIiBvcGVyYXRvcj0ib3V0IiByZXN1bHQ9InNoYWRvd0JsdXJPdXRlcjEiLz48ZmVDb2xvck1hdHJpeCB2YWx1ZXM9IjAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAuMDQgMCIgaW49InNoYWRvd0JsdXJPdXRlcjEiLz48L2ZpbHRlcj48L2RlZnM+PGcgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSg0IDIpIj48dXNlIGZpbGw9IiMwMDAiIGZpbHRlcj0idXJsKCNhKSIgeGxpbms6aHJlZj0iI2IiLz48dXNlIGZpbGwtb3BhY2l0eT0iLjkyIiBmaWxsPSIjRjlGMEZGIiB4bGluazpocmVmPSIjYiIvPjxyZWN0IHN0cm9rZT0iI0IzN0ZFQiIgeD0iLjUiIHk9Ii41IiB3aWR0aD0iMTA5IiBoZWlnaHQ9IjQ3IiByeD0iMjMuNSIvPjwvZz48dGV4dCBmb250LWZhbWlseT0iUGluZ0ZhbmdTQy1SZWd1bGFyLCBQaW5nRmFuZyBTQyIgZm9udC1zaXplPSIxMiIgZmlsbD0iIzAwMCIgZmlsbC1vcGFjaXR5PSIuNjUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDQgMikiPjx0c3BhbiB4PSIxNSIgeT0iMjkiPkNvbXBlbnNhdGlvbjwvdHNwYW4+PC90ZXh0PjwvZz48L3N2Zz4="
|
||||
/>
|
||||
<Item
|
||||
type="node"
|
||||
size="72*72"
|
||||
shape="flow-circle"
|
||||
model={{
|
||||
color: '#05A465',
|
||||
label: 'Succeed',
|
||||
stateId: 'Succeed',
|
||||
stateType: 'Succeed',
|
||||
}}
|
||||
src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iODAiIGhlaWdodD0iODAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPjxkZWZzPjxjaXJjbGUgaWQ9ImIiIGN4PSIzNiIgY3k9IjM2IiByPSIzNiIvPjxmaWx0ZXIgeD0iLTkuNyUiIHk9Ii02LjklIiB3aWR0aD0iMTE5LjQlIiBoZWlnaHQ9IjExOS40JSIgZmlsdGVyVW5pdHM9Im9iamVjdEJvdW5kaW5nQm94IiBpZD0iYSI+PGZlT2Zmc2V0IGR5PSIyIiBpbj0iU291cmNlQWxwaGEiIHJlc3VsdD0ic2hhZG93T2Zmc2V0T3V0ZXIxIi8+PGZlR2F1c3NpYW5CbHVyIHN0ZERldmlhdGlvbj0iMiIgaW49InNoYWRvd09mZnNldE91dGVyMSIgcmVzdWx0PSJzaGFkb3dCbHVyT3V0ZXIxIi8+PGZlQ29tcG9zaXRlIGluPSJzaGFkb3dCbHVyT3V0ZXIxIiBpbjI9IlNvdXJjZUFscGhhIiBvcGVyYXRvcj0ib3V0IiByZXN1bHQ9InNoYWRvd0JsdXJPdXRlcjEiLz48ZmVDb2xvck1hdHJpeCB2YWx1ZXM9IjAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAuMDQgMCIgaW49InNoYWRvd0JsdXJPdXRlcjEiLz48L2ZpbHRlcj48L2RlZnM+PGcgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSg0IDIpIj48dXNlIGZpbGw9IiMwMDAiIGZpbHRlcj0idXJsKCNhKSIgeGxpbms6aHJlZj0iI2IiLz48dXNlIGZpbGwtb3BhY2l0eT0iLjkyIiBmaWxsPSIjQ0ZFNEQ4IiB4bGluazpocmVmPSIjYiIvPjxjaXJjbGUgc3Ryb2tlPSIjMDVBNDY1IiBjeD0iMzYiIGN5PSIzNiIgcj0iMzUuNSIvPjwvZz48dGV4dCBmb250LWZhbWlseT0iUGluZ0ZhbmdTQy1SZWd1bGFyLCBQaW5nRmFuZyBTQyIgZm9udC1zaXplPSIxMiIgZmlsbD0iIzAwMCIgZmlsbC1vcGFjaXR5PSIuNjUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDQgMikiPjx0c3BhbiB4PSIxMyIgeT0iNDEiPlN1Y2NlZWQ8L3RzcGFuPjwvdGV4dD48L2c+PC9zdmc+"
|
||||
/>
|
||||
<Item
|
||||
type="node"
|
||||
size="72*72"
|
||||
shape="flow-circle"
|
||||
model={{
|
||||
color: 'red',
|
||||
label: 'Fail',
|
||||
stateId: 'Fail',
|
||||
stateType: 'Fail',
|
||||
stateProps: failPropsTemplate,
|
||||
}}
|
||||
src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iODAiIGhlaWdodD0iODAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPjxkZWZzPjxjaXJjbGUgaWQ9ImIiIGN4PSIzNiIgY3k9IjM2IiByPSIzNiIvPjxmaWx0ZXIgeD0iLTkuNyUiIHk9Ii02LjklIiB3aWR0aD0iMTE5LjQlIiBoZWlnaHQ9IjExOS40JSIgZmlsdGVyVW5pdHM9Im9iamVjdEJvdW5kaW5nQm94IiBpZD0iYSI+PGZlT2Zmc2V0IGR5PSIyIiBpbj0iU291cmNlQWxwaGEiIHJlc3VsdD0ic2hhZG93T2Zmc2V0T3V0ZXIxIi8+PGZlR2F1c3NpYW5CbHVyIHN0ZERldmlhdGlvbj0iMiIgaW49InNoYWRvd09mZnNldE91dGVyMSIgcmVzdWx0PSJzaGFkb3dCbHVyT3V0ZXIxIi8+PGZlQ29tcG9zaXRlIGluPSJzaGFkb3dCbHVyT3V0ZXIxIiBpbjI9IlNvdXJjZUFscGhhIiBvcGVyYXRvcj0ib3V0IiByZXN1bHQ9InNoYWRvd0JsdXJPdXRlcjEiLz48ZmVDb2xvck1hdHJpeCB2YWx1ZXM9IjAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAuMDQgMCIgaW49InNoYWRvd0JsdXJPdXRlcjEiLz48L2ZpbHRlcj48L2RlZnM+PGcgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSg0IDIpIj48dXNlIGZpbGw9IiMwMDAiIGZpbHRlcj0idXJsKCNhKSIgeGxpbms6aHJlZj0iI2IiLz48dXNlIGZpbGwtb3BhY2l0eT0iLjkyIiBmaWxsPSIjRkVFQUU3IiB4bGluazpocmVmPSIjYiIvPjxjaXJjbGUgc3Ryb2tlPSJyZWQiIGN4PSIzNiIgY3k9IjM2IiByPSIzNS41Ii8+PC9nPjx0ZXh0IGZvbnQtZmFtaWx5PSJQaW5nRmFuZ1NDLVJlZ3VsYXIsIFBpbmdGYW5nIFNDIiBmb250LXNpemU9IjEyIiBmaWxsPSIjMDAwIiBmaWxsLW9wYWNpdHk9Ii42NSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNCAyKSI+PHRzcGFuIHg9IjI2IiB5PSI0MSI+RmFpbDwvdHNwYW4+PC90ZXh0PjwvZz48L3N2Zz4="
|
||||
/>
|
||||
<Item
|
||||
type="node"
|
||||
size="39*39"
|
||||
shape="flow-circle"
|
||||
model={{
|
||||
color: 'red',
|
||||
label: 'Catch',
|
||||
stateId: 'Catch',
|
||||
stateType: 'Catch'
|
||||
}}
|
||||
src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDUiIGhlaWdodD0iNDUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPjxkZWZzPjxjaXJjbGUgaWQ9ImIiIGN4PSIyMCIgY3k9IjIwIiByPSIyMCIvPjxmaWx0ZXIgeD0iLTkuNyUiIHk9Ii02LjklIiB3aWR0aD0iMTE5LjQlIiBoZWlnaHQ9IjExOS40JSIgZmlsdGVyVW5pdHM9Im9iamVjdEJvdW5kaW5nQm94IiBpZD0iYSI+PGZlT2Zmc2V0IGR5PSIyIiBpbj0iU291cmNlQWxwaGEiIHJlc3VsdD0ic2hhZG93T2Zmc2V0T3V0ZXIxIi8+PGZlR2F1c3NpYW5CbHVyIHN0ZERldmlhdGlvbj0iMiIgaW49InNoYWRvd09mZnNldE91dGVyMSIgcmVzdWx0PSJzaGFkb3dCbHVyT3V0ZXIxIi8+PGZlQ29tcG9zaXRlIGluPSJzaGFkb3dCbHVyT3V0ZXIxIiBpbjI9IlNvdXJjZUFscGhhIiBvcGVyYXRvcj0ib3V0IiByZXN1bHQ9InNoYWRvd0JsdXJPdXRlcjEiLz48ZmVDb2xvck1hdHJpeCB2YWx1ZXM9IjAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAuMDQgMCIgaW49InNoYWRvd0JsdXJPdXRlcjEiLz48L2ZpbHRlcj48L2RlZnM+PGcgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSg0IDIpIj48dXNlIGZpbGw9IiMwMDAiIGZpbHRlcj0idXJsKCNhKSIgeGxpbms6aHJlZj0iI2IiLz48dXNlIGZpbGwtb3BhY2l0eT0iLjkyIiBmaWxsPSIjRkVFQUU3IiB4bGluazpocmVmPSIjYiIvPjxjaXJjbGUgc3Ryb2tlPSJyZWQiIGN4PSIxOS41IiBjeT0iMTkuNSIgcj0iMTkuNSIvPjwvZz48dGV4dCBmb250LWZhbWlseT0iUGluZ0ZhbmdTQy1SZWd1bGFyLCBQaW5nRmFuZyBTQyIgZm9udC1zaXplPSIxMiIgZmlsbD0iIzAwMCIgZmlsbC1vcGFjaXR5PSIuNjUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDQgMikiPjx0c3BhbiB4PSIzIiB5PSIyNCI+Q2F0Y2g8L3RzcGFuPjwvdGV4dD48L2c+PC9zdmc+"
|
||||
/>
|
||||
<Item
|
||||
type="node"
|
||||
size="110*48"
|
||||
shape="flow-capsule"
|
||||
model={{
|
||||
color: 'red',
|
||||
label: 'Compensation\nTrigger',
|
||||
stateId: 'CompensationTrigger',
|
||||
stateType: 'CompensationTrigger',
|
||||
}}
|
||||
src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTE4IiBoZWlnaHQ9IjU2IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj48ZGVmcz48cmVjdCBpZD0iYiIgeD0iMCIgeT0iMCIgd2lkdGg9IjExMCIgaGVpZ2h0PSI0OCIgcng9IjI0Ii8+PGZpbHRlciB4PSItOC44JSIgeT0iLTEwLjQlIiB3aWR0aD0iMTE3LjUlIiBoZWlnaHQ9IjEyOS4yJSIgZmlsdGVyVW5pdHM9Im9iamVjdEJvdW5kaW5nQm94IiBpZD0iYSI+PGZlT2Zmc2V0IGR5PSIyIiBpbj0iU291cmNlQWxwaGEiIHJlc3VsdD0ic2hhZG93T2Zmc2V0T3V0ZXIxIi8+PGZlR2F1c3NpYW5CbHVyIHN0ZERldmlhdGlvbj0iMiIgaW49InNoYWRvd09mZnNldE91dGVyMSIgcmVzdWx0PSJzaGFkb3dCbHVyT3V0ZXIxIi8+PGZlQ29tcG9zaXRlIGluPSJzaGFkb3dCbHVyT3V0ZXIxIiBpbjI9IlNvdXJjZUFscGhhIiBvcGVyYXRvcj0ib3V0IiByZXN1bHQ9InNoYWRvd0JsdXJPdXRlcjEiLz48ZmVDb2xvck1hdHJpeCB2YWx1ZXM9IjAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAuMDQgMCIgaW49InNoYWRvd0JsdXJPdXRlcjEiLz48L2ZpbHRlcj48L2RlZnM+PGcgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSg0IDIpIj48dXNlIGZpbGw9IiMwMDAiIGZpbHRlcj0idXJsKCNhKSIgeGxpbms6aHJlZj0iI2IiLz48dXNlIGZpbGwtb3BhY2l0eT0iLjkyIiBmaWxsPSIjRkVFQUU3IiB4bGluazpocmVmPSIjYiIvPjxyZWN0IHN0cm9rZT0icmVkIiB4PSIuNSIgeT0iLjUiIHdpZHRoPSIxMDkiIGhlaWdodD0iNDciIHJ4PSIyMy41Ii8+PC9nPjx0ZXh0IGZvbnQtZmFtaWx5PSJQaW5nRmFuZ1NDLVJlZ3VsYXIsIFBpbmdGYW5nIFNDIiBmb250LXNpemU9IjEyIiBmaWxsPSIjMDAwIiBmaWxsLW9wYWNpdHk9Ii42NSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNCAyKSI+PHRzcGFuIHg9IjE1IiB5PSIyMiI+Q29tcGVuc2F0aW9uPC90c3Bhbj48L3RleHQ+PHRleHQgZm9udC1mYW1pbHk9IlBpbmdGYW5nU0MtUmVndWxhciwgUGluZ0ZhbmcgU0MiIGZvbnQtc2l6ZT0iMTIiIGZpbGw9IiMwMDAiIGZpbGwtb3BhY2l0eT0iLjY1IiB0cmFuc2Zvcm09InRyYW5zbGF0ZSg0IDIpIj48dHNwYW4geD0iMzYiIHk9IjM2Ij5UcmlnZ2VyPC90c3Bhbj48L3RleHQ+PC9nPjwvc3ZnPg=="
|
||||
/>
|
||||
<Item
|
||||
type="node"
|
||||
size="110*48"
|
||||
shape="flow-rect"
|
||||
model={{
|
||||
color: '#FA8C16',
|
||||
label: 'SubStateMachine',
|
||||
stateId: 'SubStateMachine',
|
||||
stateType: 'SubStateMachine',
|
||||
stateProps: subStateMachinePropsTemplate,
|
||||
}}
|
||||
src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTE4IiBoZWlnaHQ9IjU2IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj48ZGVmcz48cmVjdCBpZD0iYiIgeD0iMCIgeT0iMCIgd2lkdGg9IjExMCIgaGVpZ2h0PSI0OCIgcng9IjQiLz48ZmlsdGVyIHg9Ii04LjglIiB5PSItMTAuNCUiIHdpZHRoPSIxMTcuNSUiIGhlaWdodD0iMTI5LjIlIiBmaWx0ZXJVbml0cz0ib2JqZWN0Qm91bmRpbmdCb3giIGlkPSJhIj48ZmVPZmZzZXQgZHk9IjIiIGluPSJTb3VyY2VBbHBoYSIgcmVzdWx0PSJzaGFkb3dPZmZzZXRPdXRlcjEiLz48ZmVHYXVzc2lhbkJsdXIgc3RkRGV2aWF0aW9uPSIyIiBpbj0ic2hhZG93T2Zmc2V0T3V0ZXIxIiByZXN1bHQ9InNoYWRvd0JsdXJPdXRlcjEiLz48ZmVDb21wb3NpdGUgaW49InNoYWRvd0JsdXJPdXRlcjEiIGluMj0iU291cmNlQWxwaGEiIG9wZXJhdG9yPSJvdXQiIHJlc3VsdD0ic2hhZG93Qmx1ck91dGVyMSIvPjxmZUNvbG9yTWF0cml4IHZhbHVlcz0iMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMC4wNCAwIiBpbj0ic2hhZG93Qmx1ck91dGVyMSIvPjwvZmlsdGVyPjwvZGVmcz48ZyBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDQgMikiPjx1c2UgZmlsbD0iIzAwMCIgZmlsdGVyPSJ1cmwoI2EpIiB4bGluazpocmVmPSIjYiIvPjx1c2UgZmlsbC1vcGFjaXR5PSIuOTIiIGZpbGw9IiNGRkYyRTgiIHhsaW5rOmhyZWY9IiNiIi8+PHJlY3Qgc3Ryb2tlLXdpZHRoPSIycHgiIHN0cm9rZT0iI0ZGQzA2OSIgeD0iLjUiIHk9Ii41IiB3aWR0aD0iMTA5IiBoZWlnaHQ9IjQ3IiByeD0iNCIvPjwvZz48dGV4dCBmb250LWZhbWlseT0iUGluZ0ZhbmdTQy1SZWd1bGFyLCBQaW5nRmFuZyBTQyIgZm9udC1zaXplPSIxMiIgZmlsbD0iIzAwMCIgZmlsbC1vcGFjaXR5PSIuNjUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDQgMikiPjx0c3BhbiB4PSI2IiB5PSIyOSI+U3ViU3RhdGVNYWNoaW5lPC90c3Bhbj48L3RleHQ+PC9nPjwvc3ZnPg=="
|
||||
/>
|
||||
</Card>
|
||||
</ItemPanel>
|
||||
);
|
||||
};
|
||||
|
||||
export default FlowItemPanel;
|
||||
@@ -0,0 +1,3 @@
|
||||
import FlowItemPanel from './FlowItemPanel';
|
||||
|
||||
export { FlowItemPanel };
|
||||
@@ -0,0 +1,20 @@
|
||||
.itemPanel {
|
||||
flex: 1;
|
||||
background: #fafafa;
|
||||
|
||||
:global {
|
||||
.ant-card {
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
.ant-card-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
> div {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import React from 'react';
|
||||
import { Card } from 'antd';
|
||||
import { Minimap } from 'gg-editor';
|
||||
|
||||
const EditorMinimap = () => {
|
||||
return (
|
||||
<Card type="inner" size="small" title="Minimap" bordered={false}>
|
||||
<Minimap height={200} />
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
export default EditorMinimap;
|
||||
@@ -0,0 +1,33 @@
|
||||
import React from 'react';
|
||||
import { Divider } from 'antd';
|
||||
import { Toolbar } from 'gg-editor';
|
||||
import ToolbarButton from './ToolbarButton';
|
||||
import styles from './index.less';
|
||||
|
||||
const FlowToolbar = ({ setShowJson }) => {
|
||||
return (
|
||||
<Toolbar className={styles.toolbar}>
|
||||
<ToolbarButton command="undo" />
|
||||
<ToolbarButton command="redo" />
|
||||
<Divider type="vertical" />
|
||||
<ToolbarButton command="copy" />
|
||||
<ToolbarButton command="paste" />
|
||||
<ToolbarButton command="delete" />
|
||||
<Divider type="vertical" />
|
||||
<ToolbarButton command="zoomIn" icon="zoom-in" text="Zoom In" />
|
||||
<ToolbarButton command="zoomOut" icon="zoom-out" text="Zoom Out" />
|
||||
<ToolbarButton command="autoZoom" icon="fit-map" text="Fit Map" />
|
||||
<ToolbarButton command="resetZoom" icon="actual-size" text="Actual Size" />
|
||||
<Divider type="vertical" />
|
||||
<ToolbarButton command="toBack" icon="to-back" text="To Back" />
|
||||
<ToolbarButton command="toFront" icon="to-front" text="To Front" />
|
||||
<Divider type="vertical" />
|
||||
<ToolbarButton command="multiSelect" icon="multi-select" text="Multi Select" />
|
||||
<Divider type="vertical" />
|
||||
<ToolbarButton command="switchWorkspace" icon="iconjson" text="Json View" onClick={() => setShowJson(true)} />
|
||||
<ToolbarButton command="switchWorkspace" icon="icondesign" text="Designer View" onClick={() => setShowJson(false)} />
|
||||
</Toolbar>
|
||||
);
|
||||
};
|
||||
|
||||
export default FlowToolbar;
|
||||
@@ -0,0 +1,36 @@
|
||||
import React from 'react';
|
||||
import { Tooltip } from 'antd';
|
||||
import { Command } from 'gg-editor';
|
||||
import upperFirst from 'lodash/upperFirst';
|
||||
import IconFont from '../../common/IconFont';
|
||||
import { IconFontExt } from '../../common/IconFont';
|
||||
import styles from './index.less';
|
||||
|
||||
const ToolbarButton = (props) => {
|
||||
const { command, icon, text, onClick } = props;
|
||||
|
||||
if (command == 'switchWorkspace') {
|
||||
return (
|
||||
<Tooltip className={styles.buttonExt}
|
||||
title={text || upperFirst(command)}
|
||||
onClick={onClick}
|
||||
>
|
||||
<IconFontExt type={`${icon || command}`} />
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Command name={command}>
|
||||
<Tooltip
|
||||
title={text || upperFirst(command)}
|
||||
placement="bottom"
|
||||
overlayClassName={styles.tooltip}
|
||||
>
|
||||
<IconFont type={`icon-${icon || command}`} />
|
||||
</Tooltip>
|
||||
</Command>
|
||||
);
|
||||
};
|
||||
|
||||
export default ToolbarButton;
|
||||
@@ -0,0 +1,3 @@
|
||||
import FlowToolbar from './FlowToolbar';
|
||||
|
||||
export { FlowToolbar };
|
||||
@@ -0,0 +1,54 @@
|
||||
.toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
:global {
|
||||
.command i {
|
||||
display: inline-block;
|
||||
width: 27px;
|
||||
height: 27px;
|
||||
margin: 0 6px;
|
||||
padding-top: 6px;
|
||||
text-align: center;
|
||||
border: 1px solid #fff;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
border: 1px solid #e6e9ed;
|
||||
}
|
||||
}
|
||||
|
||||
.disable i {
|
||||
color: rgba(0, 0, 0, 0.25);
|
||||
cursor: auto;
|
||||
|
||||
&:hover {
|
||||
border: 1px solid #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tooltip {
|
||||
:global {
|
||||
.ant-tooltip-inner {
|
||||
font-size: 12px;
|
||||
border-radius: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.buttonExt {
|
||||
display: inline-block;
|
||||
width: 27px;
|
||||
height: 27px;
|
||||
margin: 0 6px;
|
||||
padding-top: 6px;
|
||||
text-align: center;
|
||||
border: 1px solid #fff;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
border: 1px solid #e6e9ed;
|
||||
}
|
||||
}
|
||||
11
saga/seata-saga-statemachine-designer/src/index.js
Normal file
11
saga/seata-saga-statemachine-designer/src/index.js
Normal file
@@ -0,0 +1,11 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { HashRouter as Router, Route } from 'react-router-dom';
|
||||
import FlowPage from './Flow';
|
||||
|
||||
ReactDOM.render(
|
||||
<Router>
|
||||
<Route path="/" component={FlowPage} />
|
||||
</Router>,
|
||||
document.getElementById('root'),
|
||||
);
|
||||
@@ -0,0 +1,7 @@
|
||||
const postcssPresetEnv = require('postcss-preset-env');
|
||||
|
||||
module.exports = {
|
||||
plugins: [
|
||||
postcssPresetEnv,
|
||||
],
|
||||
};
|
||||
@@ -0,0 +1,57 @@
|
||||
const path = require('path');
|
||||
|
||||
const rules = [{
|
||||
test: /\.js$/,
|
||||
exclude: [
|
||||
path.resolve(__dirname, 'node_modules'),
|
||||
path.resolve(__dirname, '../ggeditor/gg-editor-core/bundle.js'),
|
||||
],
|
||||
use: {
|
||||
loader: 'babel-loader',
|
||||
},
|
||||
}, {
|
||||
test: /\.less$/,
|
||||
use: [{
|
||||
loader: 'style-loader',
|
||||
}, {
|
||||
loader: 'css-loader',
|
||||
options: {
|
||||
modules: true,
|
||||
camelCase: true,
|
||||
importLoaders: 1,
|
||||
localIdentName: '[local]--[hash:base64:5]',
|
||||
},
|
||||
}, {
|
||||
loader: 'postcss-loader',
|
||||
options: {
|
||||
config: {
|
||||
path: path.resolve(__dirname, './postcss.config.js'),
|
||||
},
|
||||
},
|
||||
}, {
|
||||
loader: 'less-loader',
|
||||
}],
|
||||
}, {
|
||||
test: /\.css$/,
|
||||
use: [{
|
||||
loader: 'style-loader',
|
||||
}, {
|
||||
loader: 'css-loader',
|
||||
}],
|
||||
}];
|
||||
|
||||
const externals = {
|
||||
react: {
|
||||
root: 'React',
|
||||
commonjs: 'react',
|
||||
commonjs2: 'react',
|
||||
amd: 'react',
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
module: {
|
||||
rules,
|
||||
},
|
||||
externals,
|
||||
};
|
||||
@@ -0,0 +1,60 @@
|
||||
const path = require('path');
|
||||
const { merge } = require('lodash');
|
||||
const baseConfig = require('./webpack.config.base');
|
||||
|
||||
const mode = 'development';
|
||||
|
||||
const entry = {
|
||||
bundle: path.resolve(__dirname, '..', 'src/index.js'),
|
||||
};
|
||||
|
||||
const alias = {
|
||||
'gg-editor': path.resolve(__dirname, '..', 'ggeditor'),
|
||||
};
|
||||
|
||||
const externals = {
|
||||
'react-dom': {
|
||||
root: 'ReactDOM',
|
||||
commonjs2: 'react-dom',
|
||||
commonjs: 'react-dom',
|
||||
amd: 'react-dom',
|
||||
},
|
||||
'react-router-dom': {
|
||||
root: 'ReactRouterDOM',
|
||||
commonjs: 'react-router-dom',
|
||||
commonjs2: 'react-router-dom',
|
||||
amd: 'react-router-dom',
|
||||
},
|
||||
antd: {
|
||||
root: 'antd',
|
||||
commonjs: 'antd',
|
||||
commonjs2: 'antd',
|
||||
amd: 'antd',
|
||||
},
|
||||
};
|
||||
|
||||
const devtool = 'cheap-module-eval-source-map';
|
||||
|
||||
const devServer = {
|
||||
contentBase: path.resolve(__dirname, '..', ''),
|
||||
publicPath: '/dist',
|
||||
disableHostCheck: true,
|
||||
};
|
||||
|
||||
const output = {
|
||||
path: path.resolve(__dirname, '..', 'dist'),
|
||||
filename: '[name].js',
|
||||
libraryTarget: 'umd',
|
||||
};
|
||||
|
||||
module.exports = merge(baseConfig, {
|
||||
mode,
|
||||
entry,
|
||||
resolve: {
|
||||
alias,
|
||||
},
|
||||
externals,
|
||||
devtool,
|
||||
devServer,
|
||||
output,
|
||||
});
|
||||
@@ -0,0 +1,53 @@
|
||||
const path = require('path');
|
||||
const { merge } = require('lodash');
|
||||
const baseConfig = require('./webpack.config.base');
|
||||
|
||||
const mode = 'production';
|
||||
|
||||
const entry = {
|
||||
bundle: path.resolve(__dirname, '..', 'src/index.js'),
|
||||
};
|
||||
|
||||
const alias = {
|
||||
'gg-editor': path.resolve(__dirname, '..', 'ggeditor'),
|
||||
};
|
||||
|
||||
const externals = {
|
||||
'react-dom': {
|
||||
root: 'ReactDOM',
|
||||
commonjs2: 'react-dom',
|
||||
commonjs: 'react-dom',
|
||||
amd: 'react-dom',
|
||||
},
|
||||
'react-router-dom': {
|
||||
root: 'ReactRouterDOM',
|
||||
commonjs: 'react-router-dom',
|
||||
commonjs2: 'react-router-dom',
|
||||
amd: 'react-router-dom',
|
||||
},
|
||||
antd: {
|
||||
root: 'antd',
|
||||
commonjs: 'antd',
|
||||
commonjs2: 'antd',
|
||||
amd: 'antd',
|
||||
},
|
||||
};
|
||||
|
||||
const devtool = 'cheap-module-source-map';
|
||||
|
||||
const output = {
|
||||
path: path.resolve(__dirname, '..', 'dist'),
|
||||
filename: '[name].js',
|
||||
libraryTarget: 'umd',
|
||||
};
|
||||
|
||||
module.exports = merge(baseConfig, {
|
||||
mode,
|
||||
entry,
|
||||
resolve: {
|
||||
alias,
|
||||
},
|
||||
externals,
|
||||
devtool,
|
||||
output,
|
||||
});
|
||||
283
saga/seata-saga-statemachine-designer/typings/index.d.ts
vendored
Normal file
283
saga/seata-saga-statemachine-designer/typings/index.d.ts
vendored
Normal file
@@ -0,0 +1,283 @@
|
||||
declare module 'gg-editor' {
|
||||
|
||||
export interface Align {
|
||||
line?: any
|
||||
item?: boolean | 'horizontal' | 'vertical' | 'center'
|
||||
grid?: boolean | 'cc' | 'tl'
|
||||
}
|
||||
|
||||
export interface Grid {
|
||||
cell?: number
|
||||
line?: any
|
||||
}
|
||||
|
||||
export interface Shortcut {
|
||||
clear?: boolean
|
||||
selectAll?: boolean
|
||||
undo?: boolean
|
||||
redo?: boolean
|
||||
delete?: boolean
|
||||
zoomIn?: boolean
|
||||
zoomOut?: boolean
|
||||
autoZoom?: boolean
|
||||
resetZoom?: boolean
|
||||
toFront?: boolean
|
||||
toBack?: boolean
|
||||
copy?: boolean
|
||||
paste?: boolean
|
||||
multiSelect?: boolean
|
||||
addGroup?: boolean
|
||||
unGroup?: boolean
|
||||
append?: boolean
|
||||
appendChild?: boolean
|
||||
collaspeExpand?: boolean
|
||||
}
|
||||
|
||||
interface ReactProps {
|
||||
style?: React.CSSProperties
|
||||
className?: string
|
||||
}
|
||||
|
||||
export interface BasicProps extends ReactProps {
|
||||
/** 初始数据 */
|
||||
data?: any
|
||||
/** G6的配置项 @see https://www.yuque.com/antv/g6/graph */
|
||||
graph?: any
|
||||
/** 快捷键配置,内置命令 */
|
||||
shortcut?: Shortcut
|
||||
}
|
||||
|
||||
export interface FlowProps extends BasicProps {
|
||||
/** 对齐配置 */
|
||||
align?: Align
|
||||
/** 网格线配置 */
|
||||
grid?: Grid
|
||||
/** default: true */
|
||||
noEndEdge?: boolean
|
||||
}
|
||||
|
||||
export interface MindProps extends BasicProps {
|
||||
|
||||
}
|
||||
|
||||
export interface KoniProps extends BasicProps {
|
||||
|
||||
}
|
||||
|
||||
export interface CommondProps {
|
||||
name: string
|
||||
}
|
||||
|
||||
export interface MninimapProps extends ReactProps {
|
||||
/** 容器 id */
|
||||
container?: string
|
||||
width?: number
|
||||
height?: number
|
||||
/** 视窗样式,参考 G 绘图属性 */
|
||||
viewportWindowStyle?: any
|
||||
/** 背景样式,参考 G 绘图属性 */
|
||||
viewportBackStyle?: any
|
||||
}
|
||||
|
||||
export interface ItemPanelProps extends ReactProps {
|
||||
/** 元素类型,可选类型:node edge */
|
||||
type: string
|
||||
/** 元素尺寸,书写格式:50*50 */
|
||||
size: string
|
||||
/** 元素形状,内置形状:node、edge */
|
||||
shape: string
|
||||
/** 元素初始 model */
|
||||
model?: any
|
||||
/** 元素概览 src */
|
||||
src: string
|
||||
}
|
||||
|
||||
export interface RegisterProps extends ReactProps{
|
||||
/** 节点名称 */
|
||||
name?: string
|
||||
/** 节点配置 */
|
||||
config?: any
|
||||
/** 继承图形 */
|
||||
extend?: string
|
||||
}
|
||||
|
||||
export interface RegisterBehaviourProps extends ReactProps{
|
||||
/** 行为名称 */
|
||||
name?: string
|
||||
/** 行为配置 function(page) */
|
||||
behaviour?: any
|
||||
/** 继承行为 */
|
||||
dependences?: string[]
|
||||
}
|
||||
|
||||
export interface GGEditorEvent {
|
||||
action: 'add' | 'update' | 'remove' | 'changeData'
|
||||
item?: any
|
||||
shape?: any
|
||||
x?: number
|
||||
y?: number
|
||||
domX?: number
|
||||
domY?: number
|
||||
/** DOM 原生事件 */
|
||||
domeEvent?: any
|
||||
/** drag 拖动图项 */
|
||||
currentIem?: any
|
||||
/** drag 拖动图形 */
|
||||
currentShape?: any
|
||||
/** mouseleave dragleave 到达的图形 */
|
||||
toShape?: any
|
||||
/** mouseleave dragleave 到达的图项 */
|
||||
toItem?: any
|
||||
}
|
||||
|
||||
/** 此类事件可以结合前缀 node、edge、group、guide、anchor 组合使用,例如: */
|
||||
export interface GraphMouseReactEventsProps {
|
||||
/** 鼠标左键点击事件 */
|
||||
onClick?: (e: GGEditorEvent) => void
|
||||
/** 鼠标左键双击事件 */
|
||||
onDoubleClick?: (e: GGEditorEvent) => void
|
||||
/** 鼠标移入事件 */
|
||||
onMouseEnter?: (e: GGEditorEvent) => void
|
||||
/** 鼠标移除事件 */
|
||||
onMouseLeave?: (e: GGEditorEvent) => void
|
||||
/** 鼠标按下事件 */
|
||||
onMouseDown?: (e: GGEditorEvent) => void
|
||||
/** 鼠标抬起事件 */
|
||||
onMouseUp?: (e: GGEditorEvent) => void
|
||||
/** 鼠标移动事件 */
|
||||
onMouseMove?: (e: GGEditorEvent) => void
|
||||
/** 鼠标开始拖拽事件 */
|
||||
onDragStart?: (e: GGEditorEvent) => void
|
||||
/** 鼠标拖拽事件 */
|
||||
onDrag?: (e: GGEditorEvent) => void
|
||||
/** 鼠标拖拽结束事件 */
|
||||
onDragEnd?: (e: GGEditorEvent) => void
|
||||
/** 鼠标拖拽进入事件 */
|
||||
onDragEnter?: (e: GGEditorEvent) => void
|
||||
/** 鼠标拖拽移出事件 */
|
||||
onDragLeave?: (e: GGEditorEvent) => void
|
||||
/** 鼠标拖拽放置事件 */
|
||||
onDrop?: (e: GGEditorEvent) => void
|
||||
/** 鼠标右键菜单事件 */
|
||||
onContextMenu?: (e: GGEditorEvent) => void
|
||||
}
|
||||
|
||||
export interface GraphOtherReactEventsProps {
|
||||
/** 鼠标滚轮事件 */
|
||||
onMouseWheel?: (e: GGEditorEvent) => void
|
||||
/** 键盘按键按下事件 */
|
||||
onKeyDown?: (e: GGEditorEvent) => void
|
||||
/** 键盘按键抬起事件 */
|
||||
onKeyUp?: (e: GGEditorEvent) => void
|
||||
/** 子项数据变化前 */
|
||||
onBeforeChange?: (e: GGEditorEvent) => void
|
||||
/** 子项数据变化后 */
|
||||
onAfterChange?: (e: GGEditorEvent) => void
|
||||
/** 画布尺寸变化前 */
|
||||
onBeforeChangeSize?: (e: GGEditorEvent) => void
|
||||
/** 画布尺寸变化后 */
|
||||
onAfterChangeSize?: (e: GGEditorEvent) => void
|
||||
/** 视口变化前 */
|
||||
onBeforeViewportChange?: (e: GGEditorEvent) => void
|
||||
/** 视口变化后 */
|
||||
onAfterViewportChange?: (e: GGEditorEvent) => void
|
||||
/** 激活前 */
|
||||
onBeforeItemActived?: (e: GGEditorEvent) => void
|
||||
}
|
||||
|
||||
export interface PageReactEventsProps {
|
||||
/** 激活后 */
|
||||
onAfterItemActived?: (e: GGEditorEvent) => void
|
||||
/** 取消激活前 */
|
||||
onBeforeItemInactivated?: (e: GGEditorEvent) => void
|
||||
/** 取消激活后 */
|
||||
onAfterItemInactivated?: (e: GGEditorEvent) => void
|
||||
/** 选中前 */
|
||||
onBeforeItemSelected?: (e: GGEditorEvent) => void
|
||||
/** 选中后 */
|
||||
onAfterItemSelected?: (e: GGEditorEvent) => void
|
||||
/** 取消选中前 */
|
||||
onBeforeItemUnselected?: (e: GGEditorEvent) => void
|
||||
/** 取消选中后 */
|
||||
onAfterItemUnselected?: (e: GGEditorEvent) => void
|
||||
/** 键盘按键抬起事件(节点编辑 */
|
||||
onKeyUpEditLabel?: (e: GGEditorEvent) => void
|
||||
}
|
||||
|
||||
export interface EditorCommand {
|
||||
name: string
|
||||
queue: boolean
|
||||
}
|
||||
|
||||
export interface PropsApi {
|
||||
propsApi: {
|
||||
executeCommand?(command: EditorCommand)
|
||||
read?(data: any)
|
||||
save?(): any
|
||||
add?(type: any, model: any)
|
||||
find?(id: any)
|
||||
update?(item: any, model: any)
|
||||
remove?(item: any)
|
||||
getSelected?()
|
||||
}
|
||||
}
|
||||
|
||||
export interface EditorReactEventsProps {
|
||||
onAfterCommandExecute?: (e: EditorCommand) => void
|
||||
onBeforeCommandExecute?: (e: EditorCommand) => void
|
||||
}
|
||||
export default class GGEditor extends React.Component<ReactProps & EditorReactEventsProps, any> {
|
||||
static setTrackable(state: boolean)
|
||||
}
|
||||
|
||||
/** 流程图 @see http://ggeditor.com/docs/api/flow.zh-CN.html */
|
||||
export const Flow: React.ComponentClass<FlowProps & GraphMouseReactEventsProps & GraphOtherReactEventsProps & PageReactEventsProps, any>
|
||||
|
||||
/** 思维导图 @see http://ggeditor.com/docs/api/mind.zh-CN.html */
|
||||
export const Mind: React.ComponentClass<MindProps & GraphMouseReactEventsProps & GraphOtherReactEventsProps & PageReactEventsProps, any>
|
||||
|
||||
/** 脑图 */
|
||||
export const Koni: React.ComponentClass<KoniProps & GraphMouseReactEventsProps & GraphOtherReactEventsProps & PageReactEventsProps, any>
|
||||
|
||||
/** 此组件只能嵌套在 <Toolbar /> 或 <ContextMenu /> 组件内使用: @see http://ggeditor.com/docs/api/command.zh-CN.html */
|
||||
export const Command: React.ComponentClass<CommondProps, any>
|
||||
|
||||
/** 不指定宽高的情况下则自动适应容器尺寸 @see http://ggeditor.com/docs/api/minimap.zh-CN.html */
|
||||
export const Minimap: React.ComponentClass<MninimapProps, any>
|
||||
|
||||
/** 右键菜单,负责菜单显示隐藏,命令按钮绑定与可用禁用状态控制。 @see http://ggeditor.com/docs/api/contextMenu.zh-CN.html */
|
||||
export const ContextMenu: React.ComponentClass<BasicProps, any>
|
||||
|
||||
/** 工具栏,负责命令按钮绑定与可用禁用状态控制。 @see http://ggeditor.com/docs/api/toolbar.zh-CN.html */
|
||||
export const Toolbar: React.ComponentClass<BasicProps, any>
|
||||
|
||||
/** 元素面板栏 必需配合 <Item /> 组件使用,如果 <Item /> 包含 src 属性则自动显示元素概览图片。 @see http://ggeditor.com/docs/api/itemPanel.zh-CN.html */
|
||||
export const ItemPanel: React.ComponentClass<ReactProps, any>
|
||||
export const Item: React.ComponentClass<ItemPanelProps, any>
|
||||
|
||||
/** 属性栏会自动根据不同页面状态显示对应面板,例如:选中节点时则只会显示 NodePanel @see http://ggeditor.com/docs/api/detailPanel.zh-CN.html */
|
||||
export const DetailPanel: React.ComponentClass<ReactProps, any>
|
||||
|
||||
export const RegisterNode: React.ComponentClass<RegisterProps, any>
|
||||
export const RegisterEdge: React.ComponentClass<RegisterProps, any>
|
||||
export const RegisterGroup: React.ComponentClass<RegisterProps, any>
|
||||
export const RegisterCommand: React.ComponentClass<RegisterProps, any>
|
||||
export const RegisterBehaviour: React.ComponentClass<RegisterBehaviourProps, any>
|
||||
|
||||
export const CanvasMenu: React.ComponentClass<ReactProps, any>
|
||||
export const EdgeMenu: React.ComponentClass<ReactProps, any>
|
||||
export const GroupMenu: React.ComponentClass<ReactProps, any>
|
||||
export const MultiMenu: React.ComponentClass<ReactProps, any>
|
||||
export const NodeMenu: React.ComponentClass<ReactProps, any>
|
||||
|
||||
export const CanvasPanel: React.ComponentClass<ReactProps, any>
|
||||
export const EdgePanel: React.ComponentClass<ReactProps, any>
|
||||
export const GroupPanel: React.ComponentClass<ReactProps, any>
|
||||
export const MultiPanel: React.ComponentClass<ReactProps, any>
|
||||
export const NodePanel: React.ComponentClass<ReactProps, any>
|
||||
|
||||
export const KoniCustomNode: React.ComponentClass<ReactProps & GraphMouseReactEventsProps & GraphOtherReactEventsProps & PageReactEventsProps, any>
|
||||
|
||||
/** 这里会带一个 Props 属性 @see http://ggeditor.com/docs/api/propsAPI.zh-CN.html */
|
||||
export function withPropsAPI(com: React.ComponentClass<ReactProps, any>): React.ComponentClass<any, any>
|
||||
}
|
||||
Reference in New Issue
Block a user