81 |
82 |
Import Warnings
83 |
84 |
85 | One or more problems have been identified when trying to import the
86 | BPMN 2.0 diagram:
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 | This may have been caused by malformed input data. As a result the
95 | diagram may not render correctly.
96 |
97 |
98 |
Need help on this?
99 |
100 |
101 | File a report in{" "}
102 |
103 | our forum
104 | . Attach your diagram and the above error log.
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
Keyboard Shortcuts
116 |
117 |
118 |
119 | Undo
120 | ⌘ + Z
121 |
122 |
123 | Redo
124 | ⌘ + ⇧ + Z
125 |
126 |
127 | Select All
128 | ⌘ + A
129 |
130 |
131 | Scrolling (Vertical)
132 | ⌥ + Scrolling
133 |
134 |
135 | Scrolling (Horizontal)
136 | ⌥ + ⇧ + Scrolling
137 |
138 |
139 | Direct Editing
140 | E
141 |
142 |
143 | Hand Tool
144 | H
145 |
146 |
147 | Lasso Tool
148 | L
149 |
150 |
151 | Space Tool
152 | S
153 |
154 |
155 |
156 |
157 |
158 |
159 |
Keyboard Shortcuts
160 |
161 |
162 |
163 | Undo
164 |
165 | ctrl + Z
166 |
167 |
168 |
169 | Redo
170 |
171 | ctrl + ⇧ + Z
172 |
173 |
174 |
175 | Select All
176 |
177 | ctrl + A
178 |
179 |
180 |
181 | Scrolling (Vertical)
182 | ctrl + Scrolling
183 |
184 |
185 | Scrolling (Horizontal)
186 | ctrl + ⇧ + Scrolling
187 |
188 |
189 | Direct Editing
190 | E
191 |
192 |
193 | Hand Tool
194 | H
195 |
196 |
197 | Lasso Tool
198 | L
199 |
200 |
201 | Space Tool
202 | S
203 |
204 |
205 |
206 |
207 |
208 |
209 | );
210 |
--------------------------------------------------------------------------------
/src/containers/BpmnBoard/components/EditingTools.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export default ({ onUndo, onRedo, onSave }) => (
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | {/*
22 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | */}
34 |
35 |
36 | );
37 |
--------------------------------------------------------------------------------
/src/containers/BpmnBoard/components/FileControls.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export default ({ onOpen, onCreate, onSaveFile, onSaveImage }) => (
4 |
5 |
6 |
7 |
11 |
12 |
13 |
14 |
15 |
16 |
20 |
21 |
22 |
23 |
24 |
56 |
57 | );
58 |
--------------------------------------------------------------------------------
/src/containers/BpmnBoard/components/ScreenError.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export default () => (
4 |
5 |
6 |
7 |
Ooops, we could not display the diagram.
8 |
9 |
10 | You believe your input is valid{" "}
11 | BPMN 2.0 XML ?
12 |
13 |
14 |
15 |
16 | Consult our{" "}
17 |
18 | forum
19 | {" "}
20 | or
21 |
22 | file an issue
23 |
24 | with the details shown below.
25 |
26 |
27 |
28 |
29 | Import Error Details
30 |
31 |
32 |
33 |
34 | );
35 |
--------------------------------------------------------------------------------
/src/containers/BpmnBoard/components/ScreenLoading.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export default ({ text = 'loading diagram, please hang tight' }) => (
4 |
5 |
6 |
7 |
8 |
9 |
10 | {text}
11 |
12 |
13 |
14 |
15 | );
16 |
--------------------------------------------------------------------------------
/src/containers/BpmnBoard/components/ZoomControls.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export default ({ onZoomIn, onZoomOut, onZoomReset }) => (
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | );
30 |
--------------------------------------------------------------------------------
/src/containers/BpmnBoard/custom-modeler/custom/CustomContextPadProvider.js:
--------------------------------------------------------------------------------
1 | import inherits from 'inherits';
2 |
3 | import ContextPadProvider from 'bpmn-js/lib/features/context-pad/ContextPadProvider';
4 |
5 | import {
6 | isAny
7 | } from 'bpmn-js/lib/features/modeling/util/ModelingUtil';
8 |
9 | import {
10 | assign,
11 | bind
12 | } from 'min-dash';
13 |
14 |
15 | export default function CustomContextPadProvider(injector, connect, translate) {
16 |
17 | injector.invoke(ContextPadProvider, this);
18 |
19 | var cached = bind(this.getContextPadEntries, this);
20 |
21 | this.getContextPadEntries = function(element) {
22 | var actions = cached(element);
23 |
24 | var businessObject = element.businessObject;
25 |
26 | function startConnect(event, element, autoActivate) {
27 | connect.start(event, element, autoActivate);
28 | }
29 |
30 | if (isAny(businessObject, [ 'custom:triangle', 'custom:circle'])) {
31 | assign(actions, {
32 | 'connect': {
33 | group: 'connect',
34 | className: 'bpmn-icon-connection-multi',
35 | title: translate('Connect using custom connection'),
36 | action: {
37 | click: startConnect,
38 | dragstart: startConnect
39 | }
40 | }
41 | });
42 | }
43 |
44 | return actions;
45 | };
46 | }
47 |
48 | inherits(CustomContextPadProvider, ContextPadProvider);
49 |
50 | CustomContextPadProvider.$inject = [
51 | 'injector',
52 | 'connect',
53 | 'translate'
54 | ];
--------------------------------------------------------------------------------
/src/containers/BpmnBoard/custom-modeler/custom/CustomElementFactory.js:
--------------------------------------------------------------------------------
1 | import {
2 | assign
3 | } from 'min-dash';
4 |
5 | import inherits from 'inherits';
6 |
7 | import BpmnElementFactory from 'bpmn-js/lib/features/modeling/ElementFactory';
8 | import {
9 | DEFAULT_LABEL_SIZE
10 | } from 'bpmn-js/lib/util/LabelUtil';
11 |
12 |
13 | /**
14 | * A custom factory that knows how to create BPMN _and_ custom elements.
15 | */
16 | export default function CustomElementFactory(bpmnFactory, moddle) {
17 | BpmnElementFactory.call(this, bpmnFactory, moddle);
18 |
19 | var self = this;
20 |
21 | /**
22 | * Create a diagram-js element with the given type (any of shape, connection, label).
23 | *
24 | * @param {String} elementType
25 | * @param {Object} attrs
26 | *
27 | * @return {djs.model.Base}
28 | */
29 | this.create = function(elementType, attrs) {
30 | var type = attrs.type;
31 |
32 | if (elementType === 'label') {
33 | return self.baseCreate(elementType, assign({ type: 'label' }, DEFAULT_LABEL_SIZE, attrs));
34 | }
35 |
36 | // add type to businessObject if custom
37 | if (/^custom:/.test(type)) {
38 | if (!attrs.businessObject) {
39 | attrs.businessObject = {
40 | type: type
41 | };
42 |
43 | if (attrs.id) {
44 | assign(attrs.businessObject, {
45 | id: attrs.id
46 | });
47 | }
48 | }
49 |
50 | // add width and height if shape
51 | if (!/:connection$/.test(type)) {
52 | assign(attrs, self._getCustomElementSize(type));
53 | }
54 |
55 | if (!('$instanceOf' in attrs.businessObject)) {
56 | // ensure we can use ModelUtil#is for type checks
57 | Object.defineProperty(attrs.businessObject, '$instanceOf', {
58 | value: function(type) {
59 | return this.type === type;
60 | }
61 | });
62 | }
63 |
64 | return self.baseCreate(elementType, attrs);
65 | }
66 |
67 | return self.createBpmnElement(elementType, attrs);
68 | };
69 | }
70 |
71 | inherits(CustomElementFactory, BpmnElementFactory);
72 |
73 | CustomElementFactory.$inject = [
74 | 'bpmnFactory',
75 | 'moddle'
76 | ];
77 |
78 |
79 | /**
80 | * Returns the default size of custom shapes.
81 | *
82 | * The following example shows an interface on how
83 | * to setup the custom shapes's dimensions.
84 | *
85 | * @example
86 | *
87 | * var shapes = {
88 | * triangle: { width: 40, height: 40 },
89 | * rectangle: { width: 100, height: 20 }
90 | * };
91 | *
92 | * return shapes[type];
93 | *
94 | *
95 | * @param {String} type
96 | *
97 | * @return {Dimensions} a {width, height} object representing the size of the element
98 | */
99 | CustomElementFactory.prototype._getCustomElementSize = function(type) {
100 | var shapes = {
101 | __default: { width: 100, height: 80 },
102 | 'custom:triangle': { width: 40, height: 40 },
103 | 'custom:circle': { width: 140, height: 140 }
104 | };
105 |
106 | return shapes[type] || shapes.__default;
107 | };
108 |
--------------------------------------------------------------------------------
/src/containers/BpmnBoard/custom-modeler/custom/CustomPalette.js:
--------------------------------------------------------------------------------
1 | import {
2 | assign
3 | } from 'min-dash';
4 |
5 |
6 | /**
7 | * A palette that allows you to create BPMN _and_ custom elements.
8 | */
9 | export default function PaletteProvider(palette, create, elementFactory, spaceTool, lassoTool) {
10 |
11 | this._create = create;
12 | this._elementFactory = elementFactory;
13 | this._spaceTool = spaceTool;
14 | this._lassoTool = lassoTool;
15 |
16 | palette.registerProvider(this);
17 | }
18 |
19 | PaletteProvider.$inject = [
20 | 'palette',
21 | 'create',
22 | 'elementFactory',
23 | 'spaceTool',
24 | 'lassoTool'
25 | ];
26 |
27 |
28 | PaletteProvider.prototype.getPaletteEntries = function(element) {
29 |
30 | var actions = {},
31 | create = this._create,
32 | elementFactory = this._elementFactory,
33 | spaceTool = this._spaceTool,
34 | lassoTool = this._lassoTool;
35 |
36 |
37 | function createAction(type, group, className, title, options) {
38 |
39 | function createListener(event) {
40 | var shape = elementFactory.createShape(assign({ type: type }, options));
41 |
42 | if (options) {
43 | shape.businessObject.di.isExpanded = options.isExpanded;
44 | }
45 |
46 | create.start(event, shape);
47 | }
48 |
49 | var shortType = type.replace(/^bpmn:/, '');
50 |
51 | return {
52 | group: group,
53 | className: className,
54 | title: title || 'Create ' + shortType,
55 | action: {
56 | dragstart: createListener,
57 | click: createListener
58 | }
59 | };
60 | }
61 |
62 | function createParticipant(event, collapsed) {
63 | create.start(event, elementFactory.createParticipantShape(collapsed));
64 | }
65 |
66 | assign(actions, {
67 | 'custom-triangle': createAction(
68 | 'custom:triangle', 'custom', 'icon-custom-triangle'
69 | ),
70 | 'custom-circle': createAction(
71 | 'custom:circle', 'custom', 'icon-custom-circle'
72 | ),
73 | 'custom-separator': {
74 | group: 'custom',
75 | separator: true
76 | },
77 | 'lasso-tool': {
78 | group: 'tools',
79 | className: 'bpmn-icon-lasso-tool',
80 | title: 'Activate the lasso tool',
81 | action: {
82 | click: function(event) {
83 | lassoTool.activateSelection(event);
84 | }
85 | }
86 | },
87 | 'space-tool': {
88 | group: 'tools',
89 | className: 'bpmn-icon-space-tool',
90 | title: 'Activate the create/remove space tool',
91 | action: {
92 | click: function(event) {
93 | spaceTool.activateSelection(event);
94 | }
95 | }
96 | },
97 | 'tool-separator': {
98 | group: 'tools',
99 | separator: true
100 | },
101 | 'create.start-event': createAction(
102 | 'bpmn:StartEvent', 'event', 'bpmn-icon-start-event-none'
103 | ),
104 | 'create.intermediate-event': createAction(
105 | 'bpmn:IntermediateThrowEvent', 'event', 'bpmn-icon-intermediate-event-none'
106 | ),
107 | 'create.end-event': createAction(
108 | 'bpmn:EndEvent', 'event', 'bpmn-icon-end-event-none'
109 | ),
110 | 'create.exclusive-gateway': createAction(
111 | 'bpmn:ExclusiveGateway', 'gateway', 'bpmn-icon-gateway-xor'
112 | ),
113 | 'create.task': createAction(
114 | 'bpmn:Task', 'activity', 'bpmn-icon-task'
115 | ),
116 | 'create.subprocess-expanded': createAction(
117 | 'bpmn:SubProcess', 'activity', 'bpmn-icon-subprocess-expanded', 'Create expanded SubProcess',
118 | { isExpanded: true }
119 | ),
120 | 'create.participant-expanded': {
121 | group: 'collaboration',
122 | className: 'bpmn-icon-participant',
123 | title: 'Create Pool/Participant',
124 | action: {
125 | dragstart: createParticipant,
126 | click: createParticipant
127 | }
128 | }
129 | });
130 |
131 | return actions;
132 | };
133 |
--------------------------------------------------------------------------------
/src/containers/BpmnBoard/custom-modeler/custom/CustomRenderer.js:
--------------------------------------------------------------------------------
1 | import inherits from 'inherits';
2 |
3 | import BaseRenderer from 'diagram-js/lib/draw/BaseRenderer';
4 |
5 | import {
6 | componentsToPath,
7 | createLine
8 | } from 'diagram-js/lib/util/RenderUtil';
9 |
10 | import {
11 | append as svgAppend,
12 | attr as svgAttr,
13 | create as svgCreate
14 | } from 'tiny-svg';
15 |
16 |
17 | /**
18 | * A renderer that knows how to render custom elements.
19 | */
20 | export default function CustomRenderer(eventBus, styles) {
21 |
22 | BaseRenderer.call(this, eventBus, 2000);
23 |
24 | var computeStyle = styles.computeStyle;
25 |
26 | this.drawTriangle = function(p, side) {
27 | var halfSide = side / 2,
28 | points,
29 | attrs;
30 |
31 | points = [ halfSide, 0, side, side, 0, side ];
32 |
33 | attrs = computeStyle(attrs, {
34 | stroke: '#3CAA82',
35 | strokeWidth: 2,
36 | fill: '#3CAA82'
37 | });
38 |
39 | var polygon = svgCreate('polygon');
40 |
41 | svgAttr(polygon, {
42 | points: points
43 | });
44 |
45 | svgAttr(polygon, attrs);
46 |
47 | svgAppend(p, polygon);
48 |
49 | return polygon;
50 | };
51 |
52 | this.getTrianglePath = function(element) {
53 | var x = element.x,
54 | y = element.y,
55 | width = element.width,
56 | height = element.height;
57 |
58 | var trianglePath = [
59 | ['M', x + width / 2, y],
60 | ['l', width / 2, height],
61 | ['l', -width, 0 ],
62 | ['z']
63 | ];
64 |
65 | return componentsToPath(trianglePath);
66 | };
67 |
68 | this.drawCircle = function(p, width, height) {
69 | var cx = width / 2,
70 | cy = height / 2;
71 | // eslint-disable-next-line
72 | var attrs = computeStyle(attrs, {
73 | stroke: '#4488aa',
74 | strokeWidth: 4,
75 | fill: 'white'
76 | });
77 |
78 | var circle = svgCreate('circle');
79 |
80 | svgAttr(circle, {
81 | cx: cx,
82 | cy: cy,
83 | r: Math.round((width + height) / 4)
84 | });
85 |
86 | svgAttr(circle, attrs);
87 |
88 | svgAppend(p, circle);
89 |
90 | return circle;
91 | };
92 |
93 | this.getCirclePath = function(shape) {
94 | var cx = shape.x + shape.width / 2,
95 | cy = shape.y + shape.height / 2,
96 | radius = shape.width / 2;
97 |
98 | var circlePath = [
99 | ['M', cx, cy],
100 | ['m', 0, -radius],
101 | ['a', radius, radius, 0, 1, 1, 0, 2 * radius],
102 | ['a', radius, radius, 0, 1, 1, 0, -2 * radius],
103 | ['z']
104 | ];
105 |
106 | return componentsToPath(circlePath);
107 | };
108 |
109 | this.drawCustomConnection = function(p, element) {
110 | // eslint-disable-next-line
111 | var attrs = computeStyle(attrs, {
112 | stroke: '#ff471a',
113 | strokeWidth: 2
114 | });
115 |
116 | return svgAppend(p, createLine(element.waypoints, attrs));
117 | };
118 |
119 | this.getCustomConnectionPath = function(connection) {
120 | var waypoints = connection.waypoints.map(function(p) {
121 | return p.original || p;
122 | });
123 |
124 | var connectionPath = [
125 | ['M', waypoints[0].x, waypoints[0].y]
126 | ];
127 |
128 | waypoints.forEach(function(waypoint, index) {
129 | if (index !== 0) {
130 | connectionPath.push(['L', waypoint.x, waypoint.y]);
131 | }
132 | });
133 |
134 | return componentsToPath(connectionPath);
135 | };
136 | }
137 |
138 | inherits(CustomRenderer, BaseRenderer);
139 |
140 | CustomRenderer.$inject = [ 'eventBus', 'styles' ];
141 |
142 |
143 | CustomRenderer.prototype.canRender = function(element) {
144 | return /^custom:/.test(element.type);
145 | };
146 |
147 | CustomRenderer.prototype.drawShape = function(p, element) {
148 | var type = element.type;
149 |
150 | if (type === 'custom:triangle') {
151 | return this.drawTriangle(p, element.width);
152 | }
153 |
154 | if (type === 'custom:circle') {
155 | return this.drawCircle(p, element.width, element.height);
156 | }
157 | };
158 |
159 | CustomRenderer.prototype.getShapePath = function(shape) {
160 | var type = shape.type;
161 |
162 | if (type === 'custom:triangle') {
163 | return this.getTrianglePath(shape);
164 | }
165 |
166 | if (type === 'custom:circle') {
167 | return this.getCirclePath(shape);
168 | }
169 | };
170 |
171 | CustomRenderer.prototype.drawConnection = function(p, element) {
172 |
173 | var type = element.type;
174 |
175 | if (type === 'custom:connection') {
176 | return this.drawCustomConnection(p, element);
177 | }
178 | };
179 |
180 |
181 | CustomRenderer.prototype.getConnectionPath = function(connection) {
182 |
183 | var type = connection.type;
184 |
185 | if (type === 'custom:connection') {
186 | return this.getCustomConnectionPath(connection);
187 | }
188 | };
189 |
--------------------------------------------------------------------------------
/src/containers/BpmnBoard/custom-modeler/custom/CustomRules.js:
--------------------------------------------------------------------------------
1 | import {
2 | reduce
3 | } from 'min-dash';
4 |
5 | import inherits from 'inherits';
6 |
7 | import {
8 | is
9 | } from 'bpmn-js/lib/util/ModelUtil';
10 |
11 | import RuleProvider from 'diagram-js/lib/features/rules/RuleProvider';
12 |
13 | var HIGH_PRIORITY = 1500;
14 |
15 |
16 | function isCustom(element) {
17 | return element && /^custom:/.test(element.type);
18 | }
19 |
20 | /**
21 | * Specific rules for custom elements
22 | */
23 | export default function CustomRules(eventBus) {
24 | RuleProvider.call(this, eventBus);
25 | }
26 |
27 | inherits(CustomRules, RuleProvider);
28 |
29 | CustomRules.$inject = [ 'eventBus' ];
30 |
31 |
32 | CustomRules.prototype.init = function() {
33 |
34 | /**
35 | * Can shape be created on target container?
36 | */
37 | function canCreate(shape, target) {
38 |
39 | // only judge about custom elements
40 | if (!isCustom(shape)) {
41 | return;
42 | }
43 |
44 | // allow creation on processes
45 | return is(target, 'bpmn:Process') || is(target, 'bpmn:Participant') || is(target, 'bpmn:Collaboration');
46 | }
47 |
48 | /**
49 | * Can source and target be connected?
50 | */
51 | function canConnect(source, target) {
52 |
53 | // only judge about custom elements
54 | if (!isCustom(source) && !isCustom(target)) {
55 | return;
56 | }
57 |
58 | // allow connection between custom shape and task
59 | if (isCustom(source)) {
60 | if (is(target, 'bpmn:Task')) {
61 | return { type: 'custom:connection' };
62 | } else {
63 | return false;
64 | }
65 | } else if (isCustom(target)) {
66 | if (is(source, 'bpmn:Task')) {
67 | return { type: 'custom:connection' };
68 | } else {
69 | return false;
70 | }
71 | }
72 | }
73 |
74 | this.addRule('elements.move', HIGH_PRIORITY, function(context) {
75 |
76 | var target = context.target,
77 | shapes = context.shapes;
78 |
79 | var type;
80 |
81 | // do not allow mixed movements of custom / BPMN shapes
82 | // if any shape cannot be moved, the group cannot be moved, too
83 | var allowed = reduce(shapes, function(result, s) {
84 | if (type === undefined) {
85 | type = isCustom(s);
86 | }
87 |
88 | if (type !== isCustom(s) || result === false) {
89 | return false;
90 | }
91 |
92 | return canCreate(s, target);
93 | }, undefined);
94 |
95 | // reject, if we have at least one
96 | // custom element that cannot be moved
97 | return allowed;
98 | });
99 |
100 | this.addRule('shape.create', HIGH_PRIORITY, function(context) {
101 | var target = context.target,
102 | shape = context.shape;
103 |
104 | return canCreate(shape, target);
105 | });
106 |
107 | this.addRule('shape.resize', HIGH_PRIORITY, function(context) {
108 | var shape = context.shape;
109 |
110 | if (isCustom(shape)) {
111 | // cannot resize custom elements
112 | return false;
113 | }
114 | });
115 |
116 | this.addRule('connection.create', HIGH_PRIORITY, function(context) {
117 | var source = context.source,
118 | target = context.target;
119 |
120 | return canConnect(source, target);
121 | });
122 |
123 | this.addRule('connection.reconnectStart', HIGH_PRIORITY, function(context) {
124 | var connection = context.connection,
125 | source = context.hover || context.source,
126 | target = connection.target;
127 |
128 | return canConnect(source, target, connection);
129 | });
130 |
131 | this.addRule('connection.reconnectEnd', HIGH_PRIORITY, function(context) {
132 | var connection = context.connection,
133 | source = connection.source,
134 | target = context.hover || context.target;
135 |
136 | return canConnect(source, target, connection);
137 | });
138 |
139 | };
140 |
--------------------------------------------------------------------------------
/src/containers/BpmnBoard/custom-modeler/custom/CustomUpdater.js:
--------------------------------------------------------------------------------
1 | import inherits from 'inherits';
2 |
3 | import {
4 | pick,
5 | assign
6 | } from 'min-dash';
7 |
8 | import CommandInterceptor from 'diagram-js/lib/command/CommandInterceptor';
9 |
10 | import {
11 | add as collectionAdd,
12 | remove as collectionRemove
13 | } from 'diagram-js/lib/util/Collections';
14 |
15 |
16 | /**
17 | * A handler responsible for updating the custom element's businessObject
18 | * once changes on the diagram happen.
19 | */
20 | export default function CustomUpdater(eventBus, bpmnjs) {
21 |
22 | CommandInterceptor.call(this, eventBus);
23 |
24 | function updateCustomElement(e) {
25 | var context = e.context,
26 | shape = context.shape,
27 | businessObject = shape.businessObject;
28 |
29 | if (!isCustom(shape)) {
30 | return;
31 | }
32 |
33 | var parent = shape.parent;
34 |
35 | var customElements = bpmnjs._customElements;
36 |
37 | // make sure element is added / removed from bpmnjs.customElements
38 | if (!parent) {
39 | collectionRemove(customElements, businessObject);
40 | } else {
41 | collectionAdd(customElements, businessObject);
42 | }
43 |
44 | // save custom element position
45 | assign(businessObject, pick(shape, [ 'x', 'y' ]));
46 | }
47 |
48 | function updateCustomConnection(e) {
49 |
50 | var context = e.context,
51 | connection = context.connection,
52 | source = connection.source,
53 | target = connection.target,
54 | businessObject = connection.businessObject;
55 |
56 | var parent = connection.parent;
57 |
58 | var customElements = bpmnjs._customElements;
59 |
60 | // make sure element is added / removed from bpmnjs.customElements
61 | if (!parent) {
62 | collectionRemove(customElements, businessObject);
63 | } else {
64 | collectionAdd(customElements, businessObject);
65 | }
66 |
67 | // update waypoints
68 | assign(businessObject, {
69 | waypoints: copyWaypoints(connection)
70 | });
71 |
72 | if (source && target) {
73 | assign(businessObject, {
74 | source: source.id,
75 | target: target.id
76 | });
77 | }
78 |
79 | }
80 |
81 | this.executed([
82 | 'shape.create',
83 | 'shape.move',
84 | 'shape.delete'
85 | ], ifCustomElement(updateCustomElement));
86 |
87 | this.reverted([
88 | 'shape.create',
89 | 'shape.move',
90 | 'shape.delete'
91 | ], ifCustomElement(updateCustomElement));
92 |
93 | this.executed([
94 | 'connection.create',
95 | 'connection.reconnectStart',
96 | 'connection.reconnectEnd',
97 | 'connection.updateWaypoints',
98 | 'connection.delete',
99 | 'connection.layout',
100 | 'connection.move'
101 | ], ifCustomElement(updateCustomConnection));
102 |
103 | this.reverted([
104 | 'connection.create',
105 | 'connection.reconnectStart',
106 | 'connection.reconnectEnd',
107 | 'connection.updateWaypoints',
108 | 'connection.delete',
109 | 'connection.layout',
110 | 'connection.move'
111 | ], ifCustomElement(updateCustomConnection));
112 |
113 | }
114 |
115 | inherits(CustomUpdater, CommandInterceptor);
116 |
117 | CustomUpdater.$inject = [ 'eventBus', 'bpmnjs' ];
118 |
119 |
120 | /////// helpers ///////////////////////////////////
121 |
122 | function copyWaypoints(connection) {
123 | return connection.waypoints.map(function(p) {
124 | return { x: p.x, y: p.y };
125 | });
126 | }
127 |
128 | function isCustom(element) {
129 | return element && /custom:/.test(element.type);
130 | }
131 |
132 | function ifCustomElement(fn) {
133 | return function(event) {
134 | var context = event.context,
135 | element = context.shape || context.connection;
136 |
137 | if (isCustom(element)) {
138 | fn(event);
139 | }
140 | };
141 | }
--------------------------------------------------------------------------------
/src/containers/BpmnBoard/custom-modeler/custom/index.js:
--------------------------------------------------------------------------------
1 | import CustomElementFactory from './CustomElementFactory';
2 | import CustomRenderer from './CustomRenderer';
3 | import CustomPalette from './CustomPalette';
4 | import CustomRules from './CustomRules';
5 | import CustomUpdater from './CustomUpdater';
6 | import CustomContextPadProvider from './CustomContextPadProvider';
7 |
8 | export default {
9 | __init__: [
10 | 'customRenderer',
11 | 'paletteProvider',
12 | 'customRules',
13 | 'customUpdater',
14 | 'contextPadProvider'
15 | ],
16 | elementFactory: [ 'type', CustomElementFactory ],
17 | customRenderer: [ 'type', CustomRenderer ],
18 | paletteProvider: [ 'type', CustomPalette ],
19 | customRules: [ 'type', CustomRules ],
20 | customUpdater: [ 'type', CustomUpdater ],
21 | contextPadProvider: [ 'type', CustomContextPadProvider ]
22 | };
23 |
--------------------------------------------------------------------------------
/src/containers/BpmnBoard/custom-modeler/index.js:
--------------------------------------------------------------------------------
1 | import Modeler from 'bpmn-js/lib/Modeler';
2 |
3 | import {
4 | assign,
5 | isArray
6 | } from 'min-dash';
7 |
8 | import inherits from 'inherits';
9 |
10 | import CustomModule from './custom';
11 |
12 |
13 | export default function CustomModeler(options) {
14 | Modeler.call(this, options);
15 |
16 | this._customElements = [];
17 | }
18 |
19 | inherits(CustomModeler, Modeler);
20 |
21 | CustomModeler.prototype._modules = [].concat(
22 | CustomModeler.prototype._modules,
23 | [
24 | CustomModule
25 | ]
26 | );
27 |
28 | /**
29 | * Add a single custom element to the underlying diagram
30 | *
31 | * @param {Object} customElement
32 | */
33 | CustomModeler.prototype._addCustomShape = function(customElement) {
34 |
35 | this._customElements.push(customElement);
36 |
37 | var canvas = this.get('canvas'),
38 | elementFactory = this.get('elementFactory');
39 |
40 | var customAttrs = assign({ businessObject: customElement }, customElement);
41 |
42 | var customShape = elementFactory.create('shape', customAttrs);
43 |
44 | return canvas.addShape(customShape);
45 |
46 | };
47 |
48 | CustomModeler.prototype._addCustomConnection = function(customElement) {
49 |
50 | this._customElements.push(customElement);
51 |
52 | var canvas = this.get('canvas'),
53 | elementFactory = this.get('elementFactory'),
54 | elementRegistry = this.get('elementRegistry');
55 |
56 | var customAttrs = assign({ businessObject: customElement }, customElement);
57 |
58 | var connection = elementFactory.create('connection', assign(customAttrs, {
59 | source: elementRegistry.get(customElement.source),
60 | target: elementRegistry.get(customElement.target)
61 | }),
62 | elementRegistry.get(customElement.source).parent);
63 |
64 | return canvas.addConnection(connection);
65 |
66 | };
67 |
68 | /**
69 | * Add a number of custom elements and connections to the underlying diagram.
70 | *
71 | * @param {Array
} customElements
72 | */
73 | CustomModeler.prototype.addCustomElements = function(customElements) {
74 |
75 | if (!isArray(customElements)) {
76 | throw new Error('argument must be an array');
77 | }
78 |
79 | var shapes = [],
80 | connections = [];
81 |
82 | customElements.forEach(function(customElement) {
83 | if (isCustomConnection(customElement)) {
84 | connections.push(customElement);
85 | } else {
86 | shapes.push(customElement);
87 | }
88 | });
89 |
90 | // add shapes before connections so that connections
91 | // can already rely on the shapes being part of the diagram
92 | shapes.forEach(this._addCustomShape, this);
93 |
94 | connections.forEach(this._addCustomConnection, this);
95 | };
96 |
97 | /**
98 | * Get custom elements with their current status.
99 | *
100 | * @return {Array} custom elements on the diagram
101 | */
102 | CustomModeler.prototype.getCustomElements = function() {
103 | return this._customElements;
104 | };
105 |
106 |
107 | function isCustomConnection(element) {
108 | return element.type === 'custom:connection';
109 | }
110 |
--------------------------------------------------------------------------------
/src/containers/BpmnBoard/descriptors/magic.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Magic",
3 | "prefix": "magic",
4 | "uri": "http://magic",
5 | "xml": {
6 | "tagAlias": "lowerCase"
7 | },
8 | "associations": [],
9 | "types": [
10 | {
11 | "name": "BewitchedStartEvent",
12 | "extends": ["bpmn:StartEvent"],
13 | "properties": [
14 | {
15 | "name": "spell",
16 | "isAttr": true,
17 | "type": "String"
18 | }
19 | ]
20 | }
21 | ]
22 | }
23 |
--------------------------------------------------------------------------------
/src/containers/BpmnBoard/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component, Fragment } from "react";
2 | // import BpmnModeler from "bpmn-js/lib/Modeler";
3 | import BpmnModeler from "./custom-modeler";
4 | import propertiesPanelModule from "bpmn-js-properties-panel";
5 | // import propertiesProviderModule from "bpmn-js-properties-panel/lib/provider/bpmn";
6 | import propertiesProviderModule from "./provider/magic";
7 | import magicModdleDescriptor from "./descriptors/magic";
8 |
9 | import ZoomControls from "./components/ZoomControls";
10 | import FileControls from "./components/FileControls";
11 | import EditingTools from './components/EditingTools';
12 |
13 | import "./style/app.less";
14 |
15 | import xmlStr from "../../assets/bpmn/xmlStr";
16 |
17 | let scale = 1;
18 |
19 | export default class extends Component {
20 | componentDidMount() {
21 | document.body.className = "shown";
22 |
23 | this.bpmnModeler = new BpmnModeler({
24 | additionalModules: [propertiesPanelModule, propertiesProviderModule],
25 | container: "#canvas",
26 | propertiesPanel: {
27 | parent: "#properties-panel"
28 | },
29 | moddleExtensions: {
30 | magic: magicModdleDescriptor
31 | }
32 | });
33 |
34 | // this.bpmnModeler.on('commandStack.changed', this.onChange);
35 |
36 | const { xml = xmlStr } = this.props;
37 |
38 | this.renderDiagram(xml);
39 | }
40 |
41 | componentWillReceiveProps(nextProps) {
42 | const { xml } = nextProps;
43 | if (xml && xml !== this.props.xml) {
44 | this.renderDiagram(xml);
45 | }
46 | }
47 |
48 | shouldComponentUpdate() {
49 | return false;
50 | }
51 |
52 | renderDiagram = (xml) => {
53 | this.bpmnModeler.importXML(xml, err => {
54 | if (err) {
55 | // import failed :-(
56 | console.log("error rendering", err);
57 | } else {
58 | // we did well!
59 | this.bpmnModeler.getDefinitions()
60 | console.log("successfully rendered");
61 | }
62 | });
63 | };
64 |
65 | handleSave = (e) => {
66 | this.bpmnModeler.saveXML({ format: true }, (err, xml) => {
67 | console.log(xml);
68 | console.log(this.bpmnModeler.getDefinitions());
69 | });
70 | }
71 |
72 | handleRedo = () => {
73 | this.bpmnModeler.get('commandStack').redo();
74 | };
75 |
76 | handleUndo = () => {
77 | this.bpmnModeler.get('commandStack').undo();
78 | };
79 |
80 | handleZoom = () => {
81 | this.bpmnModeler.get('canvas').zoom(scale);
82 | }
83 |
84 | handleZoomIn = () => {
85 | scale += 0.1;
86 | this.handleZoom();
87 | };
88 |
89 | handleZoomOut = () => {
90 | if (scale <= 0.3) {
91 | scale = 0.2
92 | } else {
93 | scale -= 0.1;
94 | };
95 | this.handleZoom();
96 | };
97 |
98 | handleZoomReset = () => {
99 | scale = 1;
100 | this.handleZoom();
101 | };
102 |
103 | handleOpen = () => {};
104 |
105 | handleCreate = () => {};
106 |
107 | handleSaveFile = () => {};
108 |
109 | handleSaveImage = () => {};
110 |
111 | render() {
112 | return (
113 |
114 |
118 |
123 |
129 |
134 |
135 | );
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/src/containers/BpmnBoard/provider/magic/MagicPropertiesProvider.js:
--------------------------------------------------------------------------------
1 | import inherits from 'inherits';
2 |
3 | import PropertiesActivator from 'bpmn-js-properties-panel/lib/PropertiesActivator';
4 |
5 | // Require all properties you need from existing providers.
6 | // In this case all available bpmn relevant properties without camunda extensions.
7 | import processProps from 'bpmn-js-properties-panel/lib/provider/bpmn/parts/ProcessProps';
8 | import eventProps from 'bpmn-js-properties-panel/lib/provider/bpmn/parts/EventProps';
9 | import linkProps from 'bpmn-js-properties-panel/lib/provider/bpmn/parts/LinkProps';
10 | import documentationProps from 'bpmn-js-properties-panel/lib/provider/bpmn/parts/DocumentationProps';
11 | import idProps from 'bpmn-js-properties-panel/lib/provider/bpmn/parts/IdProps';
12 | import nameProps from 'bpmn-js-properties-panel/lib/provider/bpmn/parts/NameProps';
13 |
14 |
15 | // Require your custom property entries.
16 | import spellProps from './parts/SpellProps';
17 |
18 |
19 | // The general tab contains all bpmn relevant properties.
20 | // The properties are organized in groups.
21 | function createGeneralTabGroups(element, bpmnFactory, elementRegistry, translate) {
22 |
23 | var generalGroup = {
24 | id: 'general',
25 | label: 'General',
26 | entries: []
27 | };
28 | idProps(generalGroup, element, translate);
29 | nameProps(generalGroup, element, translate);
30 | processProps(generalGroup, element, translate);
31 |
32 | var detailsGroup = {
33 | id: 'details',
34 | label: 'Details',
35 | entries: []
36 | };
37 | linkProps(detailsGroup, element, translate);
38 | eventProps(detailsGroup, element, bpmnFactory, elementRegistry, translate);
39 |
40 | var documentationGroup = {
41 | id: 'documentation',
42 | label: 'Documentation',
43 | entries: []
44 | };
45 |
46 | documentationProps(documentationGroup, element, bpmnFactory, translate);
47 |
48 | return[
49 | generalGroup,
50 | detailsGroup,
51 | documentationGroup
52 | ];
53 | }
54 |
55 | // Create the custom magic tab
56 | function createMagicTabGroups(element, elementRegistry) {
57 |
58 | // Create a group called "Black Magic".
59 | var blackMagicGroup = {
60 | id: 'black-magic',
61 | label: 'Black Magic',
62 | entries: []
63 | };
64 |
65 | // Add the spell props to the black magic group.
66 | spellProps(blackMagicGroup, element);
67 |
68 | return [
69 | blackMagicGroup
70 | ];
71 | }
72 |
73 | export default function MagicPropertiesProvider(
74 | eventBus, bpmnFactory, elementRegistry,
75 | translate) {
76 |
77 | PropertiesActivator.call(this, eventBus);
78 |
79 | this.getTabs = function(element) {
80 |
81 | var generalTab = {
82 | id: 'general',
83 | label: 'General',
84 | groups: createGeneralTabGroups(element, bpmnFactory, elementRegistry, translate)
85 | };
86 |
87 | // The "magic" tab
88 | var magicTab = {
89 | id: 'magic',
90 | label: 'Magic',
91 | groups: createMagicTabGroups(element, elementRegistry)
92 | };
93 |
94 | // Show general + "magic" tab
95 | return [
96 | generalTab,
97 | magicTab
98 | ];
99 | };
100 | }
101 |
102 | inherits(MagicPropertiesProvider, PropertiesActivator);
--------------------------------------------------------------------------------
/src/containers/BpmnBoard/provider/magic/index.js:
--------------------------------------------------------------------------------
1 | import MagicPropertiesProvider from './MagicPropertiesProvider';
2 |
3 | export default {
4 | __init__: [ 'propertiesProvider' ],
5 | propertiesProvider: [ 'type', MagicPropertiesProvider ]
6 | };
--------------------------------------------------------------------------------
/src/containers/BpmnBoard/provider/magic/parts/SpellProps.js:
--------------------------------------------------------------------------------
1 | import entryFactory from 'bpmn-js-properties-panel/lib/factory/EntryFactory';
2 |
3 | import {
4 | is
5 | } from 'bpmn-js/lib/util/ModelUtil';
6 |
7 |
8 | export default function(group, element) {
9 |
10 | // Only return an entry, if the currently selected
11 | // element is a start event.
12 |
13 | if (is(element, 'bpmn:StartEvent')) {
14 | group.entries.push(entryFactory.selectBox({
15 | id : 'spell',
16 | description : 'Apply a black magic spell',
17 | label : 'Spell',
18 | modelProperty : 'spell',
19 | selectOptions: [{
20 | name: 'one',
21 | value: 1
22 | }, {
23 | name: 'two',
24 | value: 2
25 | }, {
26 | name: 'three',
27 | value: 3
28 | }]
29 | }));
30 | }
31 | }
--------------------------------------------------------------------------------
/src/containers/BpmnBoard/style/app.less:
--------------------------------------------------------------------------------
1 | @import "../../../../node_modules/bpmn-js/dist/assets/diagram-js.css";
2 | @import "../../../../node_modules/bpmn-js/dist/assets/bpmn-font/css/bpmn.css";
3 | @import "../../../../node_modules/bpmn-js-properties-panel/styles/properties.less";
4 |
5 | #properties-panel {
6 | position: absolute;
7 | top: 0;
8 | bottom: 0;
9 | right: 0;
10 | width: 260px;
11 | z-index: 10;
12 | border-left: 1px solid #ccc;
13 | overflow: auto;
14 | &:empty {
15 | display: none;
16 | }
17 | > .djs-properties-panel {
18 | padding-bottom: 70px;
19 | min-height:100%;
20 | }
21 | }
22 |
23 | * {
24 | box-sizing: border-box;
25 | }
26 | body,
27 | html {
28 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
29 | font-size: 12px;
30 | color: #444;
31 | height: 100%;
32 | padding: 0;
33 | margin: 0;
34 | }
35 | h1,
36 | h2,
37 | h3,
38 | h4 {
39 | font-weight: normal;
40 | }
41 | h2 {
42 | margin-top: 30px;
43 | margin-bottom: 10px;
44 | }
45 | ul {
46 | padding-left: 30px;
47 | }
48 | #root {
49 | height: 100%;
50 | }
51 | @font-face {
52 | font-family: "app";
53 | src: url("./font/app.eot"),
54 | url("./font/app.woff") format("woff"),
55 | url("./font/app.ttf") format("truetype");
56 | font-weight: normal;
57 | font-style: normal;
58 | }
59 | [class^="icon-"]:before,
60 | [class*=" icon-"]:before {
61 | font-style: normal;
62 | font-weight: normal;
63 | speak: none;
64 | display: inline-block;
65 | text-decoration: inherit;
66 | width: 1em;
67 | text-align: center;
68 | font-variant: normal;
69 | text-transform: none;
70 | line-height: 1em;
71 | }
72 | [class^="icon-"]:before,
73 | [class*=" icon-"]:before {
74 | font-family: "app";
75 | }
76 | .icon-bpmn-io-logo:before {
77 | content: "\e800";
78 | }
79 | .icon-loading:before {
80 | content: "\f415";
81 | }
82 | .icon-picture:before {
83 | content: "\f416";
84 | }
85 | .icon-plus:before {
86 | content: "\f417";
87 | }
88 | .icon-plus-circled:before {
89 | content: "\f418";
90 | }
91 | .icon-minus:before {
92 | content: "\f419";
93 | }
94 | .icon-info:before {
95 | content: "\f41a";
96 | }
97 | .icon-download:before {
98 | content: "\f41b";
99 | }
100 | .icon-undo:before {
101 | content: "\f41c";
102 | }
103 | .icon-redo:before {
104 | content: "\f41d";
105 | }
106 | .icon-open:before {
107 | content: "\f41e";
108 | }
109 | .icon-size-reset:before {
110 | content: "\f41f";
111 | }
112 | .icon-comment:before {
113 | content: "\f420";
114 | }
115 | .icon-keyboard:before {
116 | content: "\f423";
117 | }
118 | .icon-resize-full:before {
119 | content: "\f425";
120 | }
121 | .icon-resize-small:before {
122 | content: "\f426";
123 | }
124 | .animate-spin {
125 | -moz-animation: spin 2s infinite linear;
126 | -o-animation: spin 2s infinite linear;
127 | -webkit-animation: spin 2s infinite linear;
128 | animation: spin 2s infinite linear;
129 | display: inline-block;
130 | }
131 | @-moz-keyframes spin {
132 | 0% {
133 | -moz-transform: rotate(0deg);
134 | -o-transform: rotate(0deg);
135 | -webkit-transform: rotate(0deg);
136 | transform: rotate(0deg);
137 | }
138 | 100% {
139 | -moz-transform: rotate(359deg);
140 | -o-transform: rotate(359deg);
141 | -webkit-transform: rotate(359deg);
142 | transform: rotate(359deg);
143 | }
144 | }
145 | @-webkit-keyframes spin {
146 | 0% {
147 | -moz-transform: rotate(0deg);
148 | -o-transform: rotate(0deg);
149 | -webkit-transform: rotate(0deg);
150 | transform: rotate(0deg);
151 | }
152 | 100% {
153 | -moz-transform: rotate(359deg);
154 | -o-transform: rotate(359deg);
155 | -webkit-transform: rotate(359deg);
156 | transform: rotate(359deg);
157 | }
158 | }
159 | @-o-keyframes spin {
160 | 0% {
161 | -moz-transform: rotate(0deg);
162 | -o-transform: rotate(0deg);
163 | -webkit-transform: rotate(0deg);
164 | transform: rotate(0deg);
165 | }
166 | 100% {
167 | -moz-transform: rotate(359deg);
168 | -o-transform: rotate(359deg);
169 | -webkit-transform: rotate(359deg);
170 | transform: rotate(359deg);
171 | }
172 | }
173 | @-ms-keyframes spin {
174 | 0% {
175 | -moz-transform: rotate(0deg);
176 | -o-transform: rotate(0deg);
177 | -webkit-transform: rotate(0deg);
178 | transform: rotate(0deg);
179 | }
180 | 100% {
181 | -moz-transform: rotate(359deg);
182 | -o-transform: rotate(359deg);
183 | -webkit-transform: rotate(359deg);
184 | transform: rotate(359deg);
185 | }
186 | }
187 | @keyframes spin {
188 | 0% {
189 | -moz-transform: rotate(0deg);
190 | -o-transform: rotate(0deg);
191 | -webkit-transform: rotate(0deg);
192 | transform: rotate(0deg);
193 | }
194 | 100% {
195 | -moz-transform: rotate(359deg);
196 | -o-transform: rotate(359deg);
197 | -webkit-transform: rotate(359deg);
198 | transform: rotate(359deg);
199 | }
200 | }
201 | .project-logo,
202 | .project-logo a {
203 | color: #52b415 !important;
204 | }
205 | .content,
206 | .content > div {
207 | width: 100%;
208 | height: 100%;
209 | overflow: hidden;
210 | }
211 | .content > .screen {
212 | text-align: center;
213 | display: table;
214 | font-size: 16px;
215 | }
216 | .content > .screen .note {
217 | vertical-align: middle;
218 | text-align: center;
219 | display: table-cell;
220 | }
221 | .content .error .details {
222 | max-width: 500px;
223 | font-size: 12px;
224 | margin: 20px auto;
225 | text-align: left;
226 | color: #bd2828;
227 | }
228 | .content .error .error-log {
229 | border: solid 1px #bd2828;
230 | background: #fdf6f6;
231 | color: #bd2828;
232 | }
233 | .content .error .error-log:hover {
234 | background: #fefafa;
235 | }
236 | body:not(.error) .screen.error,
237 | body:not(.intro) .screen.intro,
238 | body:not(.loading) .screen.loading {
239 | display: none;
240 | }
241 | .screen .project-logo {
242 | font-size: 120px;
243 | }
244 | .canvas {
245 | display: block;
246 | }
247 | body.shown .canvas,
248 | body.loaded .canvas {
249 | display: block;
250 | }
251 | body.loaded .canvas svg {
252 | visibility: hidden;
253 | }
254 | body:not(.shown) .io-export,
255 | body:not(.shown) .io-zoom-controls {
256 | display: none;
257 | }
258 | .samples,
259 | .message {
260 | max-width: 700px;
261 | margin: auto;
262 | }
263 | @media (max-width: 720px) {
264 | .samples,
265 | .message {
266 | margin: 20px;
267 | }
268 | .samples {
269 | margin-bottom: 60px;
270 | }
271 | }
272 | .message {
273 | padding: 40px;
274 | font-size: 20px;
275 | }
276 | .samples {
277 | margin-top: 80px;
278 | margin-bottom: 60px;
279 | opacity: 0.4;
280 | transition: ease-in 0.1s;
281 | }
282 | .samples:hover {
283 | opacity: 1;
284 | }
285 | .samples .sample {
286 | display: inline-block;
287 | max-width: 100%;
288 | padding: 10px;
289 | vertical-align: top;
290 | position: relative;
291 | }
292 | .samples .tryit {
293 | position: absolute;
294 | right: 0;
295 | top: 0;
296 | width: auto;
297 | }
298 | .samples .caption {
299 | font-size: 11px;
300 | color: #999;
301 | }
302 | .samples .img {
303 | border-radius: 5px;
304 | box-shadow: inset 0 0 4px #999;
305 | padding: 5px;
306 | width: 100%;
307 | }
308 | .samples .sample > a {
309 | display: block;
310 | }
311 | .bjs-powered-by,
312 | .cjs-powered-by,
313 | .io-control {
314 | background: #fff;
315 | box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
316 | border-radius: 2px;
317 | padding: 5px;
318 | }
319 | .cjs-powered-by,
320 | .bjs-powered-by {
321 | padding-bottom: 2px;
322 | }
323 | .close {
324 | font-size: 21px;
325 | font-weight: 700;
326 | text-shadow: 0 1px 0 #fff;
327 | opacity: 0.2;
328 | line-height: 1;
329 | vertical-align: middle;
330 | margin-left: 5px;
331 | }
332 | .close:hover {
333 | opacity: 1;
334 | }
335 | .vr {
336 | height: 18px;
337 | display: inline-block;
338 | border-right: solid 1px #ccc;
339 | }
340 | a {
341 | color: #740076;
342 | }
343 | a:link {
344 | text-decoration: none;
345 | }
346 | a:hover {
347 | color: #a600a9;
348 | }
349 | .io-control-list {
350 | list-style: none;
351 | padding: 5px;
352 | margin: 0;
353 | }
354 | .io-control-list a,
355 | .io-control-list a:visited,
356 | .io-control-list button {
357 | padding: 0;
358 | outline: none;
359 | cursor: pointer;
360 | font-size: 22px;
361 | line-height: 26px;
362 | color: #555555;
363 | background: none;
364 | border: none;
365 | }
366 | .io-control-list a:hover,
367 | .io-control-list a:visited:hover,
368 | .io-control-list button:hover {
369 | color: #333333;
370 | }
371 | .io-control-list a.inactive,
372 | .io-control-list a:visited.inactive,
373 | .io-control-list button.inactive {
374 | color: #e0e0e0;
375 | cursor: default;
376 | }
377 | .io-control-list.io-horizontal,
378 | .io-control-list.io-horizontal li {
379 | display: inline-block;
380 | }
381 | .io-control-list.io-horizontal a {
382 | padding: 2px;
383 | margin: 0 5px;
384 | }
385 | .io-control-list.io-horizontal button {
386 | margin: 0 5px;
387 | }
388 | .io-control hr {
389 | border: none;
390 | border-top: solid 1px #eee;
391 | }
392 | .io-help,
393 | .io-legal {
394 | position: fixed;
395 | transition: ease-in 0.1s;
396 | }
397 | .io-legal {
398 | right: 100px;
399 | }
400 | .io-help {
401 | right: 20px;
402 | }
403 | body.shown .io-legal {
404 | right: 165px;
405 | }
406 | body.shown .io-help {
407 | right: 85px;
408 | }
409 | .io-legal a {
410 | font-size: 14px;
411 | line-height: 30px;
412 | }
413 | .io-help button:hover,
414 | .io-help a:hover,
415 | .io-legal a:hover {
416 | background: #f0f0f0;
417 | border-radius: 2px;
418 | }
419 | .io-import-export {
420 | position: fixed;
421 | left: 20px;
422 | }
423 | .io-help,
424 | .io-legal,
425 | .io-import-export {
426 | bottom: 25px;
427 | }
428 | .io-import {
429 | margin-right: 10px;
430 | }
431 | .io-zoom-controls {
432 | width: auto;
433 | position: fixed;
434 | right: 15px;
435 | bottom: 90px;
436 | }
437 | .io-editing-tools {
438 | width: auto;
439 | position: fixed;
440 | right: 15px;
441 | top: 20px;
442 | display: none;
443 | }
444 | .io-editing-tools .io-control {
445 | margin-left: 10px;
446 | }
447 | .io-editing-tools .io-control button {
448 | margin: 0;
449 | }
450 | .io-zoom-reset {
451 | margin-bottom: 10px;
452 | }
453 | .io-import-export .inactive {
454 | opacity: 0.3;
455 | }
456 | .import-warnings .error-log {
457 | width: 100%;
458 | }
459 | .hidden {
460 | display: none;
461 | }
462 | .io-alerts {
463 | position: fixed;
464 | top: 20px;
465 | width: 450px;
466 | text-align: center;
467 | left: 50%;
468 | margin-left: -225px;
469 | }
470 | .io-alerts .alert {
471 | display: none;
472 | background: #ffffdb;
473 | padding: 10px 20px;
474 | line-height: 20px;
475 | margin: 0 auto 10px;
476 | }
477 | .io-alerts .alert.open {
478 | display: inline-block;
479 | }
480 | .io-alerts .close {
481 | float: right;
482 | }
483 | .io-toggle-fullscreen {
484 | display: none;
485 | }
486 | .io-toggle-fullscreen.open {
487 | display: inline-block;
488 | }
489 | @media (max-width: 500px) {
490 | .io-alerts {
491 | width: 100%;
492 | text-align: center;
493 | left: 0;
494 | margin: 0;
495 | }
496 | }
497 | .io-dialog {
498 | display: none;
499 | }
500 | .io-dialog.open {
501 | display: block;
502 | }
503 | .io-dialog.open:before {
504 | content: "";
505 | position: fixed;
506 | left: 0;
507 | top: 0;
508 | bottom: 0;
509 | right: 0;
510 | background: #666;
511 | opacity: 0.2;
512 | z-index: 1001;
513 | }
514 | .io-dialog .content {
515 | position: fixed;
516 | width: 600px;
517 | left: 50%;
518 | margin-left: -300px;
519 | top: 100px;
520 | background: white;
521 | padding: 10px 30px 20px 30px;
522 | box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
523 | border-radius: 2px;
524 | height: auto;
525 | z-index: 1001;
526 | }
527 | .io-dialog .project-logo {
528 | position: absolute;
529 | bottom: 27px;
530 | right: 27px;
531 | width: 54px;
532 | height: 54px;
533 | font-size: 48px;
534 | }
535 | .keybindings-dialog .content {
536 | width: 450px;
537 | margin-left: -225px;
538 | }
539 | .keybindings-dialog .binding {
540 | padding: 5px 10px;
541 | font-family: monospace;
542 | }
543 | textarea.error-log {
544 | border: solid 1px #ccc;
545 | background: #f6f6f6;
546 | padding: 10px;
547 | margin: 10px auto;
548 | width: 100%;
549 | min-height: 150px;
550 | display: block;
551 | }
552 | textarea.error-log:hover {
553 | background: #f9f9f9;
554 | }
555 | @media (max-width: 600px) {
556 | .io-dialog .content {
557 | left: 20px;
558 | right: 20px;
559 | top: 20px;
560 | width: auto;
561 | margin: 0;
562 | }
563 | }
564 | :full-screen .icon-resize:before {
565 | content: "\e86e";
566 | }
567 | :-moz-full-screen .icon-resize:before {
568 | content: "\e86e";
569 | }
570 | :-ms-full-screen .icon-resize:before {
571 | content: "\e86e";
572 | }
573 | :-webkit-full-screen .icon-resize:before {
574 | content: "\e86e";
575 | }
576 | .icon-resize:before {
577 | content: "\e86d";
578 | }
579 | .icon-resize:before {
580 | content: "\e86d";
581 | }
582 | .icon-resize:before {
583 | content: "\e86d";
584 | }
585 | .icon-resize:before {
586 | content: "\e86d";
587 | }
588 |
589 | .icon-save {
590 | display: inline-block;
591 | width: 22px;
592 | height: 20px;
593 | background-image: url('./image/save.png');
594 | background-repeat: no-repeat;
595 | background-size: 94%;
596 | background-position-y: 2px;
597 |
598 | &:hover {
599 | background-image: url('./image/save-active.png');
600 | }
601 | }
602 |
--------------------------------------------------------------------------------
/src/containers/BpmnBoard/style/font/app.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nodejs-viathink/react-bpmn/32275a1466a368b9f7d78f11fa20de57adf19741/src/containers/BpmnBoard/style/font/app.eot
--------------------------------------------------------------------------------
/src/containers/BpmnBoard/style/font/app.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nodejs-viathink/react-bpmn/32275a1466a368b9f7d78f11fa20de57adf19741/src/containers/BpmnBoard/style/font/app.ttf
--------------------------------------------------------------------------------
/src/containers/BpmnBoard/style/font/app.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nodejs-viathink/react-bpmn/32275a1466a368b9f7d78f11fa20de57adf19741/src/containers/BpmnBoard/style/font/app.woff
--------------------------------------------------------------------------------
/src/containers/BpmnBoard/style/image/save-active.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nodejs-viathink/react-bpmn/32275a1466a368b9f7d78f11fa20de57adf19741/src/containers/BpmnBoard/style/image/save-active.png
--------------------------------------------------------------------------------
/src/containers/BpmnBoard/style/image/save.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nodejs-viathink/react-bpmn/32275a1466a368b9f7d78f11fa20de57adf19741/src/containers/BpmnBoard/style/image/save.png
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nodejs-viathink/react-bpmn/32275a1466a368b9f7d78f11fa20de57adf19741/src/index.css
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import './index.css';
4 | import App from './App';
5 | import registerServiceWorker from './registerServiceWorker';
6 |
7 | ReactDOM.render( , document.getElementById('root'));
8 | registerServiceWorker();
9 |
--------------------------------------------------------------------------------
/src/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/registerServiceWorker.js:
--------------------------------------------------------------------------------
1 | // In production, we register a service worker to serve assets from local cache.
2 |
3 | // This lets the app load faster on subsequent visits in production, and gives
4 | // it offline capabilities. However, it also means that developers (and users)
5 | // will only see deployed updates on the "N+1" visit to a page, since previously
6 | // cached resources are updated in the background.
7 |
8 | // To learn more about the benefits of this model, read https://goo.gl/KwvDNy.
9 | // This link also includes instructions on opting out of this behavior.
10 |
11 | const isLocalhost = Boolean(
12 | window.location.hostname === 'localhost' ||
13 | // [::1] is the IPv6 localhost address.
14 | window.location.hostname === '[::1]' ||
15 | // 127.0.0.1/8 is considered localhost for IPv4.
16 | window.location.hostname.match(
17 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
18 | )
19 | );
20 |
21 | export default function register() {
22 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
23 | // The URL constructor is available in all browsers that support SW.
24 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location);
25 | if (publicUrl.origin !== window.location.origin) {
26 | // Our service worker won't work if PUBLIC_URL is on a different origin
27 | // from what our page is served on. This might happen if a CDN is used to
28 | // serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374
29 | return;
30 | }
31 |
32 | window.addEventListener('load', () => {
33 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
34 |
35 | if (isLocalhost) {
36 | // This is running on localhost. Lets check if a service worker still exists or not.
37 | checkValidServiceWorker(swUrl);
38 |
39 | // Add some additional logging to localhost, pointing developers to the
40 | // service worker/PWA documentation.
41 | navigator.serviceWorker.ready.then(() => {
42 | console.log(
43 | 'This web app is being served cache-first by a service ' +
44 | 'worker. To learn more, visit https://goo.gl/SC7cgQ'
45 | );
46 | });
47 | } else {
48 | // Is not local host. Just register service worker
49 | registerValidSW(swUrl);
50 | }
51 | });
52 | }
53 | }
54 |
55 | function registerValidSW(swUrl) {
56 | navigator.serviceWorker
57 | .register(swUrl)
58 | .then(registration => {
59 | registration.onupdatefound = () => {
60 | const installingWorker = registration.installing;
61 | installingWorker.onstatechange = () => {
62 | if (installingWorker.state === 'installed') {
63 | if (navigator.serviceWorker.controller) {
64 | // At this point, the old content will have been purged and
65 | // the fresh content will have been added to the cache.
66 | // It's the perfect time to display a "New content is
67 | // available; please refresh." message in your web app.
68 | console.log('New content is available; please refresh.');
69 | } else {
70 | // At this point, everything has been precached.
71 | // It's the perfect time to display a
72 | // "Content is cached for offline use." message.
73 | console.log('Content is cached for offline use.');
74 | }
75 | }
76 | };
77 | };
78 | })
79 | .catch(error => {
80 | console.error('Error during service worker registration:', error);
81 | });
82 | }
83 |
84 | function checkValidServiceWorker(swUrl) {
85 | // Check if the service worker can be found. If it can't reload the page.
86 | fetch(swUrl)
87 | .then(response => {
88 | // Ensure service worker exists, and that we really are getting a JS file.
89 | if (
90 | response.status === 404 ||
91 | response.headers.get('content-type').indexOf('javascript') === -1
92 | ) {
93 | // No service worker found. Probably a different app. Reload the page.
94 | navigator.serviceWorker.ready.then(registration => {
95 | registration.unregister().then(() => {
96 | window.location.reload();
97 | });
98 | });
99 | } else {
100 | // Service worker found. Proceed as normal.
101 | registerValidSW(swUrl);
102 | }
103 | })
104 | .catch(() => {
105 | console.log(
106 | 'No internet connection found. App is running in offline mode.'
107 | );
108 | });
109 | }
110 |
111 | export function unregister() {
112 | if ('serviceWorker' in navigator) {
113 | navigator.serviceWorker.ready.then(registration => {
114 | registration.unregister();
115 | });
116 | }
117 | }
118 |
--------------------------------------------------------------------------------