chore(replace): separate popup menu from replace logic
This commit makes use of the provider concept introduced in diagram-js. The replace menu entries are now created in the replace menu provider. This separates BpmnReplace from the entry creation in the popup menu. Closes #428
This commit is contained in:
parent
93d4bade22
commit
eb7b5d7bb4
|
@ -14,7 +14,7 @@ var assign = require('lodash/object/assign'),
|
||||||
* A provider for BPMN 2.0 elements context pad
|
* A provider for BPMN 2.0 elements context pad
|
||||||
*/
|
*/
|
||||||
function ContextPadProvider(contextPad, modeling, elementFactory,
|
function ContextPadProvider(contextPad, modeling, elementFactory,
|
||||||
connect, create, bpmnReplace,
|
connect, create, popupMenu,
|
||||||
canvas, rules) {
|
canvas, rules) {
|
||||||
|
|
||||||
contextPad.registerProvider(this);
|
contextPad.registerProvider(this);
|
||||||
|
@ -26,7 +26,7 @@ function ContextPadProvider(contextPad, modeling, elementFactory,
|
||||||
this._elementFactory = elementFactory;
|
this._elementFactory = elementFactory;
|
||||||
this._connect = connect;
|
this._connect = connect;
|
||||||
this._create = create;
|
this._create = create;
|
||||||
this._bpmnReplace = bpmnReplace;
|
this._popupMenu = popupMenu;
|
||||||
this._canvas = canvas;
|
this._canvas = canvas;
|
||||||
this._rules = rules;
|
this._rules = rules;
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ ContextPadProvider.$inject = [
|
||||||
'elementFactory',
|
'elementFactory',
|
||||||
'connect',
|
'connect',
|
||||||
'create',
|
'create',
|
||||||
'bpmnReplace',
|
'popupMenu',
|
||||||
'canvas',
|
'canvas',
|
||||||
'rules'
|
'rules'
|
||||||
];
|
];
|
||||||
|
@ -53,7 +53,7 @@ ContextPadProvider.prototype.getContextPadEntries = function(element) {
|
||||||
elementFactory = this._elementFactory,
|
elementFactory = this._elementFactory,
|
||||||
connect = this._connect,
|
connect = this._connect,
|
||||||
create = this._create,
|
create = this._create,
|
||||||
bpmnReplace = this._bpmnReplace,
|
popupMenu = this._popupMenu,
|
||||||
canvas = this._canvas,
|
canvas = this._canvas,
|
||||||
rules = this._rules;
|
rules = this._rules;
|
||||||
|
|
||||||
|
@ -225,9 +225,14 @@ ContextPadProvider.prototype.getContextPadEntries = function(element) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var replaceOptions = bpmnReplace.getReplaceOptions(element);
|
var replaceMenu;
|
||||||
|
|
||||||
|
if (popupMenu._providers['bpmn-replace']) {
|
||||||
|
replaceMenu = popupMenu.create('bpmn-replace', element);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (replaceMenu && !replaceMenu.isEmpty()) {
|
||||||
|
|
||||||
if (replaceOptions.length) {
|
|
||||||
// Replace menu entry
|
// Replace menu entry
|
||||||
assign(actions, {
|
assign(actions, {
|
||||||
'replace': {
|
'replace': {
|
||||||
|
@ -236,7 +241,7 @@ ContextPadProvider.prototype.getContextPadEntries = function(element) {
|
||||||
title: 'Change type',
|
title: 'Change type',
|
||||||
action: {
|
action: {
|
||||||
click: function(event, element) {
|
click: function(event, element) {
|
||||||
bpmnReplace.openChooser(getReplaceMenuPosition(element), element);
|
replaceMenu.open(getReplaceMenuPosition(element));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ module.exports = {
|
||||||
require('diagram-js/lib/features/selection'),
|
require('diagram-js/lib/features/selection'),
|
||||||
require('diagram-js/lib/features/connect'),
|
require('diagram-js/lib/features/connect'),
|
||||||
require('diagram-js/lib/features/create'),
|
require('diagram-js/lib/features/create'),
|
||||||
require('../replace')
|
require('../popup-menu')
|
||||||
],
|
],
|
||||||
__init__: [ 'contextPadProvider' ],
|
__init__: [ 'contextPadProvider' ],
|
||||||
contextPadProvider: [ 'type', require('./ContextPadProvider') ]
|
contextPadProvider: [ 'type', require('./ContextPadProvider') ]
|
||||||
|
|
|
@ -0,0 +1,452 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var is = require('../../util/ModelUtil').is,
|
||||||
|
isEventSubProcess = require('../../util/DiUtil').isEventSubProcess,
|
||||||
|
getBusinessObject = require('../../util/ModelUtil').getBusinessObject,
|
||||||
|
isExpanded = require('../../util/DiUtil').isExpanded,
|
||||||
|
isDifferentType = require('./util/TypeUtil').isDifferentType;
|
||||||
|
|
||||||
|
var forEach = require('lodash/collection/forEach'),
|
||||||
|
filter = require('lodash/collection/filter');
|
||||||
|
|
||||||
|
var replaceOptions = require ('../replace/ReplaceOptions');
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This module is an element agnostic replace menu provider for the popup menu.
|
||||||
|
*/
|
||||||
|
function ReplaceMenuProvider(popupMenu, modeling, moddle, bpmnReplace, rules) {
|
||||||
|
|
||||||
|
this._popupMenu = popupMenu;
|
||||||
|
this._modeling = modeling;
|
||||||
|
this._moddle = moddle;
|
||||||
|
this._bpmnReplace = bpmnReplace;
|
||||||
|
this._rules = rules;
|
||||||
|
|
||||||
|
this.register();
|
||||||
|
}
|
||||||
|
|
||||||
|
ReplaceMenuProvider.$inject = [ 'popupMenu', 'modeling', 'moddle', 'bpmnReplace', 'rules' ];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register replace menu provider in the popup menu
|
||||||
|
*/
|
||||||
|
ReplaceMenuProvider.prototype.register = function() {
|
||||||
|
this._popupMenu.registerProvider('bpmn-replace', this);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all entries from replaceOptions for the given element and apply filters
|
||||||
|
* on them. Get for example only elements, which are different from the current one.
|
||||||
|
*
|
||||||
|
* @param {djs.model.Base} element
|
||||||
|
*
|
||||||
|
* @return {Array<Object>} a list of menu entry items
|
||||||
|
*/
|
||||||
|
ReplaceMenuProvider.prototype.getEntries = function(element) {
|
||||||
|
|
||||||
|
var businessObject = element.businessObject;
|
||||||
|
|
||||||
|
var rules = this._rules;
|
||||||
|
|
||||||
|
var entries;
|
||||||
|
|
||||||
|
if (!rules.allowed('shape.replace', { element: element })) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
var differentType = isDifferentType(element);
|
||||||
|
|
||||||
|
// start events outside event sub processes
|
||||||
|
if (is(businessObject, 'bpmn:StartEvent') && !isEventSubProcess(businessObject.$parent)) {
|
||||||
|
|
||||||
|
entries = filter(replaceOptions.START_EVENT, differentType);
|
||||||
|
|
||||||
|
return this._createEntries(element, entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
// start events inside event sub processes
|
||||||
|
if (is(businessObject, 'bpmn:StartEvent') && isEventSubProcess(businessObject.$parent)) {
|
||||||
|
|
||||||
|
entries = filter(replaceOptions.EVENT_SUB_PROCESS_START_EVENT, function(entry) {
|
||||||
|
|
||||||
|
var target = entry.target;
|
||||||
|
|
||||||
|
var isInterrupting = target.isInterrupting !== false;
|
||||||
|
|
||||||
|
var isInterruptingEqual = getBusinessObject(element).isInterrupting === isInterrupting;
|
||||||
|
|
||||||
|
// filters elements which types and event definition are equal but have have different interrupting types
|
||||||
|
return differentType(entry) || !differentType(entry) && !isInterruptingEqual;
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
return this._createEntries(element, entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
// end events
|
||||||
|
if (is(businessObject, 'bpmn:EndEvent')) {
|
||||||
|
|
||||||
|
entries = filter(replaceOptions.END_EVENT, function(entry) {
|
||||||
|
var target = entry.target;
|
||||||
|
|
||||||
|
// hide cancel end events outside transactions
|
||||||
|
if (target.eventDefinition == 'bpmn:CancelEventDefinition' && !is(businessObject.$parent, 'bpmn:Transaction')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return differentType(entry);
|
||||||
|
});
|
||||||
|
|
||||||
|
return this._createEntries(element, entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
// boundary events
|
||||||
|
if (is(businessObject, 'bpmn:BoundaryEvent')) {
|
||||||
|
|
||||||
|
entries = filter(replaceOptions.BOUNDARY_EVENT, function(entry) {
|
||||||
|
|
||||||
|
var target = entry.target;
|
||||||
|
|
||||||
|
if (target.eventDefinition == 'bpmn:CancelEventDefinition' &&
|
||||||
|
!is(businessObject.attachedToRef, 'bpmn:Transaction')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var cancelActivity = target.cancelActivity !== false;
|
||||||
|
|
||||||
|
var isCancelActivityEqual = businessObject.cancelActivity == cancelActivity;
|
||||||
|
|
||||||
|
return differentType(entry) || !differentType(entry) && !isCancelActivityEqual;
|
||||||
|
});
|
||||||
|
|
||||||
|
return this._createEntries(element, entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
// intermediate events
|
||||||
|
if (is(businessObject, 'bpmn:IntermediateCatchEvent') ||
|
||||||
|
is(businessObject, 'bpmn:IntermediateThrowEvent')) {
|
||||||
|
|
||||||
|
entries = filter(replaceOptions.INTERMEDIATE_EVENT, differentType);
|
||||||
|
|
||||||
|
return this._createEntries(element, entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
// gateways
|
||||||
|
if (is(businessObject, 'bpmn:Gateway')) {
|
||||||
|
|
||||||
|
entries = filter(replaceOptions.GATEWAY, differentType);
|
||||||
|
|
||||||
|
return this._createEntries(element, entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
// transactions
|
||||||
|
if (is(businessObject, 'bpmn:Transaction')) {
|
||||||
|
|
||||||
|
entries = filter(replaceOptions.TRANSACTION, differentType);
|
||||||
|
|
||||||
|
return this._createEntries(element, entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
// expanded event sub processes
|
||||||
|
if (isEventSubProcess(businessObject) && isExpanded(businessObject)) {
|
||||||
|
|
||||||
|
entries = filter(replaceOptions.EVENT_SUB_PROCESS, differentType);
|
||||||
|
|
||||||
|
return this._createEntries(element, entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
// expanded sub processes
|
||||||
|
if (is(businessObject, 'bpmn:SubProcess') && isExpanded(businessObject)) {
|
||||||
|
|
||||||
|
entries = filter(replaceOptions.SUBPROCESS_EXPANDED, differentType);
|
||||||
|
|
||||||
|
return this._createEntries(element, entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
// collapsed ad hoc sub processes
|
||||||
|
if (is(businessObject, 'bpmn:AdHocSubProcess') && !isExpanded(businessObject)) {
|
||||||
|
|
||||||
|
entries = filter(replaceOptions.TASK, function(entry) {
|
||||||
|
|
||||||
|
var target = entry.target;
|
||||||
|
|
||||||
|
var isTargetSubProcess = target.type === 'bpmn:SubProcess';
|
||||||
|
|
||||||
|
return isDifferentType(element, target) && !isTargetSubProcess;
|
||||||
|
});
|
||||||
|
|
||||||
|
return this._createEntries(element, entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
// sequence flows
|
||||||
|
if (is(businessObject, 'bpmn:SequenceFlow')) {
|
||||||
|
return this._createSequenceFlowEntries(element, replaceOptions.SEQUENCE_FLOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
// flow nodes
|
||||||
|
if (is(businessObject, 'bpmn:FlowNode')) {
|
||||||
|
entries = filter(replaceOptions.TASK, differentType);
|
||||||
|
|
||||||
|
return this._createEntries(element, entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a list of header items for the given element. This includes buttons
|
||||||
|
* for multi instance markers and for the ad hoc marker.
|
||||||
|
*
|
||||||
|
* @param {djs.model.Base} element
|
||||||
|
*
|
||||||
|
* @return {Array<Object>} a list of menu entry items
|
||||||
|
*/
|
||||||
|
ReplaceMenuProvider.prototype.getHeaderEntries = function(element) {
|
||||||
|
|
||||||
|
var headerEntries = [];
|
||||||
|
|
||||||
|
if (is(element, 'bpmn:Activity') && !isEventSubProcess(element)) {
|
||||||
|
headerEntries = headerEntries.concat(this._getLoopEntries(element));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is(element, 'bpmn:SubProcess') &&
|
||||||
|
!is(element, 'bpmn:Transaction') &&
|
||||||
|
!isEventSubProcess(element)) {
|
||||||
|
headerEntries.push(this._getAdHocEntry(element));
|
||||||
|
}
|
||||||
|
|
||||||
|
return headerEntries;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an array of menu entry objects for a given element and filters the replaceOptions
|
||||||
|
* according to a filter function.
|
||||||
|
*
|
||||||
|
* @param {djs.model.Base} element
|
||||||
|
* @param {Object} replaceOptions
|
||||||
|
*
|
||||||
|
* @return {Array<Object>} a list of menu items
|
||||||
|
*/
|
||||||
|
ReplaceMenuProvider.prototype._createEntries = function(element, replaceOptions) {
|
||||||
|
var menuEntries = [];
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
forEach(replaceOptions, function(definition) {
|
||||||
|
var entry = self._createMenuEntry(definition, element);
|
||||||
|
|
||||||
|
menuEntries.push(entry);
|
||||||
|
});
|
||||||
|
|
||||||
|
return menuEntries;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an array of menu entry objects for a given sequence flow.
|
||||||
|
*
|
||||||
|
* @param {djs.model.Base} element
|
||||||
|
* @param {Object} replaceOptions
|
||||||
|
|
||||||
|
* @return {Array<Object>} a list of menu items
|
||||||
|
*/
|
||||||
|
ReplaceMenuProvider.prototype._createSequenceFlowEntries = function (element, replaceOptions) {
|
||||||
|
|
||||||
|
var businessObject = getBusinessObject(element);
|
||||||
|
|
||||||
|
var menuEntries = [];
|
||||||
|
|
||||||
|
var modeling = this._modeling,
|
||||||
|
moddle = this._moddle;
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
forEach(replaceOptions, function(entry) {
|
||||||
|
|
||||||
|
switch (entry.actionName) {
|
||||||
|
case 'replace-with-default-flow':
|
||||||
|
if (businessObject.sourceRef.default !== businessObject &&
|
||||||
|
(is(businessObject.sourceRef, 'bpmn:ExclusiveGateway') ||
|
||||||
|
is(businessObject.sourceRef, 'bpmn:InclusiveGateway'))) {
|
||||||
|
|
||||||
|
menuEntries.push(self._createMenuEntry(entry, element, function() {
|
||||||
|
modeling.updateProperties(element.source, { default: businessObject });
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'replace-with-conditional-flow':
|
||||||
|
if (!businessObject.conditionExpression && is(businessObject.sourceRef, 'bpmn:Activity')) {
|
||||||
|
|
||||||
|
menuEntries.push(self._createMenuEntry(entry, element, function() {
|
||||||
|
var conditionExpression = moddle.create('bpmn:FormalExpression', { body: '' });
|
||||||
|
|
||||||
|
modeling.updateProperties(element, { conditionExpression: conditionExpression });
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// default flows
|
||||||
|
if (is(businessObject.sourceRef, 'bpmn:Activity') && businessObject.conditionExpression) {
|
||||||
|
return menuEntries.push(self._createMenuEntry(entry, element, function() {
|
||||||
|
modeling.updateProperties(element, { conditionExpression: undefined });
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
// conditional flows
|
||||||
|
if ((is(businessObject.sourceRef, 'bpmn:ExclusiveGateway') ||
|
||||||
|
is(businessObject.sourceRef, 'bpmn:InclusiveGateway')) &&
|
||||||
|
businessObject.sourceRef.default === businessObject) {
|
||||||
|
|
||||||
|
return menuEntries.push(self._createMenuEntry(entry, element, function() {
|
||||||
|
modeling.updateProperties(element.source, { default: undefined });
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return menuEntries;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates and returns a single menu entry item.
|
||||||
|
*
|
||||||
|
* @param {Object} definition a single replace options definition object
|
||||||
|
* @param {djs.model.Base} element
|
||||||
|
* @param {Function} [action] an action callback function which gets called when
|
||||||
|
* the menu entry is being triggered.
|
||||||
|
*
|
||||||
|
* @return {Object} menu entry item
|
||||||
|
*/
|
||||||
|
ReplaceMenuProvider.prototype._createMenuEntry = function(definition, element, action) {
|
||||||
|
|
||||||
|
var replaceElement = this._bpmnReplace.replaceElement;
|
||||||
|
|
||||||
|
var replaceAction = function() {
|
||||||
|
return replaceElement(element, definition.target);
|
||||||
|
};
|
||||||
|
|
||||||
|
action = action || replaceAction;
|
||||||
|
|
||||||
|
var menuEntry = {
|
||||||
|
label: definition.label,
|
||||||
|
className: definition.className,
|
||||||
|
id: definition.actionName,
|
||||||
|
action: action
|
||||||
|
};
|
||||||
|
|
||||||
|
return menuEntry;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a list of menu items containing buttons for multi instance markers
|
||||||
|
*
|
||||||
|
* @param {djs.model.Base} element
|
||||||
|
*
|
||||||
|
* @return {Array<Object>} a list of menu items
|
||||||
|
*/
|
||||||
|
ReplaceMenuProvider.prototype._getLoopEntries = function(element) {
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
function toggleLoopEntry(event, entry) {
|
||||||
|
var loopCharacteristics;
|
||||||
|
|
||||||
|
if (entry.active) {
|
||||||
|
loopCharacteristics = undefined;
|
||||||
|
} else {
|
||||||
|
loopCharacteristics = self._moddle.create(entry.options.loopCharacteristics);
|
||||||
|
|
||||||
|
if (entry.options.isSequential) {
|
||||||
|
loopCharacteristics.isSequential = entry.options.isSequential;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self._modeling.updateProperties(element, { loopCharacteristics: loopCharacteristics });
|
||||||
|
}
|
||||||
|
|
||||||
|
var businessObject = getBusinessObject(element),
|
||||||
|
loopCharacteristics = businessObject.loopCharacteristics;
|
||||||
|
|
||||||
|
var isSequential,
|
||||||
|
isLoop,
|
||||||
|
isParallel;
|
||||||
|
|
||||||
|
if (loopCharacteristics) {
|
||||||
|
isSequential = loopCharacteristics.isSequential;
|
||||||
|
isLoop = loopCharacteristics.isSequential === undefined;
|
||||||
|
isParallel = loopCharacteristics.isSequential !== undefined && !loopCharacteristics.isSequential;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var loopEntries = [
|
||||||
|
{
|
||||||
|
id: 'toggle-parallel-mi',
|
||||||
|
className: 'bpmn-icon-parallel-mi-marker',
|
||||||
|
title: 'Parallel Multi Instance',
|
||||||
|
active: isParallel,
|
||||||
|
action: toggleLoopEntry,
|
||||||
|
options: {
|
||||||
|
loopCharacteristics: 'bpmn:MultiInstanceLoopCharacteristics',
|
||||||
|
isSequential: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'toggle-sequential-mi',
|
||||||
|
className: 'bpmn-icon-sequential-mi-marker',
|
||||||
|
title: 'Sequential Multi Instance',
|
||||||
|
active: isSequential,
|
||||||
|
action: toggleLoopEntry,
|
||||||
|
options: {
|
||||||
|
loopCharacteristics: 'bpmn:MultiInstanceLoopCharacteristics',
|
||||||
|
isSequential: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'toggle-loop',
|
||||||
|
className: 'bpmn-icon-loop-marker',
|
||||||
|
title: 'Loop',
|
||||||
|
active: isLoop,
|
||||||
|
action: toggleLoopEntry,
|
||||||
|
options: {
|
||||||
|
loopCharacteristics: 'bpmn:StandardLoopCharacteristics'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
return loopEntries;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the menu items containing a button for the ad hoc marker
|
||||||
|
*
|
||||||
|
* @param {djs.model.Base} element
|
||||||
|
*
|
||||||
|
* @return {Object} a menu item
|
||||||
|
*/
|
||||||
|
ReplaceMenuProvider.prototype._getAdHocEntry = function(element) {
|
||||||
|
var businessObject = getBusinessObject(element);
|
||||||
|
|
||||||
|
var isAdHoc = is(businessObject, 'bpmn:AdHocSubProcess');
|
||||||
|
|
||||||
|
var replaceElement = this._bpmnReplace.replaceElement;
|
||||||
|
|
||||||
|
var adHocEntry = {
|
||||||
|
id: 'toggle-adhoc',
|
||||||
|
className: 'bpmn-icon-ad-hoc-marker',
|
||||||
|
title: 'Ad-hoc',
|
||||||
|
active: isAdHoc,
|
||||||
|
action: function(event, entry) {
|
||||||
|
if (isAdHoc) {
|
||||||
|
return replaceElement(element, { type: 'bpmn:SubProcess' });
|
||||||
|
} else {
|
||||||
|
return replaceElement(element, { type: 'bpmn:AdHocSubProcess' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return adHocEntry;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = ReplaceMenuProvider;
|
|
@ -0,0 +1,4 @@
|
||||||
|
module.exports = {
|
||||||
|
__init__: [ 'replaceMenuProvider' ],
|
||||||
|
replaceMenuProvider: [ 'type', require('./ReplaceMenuProvider') ]
|
||||||
|
};
|
|
@ -0,0 +1,28 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var getBusinessObject = require('../../../util/ModelUtil').getBusinessObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true, if an element is from a different type than a target definition.
|
||||||
|
* Takes into account the type and the event definition type.
|
||||||
|
*
|
||||||
|
* @param {djs.model.Base} element
|
||||||
|
*
|
||||||
|
* @return {Boolean}
|
||||||
|
*/
|
||||||
|
function isDifferentType(element) {
|
||||||
|
|
||||||
|
return function(entry) {
|
||||||
|
var target = entry.target;
|
||||||
|
|
||||||
|
var businessObject = getBusinessObject(element),
|
||||||
|
eventDefinition = businessObject.eventDefinitions && businessObject.eventDefinitions[0].$type;
|
||||||
|
|
||||||
|
var isEventDefinitionEqual = target.eventDefinition == eventDefinition,
|
||||||
|
isTypeEqual = businessObject.$type == target.type;
|
||||||
|
|
||||||
|
return (!isEventDefinitionEqual && isTypeEqual) || !isTypeEqual;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.isDifferentType = isDifferentType;
|
|
@ -1,30 +1,12 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var forEach = require('lodash/collection/forEach'),
|
var pick = require('lodash/object/pick'),
|
||||||
filter = require('lodash/collection/filter'),
|
|
||||||
pick = require('lodash/object/pick'),
|
|
||||||
assign = require('lodash/object/assign');
|
assign = require('lodash/object/assign');
|
||||||
|
|
||||||
var REPLACE_OPTIONS = require ('./ReplaceOptions');
|
|
||||||
|
|
||||||
var startEventReplace = REPLACE_OPTIONS.START_EVENT,
|
|
||||||
intermediateEventReplace = REPLACE_OPTIONS.INTERMEDIATE_EVENT,
|
|
||||||
endEventReplace = REPLACE_OPTIONS.END_EVENT,
|
|
||||||
gatewayReplace = REPLACE_OPTIONS.GATEWAY,
|
|
||||||
taskReplace = REPLACE_OPTIONS.TASK,
|
|
||||||
subProcessExpandedReplace = REPLACE_OPTIONS.SUBPROCESS_EXPANDED,
|
|
||||||
transactionReplace = REPLACE_OPTIONS.TRANSACTION,
|
|
||||||
eventSubProcessReplace = REPLACE_OPTIONS.EVENT_SUB_PROCESS,
|
|
||||||
boundaryEventReplace = REPLACE_OPTIONS.BOUNDARY_EVENT,
|
|
||||||
eventSubProcessStartEventReplace = REPLACE_OPTIONS.EVENT_SUB_PROCESS_START_EVENT,
|
|
||||||
sequenceFlowReplace = REPLACE_OPTIONS.SEQUENCE_FLOW;
|
|
||||||
|
|
||||||
var is = require('../../util/ModelUtil').is,
|
var is = require('../../util/ModelUtil').is,
|
||||||
getBusinessObject = require('../../util/ModelUtil').getBusinessObject,
|
|
||||||
isExpanded = require('../../util/DiUtil').isExpanded,
|
isExpanded = require('../../util/DiUtil').isExpanded,
|
||||||
isEventSubProcess = require('../../util/DiUtil').isEventSubProcess;
|
isEventSubProcess = require('../../util/DiUtil').isEventSubProcess;
|
||||||
|
|
||||||
|
|
||||||
var CUSTOM_PROPERTIES = [
|
var CUSTOM_PROPERTIES = [
|
||||||
'cancelActivity',
|
'cancelActivity',
|
||||||
'instantiate',
|
'instantiate',
|
||||||
|
@ -35,19 +17,9 @@ var CUSTOM_PROPERTIES = [
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A replace menu provider that gives users the controls to choose
|
* This module takes care of replacing BPMN elements
|
||||||
* and replace BPMN elements with each other.
|
|
||||||
*
|
|
||||||
* @param {BpmnFactory} bpmnFactory
|
|
||||||
* @param {Moddle} moddle
|
|
||||||
* @param {PopupMenu} popupMenu
|
|
||||||
* @param {Replace} replace
|
|
||||||
*/
|
*/
|
||||||
function BpmnReplace(bpmnFactory, moddle, popupMenu, replace, selection, modeling, eventBus, rules) {
|
function BpmnReplace(bpmnFactory, replace, selection, modeling) {
|
||||||
|
|
||||||
var self = this,
|
|
||||||
currentElement;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepares a new business object for the replacement element
|
* Prepares a new business object for the replacement element
|
||||||
|
@ -56,6 +28,7 @@ function BpmnReplace(bpmnFactory, moddle, popupMenu, replace, selection, modelin
|
||||||
* @param {djs.model.Base} element
|
* @param {djs.model.Base} element
|
||||||
* @param {Object} target
|
* @param {Object} target
|
||||||
* @param {Object} [hints]
|
* @param {Object} [hints]
|
||||||
|
*
|
||||||
* @return {djs.model.Base} the newly created element
|
* @return {djs.model.Base} the newly created element
|
||||||
*/
|
*/
|
||||||
function replaceElement(element, target, hints) {
|
function replaceElement(element, target, hints) {
|
||||||
|
@ -74,7 +47,7 @@ function BpmnReplace(bpmnFactory, moddle, popupMenu, replace, selection, modelin
|
||||||
// initialize custom BPMN extensions
|
// initialize custom BPMN extensions
|
||||||
if (target.eventDefinition) {
|
if (target.eventDefinition) {
|
||||||
var eventDefinitions = businessObject.get('eventDefinitions'),
|
var eventDefinitions = businessObject.get('eventDefinitions'),
|
||||||
eventDefinition = moddle.create(target.eventDefinition);
|
eventDefinition = bpmnFactory.create(target.eventDefinition);
|
||||||
|
|
||||||
eventDefinition.$parent = businessObject;
|
eventDefinition.$parent = businessObject;
|
||||||
eventDefinitions.push(eventDefinition);
|
eventDefinitions.push(eventDefinition);
|
||||||
|
@ -119,335 +92,9 @@ function BpmnReplace(bpmnFactory, moddle, popupMenu, replace, selection, modelin
|
||||||
return newElement;
|
return newElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function toggleLoopEntry(event, entry) {
|
|
||||||
var loopEntries = self.getLoopEntries(currentElement);
|
|
||||||
|
|
||||||
var loopCharacteristics;
|
|
||||||
|
|
||||||
if (entry.active) {
|
|
||||||
loopCharacteristics = undefined;
|
|
||||||
} else {
|
|
||||||
forEach(loopEntries, function(action) {
|
|
||||||
var options = action.options;
|
|
||||||
|
|
||||||
if (entry.id === action.id) {
|
|
||||||
loopCharacteristics = moddle.create(options.loopCharacteristics);
|
|
||||||
|
|
||||||
if (options.isSequential) {
|
|
||||||
loopCharacteristics.isSequential = options.isSequential;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
modeling.updateProperties(currentElement, { loopCharacteristics: loopCharacteristics });
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function getLoopEntries(element) {
|
|
||||||
|
|
||||||
currentElement = element;
|
|
||||||
|
|
||||||
var businessObject = getBusinessObject(element),
|
|
||||||
loopCharacteristics = businessObject.loopCharacteristics;
|
|
||||||
|
|
||||||
var isSequential,
|
|
||||||
isLoop,
|
|
||||||
isParallel;
|
|
||||||
|
|
||||||
if (loopCharacteristics) {
|
|
||||||
isSequential = loopCharacteristics.isSequential;
|
|
||||||
isLoop = loopCharacteristics.isSequential === undefined;
|
|
||||||
isParallel = loopCharacteristics.isSequential !== undefined && !loopCharacteristics.isSequential;
|
|
||||||
}
|
|
||||||
|
|
||||||
var loopEntries = [
|
|
||||||
{
|
|
||||||
id: 'toggle-parallel-mi',
|
|
||||||
className: 'bpmn-icon-parallel-mi-marker',
|
|
||||||
title: 'Parallel Multi Instance',
|
|
||||||
active: isParallel,
|
|
||||||
action: toggleLoopEntry,
|
|
||||||
options: {
|
|
||||||
loopCharacteristics: 'bpmn:MultiInstanceLoopCharacteristics',
|
|
||||||
isSequential: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'toggle-sequential-mi',
|
|
||||||
className: 'bpmn-icon-sequential-mi-marker',
|
|
||||||
title: 'Sequential Multi Instance',
|
|
||||||
active: isSequential,
|
|
||||||
action: toggleLoopEntry,
|
|
||||||
options: {
|
|
||||||
loopCharacteristics: 'bpmn:MultiInstanceLoopCharacteristics',
|
|
||||||
isSequential: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'toggle-loop',
|
|
||||||
className: 'bpmn-icon-loop-marker',
|
|
||||||
title: 'Loop',
|
|
||||||
active: isLoop,
|
|
||||||
action: toggleLoopEntry,
|
|
||||||
options: {
|
|
||||||
loopCharacteristics: 'bpmn:StandardLoopCharacteristics'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
];
|
|
||||||
return loopEntries;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function getAdHocEntry(element) {
|
|
||||||
var businessObject = getBusinessObject(element);
|
|
||||||
|
|
||||||
var isAdHoc = is(businessObject, 'bpmn:AdHocSubProcess');
|
|
||||||
|
|
||||||
var adHocEntry = {
|
|
||||||
id: 'toggle-adhoc',
|
|
||||||
className: 'bpmn-icon-ad-hoc-marker',
|
|
||||||
title: 'Ad-hoc',
|
|
||||||
active: isAdHoc,
|
|
||||||
action: function(event, entry) {
|
|
||||||
if (isAdHoc) {
|
|
||||||
return replaceElement(element, { type: 'bpmn:SubProcess' });
|
|
||||||
} else {
|
|
||||||
return replaceElement(element, { type: 'bpmn:AdHocSubProcess' });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return adHocEntry;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
this.getReplaceOptions = function(element) {
|
|
||||||
|
|
||||||
if (!rules.allowed('shape.replace', { element: element })) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
var menuEntries = [];
|
|
||||||
var businessObject = element.businessObject;
|
|
||||||
|
|
||||||
// start events outside event sub processes
|
|
||||||
if (is(businessObject, 'bpmn:StartEvent') && !isEventSubProcess(businessObject.$parent)) {
|
|
||||||
addEntries(startEventReplace, filterEvents);
|
|
||||||
} else
|
|
||||||
|
|
||||||
// start events inside event sub processes
|
|
||||||
if (is(businessObject, 'bpmn:StartEvent') && isEventSubProcess(businessObject.$parent)) {
|
|
||||||
addEntries(eventSubProcessStartEventReplace, filterEvents);
|
|
||||||
} else
|
|
||||||
|
|
||||||
if (is(businessObject, 'bpmn:IntermediateCatchEvent') ||
|
|
||||||
is(businessObject, 'bpmn:IntermediateThrowEvent')) {
|
|
||||||
|
|
||||||
addEntries(intermediateEventReplace, filterEvents);
|
|
||||||
} else
|
|
||||||
|
|
||||||
if (is(businessObject, 'bpmn:EndEvent')) {
|
|
||||||
|
|
||||||
addEntries(endEventReplace, filterEvents);
|
|
||||||
} else
|
|
||||||
|
|
||||||
if (is(businessObject, 'bpmn:Gateway')) {
|
|
||||||
|
|
||||||
addEntries(gatewayReplace, function(entry) {
|
|
||||||
|
|
||||||
return entry.target.type !== businessObject.$type;
|
|
||||||
});
|
|
||||||
} else
|
|
||||||
|
|
||||||
if (is(businessObject, 'bpmn:Transaction')) {
|
|
||||||
|
|
||||||
addEntries(transactionReplace);
|
|
||||||
} else
|
|
||||||
|
|
||||||
if (isEventSubProcess(businessObject) && isExpanded(businessObject)) {
|
|
||||||
|
|
||||||
addEntries(eventSubProcessReplace);
|
|
||||||
} else
|
|
||||||
|
|
||||||
if (is(businessObject, 'bpmn:SubProcess') && isExpanded(businessObject)) {
|
|
||||||
|
|
||||||
addEntries(subProcessExpandedReplace);
|
|
||||||
} else
|
|
||||||
|
|
||||||
if (is(businessObject, 'bpmn:AdHocSubProcess') && !isExpanded(businessObject)) {
|
|
||||||
addEntries(taskReplace, function(entry) {
|
|
||||||
return entry.target.type !== 'bpmn:SubProcess';
|
|
||||||
});
|
|
||||||
} else
|
|
||||||
|
|
||||||
if (is(businessObject, 'bpmn:BoundaryEvent')) {
|
|
||||||
addEntries(boundaryEventReplace, filterEvents);
|
|
||||||
} else
|
|
||||||
|
|
||||||
if (is(businessObject, 'bpmn:SequenceFlow')) {
|
|
||||||
addSequenceFlowEntries(sequenceFlowReplace);
|
|
||||||
} else
|
|
||||||
|
|
||||||
if (is(businessObject, 'bpmn:FlowNode')) {
|
|
||||||
addEntries(taskReplace, function(entry) {
|
|
||||||
return entry.target.type !== businessObject.$type;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function addSequenceFlowEntries(entries) {
|
|
||||||
forEach(entries, function(entry) {
|
|
||||||
|
|
||||||
switch (entry.actionName) {
|
|
||||||
case 'replace-with-default-flow':
|
|
||||||
if (businessObject.sourceRef.default !== businessObject &&
|
|
||||||
(is(businessObject.sourceRef, 'bpmn:ExclusiveGateway') ||
|
|
||||||
is(businessObject.sourceRef, 'bpmn:InclusiveGateway'))) {
|
|
||||||
|
|
||||||
menuEntries.push(addMenuEntry(entry, function() {
|
|
||||||
modeling.updateProperties(element.source, { default: businessObject });
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'replace-with-conditional-flow':
|
|
||||||
if (!businessObject.conditionExpression && is(businessObject.sourceRef, 'bpmn:Activity')) {
|
|
||||||
|
|
||||||
menuEntries.push(addMenuEntry(entry, function() {
|
|
||||||
var conditionExpression = moddle.create('bpmn:FormalExpression', { body: ''});
|
|
||||||
|
|
||||||
modeling.updateProperties(element, { conditionExpression: conditionExpression });
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// default flows
|
|
||||||
if (is(businessObject.sourceRef, 'bpmn:Activity') && businessObject.conditionExpression) {
|
|
||||||
return menuEntries.push(addMenuEntry(entry, function() {
|
|
||||||
modeling.updateProperties(element, { conditionExpression: undefined });
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
// conditional flows
|
|
||||||
if ((is(businessObject.sourceRef, 'bpmn:ExclusiveGateway') ||
|
|
||||||
is(businessObject.sourceRef, 'bpmn:InclusiveGateway')) &&
|
|
||||||
businessObject.sourceRef.default === businessObject) {
|
|
||||||
|
|
||||||
return menuEntries.push(addMenuEntry(entry, function() {
|
|
||||||
modeling.updateProperties(element.source, { default: undefined });
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function filterEvents(entry) {
|
|
||||||
|
|
||||||
var target = entry.target;
|
|
||||||
|
|
||||||
var eventDefinition = businessObject.eventDefinitions && businessObject.eventDefinitions[0].$type;
|
|
||||||
|
|
||||||
var isEventDefinitionEqual = target.eventDefinition == eventDefinition,
|
|
||||||
isEventTypeEqual = businessObject.$type == target.type;
|
|
||||||
|
|
||||||
// filter for boundary events
|
|
||||||
if (is(businessObject, 'bpmn:BoundaryEvent')) {
|
|
||||||
if (target.eventDefinition == 'bpmn:CancelEventDefinition' &&
|
|
||||||
!is(businessObject.attachedToRef, 'bpmn:Transaction')) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
var cancelActivity = target.cancelActivity !== false;
|
|
||||||
|
|
||||||
var isCancelActivityEqual = businessObject.cancelActivity == cancelActivity;
|
|
||||||
|
|
||||||
return !(isEventDefinitionEqual && isEventTypeEqual && isCancelActivityEqual);
|
|
||||||
}
|
|
||||||
|
|
||||||
// filter for start events inside event sub processes
|
|
||||||
if (is(businessObject, 'bpmn:StartEvent') && isEventSubProcess(businessObject.$parent)) {
|
|
||||||
var isInterrupting = target.isInterrupting !== false;
|
|
||||||
|
|
||||||
var isInterruptingEqual = businessObject.isInterrupting == isInterrupting;
|
|
||||||
|
|
||||||
return !(isEventDefinitionEqual && isEventDefinitionEqual && isInterruptingEqual);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is(businessObject, 'bpmn:EndEvent') && target.eventDefinition == 'bpmn:CancelEventDefinition' &&
|
|
||||||
!is(businessObject.$parent, 'bpmn:Transaction')) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// filter for all other elements
|
|
||||||
return (!isEventDefinitionEqual && isEventTypeEqual) || !isEventTypeEqual;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function addEntries(entries, filterFun) {
|
|
||||||
// Filter selected type from the array
|
|
||||||
var filteredEntries = filter(entries, filterFun);
|
|
||||||
|
|
||||||
// Add entries to replace menu
|
|
||||||
forEach(filteredEntries, function(definition) {
|
|
||||||
var entry = addMenuEntry(definition);
|
|
||||||
menuEntries.push(entry);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function addMenuEntry(definition, action) {
|
|
||||||
|
|
||||||
var menuEntry = {
|
|
||||||
label: definition.label,
|
|
||||||
className: definition.className,
|
|
||||||
id: definition.actionName,
|
|
||||||
action: action
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!menuEntry.action) {
|
|
||||||
menuEntry.action = function() {
|
|
||||||
return replaceElement(element, definition.target);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return menuEntry;
|
|
||||||
}
|
|
||||||
|
|
||||||
return menuEntries;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Open a replace chooser for an element on the specified position.
|
|
||||||
*
|
|
||||||
* @param {Object} position
|
|
||||||
* @param {Object} element
|
|
||||||
*/
|
|
||||||
this.openChooser = function(position, element) {
|
|
||||||
var entries = this.getReplaceOptions(element),
|
|
||||||
headerEntries = [];
|
|
||||||
|
|
||||||
if (is(element, 'bpmn:Activity') && !isEventSubProcess(element)) {
|
|
||||||
headerEntries = headerEntries.concat(this.getLoopEntries(element));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is(element, 'bpmn:SubProcess') &&
|
|
||||||
!is(element, 'bpmn:Transaction') &&
|
|
||||||
!isEventSubProcess(element)) {
|
|
||||||
headerEntries.push(this.getAdHocEntry(element));
|
|
||||||
}
|
|
||||||
|
|
||||||
popupMenu.open({
|
|
||||||
className: 'replace-menu',
|
|
||||||
element: element,
|
|
||||||
position: position,
|
|
||||||
headerEntries: headerEntries,
|
|
||||||
entries: entries
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
this.getLoopEntries = getLoopEntries;
|
|
||||||
|
|
||||||
this.getAdHocEntry = getAdHocEntry;
|
|
||||||
|
|
||||||
this.replaceElement = replaceElement;
|
this.replaceElement = replaceElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
BpmnReplace.$inject = [ 'bpmnFactory', 'moddle', 'popupMenu', 'replace', 'selection', 'modeling', 'eventBus', 'rules' ];
|
BpmnReplace.$inject = [ 'bpmnFactory', 'replace', 'selection', 'modeling' ];
|
||||||
|
|
||||||
module.exports = BpmnReplace;
|
module.exports = BpmnReplace;
|
||||||
|
|
|
@ -723,16 +723,16 @@ module.exports.SEQUENCE_FLOW = [
|
||||||
{
|
{
|
||||||
label: 'Sequence Flow',
|
label: 'Sequence Flow',
|
||||||
actionName: 'replace-with-sequence-flow',
|
actionName: 'replace-with-sequence-flow',
|
||||||
className: 'bpmn-icon-connection',
|
className: 'bpmn-icon-connection'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Default Flow',
|
label: 'Default Flow',
|
||||||
actionName: 'replace-with-default-flow',
|
actionName: 'replace-with-default-flow',
|
||||||
className: 'bpmn-icon-default-flow',
|
className: 'bpmn-icon-default-flow'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Conditional Flow',
|
label: 'Conditional Flow',
|
||||||
actionName: 'replace-with-conditional-flow',
|
actionName: 'replace-with-conditional-flow',
|
||||||
className: 'bpmn-icon-conditional-flow',
|
className: 'bpmn-icon-conditional-flow'
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
|
@ -13,6 +13,7 @@ var contextPadModule = require('../../../../lib/features/context-pad'),
|
||||||
coreModule = require('../../../../lib/core'),
|
coreModule = require('../../../../lib/core'),
|
||||||
modelingModule = require('../../../../lib/features/modeling'),
|
modelingModule = require('../../../../lib/features/modeling'),
|
||||||
popupModule = require('diagram-js/lib/features/popup-menu'),
|
popupModule = require('diagram-js/lib/features/popup-menu'),
|
||||||
|
replaceMenuProvider = require('../../../../lib/features/popup-menu'),
|
||||||
replaceModule = require('diagram-js/lib/features/replace'),
|
replaceModule = require('diagram-js/lib/features/replace'),
|
||||||
rulesModule = require('../../../util/custom-rules');
|
rulesModule = require('../../../util/custom-rules');
|
||||||
|
|
||||||
|
@ -21,14 +22,15 @@ describe('features - context-pad', function() {
|
||||||
|
|
||||||
var diagramXML = require('../../../fixtures/bpmn/simple.bpmn');
|
var diagramXML = require('../../../fixtures/bpmn/simple.bpmn');
|
||||||
|
|
||||||
var testModules = [ contextPadModule, coreModule, modelingModule, popupModule, replaceModule, rulesModule ];
|
var testModules = [ contextPadModule, coreModule, modelingModule, popupModule,
|
||||||
|
replaceModule, rulesModule, replaceMenuProvider ];
|
||||||
|
|
||||||
beforeEach(bootstrapViewer(diagramXML, { modules: testModules }));
|
beforeEach(bootstrapViewer(diagramXML, { modules: testModules }));
|
||||||
|
|
||||||
|
|
||||||
describe('bootstrap', function() {
|
describe('bootstrap', function() {
|
||||||
|
|
||||||
it('should bootstrap', inject(function(contextPadProvider) {
|
it('should bootstrap', inject(function(contextPadProvider, replaceMenuProvider) {
|
||||||
expect(contextPadProvider).to.exist;
|
expect(contextPadProvider).to.exist;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -60,7 +62,8 @@ describe('features - context-pad', function() {
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
it('should include delete action when rule returns true', inject(function (elementRegistry, contextPad, customRules) {
|
it('should include delete action when rule returns true',
|
||||||
|
inject(function (elementRegistry, contextPad, customRules) {
|
||||||
|
|
||||||
// given
|
// given
|
||||||
customRules.addRule('elements.delete', function() {
|
customRules.addRule('elements.delete', function() {
|
||||||
|
@ -77,7 +80,8 @@ describe('features - context-pad', function() {
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
it('should NOT include delete action when rule returns false', inject(function(elementRegistry, contextPad, customRules) {
|
it('should NOT include delete action when rule returns false',
|
||||||
|
inject(function(elementRegistry, contextPad, customRules) {
|
||||||
|
|
||||||
// given
|
// given
|
||||||
customRules.addRule('elements.delete', function() {
|
customRules.addRule('elements.delete', function() {
|
||||||
|
@ -114,7 +118,8 @@ describe('features - context-pad', function() {
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
it('should include delete action when [ element ] is returned from rule', inject(function(elementRegistry, contextPad, customRules) {
|
it('should include delete action when [ element ] is returned from rule',
|
||||||
|
inject(function(elementRegistry, contextPad, customRules) {
|
||||||
|
|
||||||
// given
|
// given
|
||||||
customRules.addRule('elements.delete', function(context) {
|
customRules.addRule('elements.delete', function(context) {
|
||||||
|
@ -131,7 +136,8 @@ describe('features - context-pad', function() {
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
it('should NOT include delete action when [ ] is returned from rule', inject(function(elementRegistry, contextPad, customRules) {
|
it('should NOT include delete action when [ ] is returned from rule',
|
||||||
|
inject(function(elementRegistry, contextPad, customRules) {
|
||||||
|
|
||||||
// given
|
// given
|
||||||
customRules.addRule('elements.delete', function() {
|
customRules.addRule('elements.delete', function() {
|
||||||
|
@ -176,7 +182,7 @@ describe('features - context-pad', function() {
|
||||||
|
|
||||||
// when
|
// when
|
||||||
contextPad.trigger('click', event);
|
contextPad.trigger('click', event);
|
||||||
replaceMenuRect = domQuery('.replace-menu', container).getBoundingClientRect();
|
replaceMenuRect = domQuery('.bpmn-replace', container).getBoundingClientRect();
|
||||||
|
|
||||||
// then
|
// then
|
||||||
expect(replaceMenuRect.left).to.be.at.most(padMenuRect.left);
|
expect(replaceMenuRect.left).to.be.at.most(padMenuRect.left);
|
||||||
|
|
|
@ -1,702 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/* global bootstrapModeler, inject */
|
|
||||||
|
|
||||||
var TestHelper = require('../../../TestHelper');
|
|
||||||
|
|
||||||
var globalEvent = require('../../../util/MockEvents.js').createEvent;
|
|
||||||
|
|
||||||
var coreModule = require('../../../../lib/core'),
|
|
||||||
popupMenuModule = require('diagram-js/lib/features/popup-menu'),
|
|
||||||
modelingModule = require('../../../../lib/features/modeling'),
|
|
||||||
replaceModule = require('../../../../lib/features/replace');
|
|
||||||
|
|
||||||
var domQuery = require('min-dom/lib/query'),
|
|
||||||
domClasses = require('min-dom/lib/classes');
|
|
||||||
|
|
||||||
var is = require('../../../../lib/util/ModelUtil').is,
|
|
||||||
isExpanded = require('../../../../lib/util/DiUtil').isExpanded;
|
|
||||||
|
|
||||||
function queryEntry(popupMenu, id) {
|
|
||||||
return queryPopup(popupMenu, '[data-id="' + id + '"]');
|
|
||||||
}
|
|
||||||
|
|
||||||
function queryPopup(popupMenu, selector) {
|
|
||||||
return domQuery(selector, popupMenu._current.container);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
describe('features/popup-menu', function() {
|
|
||||||
|
|
||||||
var diagramXMLMarkers = require('../../../fixtures/bpmn/draw/activity-markers-simple.bpmn'),
|
|
||||||
diagramXMLReplace = require('../../../fixtures/bpmn/features/replace/01_replace.bpmn');
|
|
||||||
|
|
||||||
var testModules = [ coreModule, modelingModule, popupMenuModule, replaceModule ];
|
|
||||||
|
|
||||||
var openPopup = function(element, offset) {
|
|
||||||
offset = offset || 100;
|
|
||||||
|
|
||||||
TestHelper.getBpmnJS().invoke(function(bpmnReplace){
|
|
||||||
bpmnReplace.openChooser({ x: element.x + offset, y: element.y + offset }, element);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
describe('toggle', function(){
|
|
||||||
|
|
||||||
beforeEach(bootstrapModeler(diagramXMLMarkers, { modules: testModules }));
|
|
||||||
|
|
||||||
describe('active attribute', function(){
|
|
||||||
|
|
||||||
it('should be true for parallel marker', inject(function(popupMenu, bpmnReplace, elementRegistry) {
|
|
||||||
|
|
||||||
// given
|
|
||||||
var task = elementRegistry.get('ParallelTask'),
|
|
||||||
loopCharacteristics = task.businessObject.loopCharacteristics;
|
|
||||||
|
|
||||||
// when
|
|
||||||
openPopup(task);
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(is(loopCharacteristics, 'bpmn:MultiInstanceLoopCharacteristics')).to.be.true;
|
|
||||||
|
|
||||||
expect(loopCharacteristics.isSequential).to.be.false;
|
|
||||||
expect(loopCharacteristics.isSequential).to.exist;
|
|
||||||
|
|
||||||
expect(popupMenu._getEntry('toggle-parallel-mi').active).to.be.true;
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should be true for sequential marker', inject(function(popupMenu, bpmnReplace, elementRegistry) {
|
|
||||||
|
|
||||||
// given
|
|
||||||
var task = elementRegistry.get('SequentialTask'),
|
|
||||||
loopCharacteristics = task.businessObject.loopCharacteristics;
|
|
||||||
|
|
||||||
// when
|
|
||||||
openPopup(task);
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(loopCharacteristics.isSequential).to.be.true;
|
|
||||||
expect(popupMenu._getEntry('toggle-sequential-mi').active).to.be.true;
|
|
||||||
expect(is(loopCharacteristics, 'bpmn:MultiInstanceLoopCharacteristics')).to.be.true;
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should be true for loop marker', inject(function(popupMenu, bpmnReplace, elementRegistry) {
|
|
||||||
|
|
||||||
// given
|
|
||||||
var task = elementRegistry.get('LoopTask'),
|
|
||||||
loopCharacteristics = task.businessObject.loopCharacteristics;
|
|
||||||
|
|
||||||
// when
|
|
||||||
openPopup(task);
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(loopCharacteristics.isSequential).not.to.exist;
|
|
||||||
expect(popupMenu._getEntry('toggle-loop').active).to.be.true;
|
|
||||||
expect(is(loopCharacteristics, 'bpmn:MultiInstanceLoopCharacteristics')).to.be.false;
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should be true for ad hoc marker', inject(function(popupMenu, bpmnReplace, elementRegistry) {
|
|
||||||
|
|
||||||
// given
|
|
||||||
var AdHocSubProcess = elementRegistry.get('AdHocSubProcess');
|
|
||||||
|
|
||||||
// when
|
|
||||||
openPopup(AdHocSubProcess);
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(popupMenu._getEntry('toggle-adhoc').active).to.be.true;
|
|
||||||
}));
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
describe('exclusive toggle buttons', function(){
|
|
||||||
|
|
||||||
it('should not toggle non exclusive buttons off', inject(function(popupMenu, bpmnReplace, elementRegistry) {
|
|
||||||
var subProcess = elementRegistry.get('AdHocSubProcess');
|
|
||||||
|
|
||||||
openPopup(subProcess);
|
|
||||||
|
|
||||||
var entry = queryEntry(popupMenu, 'toggle-parallel-mi');
|
|
||||||
|
|
||||||
// when
|
|
||||||
popupMenu.trigger(globalEvent(entry, { x: 0, y: 0 }));
|
|
||||||
|
|
||||||
openPopup(subProcess);
|
|
||||||
|
|
||||||
// then
|
|
||||||
var adHocEntry = queryEntry(popupMenu, 'toggle-adhoc');
|
|
||||||
|
|
||||||
expect(domClasses(adHocEntry).has('active')).to.be.true;
|
|
||||||
}));
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('non exclusive toggle buttons', function(){
|
|
||||||
|
|
||||||
it('should not toggle exclusive buttons off',
|
|
||||||
inject(function(popupMenu, bpmnReplace, elementRegistry) {
|
|
||||||
|
|
||||||
// given
|
|
||||||
var subProcess = elementRegistry.get('SubProcess');
|
|
||||||
|
|
||||||
// when
|
|
||||||
|
|
||||||
// toggle parallel on
|
|
||||||
openPopup(subProcess);
|
|
||||||
|
|
||||||
var parallelEntry = queryEntry(popupMenu, 'toggle-parallel-mi');
|
|
||||||
|
|
||||||
popupMenu.trigger(globalEvent(parallelEntry, { x: 0, y: 0 }));
|
|
||||||
|
|
||||||
// toggle ad hoc on
|
|
||||||
openPopup(subProcess);
|
|
||||||
|
|
||||||
var adHocEntry = queryEntry(popupMenu, 'toggle-adhoc');
|
|
||||||
|
|
||||||
var adHocSubProcess = popupMenu.trigger(globalEvent(adHocEntry, { x: 0, y: 0 }));
|
|
||||||
|
|
||||||
openPopup(adHocSubProcess);
|
|
||||||
|
|
||||||
// then
|
|
||||||
parallelEntry = queryEntry(popupMenu, 'toggle-parallel-mi');
|
|
||||||
adHocEntry = queryEntry(popupMenu, 'toggle-adhoc');
|
|
||||||
|
|
||||||
expect(domClasses(parallelEntry).has('active')).to.be.true;
|
|
||||||
expect(domClasses(adHocEntry).has('active')).to.be.true;
|
|
||||||
}));
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('parallel toggle button', function(){
|
|
||||||
|
|
||||||
it('should toggle parallel marker off',
|
|
||||||
inject(function(popupMenu, bpmnReplace, elementRegistry) {
|
|
||||||
|
|
||||||
// given
|
|
||||||
var task = elementRegistry.get('ParallelTask');
|
|
||||||
|
|
||||||
openPopup(task);
|
|
||||||
|
|
||||||
var entry = queryEntry(popupMenu, 'toggle-parallel-mi');
|
|
||||||
|
|
||||||
// when
|
|
||||||
popupMenu.trigger(globalEvent(entry, { x: 0, y: 0 }));
|
|
||||||
|
|
||||||
openPopup(task);
|
|
||||||
|
|
||||||
var parallelEntry = queryEntry(popupMenu, 'toggle-parallel-mi');
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(task.businessObject.loopCharacteristics).not.to.exist;
|
|
||||||
expect(domClasses(parallelEntry).has('active')).to.be.false;
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should toggle parallel marker on', inject(function(popupMenu, bpmnReplace, elementRegistry) {
|
|
||||||
|
|
||||||
// given
|
|
||||||
var task = elementRegistry.get('Task');
|
|
||||||
|
|
||||||
openPopup(task);
|
|
||||||
|
|
||||||
var entry = queryEntry(popupMenu, 'toggle-parallel-mi');
|
|
||||||
|
|
||||||
// when
|
|
||||||
popupMenu.trigger(globalEvent(entry, { x: 0, y: 0 }));
|
|
||||||
|
|
||||||
openPopup(task);
|
|
||||||
|
|
||||||
var parallelEntry = queryEntry(popupMenu, 'toggle-parallel-mi');
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(domClasses(parallelEntry).has('active')).to.be.true;
|
|
||||||
expect(task.businessObject.loopCharacteristics.isSequential).to.be.false;
|
|
||||||
expect(is(task.businessObject.loopCharacteristics, 'bpmn:MultiInstanceLoopCharacteristics')).to.be.true;
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should set sequential button inactive', inject(function(popupMenu, bpmnReplace, elementRegistry) {
|
|
||||||
|
|
||||||
// given
|
|
||||||
var task = elementRegistry.get('SequentialTask');
|
|
||||||
|
|
||||||
openPopup(task);
|
|
||||||
|
|
||||||
var entry = queryEntry(popupMenu, 'toggle-parallel-mi');
|
|
||||||
|
|
||||||
// when
|
|
||||||
popupMenu.trigger(globalEvent(entry, { x: 0, y: 0 }));
|
|
||||||
|
|
||||||
openPopup(task);
|
|
||||||
|
|
||||||
var sequentialEntry = queryEntry(popupMenu, 'toggle-sequential-mi');
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(domClasses(sequentialEntry).has('active')).to.be.false;
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should set loop button inactive', inject(function(popupMenu, bpmnReplace, elementRegistry) {
|
|
||||||
|
|
||||||
// given
|
|
||||||
var task = elementRegistry.get('LoopTask');
|
|
||||||
|
|
||||||
openPopup(task);
|
|
||||||
|
|
||||||
var entry = queryEntry(popupMenu, 'toggle-parallel-mi');
|
|
||||||
|
|
||||||
// when
|
|
||||||
popupMenu.trigger(globalEvent(entry, { x: 0, y: 0 }));
|
|
||||||
|
|
||||||
openPopup(task);
|
|
||||||
|
|
||||||
var loopEntry = queryEntry(popupMenu, 'toggle-loop');
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(domClasses(loopEntry).has('active')).to.be.false;
|
|
||||||
}));
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('sequential toggle button', function(){
|
|
||||||
|
|
||||||
it('should toggle sequential marker off', inject(function(popupMenu, bpmnReplace, elementRegistry) {
|
|
||||||
|
|
||||||
// given
|
|
||||||
var task = elementRegistry.get('SequentialTask');
|
|
||||||
|
|
||||||
openPopup(task);
|
|
||||||
|
|
||||||
var entry = queryEntry(popupMenu, 'toggle-sequential-mi');
|
|
||||||
|
|
||||||
// when
|
|
||||||
popupMenu.trigger(globalEvent(entry, { x: 0, y: 0 }));
|
|
||||||
|
|
||||||
openPopup(task);
|
|
||||||
|
|
||||||
var sequentialEntry = queryEntry(popupMenu, 'toggle-sequential-mi');
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(task.businessObject.loopCharacteristics).not.to.exist;
|
|
||||||
expect(domClasses(sequentialEntry).has('active')).to.be.false;
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should toggle sequential marker on', inject(function(popupMenu, bpmnReplace, elementRegistry) {
|
|
||||||
|
|
||||||
// given
|
|
||||||
var task = elementRegistry.get('Task');
|
|
||||||
|
|
||||||
openPopup(task);
|
|
||||||
|
|
||||||
var entry = queryEntry(popupMenu, 'toggle-sequential-mi');
|
|
||||||
|
|
||||||
// when
|
|
||||||
popupMenu.trigger(globalEvent(entry, { x: 0, y: 0 }));
|
|
||||||
|
|
||||||
openPopup(task);
|
|
||||||
|
|
||||||
var sequentialEntry = queryEntry(popupMenu, 'toggle-sequential-mi');
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(domClasses(sequentialEntry).has('active')).to.be.true;
|
|
||||||
expect(task.businessObject.loopCharacteristics.isSequential).to.be.true;
|
|
||||||
expect(is(task.businessObject.loopCharacteristics, 'bpmn:MultiInstanceLoopCharacteristics')).to.be.true;
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should set loop button inactive', inject(function(popupMenu, bpmnReplace, elementRegistry) {
|
|
||||||
|
|
||||||
// given
|
|
||||||
var task = elementRegistry.get('LoopTask');
|
|
||||||
|
|
||||||
openPopup(task);
|
|
||||||
|
|
||||||
var entry = queryEntry(popupMenu, 'toggle-sequential-mi');
|
|
||||||
|
|
||||||
// when
|
|
||||||
popupMenu.trigger(globalEvent(entry, { x: 0, y: 0 }));
|
|
||||||
|
|
||||||
openPopup(task);
|
|
||||||
|
|
||||||
var loopEntry = queryEntry(popupMenu, 'toggle-loop');
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(domClasses(loopEntry).has('active')).to.be.false;
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should set parallel button inactive', inject(function(popupMenu, bpmnReplace, elementRegistry) {
|
|
||||||
|
|
||||||
// given
|
|
||||||
var task = elementRegistry.get('ParallelTask');
|
|
||||||
|
|
||||||
openPopup(task);
|
|
||||||
|
|
||||||
var entry = queryEntry(popupMenu, 'toggle-sequential-mi');
|
|
||||||
|
|
||||||
// when
|
|
||||||
popupMenu.trigger(globalEvent(entry, { x: 0, y: 0 }));
|
|
||||||
|
|
||||||
openPopup(task);
|
|
||||||
|
|
||||||
var parallelEntry = queryEntry(popupMenu, 'toggle-parallel-mi');
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(domClasses(parallelEntry).has('active')).to.be.false;
|
|
||||||
}));
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('loop toggle button', function(){
|
|
||||||
|
|
||||||
it('should toggle loop marker off', inject(function(popupMenu, bpmnReplace, elementRegistry) {
|
|
||||||
|
|
||||||
// given
|
|
||||||
var task = elementRegistry.get('LoopTask');
|
|
||||||
|
|
||||||
openPopup(task);
|
|
||||||
|
|
||||||
var entry = queryEntry(popupMenu, 'toggle-loop');
|
|
||||||
|
|
||||||
// when
|
|
||||||
popupMenu.trigger(globalEvent(entry, { x: 0, y: 0 }));
|
|
||||||
|
|
||||||
openPopup(task);
|
|
||||||
|
|
||||||
var loopEntry = queryEntry(popupMenu, 'toggle-loop');
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(domClasses(loopEntry).has('active')).to.be.false;
|
|
||||||
expect(is(task.businessObject.loopCharacteristics, 'bpmn:MultiInstanceLoopCharacteristics')).not.to.exist;
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should toggle loop marker on', inject(function(popupMenu, bpmnReplace, elementRegistry){
|
|
||||||
|
|
||||||
// given
|
|
||||||
var task = elementRegistry.get('Task');
|
|
||||||
|
|
||||||
openPopup(task);
|
|
||||||
|
|
||||||
var entry = queryEntry(popupMenu, 'toggle-loop');
|
|
||||||
|
|
||||||
// when
|
|
||||||
popupMenu.trigger(globalEvent(entry, { x: 0, y: 0 }));
|
|
||||||
|
|
||||||
openPopup(task);
|
|
||||||
|
|
||||||
var loopEntry = queryEntry(popupMenu, 'toggle-loop');
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(domClasses(loopEntry).has('active')).to.be.true;
|
|
||||||
expect(is(task.businessObject.loopCharacteristics, 'bpmn:StandardLoopCharacteristics')).to.be.true;
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should set sequential button inactive', inject(function(popupMenu, bpmnReplace, elementRegistry) {
|
|
||||||
|
|
||||||
// given
|
|
||||||
var task = elementRegistry.get('SequentialTask');
|
|
||||||
|
|
||||||
openPopup(task);
|
|
||||||
|
|
||||||
var entry = queryEntry(popupMenu, 'toggle-loop');
|
|
||||||
|
|
||||||
// when
|
|
||||||
popupMenu.trigger(globalEvent(entry, { x: 0, y: 0 }));
|
|
||||||
|
|
||||||
openPopup(task);
|
|
||||||
|
|
||||||
var sequentialEntry = queryEntry(popupMenu, 'toggle-sequential-mi');
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(domClasses(sequentialEntry).has('active')).to.be.false;
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should set parallel button inactive', inject(function(popupMenu, bpmnReplace, elementRegistry) {
|
|
||||||
|
|
||||||
// given
|
|
||||||
var task = elementRegistry.get('ParallelTask');
|
|
||||||
|
|
||||||
openPopup(task);
|
|
||||||
|
|
||||||
var entry = queryEntry(popupMenu, 'toggle-loop');
|
|
||||||
|
|
||||||
// when
|
|
||||||
popupMenu.trigger(globalEvent(entry, { x: 0, y: 0 }));
|
|
||||||
|
|
||||||
openPopup(task);
|
|
||||||
|
|
||||||
var parallelEntry = queryEntry(popupMenu, 'toggle-parallel-mi');
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(domClasses(parallelEntry).has('active')).to.be.false;
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('replacing', function() {
|
|
||||||
|
|
||||||
beforeEach(bootstrapModeler(diagramXMLMarkers, { modules: testModules }));
|
|
||||||
|
|
||||||
it('should retain the loop characteristics', inject(function(popupMenu, bpmnReplace, elementRegistry) {
|
|
||||||
|
|
||||||
// given
|
|
||||||
var task = elementRegistry.get('SequentialTask');
|
|
||||||
|
|
||||||
openPopup(task);
|
|
||||||
|
|
||||||
var entry = queryEntry(popupMenu, 'replace-with-send-task');
|
|
||||||
|
|
||||||
// when
|
|
||||||
// replacing the task with a send task
|
|
||||||
var sendTask = popupMenu.trigger(globalEvent(entry, { x: 0, y: 0 }));
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(sendTask.businessObject.loopCharacteristics).to.exist;
|
|
||||||
expect(sendTask.businessObject.loopCharacteristics.isSequential).to.be.true;
|
|
||||||
expect(is(sendTask.businessObject.loopCharacteristics, 'bpmn:MultiInstanceLoopCharacteristics')).to.be.true;
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should retain the loop characteristics for call activites',
|
|
||||||
inject(function(popupMenu, bpmnReplace, elementRegistry) {
|
|
||||||
|
|
||||||
// given
|
|
||||||
var task = elementRegistry.get('SequentialTask');
|
|
||||||
|
|
||||||
openPopup(task);
|
|
||||||
|
|
||||||
var entry = queryEntry(popupMenu, 'replace-with-call-activity');
|
|
||||||
|
|
||||||
// when
|
|
||||||
// replacing the task with a call activity
|
|
||||||
var callActivity = popupMenu.trigger(globalEvent(entry, { x: 0, y: 0 }));
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(callActivity.businessObject.loopCharacteristics).to.exist;
|
|
||||||
expect(callActivity.businessObject.loopCharacteristics.isSequential).to.be.true;
|
|
||||||
expect(is(callActivity.businessObject.loopCharacteristics, 'bpmn:MultiInstanceLoopCharacteristics')).to.be.true;
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should retain expanded status for sub processes',
|
|
||||||
inject(function(popupMenu, bpmnReplace, elementRegistry) {
|
|
||||||
|
|
||||||
// given
|
|
||||||
var subProcess = elementRegistry.get('SubProcess');
|
|
||||||
|
|
||||||
openPopup(subProcess);
|
|
||||||
|
|
||||||
var entry = queryEntry(popupMenu, 'replace-with-transaction');
|
|
||||||
|
|
||||||
// when
|
|
||||||
// replacing the expanded sub process with a transaction
|
|
||||||
var transaction = popupMenu.trigger(globalEvent(entry, { x: 0, y: 0 }));
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(isExpanded(transaction)).to.equal(isExpanded(subProcess));
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should retain the loop characteristics and the expanded status for transactions',
|
|
||||||
inject(function(popupMenu, bpmnReplace, elementRegistry) {
|
|
||||||
|
|
||||||
// given
|
|
||||||
var transaction = elementRegistry.get('Transaction');
|
|
||||||
|
|
||||||
openPopup(transaction);
|
|
||||||
|
|
||||||
var entry = queryEntry(popupMenu, 'replace-with-subprocess');
|
|
||||||
|
|
||||||
// when
|
|
||||||
// replacing the transaction with an expanded sub process
|
|
||||||
var subProcess = popupMenu.trigger(globalEvent(entry, { x: 0, y: 0 }));
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(isExpanded(subProcess)).to.equal(isExpanded(transaction));
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should not retain the loop characteristics morphing to an event sub process',
|
|
||||||
inject(function(popupMenu, bpmnReplace, elementRegistry, modeling) {
|
|
||||||
|
|
||||||
// given
|
|
||||||
var transaction = elementRegistry.get('Transaction');
|
|
||||||
|
|
||||||
modeling.updateProperties(transaction, { loopCharacteristics: { isparallel: true } });
|
|
||||||
|
|
||||||
openPopup(transaction);
|
|
||||||
|
|
||||||
var entry = queryEntry(popupMenu, 'replace-with-event-subprocess');
|
|
||||||
|
|
||||||
// when
|
|
||||||
// replacing the transaction with an event sub process
|
|
||||||
var subProcess = popupMenu.trigger(globalEvent(entry, { x: 0, y: 0 }));
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(isExpanded(subProcess)).to.equal(isExpanded(transaction));
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should retain the expanded property morphing to an event sub processes',
|
|
||||||
inject(function(popupMenu, bpmnReplace, elementRegistry) {
|
|
||||||
|
|
||||||
// given
|
|
||||||
var transaction = elementRegistry.get('Transaction');
|
|
||||||
|
|
||||||
openPopup(transaction);
|
|
||||||
|
|
||||||
var entry = queryEntry(popupMenu, 'replace-with-event-subprocess');
|
|
||||||
|
|
||||||
// when
|
|
||||||
// replacing the transaction with an expanded sub process
|
|
||||||
var eventSubProcess = popupMenu.trigger(globalEvent(entry, { x: 0, y: 0 }));
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(isExpanded(eventSubProcess)).to.equal(isExpanded(transaction));
|
|
||||||
}));
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('replace menu', function() {
|
|
||||||
|
|
||||||
beforeEach(bootstrapModeler(diagramXMLReplace, { modules: testModules }));
|
|
||||||
|
|
||||||
it('should contain all start events except the current one',
|
|
||||||
inject(function(popupMenu, bpmnReplace, elementRegistry) {
|
|
||||||
|
|
||||||
// given
|
|
||||||
var startEvent = elementRegistry.get('StartEvent_1');
|
|
||||||
|
|
||||||
// when
|
|
||||||
openPopup(startEvent);
|
|
||||||
|
|
||||||
var entriesContainer = queryPopup(popupMenu, '.djs-popup-body');
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(queryEntry(popupMenu, 'replace-with-none-start')).to.be.null;
|
|
||||||
expect(entriesContainer.childNodes.length).to.equal(6);
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should contain all intermediate events except the current one',
|
|
||||||
inject(function(popupMenu, bpmnReplace, elementRegistry) {
|
|
||||||
|
|
||||||
// given
|
|
||||||
var intermediateEvent = elementRegistry.get('IntermediateThrowEvent_1');
|
|
||||||
|
|
||||||
// when
|
|
||||||
openPopup(intermediateEvent);
|
|
||||||
|
|
||||||
var entriesContainer = queryPopup(popupMenu, '.djs-popup-body');
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(queryEntry(popupMenu, 'replace-with-none-intermediate-throw')).to.be.null;
|
|
||||||
expect(entriesContainer.childNodes.length).to.equal(12);
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should contain all end events except the current one',
|
|
||||||
inject(function(popupMenu, bpmnReplace, elementRegistry) {
|
|
||||||
|
|
||||||
// given
|
|
||||||
var endEvent = elementRegistry.get('EndEvent_1');
|
|
||||||
|
|
||||||
// when
|
|
||||||
openPopup(endEvent);
|
|
||||||
|
|
||||||
var entriesContainer = queryPopup(popupMenu, '.djs-popup-body');
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(queryEntry(popupMenu, 'replace-with-none-end')).to.be.null;
|
|
||||||
expect(entriesContainer.childNodes.length).to.equal(8);
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should contain all start events inside event sub process except the current one',
|
|
||||||
inject(function(popupMenu, bpmnReplace, elementRegistry) {
|
|
||||||
|
|
||||||
// given
|
|
||||||
var startEvent = elementRegistry.get('StartEvent_3');
|
|
||||||
|
|
||||||
// when
|
|
||||||
openPopup(startEvent);
|
|
||||||
|
|
||||||
var entriesContainer = queryPopup(popupMenu, '.djs-popup-body');
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(queryEntry(popupMenu, 'replace-with-non-interrupting-message-start')).to.be.null;
|
|
||||||
expect(queryEntry(popupMenu, 'replace-with-message-start')).to.exist;
|
|
||||||
expect(entriesContainer.childNodes.length).to.equal(11);
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should contain all non interrupting start events inside event sub process except the current one',
|
|
||||||
inject(function(popupMenu, bpmnReplace, elementRegistry) {
|
|
||||||
|
|
||||||
// given
|
|
||||||
var startEvent = elementRegistry.get('StartEvent_3');
|
|
||||||
|
|
||||||
var newElement = bpmnReplace.replaceElement(startEvent, {
|
|
||||||
type: 'bpmn:StartEvent',
|
|
||||||
eventDefinition: 'bpmn:ConditionalEventDefinition',
|
|
||||||
isInterrupting: false
|
|
||||||
});
|
|
||||||
|
|
||||||
// when
|
|
||||||
openPopup(newElement);
|
|
||||||
|
|
||||||
var entriesContainer = queryPopup(popupMenu, '.djs-popup-body');
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(queryEntry(popupMenu, 'replace-with-conditional-start')).to.exist;
|
|
||||||
expect(queryEntry(popupMenu, 'replace-with-non-interrupting-conditional-start')).to.be.null;
|
|
||||||
expect(entriesContainer.childNodes.length).to.equal(11);
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should contain all boundary events for an interrupting boundary event',
|
|
||||||
inject(function(popupMenu, bpmnReplace, elementRegistry) {
|
|
||||||
|
|
||||||
// given
|
|
||||||
var boundaryEvent = elementRegistry.get('BoundaryEvent_1');
|
|
||||||
|
|
||||||
// when
|
|
||||||
openPopup(boundaryEvent, 40);
|
|
||||||
|
|
||||||
var entriesContainer = queryPopup(popupMenu, '.djs-popup-body');
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(queryEntry(popupMenu, 'replace-with-conditional-intermediate-catch')).to.be.null;
|
|
||||||
expect(entriesContainer.childNodes.length).to.equal(10);
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should contain all boundary events for a non interrupting boundary event',
|
|
||||||
inject(function(popupMenu, bpmnReplace, elementRegistry) {
|
|
||||||
|
|
||||||
// given
|
|
||||||
var boundaryEvent = elementRegistry.get('BoundaryEvent_2');
|
|
||||||
|
|
||||||
// when
|
|
||||||
openPopup(boundaryEvent, 40);
|
|
||||||
|
|
||||||
var entriesContainer = queryPopup(popupMenu, '.djs-popup-body');
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(queryEntry(popupMenu, 'replace-with-non-interrupting-message-intermediate-catch')).to.be.null;
|
|
||||||
expect(entriesContainer.childNodes.length).to.equal(10);
|
|
||||||
}));
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
File diff suppressed because it is too large
Load Diff
|
@ -881,520 +881,6 @@ describe('features/replace', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
describe('Cancel Events', function () {
|
|
||||||
|
|
||||||
var diagramXML = require('../../../fixtures/bpmn/features/replace/cancel-events.bpmn');
|
|
||||||
|
|
||||||
beforeEach(bootstrapModeler(diagramXML, { modules: testModules }));
|
|
||||||
|
|
||||||
describe('- normal -', function() {
|
|
||||||
|
|
||||||
it('should show Cancel Event replace option',
|
|
||||||
inject(function(elementRegistry, bpmnReplace) {
|
|
||||||
// given
|
|
||||||
var endEvent = elementRegistry.get('EndEvent_1');
|
|
||||||
|
|
||||||
// when
|
|
||||||
var opts = bpmnReplace.getReplaceOptions(endEvent);
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(opts).to.have.length(9);
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should NOT show Cancel Event replace option',
|
|
||||||
inject(function(elementRegistry, bpmnReplace) {
|
|
||||||
// given
|
|
||||||
var endEvent = elementRegistry.get('EndEvent_2');
|
|
||||||
|
|
||||||
// when
|
|
||||||
var opts = bpmnReplace.getReplaceOptions(endEvent);
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(opts).to.have.length(8);
|
|
||||||
}));
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('- boundary events -', function() {
|
|
||||||
|
|
||||||
it('should NOT show Cancel Event replace option',
|
|
||||||
inject(function(elementRegistry, bpmnReplace) {
|
|
||||||
// given
|
|
||||||
var boundaryEvent = elementRegistry.get('BoundaryEvent_1');
|
|
||||||
|
|
||||||
// when
|
|
||||||
var opts = bpmnReplace.getReplaceOptions(boundaryEvent);
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(opts).to.have.length(12);
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should NOT show Cancel Event replace option',
|
|
||||||
inject(function(elementRegistry, bpmnReplace) {
|
|
||||||
// given
|
|
||||||
var boundaryEvent = elementRegistry.get('BoundaryEvent_2');
|
|
||||||
|
|
||||||
// when
|
|
||||||
var opts = bpmnReplace.getReplaceOptions(boundaryEvent);
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(opts).to.have.length(11);
|
|
||||||
}));
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
describe('default flows from inclusive gateways', function () {
|
|
||||||
|
|
||||||
var diagramXML = require('./BpmnReplace.defaultFlowsFromInclusiveGateways.bpmn');
|
|
||||||
|
|
||||||
beforeEach(bootstrapModeler(diagramXML, { modules: testModules }));
|
|
||||||
|
|
||||||
it ('should show Default replace option', inject(function (elementRegistry, bpmnReplace) {
|
|
||||||
// given
|
|
||||||
var sequenceFlow = elementRegistry.get('SequenceFlow_2');
|
|
||||||
|
|
||||||
// when
|
|
||||||
var opts = bpmnReplace.getReplaceOptions(sequenceFlow);
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(opts).to.have.length(1);
|
|
||||||
}));
|
|
||||||
|
|
||||||
it ('should NOT show Default replace option', inject(function (elementRegistry, bpmnReplace) {
|
|
||||||
// given
|
|
||||||
var sequenceFlow = elementRegistry.get('SequenceFlow_1');
|
|
||||||
|
|
||||||
// when
|
|
||||||
var opts = bpmnReplace.getReplaceOptions(sequenceFlow);
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(opts).to.have.length(1);
|
|
||||||
}));
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
describe('default flows', function() {
|
|
||||||
|
|
||||||
var diagramXML = require('./BpmnReplace.defaultFlows.bpmn');
|
|
||||||
|
|
||||||
beforeEach(bootstrapModeler(diagramXML, { modules: testModules }));
|
|
||||||
|
|
||||||
|
|
||||||
it('should show Default replace option', inject(function(elementRegistry, bpmnReplace) {
|
|
||||||
// given
|
|
||||||
var sequenceFlow = elementRegistry.get('SequenceFlow_3');
|
|
||||||
|
|
||||||
// when
|
|
||||||
var opts = bpmnReplace.getReplaceOptions(sequenceFlow);
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(opts).to.have.length(1);
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should NOT show Default replace option', inject(function(elementRegistry, bpmnReplace) {
|
|
||||||
// given
|
|
||||||
var sequenceFlow = elementRegistry.get('SequenceFlow_4');
|
|
||||||
|
|
||||||
// when
|
|
||||||
var opts = bpmnReplace.getReplaceOptions(sequenceFlow);
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(opts).to.have.length(0);
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should replace SequenceFlow with DefaultFlow', inject(function(elementRegistry, bpmnReplace) {
|
|
||||||
// given
|
|
||||||
var sequenceFlow = elementRegistry.get('SequenceFlow_3');
|
|
||||||
|
|
||||||
// when
|
|
||||||
var opts = bpmnReplace.getReplaceOptions(sequenceFlow);
|
|
||||||
|
|
||||||
// trigger DefaultFlow replacement
|
|
||||||
opts[0].action();
|
|
||||||
|
|
||||||
var gateway = elementRegistry.get('ExclusiveGateway_1');
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(gateway.businessObject.default).to.equal(sequenceFlow.businessObject);
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should replace SequenceFlow with DefaultFlow -> undo',
|
|
||||||
inject(function(elementRegistry, bpmnReplace, commandStack) {
|
|
||||||
// given
|
|
||||||
var sequenceFlow = elementRegistry.get('SequenceFlow_3');
|
|
||||||
|
|
||||||
// when
|
|
||||||
var opts = bpmnReplace.getReplaceOptions(sequenceFlow);
|
|
||||||
|
|
||||||
// trigger DefaultFlow replacement
|
|
||||||
opts[0].action();
|
|
||||||
|
|
||||||
commandStack.undo();
|
|
||||||
|
|
||||||
var gateway = elementRegistry.get('ExclusiveGateway_1');
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(gateway.businessObject.default).to.not.exist;
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should only have one DefaultFlow', inject(function(elementRegistry, bpmnReplace) {
|
|
||||||
// given
|
|
||||||
var sequenceFlow = elementRegistry.get('SequenceFlow_1'),
|
|
||||||
sequenceFlow2 = elementRegistry.get('SequenceFlow_3');
|
|
||||||
|
|
||||||
// when
|
|
||||||
var sequenceFlowOpts = bpmnReplace.getReplaceOptions(sequenceFlow),
|
|
||||||
sequenceFlowOpts2 = bpmnReplace.getReplaceOptions(sequenceFlow2);
|
|
||||||
|
|
||||||
// trigger DefaultFlow replacement
|
|
||||||
sequenceFlowOpts2[0].action();
|
|
||||||
sequenceFlowOpts[0].action();
|
|
||||||
|
|
||||||
var gateway = elementRegistry.get('ExclusiveGateway_1');
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(gateway.businessObject.default).to.equal(sequenceFlow.businessObject);
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should replace DefaultFlow with SequenceFlow when changing source',
|
|
||||||
inject(function(elementRegistry, bpmnReplace, modeling) {
|
|
||||||
// given
|
|
||||||
var sequenceFlow = elementRegistry.get('SequenceFlow_1'),
|
|
||||||
task = elementRegistry.get('Task_2');
|
|
||||||
|
|
||||||
var sequenceFlowOpts = bpmnReplace.getReplaceOptions(sequenceFlow);
|
|
||||||
|
|
||||||
// trigger DefaultFlow replacement
|
|
||||||
sequenceFlowOpts[0].action();
|
|
||||||
|
|
||||||
// when
|
|
||||||
modeling.reconnectStart(sequenceFlow, task, [
|
|
||||||
{ x: 686, y: 267, original: { x: 686, y: 307 } },
|
|
||||||
{ x: 686, y: 207, original: { x: 686, y: 187 } }
|
|
||||||
]);
|
|
||||||
|
|
||||||
var gateway = elementRegistry.get('ExclusiveGateway_1');
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(gateway.businessObject.default).to.not.exist;
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should replace DefaultFlow with SequenceFlow when changing source -> undo',
|
|
||||||
inject(function(elementRegistry, bpmnReplace, modeling, commandStack) {
|
|
||||||
// given
|
|
||||||
var sequenceFlow = elementRegistry.get('SequenceFlow_1'),
|
|
||||||
task = elementRegistry.get('Task_2');
|
|
||||||
|
|
||||||
var sequenceFlowOpts = bpmnReplace.getReplaceOptions(sequenceFlow);
|
|
||||||
|
|
||||||
// trigger DefaultFlow replacement
|
|
||||||
sequenceFlowOpts[0].action();
|
|
||||||
|
|
||||||
// when
|
|
||||||
modeling.reconnectStart(sequenceFlow, task, [
|
|
||||||
{ x: 686, y: 267, original: { x: 686, y: 307 } },
|
|
||||||
{ x: 686, y: 207, original: { x: 686, y: 187 } }
|
|
||||||
]);
|
|
||||||
|
|
||||||
commandStack.undo();
|
|
||||||
|
|
||||||
var gateway = elementRegistry.get('ExclusiveGateway_1');
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(gateway.businessObject.default).equal(sequenceFlow.businessObject);
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should replace DefaultFlow with SequenceFlow when changing target',
|
|
||||||
inject(function(elementRegistry, elementFactory, canvas, bpmnReplace, modeling) {
|
|
||||||
// given
|
|
||||||
var sequenceFlow = elementRegistry.get('SequenceFlow_1'),
|
|
||||||
root = canvas.getRootElement();
|
|
||||||
|
|
||||||
var intermediateEvent = elementFactory.createShape({ type: 'bpmn:IntermediateThrowEvent'});
|
|
||||||
|
|
||||||
modeling.createShape(intermediateEvent, { x: 686, y: 50 }, root);
|
|
||||||
|
|
||||||
var sequenceFlowOpts = bpmnReplace.getReplaceOptions(sequenceFlow);
|
|
||||||
|
|
||||||
// trigger DefaultFlow replacement
|
|
||||||
sequenceFlowOpts[0].action();
|
|
||||||
|
|
||||||
// when
|
|
||||||
modeling.reconnectEnd(sequenceFlow, intermediateEvent, [
|
|
||||||
{ x: 686, y: 267, original: { x: 686, y: 307 } },
|
|
||||||
{ x: 686, y: 50, original: { x: 686, y: 75 } }
|
|
||||||
]);
|
|
||||||
|
|
||||||
var gateway = elementRegistry.get('ExclusiveGateway_1');
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(gateway.businessObject.default).to.not.exist;
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should replace DefaultFlow with SequenceFlow when changing target -> undo',
|
|
||||||
inject(function(elementRegistry, elementFactory, canvas, bpmnReplace, modeling, commandStack) {
|
|
||||||
// given
|
|
||||||
var sequenceFlow = elementRegistry.get('SequenceFlow_1'),
|
|
||||||
root = canvas.getRootElement();
|
|
||||||
|
|
||||||
var intermediateEvent = elementFactory.createShape({ type: 'bpmn:IntermediateThrowEvent'});
|
|
||||||
|
|
||||||
modeling.createShape(intermediateEvent, { x: 686, y: 50 }, root);
|
|
||||||
|
|
||||||
var sequenceFlowOpts = bpmnReplace.getReplaceOptions(sequenceFlow);
|
|
||||||
|
|
||||||
// trigger DefaultFlow replacement
|
|
||||||
sequenceFlowOpts[0].action();
|
|
||||||
|
|
||||||
// when
|
|
||||||
modeling.reconnectEnd(sequenceFlow, intermediateEvent, [
|
|
||||||
{ x: 686, y: 267, original: { x: 686, y: 307 } },
|
|
||||||
{ x: 686, y: 50, original: { x: 686, y: 75 } }
|
|
||||||
]);
|
|
||||||
|
|
||||||
commandStack.undo();
|
|
||||||
|
|
||||||
var gateway = elementRegistry.get('ExclusiveGateway_1');
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(gateway.businessObject.default).equal(sequenceFlow.businessObject);
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should keep DefaultFlow when morphing Gateway', inject(function(elementRegistry, bpmnReplace) {
|
|
||||||
// given
|
|
||||||
var sequenceFlow = elementRegistry.get('SequenceFlow_3'),
|
|
||||||
exclusiveGateway = elementRegistry.get('ExclusiveGateway_1');
|
|
||||||
|
|
||||||
// when
|
|
||||||
var opts = bpmnReplace.getReplaceOptions(sequenceFlow);
|
|
||||||
|
|
||||||
// trigger DefaultFlow replacement
|
|
||||||
opts[0].action();
|
|
||||||
|
|
||||||
var inclusiveGateway = bpmnReplace.replaceElement(exclusiveGateway, { type: 'bpmn:InclusiveGateway'});
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(inclusiveGateway.businessObject.default).to.equal(sequenceFlow.businessObject);
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should keep DefaultFlow when morphing Gateway -> undo',
|
|
||||||
inject(function(elementRegistry, bpmnReplace, commandStack) {
|
|
||||||
// given
|
|
||||||
var sequenceFlow = elementRegistry.get('SequenceFlow_3'),
|
|
||||||
exclusiveGateway = elementRegistry.get('ExclusiveGateway_1');
|
|
||||||
|
|
||||||
// when
|
|
||||||
var opts = bpmnReplace.getReplaceOptions(sequenceFlow);
|
|
||||||
|
|
||||||
// trigger DefaultFlow replacement
|
|
||||||
opts[0].action();
|
|
||||||
|
|
||||||
bpmnReplace.replaceElement(exclusiveGateway, { type: 'bpmn:InclusiveGateway'});
|
|
||||||
|
|
||||||
commandStack.undo();
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(exclusiveGateway.businessObject.default).to.equal(sequenceFlow.businessObject);
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
describe('conditional flows', function() {
|
|
||||||
|
|
||||||
var diagramXML = require('./BpmnReplace.conditionalFlows.bpmn');
|
|
||||||
|
|
||||||
beforeEach(bootstrapModeler(diagramXML, { modules: testModules }));
|
|
||||||
|
|
||||||
|
|
||||||
it('should show ConditionalFlow replace option', inject(function(elementRegistry, bpmnReplace) {
|
|
||||||
// given
|
|
||||||
var sequenceFlow = elementRegistry.get('SequenceFlow_3');
|
|
||||||
|
|
||||||
//when
|
|
||||||
var opts = bpmnReplace.getReplaceOptions(sequenceFlow);
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(opts).to.have.length(1);
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should NOT show ConditionalFlow replace option', inject(function(elementRegistry, bpmnReplace) {
|
|
||||||
// given
|
|
||||||
var sequenceFlow = elementRegistry.get('SequenceFlow_1');
|
|
||||||
|
|
||||||
//when
|
|
||||||
var opts = bpmnReplace.getReplaceOptions(sequenceFlow);
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(opts).to.have.length(0);
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should morph into a ConditionalFlow', inject(function(elementRegistry, bpmnReplace) {
|
|
||||||
// given
|
|
||||||
var sequenceFlow = elementRegistry.get('SequenceFlow_2');
|
|
||||||
|
|
||||||
//when
|
|
||||||
var opts = bpmnReplace.getReplaceOptions(sequenceFlow);
|
|
||||||
|
|
||||||
// replace with ConditionalFlow
|
|
||||||
opts[0].action();
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(sequenceFlow.businessObject.conditionExpression.$type).to.equal('bpmn:FormalExpression');
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should morph into a ConditionalFlow -> undo', inject(function(elementRegistry, bpmnReplace, commandStack) {
|
|
||||||
// given
|
|
||||||
var sequenceFlow = elementRegistry.get('SequenceFlow_2');
|
|
||||||
|
|
||||||
//when
|
|
||||||
var opts = bpmnReplace.getReplaceOptions(sequenceFlow);
|
|
||||||
|
|
||||||
// replace with ConditionalFlow
|
|
||||||
opts[0].action();
|
|
||||||
|
|
||||||
commandStack.undo();
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(sequenceFlow.businessObject.conditionExpression).to.not.exist;
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should morph back into a SequenceFlow', inject(function(elementRegistry, bpmnReplace) {
|
|
||||||
// given
|
|
||||||
var sequenceFlow = elementRegistry.get('SequenceFlow_2');
|
|
||||||
|
|
||||||
// when
|
|
||||||
var opts = bpmnReplace.getReplaceOptions(sequenceFlow);
|
|
||||||
|
|
||||||
// replace with ConditionalFlow
|
|
||||||
opts[0].action();
|
|
||||||
|
|
||||||
var conditionalOpts = bpmnReplace.getReplaceOptions(sequenceFlow);
|
|
||||||
|
|
||||||
// replace with SequenceFlow
|
|
||||||
conditionalOpts[0].action();
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(sequenceFlow.businessObject.conditionExpression).to.not.exist;
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should replace ConditionalFlow with SequenceFlow when changing source',
|
|
||||||
inject(function(elementRegistry, bpmnReplace, modeling) {
|
|
||||||
// given
|
|
||||||
var sequenceFlow = elementRegistry.get('SequenceFlow_3'),
|
|
||||||
startEvent = elementRegistry.get('StartEvent_1');
|
|
||||||
|
|
||||||
var sequenceFlowOpts = bpmnReplace.getReplaceOptions(sequenceFlow);
|
|
||||||
|
|
||||||
// trigger ConditionalFlow replacement
|
|
||||||
sequenceFlowOpts[0].action();
|
|
||||||
|
|
||||||
// when
|
|
||||||
modeling.reconnectStart(sequenceFlow, startEvent, [
|
|
||||||
{ x: 196, y: 197, original: { x: 178, y: 197 } },
|
|
||||||
{ x: 497, y: 278, original: { x: 547, y: 278 } }
|
|
||||||
]);
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(sequenceFlow.businessObject.conditionExpression).to.not.exist;
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should replace ConditionalFlow with SequenceFlow when changing source -> undo',
|
|
||||||
inject(function(elementRegistry, bpmnReplace, modeling, commandStack) {
|
|
||||||
// given
|
|
||||||
var sequenceFlow = elementRegistry.get('SequenceFlow_3'),
|
|
||||||
startEvent = elementRegistry.get('StartEvent_1');
|
|
||||||
|
|
||||||
var sequenceFlowOpts = bpmnReplace.getReplaceOptions(sequenceFlow);
|
|
||||||
|
|
||||||
// trigger ConditionalFlow replacement
|
|
||||||
sequenceFlowOpts[0].action();
|
|
||||||
|
|
||||||
// when
|
|
||||||
modeling.reconnectStart(sequenceFlow, startEvent, [
|
|
||||||
{ x: 196, y: 197, original: { x: 178, y: 197 } },
|
|
||||||
{ x: 497, y: 278, original: { x: 547, y: 278 } }
|
|
||||||
]);
|
|
||||||
|
|
||||||
commandStack.undo();
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(sequenceFlow.businessObject.conditionExpression.$type).to.equal('bpmn:FormalExpression');
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should replace ConditionalFlow with SequenceFlow when changing target',
|
|
||||||
inject(function(elementRegistry, elementFactory, canvas, bpmnReplace, modeling) {
|
|
||||||
// given
|
|
||||||
var sequenceFlow = elementRegistry.get('SequenceFlow_3'),
|
|
||||||
root = canvas.getRootElement(),
|
|
||||||
intermediateEvent = elementFactory.createShape({ type: 'bpmn:IntermediateThrowEvent'});
|
|
||||||
|
|
||||||
modeling.createShape(intermediateEvent, { x: 497, y: 197 }, root);
|
|
||||||
|
|
||||||
var sequenceFlowOpts = bpmnReplace.getReplaceOptions(sequenceFlow);
|
|
||||||
|
|
||||||
// trigger ConditionalFlow replacement
|
|
||||||
sequenceFlowOpts[0].action();
|
|
||||||
|
|
||||||
// when
|
|
||||||
modeling.reconnectEnd(sequenceFlow, intermediateEvent, [
|
|
||||||
{ x: 389, y: 197, original: { x: 389, y: 197 } },
|
|
||||||
{ x: 497, y: 197, original: { x: 497, y: 197 } }
|
|
||||||
]);
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(sequenceFlow.businessObject.conditionExpression).to.not.exist;
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should replace ConditionalFlow with SequenceFlow when changing target -> undo',
|
|
||||||
inject(function(elementRegistry, elementFactory, canvas, bpmnReplace, modeling, commandStack) {
|
|
||||||
// given
|
|
||||||
var sequenceFlow = elementRegistry.get('SequenceFlow_3'),
|
|
||||||
root = canvas.getRootElement(),
|
|
||||||
intermediateEvent = elementFactory.createShape({ type: 'bpmn:IntermediateThrowEvent'});
|
|
||||||
|
|
||||||
modeling.createShape(intermediateEvent, { x: 497, y: 197 }, root);
|
|
||||||
|
|
||||||
var sequenceFlowOpts = bpmnReplace.getReplaceOptions(sequenceFlow);
|
|
||||||
|
|
||||||
// trigger ConditionalFlow replacement
|
|
||||||
sequenceFlowOpts[0].action();
|
|
||||||
|
|
||||||
// when
|
|
||||||
modeling.reconnectEnd(sequenceFlow, intermediateEvent, [
|
|
||||||
{ x: 389, y: 197, original: { x: 389, y: 197 } },
|
|
||||||
{ x: 497, y: 197, original: { x: 497, y: 197 } }
|
|
||||||
]);
|
|
||||||
|
|
||||||
commandStack.undo();
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(sequenceFlow.businessObject.conditionExpression.$type).to.equal('bpmn:FormalExpression');
|
|
||||||
}));
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('events', function() {
|
describe('events', function() {
|
||||||
|
|
||||||
var diagramXML = require('../../../fixtures/bpmn/basic.bpmn');
|
var diagramXML = require('../../../fixtures/bpmn/basic.bpmn');
|
||||||
|
|
|
@ -1,64 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var TestHelper = require('../../../TestHelper');
|
|
||||||
|
|
||||||
/* global bootstrapModeler, inject */
|
|
||||||
|
|
||||||
var modelingModule = require('../../../../lib/features/modeling'),
|
|
||||||
replaceModule = require('../../../../lib/features/replace'),
|
|
||||||
coreModule = require('../../../../lib/core');
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
describe('features/replace - chooser', function() {
|
|
||||||
|
|
||||||
var diagramXML = require('../../../fixtures/bpmn/features/replace/01_replace.bpmn');
|
|
||||||
|
|
||||||
var testModules = [ coreModule, modelingModule, replaceModule ];
|
|
||||||
|
|
||||||
beforeEach(bootstrapModeler(diagramXML, { modules: testModules }));
|
|
||||||
|
|
||||||
|
|
||||||
describe('should show chooser', function() {
|
|
||||||
|
|
||||||
it('for task', inject(function(elementRegistry, modeling, bpmnReplace) {
|
|
||||||
|
|
||||||
// given
|
|
||||||
var element = elementRegistry.get('Task_1');
|
|
||||||
|
|
||||||
// when
|
|
||||||
bpmnReplace.openChooser({ x: 100, y: 100 }, element);
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(null).not.to.exist;
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('for event event', inject(function(elementRegistry, modeling, bpmnReplace) {
|
|
||||||
|
|
||||||
// given
|
|
||||||
var element = elementRegistry.get('StartEvent_1');
|
|
||||||
|
|
||||||
// when
|
|
||||||
bpmnReplace.openChooser({ x: 100, y: 100 }, element);
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(null).not.to.exist;
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('for gateway event', inject(function(elementRegistry, modeling, bpmnReplace) {
|
|
||||||
|
|
||||||
// given
|
|
||||||
var element = elementRegistry.get('ExclusiveGateway_1');
|
|
||||||
|
|
||||||
// when
|
|
||||||
bpmnReplace.openChooser({ x: 100, y: 100 }, element);
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(null).not.to.exist;
|
|
||||||
}));
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
Loading…
Reference in New Issue