spiff-arena/bpmn-js-spiffworkflow/app/spiffworkflow/eventSelect.js

252 lines
7.6 KiB
JavaScript

import { is, isAny } from 'bpmn-js/lib/util/ModelUtil';
import { useService } from 'bpmn-js-properties-panel';
import {
ListGroup,
TextFieldEntry,
TextAreaEntry,
SelectEntry,
isTextFieldEntryEdited
} from '@bpmn-io/properties-panel';
import { getRoot } from './helpers';
function hasEventType(element, eventType) {
const events = element.businessObject.eventDefinitions;
return events && events.filter(item => is(item, eventType)).length > 0;
}
function replaceGroup(groupId, groups, group) {
const idx = groups.map(g => g.id).indexOf(groupId);
if (idx > -1)
groups.splice(idx, 1, group);
else
groups.push(group);
group.shouldOpen = true;
}
function isCatchingEvent(element) {
return isAny(element, ['bpmn:StartEvent', 'bpmn:IntermediateCatchEvent', 'bpmn:BoundaryEvent']);
}
function isThrowingEvent(element) {
return isAny(element, ['bpmn:EndEvent', 'bpmn:IntermediateThrowEvent']);
}
function getConfigureGroupForType(eventDetails, label, includeCode, getSelect) {
const { eventType, eventDefType, referenceType, idPrefix } = eventDetails;
return function (props) {
const { element, translate, moddle, commandStack } = props;
const variableName = getTextFieldForExtension(eventDetails, 'Variable Name', 'The name of the variable to store the payload in', true);
const payloadDefinition = getTextFieldForExtension(eventDetails, 'Payload', 'The expression to create the payload with', false);
const entries = [
{
id: `${idPrefix}-select`,
element,
component: getSelect,
isEdited: isTextFieldEntryEdited,
moddle,
commandStack,
},
];
if (includeCode) {
const codeField = getCodeTextField(eventDetails, `${label} Code`);
entries.push({
id: `${idPrefix}-code`,
element,
component: codeField,
isEdited: isTextFieldEntryEdited,
moddle,
commandStack,
});
}
if (isCatchingEvent(element)) {
entries.push({
id: `${idPrefix}-variable`,
element,
component: variableName,
isEdited: isTextFieldEntryEdited,
moddle,
commandStack,
});
} else if (isThrowingEvent(element)) {
entries.push({
id: `${idPrefix}-payload`,
element,
component: payloadDefinition,
isEdited: isTextFieldEntryEdited,
moddle,
commandStack,
});
};
return {
id: `${idPrefix}-group`,
label: label,
entries,
}
}
}
function getSelectorForType(eventDetails) {
const { eventType, eventDefType, referenceType, idPrefix } = eventDetails;
return function (props) {
const { element, translate, moddle, commandStack } = props;
const debounce = useService('debounceInput');
const root = getRoot(element.businessObject);
const getValue = () => {
const eventDef = element.businessObject.eventDefinitions.find(v => v.$type == eventDefType);
return (eventDef && eventDef.get(referenceType)) ? eventDef.get(referenceType).id : '';
};
const setValue = (value) => {
const bpmnEvent = root.rootElements.find(e => e.id == value);
// not sure how to handle multiple event definitions
const eventDef = element.businessObject.eventDefinitions.find(v => v.$type == eventDefType);
// really not sure what to do here if one of these can't be found either
if (bpmnEvent && eventDef)
eventDef.set(referenceType, bpmnEvent);
commandStack.execute('element.updateProperties', {
element,
moddleElement: element.businessObject,
properties: {},
});
};
const getOptions = (val) => {
const matching = root.rootElements ? root.rootElements.filter(elem => elem.$type === eventType) : [];
const options = [];
matching.map(option => options.push({label: option.name, value: option.id}));
return options;
}
return SelectEntry({
id: `${idPrefix}-select`,
element,
description: 'Select item',
getValue,
setValue,
getOptions,
debounce,
});
}
}
function getTextFieldForExtension(eventDetails, label, description, catching) {
const { eventType, eventDefType, referenceType, idPrefix } = eventDetails;
return function (props) {
const { element, moddle, commandStack } = props;
const debounce = useService('debounceInput');
const translate = useService('translate');
const root = getRoot(element.businessObject);
const extensionName = (catching) ? 'spiffworkflow:variableName' : 'spiffworkflow:payloadExpression';
const getEvent = () => {
const eventDef = element.businessObject.eventDefinitions.find(v => v.$type == eventDefType);
const bpmnEvent = eventDef.get(referenceType);
return bpmnEvent;
};
const getValue = () => {
// I've put the variable name (and payload) on the event for consistency with messages.
// However, when I think about this, I wonder if it shouldn't be on the event definition.
// I think that's something we should address in the future.
// Creating a payload and defining access to it are both process-specific, and that's an argument for leaving
// it in the event definition
const bpmnEvent = getEvent();
if (bpmnEvent && bpmnEvent.extensionElements) {
const extension = bpmnEvent.extensionElements.get('values').find(ext => ext.$instanceOf(extensionName));
return (extension) ? extension.value : null;
}
}
const setValue = (value) => {
const bpmnEvent = getEvent();
if (bpmnEvent) {
if (!bpmnEvent.extensionElements)
bpmnEvent.extensionElements = moddle.create('bpmn:ExtensionElements');
const extensions = bpmnEvent.extensionElements.get('values');
const extension = extensions.find(ext => ext.$instanceOf(extensionName));
if (!extension) {
const newExt = moddle.create(extensionName);
newExt.value = value;
extensions.push(newExt);
} else
extension.value = value;
} // not sure what to do if the event hasn't been set
};
if (catching) {
return TextFieldEntry({
element,
id: `${idPrefix}-variable-name`,
description: description,
label: translate(label),
getValue,
setValue,
debounce,
});
} else {
return TextAreaEntry({
element,
id: `${idPrefix}-payload-expression`,
description: description,
label: translate(label),
getValue,
setValue,
debounce,
});
}
}
}
function getCodeTextField(eventDetails, label) {
const { eventType, eventDefType, referenceType, idPrefix } = eventDetails;
return function (props) {
const { element, moddle, commandStack } = props;
const translate = useService('translate');
const debounce = useService('debounceInput');
const attrName = `${idPrefix}Code`;
const getEvent = () => {
const eventDef = element.businessObject.eventDefinitions.find(v => v.$type == eventDefType);
const bpmnEvent = eventDef.get(referenceType);
return bpmnEvent;
};
const getValue = () => {
const bpmnEvent = getEvent();
return (bpmnEvent) ? bpmnEvent.get(attrName) : null;
};
const setValue = (value) => {
const bpmnEvent = getEvent();
if (bpmnEvent)
bpmnEvent.set(attrName, value);
};
return TextFieldEntry({
element,
id: `${idPrefix}-code-value`,
label: translate(label),
getValue,
setValue,
debounce,
});
}
}
export { hasEventType, getSelectorForType, getConfigureGroupForType, replaceGroup };