bpmn-js-properties-panel
Version:
A simple properties panel for bpmn-js
331 lines (248 loc) • 9.4 kB
JavaScript
;
var findExtension = require('../Helper').findExtension,
findExtensions = require('../Helper').findExtensions;
var createCamundaProperty = require('../CreateHelper').createCamundaProperty,
createInputParameter = require('../CreateHelper').createInputParameter,
createOutputParameter = require('../CreateHelper').createOutputParameter,
createCamundaIn = require('../CreateHelper').createCamundaIn,
createCamundaOut = require('../CreateHelper').createCamundaOut,
createCamundaInWithBusinessKey = require('../CreateHelper').createCamundaInWithBusinessKey,
createCamundaExecutionListenerScript = require('../CreateHelper').createCamundaExecutionListenerScript;
var CAMUNDA_SERVICE_TASK_LIKE = [
'camunda:class',
'camunda:delegateExpression',
'camunda:expression'
];
/**
* A handler that changes the modeling template of a BPMN element.
*/
function ChangeElementTemplateHandler(modeling, commandStack, bpmnFactory) {
function getOrCreateExtensionElements(element) {
var bo = element.businessObject;
var extensionElements = bo.extensionElements;
// add extension elements
if (!extensionElements) {
extensionElements = bpmnFactory.create('bpmn:ExtensionElements', {
values: []
});
modeling.updateProperties(element, {
extensionElements: extensionElements
});
}
return extensionElements;
}
function updateModelerTemplate(element, newTemplate) {
modeling.updateProperties(element, {
'camunda:modelerTemplate': newTemplate && newTemplate.id
});
}
function updateIoMappings(element, newTemplate) {
var extensionElements;
var newMappings = createInputOutputMappings(newTemplate, bpmnFactory),
oldMappings;
if (newMappings) {
extensionElements = getOrCreateExtensionElements(element);
oldMappings = findExtension(element, 'camunda:InputOutput');
commandStack.execute('properties-panel.update-businessobject-list', {
element: element,
currentObject: extensionElements,
propertyName: 'values',
objectsToAdd: [ newMappings ],
objectsToRemove: oldMappings ? [ oldMappings ] : []
});
}
}
function updateCamundaProperties(element, newTemplate) {
var extensionElements;
var newProperties = createCamundaProperties(newTemplate, bpmnFactory),
oldProperties;
if (newProperties) {
extensionElements = getOrCreateExtensionElements(element);
oldProperties = findExtension(element, 'camunda:Properties');
commandStack.execute('properties-panel.update-businessobject-list', {
element: element,
currentObject: extensionElements,
propertyName: 'values',
objectsToAdd: [ newProperties ],
objectsToRemove: oldProperties ? [ oldProperties ] : []
});
}
}
function updateProperties(element, newTemplate) {
var newProperties = createBpmnPropertyUpdates(newTemplate, bpmnFactory);
if (Object.keys(newProperties).length > 0) {
modeling.updateProperties(element, newProperties);
}
}
function updateInOut(element, newTemplate) {
var extensionElements;
var newInOut = createCamundaInOut(newTemplate, bpmnFactory),
oldInOut;
if (newInOut) {
extensionElements = getOrCreateExtensionElements(element);
oldInOut = findExtensions(extensionElements, [ 'camunda:In', 'camunda:Out' ]);
commandStack.execute('properties-panel.update-businessobject-list', {
element: element,
currentObject: extensionElements,
propertyName: 'values',
objectsToAdd: newInOut,
objectsToRemove: oldInOut
});
}
}
function updateExecutionListener(element, newTemplate) {
var newExecutionListeners = createCamundaExecutionListener(newTemplate, bpmnFactory),
oldExecutionsListeners;
if (newExecutionListeners.length) {
var extensionElements = getOrCreateExtensionElements(element);
oldExecutionsListeners = findExtensions(extensionElements, [ 'camunda:ExecutionListener' ]);
commandStack.execute('properties-panel.update-businessobject-list', {
element: element,
currentObject: extensionElements,
propertyName: 'values',
objectsToAdd: newExecutionListeners,
objectsToRemove: oldExecutionsListeners
});
}
}
/**
* Compose an element template change action, updating all
* necessary underlying properties.
*
* @param {Object} context
* @param {Object} context.element
* @param {Object} context.oldTemplate
* @param {Object} context.newTemplate
*/
this.preExecute = function(context) {
var element = context.element,
newTemplate = context.newTemplate;
// update camunda:modelerTemplate attribute
updateModelerTemplate(element, newTemplate);
if (newTemplate) {
// update camunda:inputOutput
updateIoMappings(element, newTemplate);
// update camunda:properties
updateCamundaProperties(element, newTemplate);
// update other properties (bpmn:condition, camunda:async, ...)
updateProperties(element, newTemplate);
// update camunda:in and camunda:out
updateInOut(element, newTemplate);
// update camunda:executionListener
updateExecutionListener(element, newTemplate);
}
};
}
ChangeElementTemplateHandler.$inject = [ 'modeling', 'commandStack', 'bpmnFactory' ];
module.exports = ChangeElementTemplateHandler;
/////// helpers /////////////////////////////
function createBpmnPropertyUpdates(template, bpmnFactory) {
var propertyUpdates = {};
template.properties.forEach(function(p) {
var binding = p.binding,
bindingTarget = binding.name,
propertyValue;
if (binding.type === 'property') {
if (bindingTarget === 'conditionExpression') {
propertyValue = bpmnFactory.create('bpmn:FormalExpression', {
body: p.value,
language: binding.scriptFormat
});
} else {
propertyValue = p.value;
}
// assigning camunda:async to true|false
// assigning bpmn:conditionExpression to { $type: 'bpmn:FormalExpression', ... }
propertyUpdates[bindingTarget] = propertyValue;
// make sure we unset other "implementation types"
// when applying a camunda:class template onto a preconfigured
// camunda:delegateExpression element
if (CAMUNDA_SERVICE_TASK_LIKE.indexOf(bindingTarget) !== -1) {
CAMUNDA_SERVICE_TASK_LIKE.forEach(function(prop) {
if (prop !== bindingTarget) {
propertyUpdates[prop] = undefined;
}
});
}
}
});
return propertyUpdates;
}
function createCamundaProperties(template, bpmnFactory) {
var properties = [];
template.properties.forEach(function(p) {
var binding = p.binding,
bindingType = binding.type;
if (bindingType === 'camunda:property') {
properties.push(createCamundaProperty(
binding, p.value, bpmnFactory
));
}
});
if (properties.length) {
return bpmnFactory.create('camunda:Properties', {
values: properties
});
}
}
function createInputOutputMappings(template, bpmnFactory) {
var inputParameters = [],
outputParameters = [];
template.properties.forEach(function(p) {
var binding = p.binding,
bindingType = binding.type;
if (bindingType === 'camunda:inputParameter') {
inputParameters.push(createInputParameter(
binding, p.value, bpmnFactory
));
}
if (bindingType === 'camunda:outputParameter') {
outputParameters.push(createOutputParameter(
binding, p.value, bpmnFactory
));
}
});
// do we need to create new ioMappings (?)
if (outputParameters.length || inputParameters.length) {
return bpmnFactory.create('camunda:InputOutput', {
inputParameters: inputParameters,
outputParameters: outputParameters
});
}
}
function createCamundaInOut(template, bpmnFactory) {
var inOuts = [];
template.properties.forEach(function(p) {
var binding = p.binding,
bindingType = binding.type;
if (bindingType === 'camunda:in') {
inOuts.push(createCamundaIn(
binding, p.value, bpmnFactory
));
} else
if (bindingType === 'camunda:out') {
inOuts.push(createCamundaOut(
binding, p.value, bpmnFactory
));
} else
if (bindingType === 'camunda:in:businessKey') {
inOuts.push(createCamundaInWithBusinessKey(
binding, p.value, bpmnFactory
));
}
});
return inOuts;
}
function createCamundaExecutionListener(template, bpmnFactory) {
var executionListener = [];
template.properties.forEach(function(p) {
var binding = p.binding,
bindingType = binding.type;
if (bindingType === 'camunda:executionListener') {
executionListener.push(createCamundaExecutionListenerScript(
binding, p.value, bpmnFactory
));
}
});
return executionListener;
}