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 ResizeLaneBehavior from './ResizeLaneBehavior';
|
||||
import RemoveElementBehavior from './RemoveElementBehavior';
|
||||
import SubProcessStartEventBehavior from './SubProcessStartEventBehavior';
|
||||
import ToggleElementCollapseBehaviour from './ToggleElementCollapseBehaviour';
|
||||
import UnclaimIdBehavior from './UnclaimIdBehavior';
|
||||
import UpdateFlowNodeRefsBehavior from './UpdateFlowNodeRefsBehavior';
|
||||
|
@ -50,6 +51,7 @@ export default {
|
|||
'replaceElementBehaviour',
|
||||
'resizeLaneBehavior',
|
||||
'toggleElementCollapseBehaviour',
|
||||
'subProcessStartEventBehavior',
|
||||
'unclaimIdBehavior',
|
||||
'unsetDefaultFlowBehavior',
|
||||
'updateFlowNodeRefsBehavior'
|
||||
|
@ -77,6 +79,7 @@ export default {
|
|||
resizeLaneBehavior: [ 'type', ResizeLaneBehavior ],
|
||||
removeElementBehavior: [ 'type', RemoveElementBehavior ],
|
||||
toggleElementCollapseBehaviour : [ 'type', ToggleElementCollapseBehaviour ],
|
||||
subProcessStartEventBehavior: [ 'type', SubProcessStartEventBehavior ],
|
||||
unclaimIdBehavior: [ 'type', UnclaimIdBehavior ],
|
||||
updateFlowNodeRefsBehavior: [ 'type', UpdateFlowNodeRefsBehavior ],
|
||||
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