diff options
Diffstat (limited to 'sdc-workflow-designer-ui/src/main/frontend/src/features/version/composition/custom-properties-provider/provider/camunda/parts')
13 files changed, 1654 insertions, 0 deletions
diff --git a/sdc-workflow-designer-ui/src/main/frontend/src/features/version/composition/custom-properties-provider/provider/camunda/parts/InputOutputParameterProps.js b/sdc-workflow-designer-ui/src/main/frontend/src/features/version/composition/custom-properties-provider/provider/camunda/parts/InputOutputParameterProps.js new file mode 100644 index 00000000..d221c6e3 --- /dev/null +++ b/sdc-workflow-designer-ui/src/main/frontend/src/features/version/composition/custom-properties-provider/provider/camunda/parts/InputOutputParameterProps.js @@ -0,0 +1,21 @@ +import inputOutputParameter from './implementation/InputOutputParameter'; +import assign from 'lodash.assign'; + +export default function( + group, + element, + bpmnFactory, + options, + translate, + config +) { + group.entries = group.entries.concat( + inputOutputParameter( + element, + bpmnFactory, + assign({}, options), + translate, + config + ) + ); +} diff --git a/sdc-workflow-designer-ui/src/main/frontend/src/features/version/composition/custom-properties-provider/provider/camunda/parts/InputOutputProps.js b/sdc-workflow-designer-ui/src/main/frontend/src/features/version/composition/custom-properties-provider/provider/camunda/parts/InputOutputProps.js new file mode 100644 index 00000000..bdcbab46 --- /dev/null +++ b/sdc-workflow-designer-ui/src/main/frontend/src/features/version/composition/custom-properties-provider/provider/camunda/parts/InputOutputProps.js @@ -0,0 +1,13 @@ +'use strict'; + +import inputOutput from './implementation/InputOutput'; + +export default function(group, element, bpmnFactory, translate) { + const inputOutputEntry = inputOutput(element, bpmnFactory, {}, translate); + + group.entries = group.entries.concat(inputOutputEntry.entries); + + return { + getSelectedParameter: inputOutputEntry.getSelectedParameter + }; +} diff --git a/sdc-workflow-designer-ui/src/main/frontend/src/features/version/composition/custom-properties-provider/provider/camunda/parts/WorkflowServiceTaskDelegateProps.js b/sdc-workflow-designer-ui/src/main/frontend/src/features/version/composition/custom-properties-provider/provider/camunda/parts/WorkflowServiceTaskDelegateProps.js new file mode 100644 index 00000000..bc871357 --- /dev/null +++ b/sdc-workflow-designer-ui/src/main/frontend/src/features/version/composition/custom-properties-provider/provider/camunda/parts/WorkflowServiceTaskDelegateProps.js @@ -0,0 +1,123 @@ +import inherits from 'inherits'; + +import ImplementationTypeHelper from 'bpmn-js-properties-panel/lib/helper/ImplementationTypeHelper'; +import ServiceTaskDelegateProps from 'bpmn-js-properties-panel/lib/provider/camunda/parts/ServiceTaskDelegateProps'; +import workflowImplementationType from './implementation/WorkflowImplementationType'; +import workflowActivity from './implementation/WorkflowActivity'; +import { + implementationType as implementationTypeConst, + serviceTaskEntries +} from './implementation/implementationConstants'; +import Delegate from './implementation/Delegate'; +import ResultVariable from './implementation/ResultVariable'; + +const getImplementationType = element => { + let implementationType = ImplementationTypeHelper.getImplementationType( + element + ); + + if (!implementationType || implementationType === 'expression') { + const bo = getBusinessObject(element); + if (bo) { + if ( + typeof bo.get(implementationTypeConst.ACTIVITY) !== 'undefined' + ) { + return 'workflowActivity'; + } + } + } + + return implementationType; +}; + +const hideResultVariable = element => { + return getImplementationType(element) !== 'expression'; +}; + +const getBusinessObject = element => + ImplementationTypeHelper.getServiceTaskLikeBusinessObject(element); + +const isDmnCapable = element => ImplementationTypeHelper.isDmnCapable(element); + +const isExternalCapable = element => + ImplementationTypeHelper.isExternalCapable(element); + +const isServiceTaskLike = element => + ImplementationTypeHelper.isServiceTaskLike(element); + +function WorkflowServiceTaskDelegateProps( + group, + element, + config, + bpmnFactory, + translate +) { + ServiceTaskDelegateProps.call(this, group, element, bpmnFactory, translate); + + if (isServiceTaskLike(getBusinessObject(element))) { + group.entries = group.entries.filter( + entry => + entry.id !== serviceTaskEntries.IMPLEMENTATION && + entry.id !== serviceTaskEntries.DELEGATE && + entry.id !== serviceTaskEntries.RESULT_VARIABLE + ); + + group.entries = group.entries.concat( + workflowActivity( + element, + config, + bpmnFactory, + { + getBusinessObject: getBusinessObject, + getImplementationType: getImplementationType + }, + translate + ) + ); + + group.entries = group.entries.concat( + Delegate( + element, + bpmnFactory, + { + getBusinessObject: getBusinessObject, + getImplementationType: getImplementationType + }, + translate + ) + ); + + group.entries = group.entries.concat( + ResultVariable( + element, + bpmnFactory, + { + getBusinessObject: getBusinessObject, + getImplementationType: getImplementationType, + hideResultVariable: hideResultVariable + }, + translate + ) + ); + group.entries = group.entries.concat( + workflowImplementationType( + element, + bpmnFactory, + { + getBusinessObject: getBusinessObject, + getImplementationType: getImplementationType, + hasDmnSupport: isDmnCapable(element), + hasExternalSupport: isExternalCapable( + getBusinessObject(element) + ), + hasServiceTaskLikeSupport: true + }, + translate + ) + ); + } +} + +inherits(WorkflowServiceTaskDelegateProps, ServiceTaskDelegateProps); + +export default WorkflowServiceTaskDelegateProps; diff --git a/sdc-workflow-designer-ui/src/main/frontend/src/features/version/composition/custom-properties-provider/provider/camunda/parts/createInputOutputTabGroups.js b/sdc-workflow-designer-ui/src/main/frontend/src/features/version/composition/custom-properties-provider/provider/camunda/parts/createInputOutputTabGroups.js new file mode 100644 index 00000000..3dede1a9 --- /dev/null +++ b/sdc-workflow-designer-ui/src/main/frontend/src/features/version/composition/custom-properties-provider/provider/camunda/parts/createInputOutputTabGroups.js @@ -0,0 +1,58 @@ +import inputOutputParameter from './InputOutputParameterProps'; +import inputOutput from './InputOutputProps'; +const is = require('bpmn-js/lib/util/ModelUtil').is; + +var getInputOutputParameterLabel = function(param, translate) { + if (is(param, 'camunda:InputParameter')) { + return translate('Input Parameter'); + } + + if (is(param, 'camunda:OutputParameter')) { + return translate('Output Parameter'); + } + + return ''; +}; + +export default function createInputOutputTabGroups( + element, + bpmnFactory, + elementRegistry, + translate, + config +) { + var inputOutputGroup = { + id: 'input-output', + label: translate('Parameters'), + entries: [] + }; + + var options = inputOutput( + inputOutputGroup, + element, + bpmnFactory, + translate + ); + var inputOutputParameterGroup = { + id: 'input-output-parameter', + entries: [], + enabled: function(element, node) { + return options.getSelectedParameter(element, node); + }, + label: function(element, node) { + var param = options.getSelectedParameter(element, node); + return getInputOutputParameterLabel(param, translate); + } + }; + + inputOutputParameter( + inputOutputParameterGroup, + element, + bpmnFactory, + options, + translate, + config + ); + + return [inputOutputGroup, inputOutputParameterGroup]; +} diff --git a/sdc-workflow-designer-ui/src/main/frontend/src/features/version/composition/custom-properties-provider/provider/camunda/parts/implementation/Delegate.js b/sdc-workflow-designer-ui/src/main/frontend/src/features/version/composition/custom-properties-provider/provider/camunda/parts/implementation/Delegate.js new file mode 100644 index 00000000..f6a0b247 --- /dev/null +++ b/sdc-workflow-designer-ui/src/main/frontend/src/features/version/composition/custom-properties-provider/provider/camunda/parts/implementation/Delegate.js @@ -0,0 +1,78 @@ +'use strict'; + +import entryFactory from 'bpmn-js-properties-panel/lib/factory/EntryFactory'; +import cmdHelper from 'bpmn-js-properties-panel/lib/helper/CmdHelper'; + +const DELEGATE_TYPES = ['class', 'expression', 'delegateExpression']; + +const PROPERTIES = { + class: 'camunda:class', + expression: 'camunda:expression', + delegateExpression: 'camunda:delegateExpression' +}; + +function isDelegate(type) { + return DELEGATE_TYPES.indexOf(type) !== -1; +} + +function getAttribute(type) { + return PROPERTIES[type]; +} + +export default function(element, bpmnFactory, options, translate) { + var getImplementationType = options.getImplementationType, + getBusinessObject = options.getBusinessObject; + + function getDelegationLabel(type) { + switch (type) { + case 'class': + return translate('Java Class'); + case 'expression': + return translate('Expression'); + case 'delegateExpression': + return translate('Delegate Expression'); + default: + return ''; + } + } + + var delegateEntry = entryFactory.textField({ + id: 'delegate', + label: translate('Value'), + dataValueLabel: 'delegationLabel', + modelProperty: 'delegate', + + get: function(element) { + var bo = getBusinessObject(element); + var type = getImplementationType(element); + var attr = getAttribute(type); + var label = getDelegationLabel(type); + return { + delegate: bo.get(attr), + delegationLabel: label + }; + }, + + set: function(element, values) { + var bo = getBusinessObject(element); + var type = getImplementationType(element); + var attr = getAttribute(type); + var prop = {}; + prop[attr] = values.delegate || ''; + return cmdHelper.updateBusinessObject(element, bo, prop); + }, + + validate: function(element, values) { + return isDelegate(getImplementationType(element)) && + !values.delegate + ? { delegate: 'Must provide a value' } + : {}; + }, + + hidden: function(element) { + return !isDelegate(getImplementationType(element)); + } + }); + + return [delegateEntry]; +} diff --git a/sdc-workflow-designer-ui/src/main/frontend/src/features/version/composition/custom-properties-provider/provider/camunda/parts/implementation/InputOutput.js b/sdc-workflow-designer-ui/src/main/frontend/src/features/version/composition/custom-properties-provider/provider/camunda/parts/implementation/InputOutput.js new file mode 100644 index 00000000..2bbef4f2 --- /dev/null +++ b/sdc-workflow-designer-ui/src/main/frontend/src/features/version/composition/custom-properties-provider/provider/camunda/parts/implementation/InputOutput.js @@ -0,0 +1,289 @@ +import inputOutputHelper from './InputOutputHelper'; +var getBusinessObject = require('bpmn-js/lib/util/ModelUtil').getBusinessObject; + +var elementHelper = require('bpmn-js-properties-panel/lib/helper/ElementHelper'), + extensionElementsHelper = require('bpmn-js-properties-panel/lib/helper/ExtensionElementsHelper'), + cmdHelper = require('bpmn-js-properties-panel/lib/helper/CmdHelper'); + +var extensionElementsEntry = require('bpmn-js-properties-panel/lib/provider/camunda/parts/implementation//ExtensionElements'); + +function getInputOutput(element, insideConnector) { + return inputOutputHelper.getInputOutput(element, insideConnector); +} + +function getConnector(element) { + return inputOutputHelper.getConnector(element); +} + +function getInputParameters(element, insideConnector) { + return inputOutputHelper.getInputParameters(element, insideConnector); +} + +function getOutputParameters(element, insideConnector) { + return inputOutputHelper.getOutputParameters(element, insideConnector); +} + +function getInputParameter(element, insideConnector, idx) { + return inputOutputHelper.getInputParameter(element, insideConnector, idx); +} + +function getOutputParameter(element, insideConnector, idx) { + return inputOutputHelper.getOutputParameter(element, insideConnector, idx); +} + +export function createElement(type, parent, factory, properties) { + const el = elementHelper.createElement(type, properties, parent, factory); + return el; +} + +export function createInputOutput(parent, bpmnFactory, properties) { + return createElement( + 'camunda:InputOutput', + parent, + bpmnFactory, + properties + ); +} + +function createParameter(type, parent, bpmnFactory, properties) { + return createElement(type, parent, bpmnFactory, properties); +} + +function ensureInputOutputSupported(element, insideConnector) { + return inputOutputHelper.isInputOutputSupported(element, insideConnector); +} + +function ensureOutparameterSupported(element, insideConnector) { + return inputOutputHelper.areOutputParametersSupported( + element, + insideConnector + ); +} + +export default function(element, bpmnFactory, options, translate) { + var TYPE_LABEL = { + 'camunda:Map': translate('Map'), + 'camunda:List': translate('List'), + 'camunda:Script': translate('Script') + }; + + options = options || {}; + + var insideConnector = !!options.insideConnector, + idPrefix = options.idPrefix || ''; + + var getSelected = function(element, node) { + var selection = (inputEntry && + inputEntry.getSelected(element, node)) || { idx: -1 }; + + var parameter = getInputParameter( + element, + insideConnector, + selection.idx + ); + if (!parameter && outputEntry) { + selection = outputEntry.getSelected(element, node); + parameter = getOutputParameter( + element, + insideConnector, + selection.idx + ); + } + return parameter; + }; + + var result = { + getSelectedParameter: getSelected + }; + + var entries = (result.entries = []); + + if (!ensureInputOutputSupported(element)) { + return result; + } + + var newElement = function(type, prop, elementData) { + return function(element, extensionElements, value) { + var commands = []; + + var inputOutput = getInputOutput(element, insideConnector); + if (!inputOutput) { + var parent = !insideConnector + ? extensionElements + : getConnector(element); + + inputOutput = createInputOutput(parent, bpmnFactory, { + inputParameters: [], + outputParameters: [] + }); + + if (!insideConnector) { + commands.push( + cmdHelper.addAndRemoveElementsFromList( + element, + extensionElements, + 'values', + 'extensionElements', + [inputOutput], + [] + ) + ); + } else { + commands.push( + cmdHelper.updateBusinessObject(element, parent, { + inputOutput: inputOutput + }) + ); + } + } + + var newElem = elementData + ? createParameter(type, inputOutput, bpmnFactory, elementData) + : createParameter(type, inputOutput, bpmnFactory, { + name: value + }); + + commands.push( + cmdHelper.addElementsTolist(element, inputOutput, prop, [ + newElem + ]) + ); + + return commands; + }; + }; + + var removeElement = function(getter, prop, otherProp) { + return function(element, extensionElements, value, idx) { + var inputOutput = getInputOutput(element, insideConnector); + var parameter = getter(element, insideConnector, idx); + + var commands = []; + commands.push( + cmdHelper.removeElementsFromList( + element, + inputOutput, + prop, + null, + [parameter] + ) + ); + + var firstLength = inputOutput.get(prop).length - 1; + var secondLength = (inputOutput.get(otherProp) || []).length; + + if (!firstLength && !secondLength) { + if (!insideConnector) { + commands.push( + extensionElementsHelper.removeEntry( + getBusinessObject(element), + element, + inputOutput + ) + ); + } else { + var connector = getConnector(element); + commands.push( + cmdHelper.updateBusinessObject(element, connector, { + inputOutput: undefined + }) + ); + } + } + + return commands; + }; + }; + + var setOptionLabelValue = function(getter) { + return function(element, node, option, property, value, idx) { + var parameter = getter(element, insideConnector, idx); + + var suffix = 'Text'; + + var definition = parameter.get('definition'); + if (typeof definition !== 'undefined') { + var type = definition.$type; + suffix = TYPE_LABEL[type]; + } + + option.text = (value || '') + ' : ' + suffix; + }; + }; + + // input parameters /////////////////////////////////////////////////////////////// + + var inputEntry = extensionElementsEntry(element, bpmnFactory, { + id: idPrefix + 'inputs', + label: translate('Input Parameters'), + modelProperty: 'name', + prefix: 'Input', + resizable: true, + + createExtensionElement: inputOutputHelper.isCreateDeleteSupported( + element + ) + ? newElement('camunda:InputParameter', 'inputParameters') + : undefined, + removeExtensionElement: inputOutputHelper.isCreateDeleteSupported( + element + ) + ? removeElement( + getInputParameter, + 'inputParameters', + 'outputParameters' + ) + : undefined, + + getExtensionElements: function(element) { + return getInputParameters(element, insideConnector); + }, + + onSelectionChange: function(element, node) { + outputEntry && outputEntry.deselect(element, node); + }, + + setOptionLabelValue: setOptionLabelValue(getInputParameter) + }); + entries.push(inputEntry); + + // output parameters /////////////////////////////////////////////////////// + + if (ensureOutparameterSupported(element, insideConnector)) { + var outputEntry = extensionElementsEntry(element, bpmnFactory, { + id: idPrefix + 'outputs', + label: translate('Output Parameters'), + modelProperty: 'name', + prefix: 'Output', + resizable: true, + + createExtensionElement: inputOutputHelper.isCreateDeleteSupported( + element + ) + ? newElement('camunda:OutputParameter', 'outputParameters') + : undefined, + removeExtensionElement: inputOutputHelper.isCreateDeleteSupported( + element + ) + ? removeElement( + getOutputParameter, + 'outputParameters', + 'inputParameters' + ) + : inputOutputHelper.isCreateDeleteSupported(element), + + getExtensionElements: function(element) { + return getOutputParameters(element, insideConnector); + }, + + onSelectionChange: function(element, node) { + inputEntry.deselect(element, node); + }, + + setOptionLabelValue: setOptionLabelValue(getOutputParameter) + }); + entries.push(outputEntry); + } + + return result; +} diff --git a/sdc-workflow-designer-ui/src/main/frontend/src/features/version/composition/custom-properties-provider/provider/camunda/parts/implementation/InputOutputHelper.js b/sdc-workflow-designer-ui/src/main/frontend/src/features/version/composition/custom-properties-provider/provider/camunda/parts/implementation/InputOutputHelper.js new file mode 100644 index 00000000..595ab799 --- /dev/null +++ b/sdc-workflow-designer-ui/src/main/frontend/src/features/version/composition/custom-properties-provider/provider/camunda/parts/implementation/InputOutputHelper.js @@ -0,0 +1,173 @@ +var ModelUtil = require('bpmn-js/lib/util/ModelUtil'), + is = ModelUtil.is, + getBusinessObject = ModelUtil.getBusinessObject; + +var extensionElementsHelper = require('bpmn-js-properties-panel/lib/helper/ExtensionElementsHelper'), + implementationTypeHelper = require('bpmn-js-properties-panel/lib/helper/ImplementationTypeHelper'); +import { implementationType } from './implementationConstants'; + +var InputOutputHelper = {}; + +function getElements(bo, type, prop) { + var elems = extensionElementsHelper.getExtensionElements(bo, type) || []; + return !prop ? elems : (elems[0] || {})[prop] || []; +} + +function getParameters(element, prop, insideConnector) { + var inputOutput = InputOutputHelper.getInputOutput( + element, + insideConnector + ); + return (inputOutput && inputOutput.get(prop)) || []; +} + +/** + * Get a inputOutput from the business object + * + * @param {djs.model.Base} element + * @param {boolean} insideConnector + * + * @return {ModdleElement} the inputOutput object + */ +InputOutputHelper.getInputOutput = function(element, insideConnector) { + if (!insideConnector) { + var bo = getBusinessObject(element); + return (getElements(bo, 'camunda:InputOutput') || [])[0]; + } + var connector = this.getConnector(element); + + return connector && connector.get('inputOutput'); +}; + +/** + * Get a connector from the business object + * + * @param {djs.model.Base} element + * + * @return {ModdleElement} the connector object + */ +InputOutputHelper.getConnector = function(element) { + var bo = implementationTypeHelper.getServiceTaskLikeBusinessObject(element); + return bo && (getElements(bo, 'camunda:Connector') || [])[0]; +}; + +/** + * Return all input parameters existing in the business object, and + * an empty array if none exist. + * + * @param {djs.model.Base} element + * @param {boolean} insideConnector + * + * @return {Array} a list of input parameter objects + */ +InputOutputHelper.getInputParameters = function(element, insideConnector) { + return getParameters.apply(this, [ + element, + 'inputParameters', + insideConnector + ]); +}; + +/** + * Return all output parameters existing in the business object, and + * an empty array if none exist. + * + * @param {djs.model.Base} element + * @param {boolean} insideConnector + * + * @return {Array} a list of output parameter objects + */ +InputOutputHelper.getOutputParameters = function(element, insideConnector) { + return getParameters.apply(this, [ + element, + 'outputParameters', + insideConnector + ]); +}; + +/** + * Get a input parameter from the business object at given index + * + * @param {djs.model.Base} element + * @param {boolean} insideConnector + * @param {number} idx + * + * @return {ModdleElement} input parameter + */ +InputOutputHelper.getInputParameter = function(element, insideConnector, idx) { + return this.getInputParameters(element, insideConnector)[idx]; +}; + +/** + * Get a output parameter from the business object at given index + * + * @param {djs.model.Base} element + * @param {boolean} insideConnector + * @param {number} idx + * + * @return {ModdleElement} output parameter + */ +InputOutputHelper.getOutputParameter = function(element, insideConnector, idx) { + return this.getOutputParameters(element, insideConnector)[idx]; +}; + +/** + * Returns 'true' if the given element supports inputOutput + * + * @param {djs.model.Base} element + * @param {boolean} insideConnector + * + * @return {boolean} a boolean value + */ +InputOutputHelper.isInputOutputSupported = function(element, insideConnector) { + var bo = getBusinessObject(element); + return ( + insideConnector || + is(bo, 'bpmn:Process') || + (is(bo, 'bpmn:FlowNode') && + !is(bo, 'bpmn:StartEvent') && + !is(bo, 'bpmn:BoundaryEvent') && + !(is(bo, 'bpmn:SubProcess') && bo.get('triggeredByEvent'))) + ); +}; + +/** + * Returns 'true' if the given element supports output parameters + * + * @param {djs.model.Base} element + * @param {boolean} insideConnector + * + * @return {boolean} a boolean value + */ +InputOutputHelper.areOutputParametersSupported = function( + element, + insideConnector +) { + var bo = getBusinessObject(element); + return ( + insideConnector || (!is(bo, 'bpmn:EndEvent') && !bo.loopCharacteristics) + ); +}; + +InputOutputHelper.isCreateDeleteSupported = function(element) { + const bo = getBusinessObject(element); + return ( + (element.type !== 'bpmn:ServiceTask' || + !bo[implementationType.ACTIVITY]) && + element.type !== 'bpmn:Process' + ); +}; + +InputOutputHelper.isWorkflowTargetSupported = function(element, selected) { + const bo = getBusinessObject(element); + return ( + is(bo, 'bpmn:ServiceTask') && is(selected, 'camunda:OutputParameter') + ); +}; + +InputOutputHelper.isWorkflowSourceSupported = function(element, selected) { + const bo = getBusinessObject(element); + return is(bo, 'bpmn:ServiceTask') && is(selected, 'camunda:InputParameter'); +}; + +export default InputOutputHelper; diff --git a/sdc-workflow-designer-ui/src/main/frontend/src/features/version/composition/custom-properties-provider/provider/camunda/parts/implementation/InputOutputParameter.js b/sdc-workflow-designer-ui/src/main/frontend/src/features/version/composition/custom-properties-provider/provider/camunda/parts/implementation/InputOutputParameter.js new file mode 100644 index 00000000..10e258e3 --- /dev/null +++ b/sdc-workflow-designer-ui/src/main/frontend/src/features/version/composition/custom-properties-provider/provider/camunda/parts/implementation/InputOutputParameter.js @@ -0,0 +1,424 @@ +import inputOutputHelper from './InputOutputHelper'; + +var is = require('bpmn-js/lib/util/ModelUtil').is; + +var elementHelper = require('bpmn-js-properties-panel/lib/helper/ElementHelper'), + cmdHelper = require('bpmn-js-properties-panel/lib/helper/CmdHelper'), + utils = require('bpmn-js-properties-panel/lib/Utils'); + +var entryFactory = require('bpmn-js-properties-panel/lib/factory/EntryFactory'), + script = require('bpmn-js-properties-panel/lib/provider/camunda/parts/implementation/Script')( + 'scriptFormat', + 'value', + true + ); + +function createElement(type, parent, factory, properties) { + return elementHelper.createElement(type, properties, parent, factory); +} + +function isScript(elem) { + return is(elem, 'camunda:Script'); +} + +function isList(elem) { + return is(elem, 'camunda:List'); +} + +function isMap(elem) { + return is(elem, 'camunda:Map'); +} + +function ensureInputOutputSupported(element, insideConnector) { + return inputOutputHelper.isInputOutputSupported(element, insideConnector); +} + +export default function(element, bpmnFactory, options, translate) { + var typeInfo = { + 'camunda:Map': { + value: 'map', + label: translate('Map') + }, + 'camunda:List': { + value: 'list', + label: translate('List') + }, + 'camunda:Script': { + value: 'script', + label: translate('Script') + } + }; + + options = options || {}; + + var insideConnector = !!options.insideConnector, + idPrefix = options.idPrefix || ''; + + var getSelected = options.getSelectedParameter; + + if (!ensureInputOutputSupported(element, insideConnector)) { + return []; + } + + var entries = []; + + var isSelected = function(element, node) { + return getSelected(element, node); + }; + + // parameter name //////////////////////////////////////////////////////// + + entries.push( + entryFactory.validationAwareTextField({ + id: idPrefix + 'parameterName', + label: 'Name', + modelProperty: 'name', + + getProperty: function(element, node) { + return (getSelected(element, node) || {}).name; + }, + + setProperty: function(element, values, node) { + var param = getSelected(element, node); + return cmdHelper.updateBusinessObject(element, param, values); + }, + + validate: function(element, values, node) { + var bo = getSelected(element, node); + + var validation = {}; + if (bo) { + var nameValue = values.name; + + if (nameValue) { + if (utils.containsSpace(nameValue)) { + validation.name = 'Name must not contain spaces'; + } + } else { + validation.name = 'Parameter must have a name'; + } + } + + return validation; + }, + + hidden: function(element, node) { + return !isSelected(element, node); + }, + disabled: function(element) { + return !inputOutputHelper.isCreateDeleteSupported(element); + } + }) + ); + + // parameter type ////////////////////////////////////////////////////// + + var selectOptions = [ + { value: 'text', name: 'Text' }, + { value: 'script', name: 'Script' }, + { value: 'list', name: 'List' }, + { value: 'map', name: 'Map' } + ]; + + entries.push( + entryFactory.selectBox({ + id: idPrefix + 'parameterType', + label: 'Type', + selectOptions: selectOptions, + modelProperty: 'parameterType', + + get: function(element, node) { + var bo = getSelected(element, node); + + var parameterType = 'text'; + + if (typeof bo !== 'undefined') { + var definition = bo.get('definition'); + if (typeof definition !== 'undefined') { + var type = definition.$type; + parameterType = typeInfo[type].value; + } + } + + return { + parameterType: parameterType + }; + }, + + set: function(element, values, node) { + var bo = getSelected(element, node); + + var properties = { + value: undefined, + definition: undefined + }; + + var createParameterTypeElem = function(type) { + return createElement(type, bo, bpmnFactory); + }; + + var parameterType = values.parameterType; + + if (parameterType === 'script') { + properties.definition = createParameterTypeElem( + 'camunda:Script' + ); + } else if (parameterType === 'list') { + properties.definition = createParameterTypeElem( + 'camunda:List' + ); + } else if (parameterType === 'map') { + properties.definition = createParameterTypeElem( + 'camunda:Map' + ); + } + + return cmdHelper.updateBusinessObject(element, bo, properties); + }, + + show: function(element, node) { + return isSelected(element, node); + }, + disabled: function(element) { + return !inputOutputHelper.isCreateDeleteSupported(element); + } + }) + ); + + // parameter value (type = text) /////////////////////////////////////////////////////// + + entries.push( + entryFactory.textBox({ + id: idPrefix + 'parameterType-text', + label: 'Value', + modelProperty: 'value', + get: function(element, node) { + return { + value: (getSelected(element, node) || {}).value + }; + }, + + set: function(element, values, node) { + var param = getSelected(element, node); + values.value = values.value || undefined; + return cmdHelper.updateBusinessObject(element, param, values); + }, + + show: function(element, node) { + var bo = getSelected(element, node); + return bo && !bo.definition; + } + }) + ); + + // parameter value (type = script) /////////////////////////////////////////////////////// + + entries.push({ + id: idPrefix + 'parameterType-script', + html: '<div data-show="isScript">' + script.template + '</div>', + get: function(element, node) { + var bo = getSelected(element, node); + return bo && isScript(bo.definition) + ? script.get(element, bo.definition) + : {}; + }, + + set: function(element, values, node) { + var bo = getSelected(element, node); + var update = script.set(element, values); + return cmdHelper.updateBusinessObject( + element, + bo.definition, + update + ); + }, + + validate: function(element, values, node) { + var bo = getSelected(element, node); + return bo && isScript(bo.definition) + ? script.validate(element, bo.definition) + : {}; + }, + + isScript: function(element, node) { + var bo = getSelected(element, node); + return bo && isScript(bo.definition); + }, + + script: script + }); + + // parameter value (type = list) /////////////////////////////////////////////////////// + + entries.push( + entryFactory.table({ + id: idPrefix + 'parameterType-list', + modelProperties: ['value'], + labels: ['Value'], + + getElements: function(element, node) { + var bo = getSelected(element, node); + + if (bo && isList(bo.definition)) { + return bo.definition.items; + } + + return []; + }, + + updateElement: function(element, values, node, idx) { + var bo = getSelected(element, node); + var item = bo.definition.items[idx]; + return cmdHelper.updateBusinessObject(element, item, values); + }, + + addElement: function(element, node) { + var bo = getSelected(element, node); + var newValue = createElement( + 'camunda:Value', + bo.definition, + bpmnFactory, + { value: undefined } + ); + return cmdHelper.addElementsTolist( + element, + bo.definition, + 'items', + [newValue] + ); + }, + + removeElement: function(element, node, idx) { + var bo = getSelected(element, node); + return cmdHelper.removeElementsFromList( + element, + bo.definition, + 'items', + null, + [bo.definition.items[idx]] + ); + }, + + editable: function(element, node, prop, idx) { + var bo = getSelected(element, node); + var item = bo.definition.items[idx]; + return !isMap(item) && !isList(item) && !isScript(item); + }, + + setControlValue: function(element, node, input, prop, value, idx) { + var bo = getSelected(element, node); + var item = bo.definition.items[idx]; + + if (!isMap(item) && !isList(item) && !isScript(item)) { + input.value = value; + } else { + input.value = typeInfo[item.$type].label; + } + }, + + show: function(element, node) { + var bo = getSelected(element, node); + return bo && bo.definition && isList(bo.definition); + } + }) + ); + + // parameter value (type = map) /////////////////////////////////////////////////////// + + entries.push( + entryFactory.table({ + id: idPrefix + 'parameterType-map', + modelProperties: ['key', 'value'], + labels: ['Key', 'Value'], + addLabel: 'Add Entry', + + getElements: function(element, node) { + var bo = getSelected(element, node); + + if (bo && isMap(bo.definition)) { + return bo.definition.entries; + } + + return []; + }, + + updateElement: function(element, values, node, idx) { + var bo = getSelected(element, node); + var entry = bo.definition.entries[idx]; + + if ( + isMap(entry.definition) || + isList(entry.definition) || + isScript(entry.definition) + ) { + values = { + key: values.key + }; + } + + return cmdHelper.updateBusinessObject(element, entry, values); + }, + + addElement: function(element, node) { + var bo = getSelected(element, node); + var newEntry = createElement( + 'camunda:Entry', + bo.definition, + bpmnFactory, + { key: undefined, value: undefined } + ); + return cmdHelper.addElementsTolist( + element, + bo.definition, + 'entries', + [newEntry] + ); + }, + + removeElement: function(element, node, idx) { + var bo = getSelected(element, node); + return cmdHelper.removeElementsFromList( + element, + bo.definition, + 'entries', + null, + [bo.definition.entries[idx]] + ); + }, + + editable: function(element, node, prop, idx) { + var bo = getSelected(element, node); + var entry = bo.definition.entries[idx]; + return ( + prop === 'key' || + (!isMap(entry.definition) && + !isList(entry.definition) && + !isScript(entry.definition)) + ); + }, + + setControlValue: function(element, node, input, prop, value, idx) { + var bo = getSelected(element, node); + var entry = bo.definition.entries[idx]; + + if ( + prop === 'key' || + (!isMap(entry.definition) && + !isList(entry.definition) && + !isScript(entry.definition)) + ) { + input.value = value; + } else { + input.value = typeInfo[entry.definition.$type].label; + } + }, + + show: function(element, node) { + var bo = getSelected(element, node); + return bo && bo.definition && isMap(bo.definition); + } + }) + ); + + return entries; +} diff --git a/sdc-workflow-designer-ui/src/main/frontend/src/features/version/composition/custom-properties-provider/provider/camunda/parts/implementation/InputOutputUpdater.js b/sdc-workflow-designer-ui/src/main/frontend/src/features/version/composition/custom-properties-provider/provider/camunda/parts/implementation/InputOutputUpdater.js new file mode 100644 index 00000000..056a2dba --- /dev/null +++ b/sdc-workflow-designer-ui/src/main/frontend/src/features/version/composition/custom-properties-provider/provider/camunda/parts/implementation/InputOutputUpdater.js @@ -0,0 +1,74 @@ +/* +* Copyright © 2018 European Support Limited +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +*http://www.apache.org/licenses/LICENSE-2.0 +* + * Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import cmdHelper from 'bpmn-js-properties-panel/lib/helper/CmdHelper'; +import { createInputOutput, createElement } from './InputOutput'; +import InputOutputHelper from './InputOutputHelper'; +import { INPUT, OUTPUT } from './implementationConstants'; + +export default ({ element, bo, bpmnFactory, activityInputsOutputs }) => { + const commands = []; + const existedInputOutput = InputOutputHelper.getInputOutput(element); + + let newInputOutput = createInputOutput(element, bpmnFactory, { + inputParameters: [], + outputParameters: [] + }); + + const inputs = activityInputsOutputs.inputs.map(({ name, value }) => + createElement(INPUT, newInputOutput, bpmnFactory, { + name, + type: 'Text', + value + }) + ); + + const outputs = activityInputsOutputs.outputs.map(({ name, value }) => + createElement(OUTPUT, newInputOutput, bpmnFactory, { + name, + type: 'Text', + value + }) + ); + + newInputOutput.inputParameters = inputs; + newInputOutput.outputParameters = outputs; + + const objectToRemove = existedInputOutput ? [existedInputOutput] : []; + const extensionElements = + bo.extensionElements || + createElement('bpmn:ExtensionElements', bo, bpmnFactory, []); + + if (!bo.extensionElements) { + commands.push( + cmdHelper.updateBusinessObject(element, bo, { + extensionElements + }) + ); + } + + commands.push( + cmdHelper.addAndRemoveElementsFromList( + element, + extensionElements, + 'values', + 'extensionElements', + [newInputOutput], + objectToRemove + ) + ); + return commands; +}; diff --git a/sdc-workflow-designer-ui/src/main/frontend/src/features/version/composition/custom-properties-provider/provider/camunda/parts/implementation/ResultVariable.js b/sdc-workflow-designer-ui/src/main/frontend/src/features/version/composition/custom-properties-provider/provider/camunda/parts/implementation/ResultVariable.js new file mode 100644 index 00000000..a0b425fe --- /dev/null +++ b/sdc-workflow-designer-ui/src/main/frontend/src/features/version/composition/custom-properties-provider/provider/camunda/parts/implementation/ResultVariable.js @@ -0,0 +1,52 @@ +'use strict'; + +import { is } from 'bpmn-js/lib/util/ModelUtil'; + +import assign from 'lodash.assign'; + +var entryFactory = require('bpmn-js-properties-panel/lib/factory/EntryFactory'), + cmdHelper = require('bpmn-js-properties-panel/lib/helper/CmdHelper'); + +export default function(element, bpmnFactory, options, translate) { + var getBusinessObject = options.getBusinessObject, + hideResultVariable = options.hideResultVariable, + id = options.id || 'resultVariable'; + + var resultVariableEntry = entryFactory.textField({ + id: id, + label: translate('Result Variable'), + modelProperty: 'resultVariable', + + get: function(element) { + var bo = getBusinessObject(element); + return { resultVariable: bo.get('camunda:resultVariable') }; + }, + + set: function(element, values) { + var bo = getBusinessObject(element); + + var resultVariable = values.resultVariable || undefined; + + var props = { + 'camunda:resultVariable': resultVariable + }; + + if (is(bo, 'camunda:DmnCapable') && !resultVariable) { + props = assign( + { 'camunda:mapDecisionResult': 'resultList' }, + props + ); + } + + return cmdHelper.updateBusinessObject(element, bo, props); + }, + + hidden: function() { + if (typeof hideResultVariable === 'function') { + return hideResultVariable.apply(resultVariableEntry, arguments); + } + } + }); + + return [resultVariableEntry]; +} diff --git a/sdc-workflow-designer-ui/src/main/frontend/src/features/version/composition/custom-properties-provider/provider/camunda/parts/implementation/WorkflowActivity.js b/sdc-workflow-designer-ui/src/main/frontend/src/features/version/composition/custom-properties-provider/provider/camunda/parts/implementation/WorkflowActivity.js new file mode 100644 index 00000000..6616f6a4 --- /dev/null +++ b/sdc-workflow-designer-ui/src/main/frontend/src/features/version/composition/custom-properties-provider/provider/camunda/parts/implementation/WorkflowActivity.js @@ -0,0 +1,89 @@ +import entryFactory from 'bpmn-js-properties-panel/lib/factory/EntryFactory'; +import cmdHelper from 'bpmn-js-properties-panel/lib/helper/CmdHelper'; +import { + implementationType, + IMPLEMENTATION_TYPE_VALUE, + SERVICE_TASK_NAME +} from './implementationConstants'; + +import InputOutputUpdater from './InputOutputUpdater'; + +const workflowActivity = (element, config, bpmnFactory, options, translate) => { + const { getImplementationType, getBusinessObject } = options; + + const isWorkflowActivity = element => + getImplementationType(element) === 'workflowActivity'; + + const workflowActivityEntry = entryFactory.selectBox({ + id: 'activitySelect', + label: translate('Activity Spec'), + selectOptions: config.activities, + emptyParameter: true, + modelProperty: 'workflowActivity', + + get: function(element) { + var bo = getBusinessObject(element); + const value = bo.get(implementationType.ACTIVITY); + const activityValue = + value && value.indexOf(IMPLEMENTATION_TYPE_VALUE) > -1 + ? value.substr(IMPLEMENTATION_TYPE_VALUE.length) + : ''; + + return { + workflowActivity: activityValue + }; + }, + + set: function(element, values) { + var bo = getBusinessObject(element); + + const commands = []; + const dataForUpdate = {}; + + const activityInputsOutputs = config.getActivityInputsOutputs( + values.workflowActivity + ); + + dataForUpdate[ + implementationType.ACTIVITY + ] = `${IMPLEMENTATION_TYPE_VALUE}${values.workflowActivity}`; + + dataForUpdate[implementationType.EXPRESSION] = + implementationType.EXPRESSION_VALUE; + + dataForUpdate[SERVICE_TASK_NAME] = values.workflowActivity; + + commands.push( + cmdHelper.updateBusinessObject(element, bo, dataForUpdate) + ); + return [ + ...commands, + ...InputOutputUpdater({ + element, + bo, + bpmnFactory, + activityInputsOutputs, + commands + }) + ]; + }, + + validate: function(element, values) { + const hasErrors = + isWorkflowActivity(element) && !values.workflowActivity; + config.validationUpdate(element, !hasErrors); + + return hasErrors + ? { workflowActivity: 'Must provide a value' } + : {}; + }, + + hidden: function(element) { + return !isWorkflowActivity(element); + } + }); + + return [workflowActivityEntry]; +}; + +export default workflowActivity; diff --git a/sdc-workflow-designer-ui/src/main/frontend/src/features/version/composition/custom-properties-provider/provider/camunda/parts/implementation/WorkflowImplementationType.js b/sdc-workflow-designer-ui/src/main/frontend/src/features/version/composition/custom-properties-provider/provider/camunda/parts/implementation/WorkflowImplementationType.js new file mode 100644 index 00000000..729cc22b --- /dev/null +++ b/sdc-workflow-designer-ui/src/main/frontend/src/features/version/composition/custom-properties-provider/provider/camunda/parts/implementation/WorkflowImplementationType.js @@ -0,0 +1,226 @@ +var entryFactory = require('bpmn-js-properties-panel/lib/factory/EntryFactory'), + cmdHelper = require('bpmn-js-properties-panel/lib/helper/CmdHelper'), + extensionElementsHelper = require('bpmn-js-properties-panel/lib/helper/ExtensionElementsHelper'), + elementHelper = require('bpmn-js-properties-panel/lib/helper/ElementHelper'); + +var assign = require('lodash.assign'); +var map = require('lodash.map'); +import { implementationType } from './implementationConstants'; + +var DEFAULT_DELEGATE_PROPS = ['class', 'expression', 'delegateExpression']; + +var DELEGATE_PROPS = { + 'camunda:class': undefined, + 'camunda:expression': undefined, + 'camunda:delegateExpression': undefined, + 'camunda:resultVariable': undefined +}; + +var DMN_CAPABLE_PROPS = { + 'camunda:decisionRef': undefined, + 'camunda:decisionRefBinding': 'latest', + 'camunda:decisionRefVersion': undefined, + 'camunda:mapDecisionResult': 'resultList', + 'camunda:decisionRefTenantId': undefined +}; + +var EXTERNAL_CAPABLE_PROPS = { + 'camunda:type': undefined, + 'camunda:topic': undefined +}; + +const ACTIVITY_PROPS = {}; + +ACTIVITY_PROPS[implementationType] = undefined; + +export default function(element, bpmnFactory, options, translate) { + var DEFAULT_OPTIONS = [ + { value: 'class', name: translate('Java Class') }, + { value: 'expression', name: translate('Expression') }, + { value: 'delegateExpression', name: translate('Delegate Expression') } + ]; + + var DMN_OPTION = [{ value: 'dmn', name: translate('DMN') }]; + + var EXTERNAL_OPTION = [{ value: 'external', name: translate('External') }]; + + var CONNECTOR_OPTION = [ + { value: 'connector', name: translate('Connector') } + ]; + + var SCRIPT_OPTION = [{ value: 'script', name: translate('Script') }]; + + var ACTIVITY_OPTION = [ + { value: 'workflowActivity', name: translate('Activity') } + ]; + + var getType = options.getImplementationType, + getBusinessObject = options.getBusinessObject; + + var hasDmnSupport = options.hasDmnSupport, + hasExternalSupport = options.hasExternalSupport, + hasServiceTaskLikeSupport = options.hasServiceTaskLikeSupport, + hasScriptSupport = options.hasScriptSupport; + + var entries = []; + + var selectOptions = DEFAULT_OPTIONS.concat([]); + + if (hasDmnSupport) { + selectOptions = selectOptions.concat(DMN_OPTION); + } + + if (hasExternalSupport) { + selectOptions = selectOptions.concat(EXTERNAL_OPTION); + } + + if (hasServiceTaskLikeSupport) { + selectOptions = selectOptions.concat(CONNECTOR_OPTION); + } + + if (hasScriptSupport) { + selectOptions = selectOptions.concat(SCRIPT_OPTION); + } + + selectOptions = selectOptions.concat(ACTIVITY_OPTION); + + selectOptions.push({ value: '' }); + + entries.push( + entryFactory.selectBox({ + id: 'implementation', + label: translate('Implementation'), + selectOptions: selectOptions, + modelProperty: 'implType', + + get: function(element) { + return { + implType: getType(element) || '' + }; + }, + + set: function(element, values) { + var bo = getBusinessObject(element); + var oldType = getType(element); + var newType = values.implType; + var props = assign({}, DELEGATE_PROPS); + + if (DEFAULT_DELEGATE_PROPS.indexOf(newType) !== -1) { + var newValue = ''; + if (DEFAULT_DELEGATE_PROPS.indexOf(oldType) !== -1) { + newValue = bo.get('camunda:' + oldType); + } + + props['camunda:' + newType] = newValue; + } + + if (hasDmnSupport) { + props = assign(props, DMN_CAPABLE_PROPS); + if (newType === 'dmn') { + props['camunda:decisionRef'] = ''; + } + } + + if (hasExternalSupport) { + props = assign(props, EXTERNAL_CAPABLE_PROPS); + if (newType === 'external') { + props['camunda:type'] = 'external'; + props['camunda:topic'] = ''; + } + } + + if (hasScriptSupport) { + props['camunda:script'] = undefined; + + if (newType === 'script') { + props['camunda:script'] = elementHelper.createElement( + 'camunda:Script', + {}, + bo, + bpmnFactory + ); + } + } + props = assign(props, ACTIVITY_PROPS); + props[implementationType.ACTIVITY] = undefined; + + var commands = []; + if (newType === 'workflowActivity') { + props[implementationType.ACTIVITY] = ''; + props[implementationType.RESULT_VARIABLE] = undefined; + props[implementationType.EXPRESSION] = undefined; + } else { + var inputsOutputs = extensionElementsHelper.getExtensionElements( + bo, + 'camunda:InputOutput' + ); + commands.push( + map(inputsOutputs, function(inputOutput) { + return extensionElementsHelper.removeEntry( + bo, + element, + inputOutput + ); + }) + ); + } + + commands.push( + cmdHelper.updateBusinessObject(element, bo, props) + ); + + if (hasServiceTaskLikeSupport) { + var connectors = extensionElementsHelper.getExtensionElements( + bo, + 'camunda:Connector' + ); + commands.push( + map(connectors, function(connector) { + return extensionElementsHelper.removeEntry( + bo, + element, + connector + ); + }) + ); + + if (newType === 'connector') { + var extensionElements = bo.get('extensionElements'); + if (!extensionElements) { + extensionElements = elementHelper.createElement( + 'bpmn:ExtensionElements', + { values: [] }, + bo, + bpmnFactory + ); + commands.push( + cmdHelper.updateBusinessObject(element, bo, { + extensionElements: extensionElements + }) + ); + } + var connector = elementHelper.createElement( + 'camunda:Connector', + {}, + extensionElements, + bpmnFactory + ); + commands.push( + cmdHelper.addAndRemoveElementsFromList( + element, + extensionElements, + 'values', + 'extensionElements', + [connector], + [] + ) + ); + } + } + return commands; + } + }) + ); + + return entries; +} diff --git a/sdc-workflow-designer-ui/src/main/frontend/src/features/version/composition/custom-properties-provider/provider/camunda/parts/implementation/implementationConstants.js b/sdc-workflow-designer-ui/src/main/frontend/src/features/version/composition/custom-properties-provider/provider/camunda/parts/implementation/implementationConstants.js new file mode 100644 index 00000000..efc70800 --- /dev/null +++ b/sdc-workflow-designer-ui/src/main/frontend/src/features/version/composition/custom-properties-provider/provider/camunda/parts/implementation/implementationConstants.js @@ -0,0 +1,34 @@ +/* +* Copyright © 2018 European Support Limited +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +*http://www.apache.org/licenses/LICENSE-2.0 +* + * Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +export const implementationType = { + ACTIVITY: 'implementation', + EXPRESSION: 'camunda:expression', + EXPRESSION_VALUE: '${ExecuteActivity.execute(execution)}', + RESULT_VARIABLE: 'camunda:resultVariable' +}; + +export const IMPLEMENTATION_TYPE_VALUE = 'activity:'; +export const SERVICE_TASK_NAME = 'name'; + +export const serviceTaskEntries = { + IMPLEMENTATION: 'implementation', + DELEGATE: 'delegate', + RESULT_VARIABLE: 'resultVariable' +}; + +export const INPUT = 'camunda:InputParameter'; +export const OUTPUT = 'camunda:OutputParameter'; |