feat(modeling): add subprocess with start event included
When: 1. Creating expanded subprocess from palette. 2. Replacing task with expanded subprocess.
This commit is contained in:
parent
9e5a5f4944
commit
3a0f044d9e
|
@ -0,0 +1,69 @@
|
||||||
|
import inherits from 'inherits';
|
||||||
|
|
||||||
|
import CommandInterceptor from 'diagram-js/lib/command/CommandInterceptor';
|
||||||
|
|
||||||
|
import { is } from '../../../util/ModelUtil';
|
||||||
|
import { isExpanded } from '../../../util/DiUtil.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add start event child by default when creating an expanded subprocess
|
||||||
|
* with create.start or replacing a task with an expanded subprocess.
|
||||||
|
*/
|
||||||
|
export default function SubProcessStartEventBehavior(eventBus, modeling) {
|
||||||
|
CommandInterceptor.call(this, eventBus);
|
||||||
|
|
||||||
|
eventBus.on('create.start', function(event) {
|
||||||
|
var shape = event.context.shape,
|
||||||
|
hints = event.context.hints;
|
||||||
|
|
||||||
|
hints.shouldAddStartEvent = is(shape, 'bpmn:SubProcess') && isExpanded(shape);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.postExecuted('shape.create', function(event) {
|
||||||
|
var shape = event.context.shape,
|
||||||
|
hints = event.context.hints,
|
||||||
|
position;
|
||||||
|
|
||||||
|
if (!hints.shouldAddStartEvent) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
position = calculatePositionRelativeToShape(shape);
|
||||||
|
|
||||||
|
modeling.createShape({ type: 'bpmn:StartEvent' }, position, shape);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.postExecuted('shape.replace', function(event) {
|
||||||
|
var oldShape = event.context.oldShape,
|
||||||
|
newShape = event.context.newShape,
|
||||||
|
position;
|
||||||
|
|
||||||
|
if (
|
||||||
|
!is(newShape, 'bpmn:SubProcess') ||
|
||||||
|
!is(oldShape, 'bpmn:Task') ||
|
||||||
|
!isExpanded(newShape)
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
position = calculatePositionRelativeToShape(newShape);
|
||||||
|
|
||||||
|
modeling.createShape({ type: 'bpmn:StartEvent' }, position, newShape);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
SubProcessStartEventBehavior.$inject = [
|
||||||
|
'eventBus',
|
||||||
|
'modeling'
|
||||||
|
];
|
||||||
|
|
||||||
|
inherits(SubProcessStartEventBehavior, CommandInterceptor);
|
||||||
|
|
||||||
|
// helpers //////////
|
||||||
|
|
||||||
|
function calculatePositionRelativeToShape(shape) {
|
||||||
|
return {
|
||||||
|
x: shape.x + shape.width / 6,
|
||||||
|
y: shape.y + shape.height / 2
|
||||||
|
};
|
||||||
|
}
|
|
@ -20,6 +20,7 @@ import RemoveParticipantBehavior from './RemoveParticipantBehavior';
|
||||||
import ReplaceElementBehaviour from './ReplaceElementBehaviour';
|
import ReplaceElementBehaviour from './ReplaceElementBehaviour';
|
||||||
import ResizeLaneBehavior from './ResizeLaneBehavior';
|
import ResizeLaneBehavior from './ResizeLaneBehavior';
|
||||||
import RemoveElementBehavior from './RemoveElementBehavior';
|
import RemoveElementBehavior from './RemoveElementBehavior';
|
||||||
|
import SubProcessStartEventBehavior from './SubProcessStartEventBehavior';
|
||||||
import ToggleElementCollapseBehaviour from './ToggleElementCollapseBehaviour';
|
import ToggleElementCollapseBehaviour from './ToggleElementCollapseBehaviour';
|
||||||
import UnclaimIdBehavior from './UnclaimIdBehavior';
|
import UnclaimIdBehavior from './UnclaimIdBehavior';
|
||||||
import UpdateFlowNodeRefsBehavior from './UpdateFlowNodeRefsBehavior';
|
import UpdateFlowNodeRefsBehavior from './UpdateFlowNodeRefsBehavior';
|
||||||
|
@ -50,6 +51,7 @@ export default {
|
||||||
'replaceElementBehaviour',
|
'replaceElementBehaviour',
|
||||||
'resizeLaneBehavior',
|
'resizeLaneBehavior',
|
||||||
'toggleElementCollapseBehaviour',
|
'toggleElementCollapseBehaviour',
|
||||||
|
'subProcessStartEventBehavior',
|
||||||
'unclaimIdBehavior',
|
'unclaimIdBehavior',
|
||||||
'unsetDefaultFlowBehavior',
|
'unsetDefaultFlowBehavior',
|
||||||
'updateFlowNodeRefsBehavior'
|
'updateFlowNodeRefsBehavior'
|
||||||
|
@ -77,6 +79,7 @@ export default {
|
||||||
resizeLaneBehavior: [ 'type', ResizeLaneBehavior ],
|
resizeLaneBehavior: [ 'type', ResizeLaneBehavior ],
|
||||||
removeElementBehavior: [ 'type', RemoveElementBehavior ],
|
removeElementBehavior: [ 'type', RemoveElementBehavior ],
|
||||||
toggleElementCollapseBehaviour : [ 'type', ToggleElementCollapseBehaviour ],
|
toggleElementCollapseBehaviour : [ 'type', ToggleElementCollapseBehaviour ],
|
||||||
|
subProcessStartEventBehavior: [ 'type', SubProcessStartEventBehavior ],
|
||||||
unclaimIdBehavior: [ 'type', UnclaimIdBehavior ],
|
unclaimIdBehavior: [ 'type', UnclaimIdBehavior ],
|
||||||
updateFlowNodeRefsBehavior: [ 'type', UpdateFlowNodeRefsBehavior ],
|
updateFlowNodeRefsBehavior: [ 'type', UpdateFlowNodeRefsBehavior ],
|
||||||
unsetDefaultFlowBehavior: [ 'type', UnsetDefaultFlowBehavior ]
|
unsetDefaultFlowBehavior: [ 'type', UnsetDefaultFlowBehavior ]
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" id="Definitions_007va6i" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="3.2.0-dev">
|
||||||
|
<bpmn:process id="Process_1giw3j5" isExecutable="true">
|
||||||
|
<bpmn:task id="Task_1" />
|
||||||
|
<bpmn:subProcess id="SubProcess_1" />
|
||||||
|
</bpmn:process>
|
||||||
|
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||||
|
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1giw3j5">
|
||||||
|
<bpmndi:BPMNShape id="Task_07xra8r_di" bpmnElement="Task_1">
|
||||||
|
<dc:Bounds x="156" y="81" width="100" height="80" />
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape id="SubProcess_01nq2r1_di" bpmnElement="SubProcess_1" isExpanded="true">
|
||||||
|
<dc:Bounds x="160" y="280" width="350" height="200" />
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
</bpmndi:BPMNPlane>
|
||||||
|
</bpmndi:BPMNDiagram>
|
||||||
|
</bpmn:definitions>
|
|
@ -0,0 +1,127 @@
|
||||||
|
import {
|
||||||
|
bootstrapModeler,
|
||||||
|
inject
|
||||||
|
} from 'test/TestHelper';
|
||||||
|
|
||||||
|
import coreModule from 'lib/core';
|
||||||
|
import createModule from 'diagram-js/lib/features/create';
|
||||||
|
import draggingModule from 'diagram-js/lib/features/create';
|
||||||
|
import modelingModule from 'lib/features/modeling';
|
||||||
|
import replaceModule from 'lib/features/replace';
|
||||||
|
|
||||||
|
import { is } from 'lib/util/ModelUtil';
|
||||||
|
import { createCanvasEvent as canvasEvent } from 'test/util/MockEvents';
|
||||||
|
|
||||||
|
describe('features/modeling/behavior - subprocess start event', function() {
|
||||||
|
|
||||||
|
var diagramXML = require('./SubProcessBehavior.start-event.bpmn');
|
||||||
|
|
||||||
|
beforeEach(bootstrapModeler(diagramXML, {
|
||||||
|
modules: [
|
||||||
|
coreModule,
|
||||||
|
createModule,
|
||||||
|
draggingModule,
|
||||||
|
modelingModule,
|
||||||
|
replaceModule
|
||||||
|
]
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
describe('create', function() {
|
||||||
|
|
||||||
|
it('should contain start event child', inject(
|
||||||
|
function(canvas, elementFactory, create, dragging) {
|
||||||
|
|
||||||
|
// given
|
||||||
|
var rootElement = canvas.getRootElement(),
|
||||||
|
subProcess = elementFactory.createShape({
|
||||||
|
type: 'bpmn:SubProcess',
|
||||||
|
isExpanded: true
|
||||||
|
}),
|
||||||
|
startEvents;
|
||||||
|
|
||||||
|
// when
|
||||||
|
create.start(canvasEvent({ x: 0, y: 0 }), subProcess);
|
||||||
|
|
||||||
|
dragging.hover({ element: rootElement });
|
||||||
|
|
||||||
|
dragging.move(canvasEvent({ x: 600, y: 150 }));
|
||||||
|
|
||||||
|
dragging.end();
|
||||||
|
|
||||||
|
// then
|
||||||
|
startEvents = getChildStartEvents(subProcess);
|
||||||
|
|
||||||
|
expect(startEvents).to.have.length(1);
|
||||||
|
}
|
||||||
|
));
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
describe('replace', function() {
|
||||||
|
|
||||||
|
describe('task -> expanded subprocess', function() {
|
||||||
|
|
||||||
|
it('should add start event child to subprocess', inject(
|
||||||
|
function(elementRegistry, bpmnReplace) {
|
||||||
|
|
||||||
|
// given
|
||||||
|
var task = elementRegistry.get('Task_1'),
|
||||||
|
expandedSubProcess,
|
||||||
|
startEvents;
|
||||||
|
|
||||||
|
// when
|
||||||
|
expandedSubProcess = bpmnReplace.replaceElement(task, {
|
||||||
|
type: 'bpmn:SubProcess',
|
||||||
|
isExpanded: true
|
||||||
|
});
|
||||||
|
|
||||||
|
// then
|
||||||
|
startEvents = getChildStartEvents(expandedSubProcess);
|
||||||
|
|
||||||
|
expect(startEvents).to.have.length(1);
|
||||||
|
}
|
||||||
|
));
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
describe('task -> collapsed subprocess', function() {
|
||||||
|
|
||||||
|
it('should NOT add start event child to subprocess', inject(
|
||||||
|
function(elementRegistry, bpmnReplace) {
|
||||||
|
|
||||||
|
// given
|
||||||
|
var task = elementRegistry.get('Task_1'),
|
||||||
|
collapsedSubProcess,
|
||||||
|
startEvents;
|
||||||
|
|
||||||
|
// when
|
||||||
|
collapsedSubProcess = bpmnReplace.replaceElement(task, {
|
||||||
|
type: 'bpmn:SubProcess',
|
||||||
|
isExpanded: false
|
||||||
|
});
|
||||||
|
|
||||||
|
// then
|
||||||
|
startEvents = getChildStartEvents(collapsedSubProcess);
|
||||||
|
|
||||||
|
expect(startEvents).to.have.length(0);
|
||||||
|
}
|
||||||
|
));
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
// helpers //////////
|
||||||
|
|
||||||
|
function isStartEvent(element) {
|
||||||
|
return is(element, 'bpmn:StartEvent');
|
||||||
|
}
|
||||||
|
|
||||||
|
function getChildStartEvents(element) {
|
||||||
|
return element.children.filter(isStartEvent);
|
||||||
|
}
|
Loading…
Reference in New Issue