Merge pull request #12 from sartography/feature/messages

Feature/messages
This commit is contained in:
jasquat 2022-08-23 16:44:50 -04:00 committed by GitHub
commit 8c64db1112
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 2988 additions and 268 deletions

53
.eslintrc.js Normal file
View File

@ -0,0 +1,53 @@
module.exports = {
env: {
browser: true,
es2021: true,
},
extends: [
'airbnb',
'plugin:prettier/recommended',
'plugin:sonarjs/recommended',
'plugin:import/errors',
'plugin:import/warnings',
],
parserOptions: {
ecmaFeatures: {
jsx: true,
},
ecmaVersion: 'latest',
sourceType: 'module',
},
rules: {
'jsx-a11y/no-autofocus': 'off',
'jsx-a11y/label-has-associated-control': 'off',
'no-console': 'off',
'no-unused-vars': [
'error',
{
destructuredArrayIgnorePattern: '^_',
varsIgnorePattern: '_',
argsIgnorePattern: '^_',
},
],
'import/extensions': [
'error',
'ignorePackages',
{
js: 'never',
jsx: 'never',
ts: 'never',
tsx: 'never',
},
],
// We could try turning these on at some point but do not want to force it now
'react/react-in-jsx-scope': 'off',
'react/prop-types': 'off',
'react/jsx-filename-extension': [1, { extensions: ['.js', '.jsx'] }],
'no-use-before-define': 0,
'func-names': 'off',
'react/destructuring-assignment': 'off',
'import/prefer-default-export': 'off',
'no-restricted-syntax': 'off',
},
};

3
.prettierrc.js Normal file
View File

@ -0,0 +1,3 @@
module.exports = {
singleQuote: true,
};

View File

@ -1,19 +1,24 @@
import BpmnModeler from 'bpmn-js/lib/Modeler';
import diagramXML from '../test/spec/bpmn/diagram.bpmn';
import { BpmnPropertiesPanelModule, BpmnPropertiesProviderModule } from 'bpmn-js-properties-panel';
import {
BpmnPropertiesPanelModule,
BpmnPropertiesProviderModule,
} from 'bpmn-js-properties-panel';
import FileSaver from 'file-saver';
import diagramXML from '../test/spec/bpmn/basic_message.bpmn';
import spiffworkflow from './spiffworkflow';
const modelerEl = document.getElementById('modeler');
const panelEl = document.getElementById('panel');
const spiffModdleExtension = require('./spiffworkflow/moddle/spiffworkflow.json');
let bpmnModeler;
// create modeler
try {
const bpmnModeler = new BpmnModeler({
bpmnModeler = new BpmnModeler({
container: modelerEl,
propertiesPanel: {
parent: panelEl
parent: panelEl,
},
additionalModules: [
spiffworkflow,
@ -21,21 +26,20 @@ try {
BpmnPropertiesProviderModule,
],
moddleExtensions: {
spiffworkflowModdle: spiffModdleExtension
}
spiffworkflowModdle: spiffModdleExtension,
},
});
// import XML
bpmnModeler.importXML(diagramXML).then(() => {});
} catch (error) {
if (error.constructor.name === 'AggregateError') {
console.log(error.message);
console.log(error.name);
console.log(error.errors);
}
throw error;
}
// import XML
bpmnModeler.importXML(diagramXML).then(() => {});
/** ****************************************
* Below are a few helper methods so we can upload and download files
@ -47,13 +51,13 @@ try {
* Just a quick bit of code so we can save the XML that is output.
* Helps for debugging against other libraries (like SpiffWorkflow)
*/
let btn = document.getElementById('downloadButton');
btn.addEventListener('click', event => {
const btn = document.getElementById('downloadButton');
btn.addEventListener('click', (_event) => {
saveXML();
});
async function saveXML() {
const { xml } = await bpmnModeler.saveXML({ format: true });
const blob = new Blob([ xml ], { type: 'text/xml' });
const blob = new Blob([xml], { type: 'text/xml' });
FileSaver.saveAs(blob, 'diagram.bpmn');
}
@ -61,14 +65,30 @@ async function saveXML() {
* Just a quick bit of code so we can open a local XML file
* Helps for debugging against other libraries (like SpiffWorkflow)
*/
let uploadBtn = document.getElementById('uploadButton');
uploadBtn.addEventListener('click', event => {
const uploadBtn = document.getElementById('uploadButton');
uploadBtn.addEventListener('click', (_event) => {
openFile(displayFile);
});
function clickElem(elem) {
var eventMouse = document.createEvent('MouseEvents');
eventMouse.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
const eventMouse = document.createEvent('MouseEvents');
eventMouse.initMouseEvent(
'click',
true,
false,
window,
0,
0,
0,
0,
0,
false,
false,
false,
false,
0,
null
);
elem.dispatchEvent(eventMouse);
}
@ -76,15 +96,15 @@ function displayFile(contents) {
bpmnModeler.importXML(contents).then(() => {});
}
export function openFile(func) {
let readFile = function(e) {
var file = e.target.files[0];
export default function openFile(func) {
const readFile = function readFileCallback(e) {
const file = e.target.files[0];
if (!file) {
return;
}
var reader = new FileReader();
reader.onload = function(e) {
var contents = e.target.result;
const reader = new FileReader();
reader.onload = function onloadCallback(onloadEvent) {
const contents = onloadEvent.target.result;
fileInput.func(contents);
document.body.removeChild(fileInput);
};
@ -98,4 +118,3 @@ export function openFile(func) {
document.body.appendChild(fileInput);
clickElem(fileInput);
}

View File

@ -8,6 +8,7 @@
<link rel="stylesheet" href="vendor/bpmn-js/assets/bpmn-font/css/bpmn-embedded.css"/>
<link rel="stylesheet" href="vendor/bpmn-js-properties-panel/assets/properties-panel.css"/>
<link rel="stylesheet" href="css/app.css"/>
<link rel="shortcut icon" href="#">
<!-- Just have this for the download file icon -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">

View File

@ -1,8 +1,11 @@
import { useService } from 'bpmn-js-properties-panel';
import { isTextFieldEntryEdited, TextFieldEntry } from '@bpmn-io/properties-panel';
import {
isTextFieldEntryEdited,
TextFieldEntry,
} from '@bpmn-io/properties-panel';
import { without } from 'min-dash';
import { findDataObjects, findDataReferenceShapes } from '../DataObjectHelpers';
import { is } from 'bpmn-js/lib/util/ModelUtil';
import { findDataObjects, findDataReferenceShapes } from '../DataObjectHelpers';
/**
* Provides a list of data objects, and allows you to add / remove data objects, and change their ids.
@ -10,10 +13,10 @@ import { is } from 'bpmn-js/lib/util/ModelUtil';
* @constructor
*/
export function DataObjectArray(props) {
const moddle = props.moddle;
const element = props.element;
const commandStack = props.commandStack;
const elementRegistry = props.elementRegistry;
const { moddle } = props;
const { element } = props;
const { commandStack } = props;
const { elementRegistry } = props;
let process;
// This element might be a process, or something that will reference a process.
@ -23,36 +26,40 @@ export function DataObjectArray(props) {
process = element.businessObject.processRef;
}
let dataObjects = findDataObjects(process);
const dataObjects = findDataObjects(process);
const items = dataObjects.map((dataObject, index) => {
const id = process.id + '-dataObj-' + index;
const id = `${process.id}-dataObj-${index}`;
return {
id: id,
id,
label: dataObject.id,
entries:
DataObjectGroup({
idPrefix: id,
element,
dataObject
})
,
autoFocusEntry: id + '-dataObject',
remove: removeFactory({ element, dataObject, process, commandStack, elementRegistry })
entries: DataObjectGroup({
idPrefix: id,
element,
dataObject,
}),
autoFocusEntry: `${id}-dataObject`,
remove: removeFactory({
element,
dataObject,
process,
commandStack,
elementRegistry,
}),
};
});
function add(event) {
event.stopPropagation();
let newDataObject = moddle.create('bpmn:DataObject');
let newElements = process.get('flowElements');
const newDataObject = moddle.create('bpmn:DataObject');
const newElements = process.get('flowElements');
newDataObject.id = moddle.ids.nextPrefixed('DataObject_');
newElements.push(newDataObject);
commandStack.execute('element.updateModdleProperties', {
element,
moddleElement: process,
properties: {
flowElements: newElements
}
flowElements: newElements,
},
});
}
@ -60,105 +67,85 @@ export function DataObjectArray(props) {
}
function removeFactory(props) {
const {
element,
dataObject,
process,
commandStack,
} = props;
const { element, dataObject, process, commandStack } = props;
return function(event) {
return function (event) {
event.stopPropagation();
commandStack.execute('element.updateModdleProperties', {
element,
moddleElement: process,
properties: {
flowElements: without(process.get('flowElements'), dataObject)
}
flowElements: without(process.get('flowElements'), dataObject),
},
});
// Also update the label of all the references
let references = findDataReferenceShapes(element, dataObject.id);
const references = findDataReferenceShapes(element, dataObject.id);
for (const ref of references) {
commandStack.execute('element.updateProperties', {
element: ref,
moddleElement: ref.businessObject,
properties: {
'name': '???'
name: '???',
},
changed:[ ref ] // everything is already marked as changed, don't recalculate.
changed: [ref], // everything is already marked as changed, don't recalculate.
});
}
};
}
function DataObjectGroup(props) {
const {
idPrefix,
dataObject
} = props;
const { idPrefix, dataObject } = props;
let entries = [
return [
{
id: idPrefix + '-dataObject',
id: `${idPrefix}-dataObject`,
component: DataObjectTextField,
isEdited: isTextFieldEntryEdited,
idPrefix,
dataObject
}
dataObject,
},
];
return entries;
}
function DataObjectTextField(props) {
const {
idPrefix,
element,
parameter,
dataObject
} = props;
const { idPrefix, element, parameter, dataObject } = props;
const commandStack = useService('commandStack');
const debounce = useService('debounceInput');
const setValue = (value) => {
commandStack.execute(
'element.updateModdleProperties',
{
element,
moddleElement: dataObject,
properties: {
'id': value
}
}
);
commandStack.execute('element.updateModdleProperties', {
element,
moddleElement: dataObject,
properties: {
id: value,
},
});
// Also update the label of all the references
let references = findDataReferenceShapes(element, dataObject.id);
const references = findDataReferenceShapes(element, dataObject.id);
for (const ref of references) {
commandStack.execute('element.updateProperties', {
element: ref,
moddleElement: ref.businessObject,
properties: {
'name': value
name: value,
},
changed:[ ref ] // everything is already marked as changed, don't recalculate.
changed: [ref], // everything is already marked as changed, don't recalculate.
});
}
};
const getValue = (parameter) => {
const getValue = () => {
return dataObject.id;
};
return TextFieldEntry({
element: parameter,
id: idPrefix + '-id',
id: `${idPrefix}-id`,
label: 'Data Object Id',
getValue,
setValue,
debounce
debounce,
});
}

View File

@ -2,16 +2,35 @@ import { is, isAny } from 'bpmn-js/lib/util/ModelUtil';
import { ListGroup, isTextFieldEntryEdited } from '@bpmn-io/properties-panel';
import { DataObjectSelect } from './DataObjectSelect';
import { DataObjectArray } from './DataObjectArray';
const LOW_PRIORITY = 500;
export default function DataObjectPropertiesProvider(propertiesPanel, translate, moddle, commandStack, elementRegistry) {
this.getGroups = function(element) {
return function(groups) {
export default function DataObjectPropertiesProvider(
propertiesPanel,
translate,
moddle,
commandStack,
elementRegistry
) {
this.getGroups = function (element) {
return function (groups) {
if (is(element, 'bpmn:DataObjectReference')) {
groups.push(createDataObjectSelector(element, translate, moddle, commandStack));
groups.push(
createDataObjectSelector(element, translate, moddle, commandStack)
);
}
if (isAny(element, [ 'bpmn:Process', 'bpmn:SubProcess', 'bpmn:Participant' ])) {
groups.push(createDataObjectEditor(element, translate, moddle, commandStack, elementRegistry));
if (
isAny(element, ['bpmn:Process', 'bpmn:SubProcess', 'bpmn:Participant'])
) {
groups.push(
createDataObjectEditor(
element,
translate,
moddle,
commandStack,
elementRegistry
)
);
}
return groups;
};
@ -19,7 +38,13 @@ export default function DataObjectPropertiesProvider(propertiesPanel, translate,
propertiesPanel.registerProvider(LOW_PRIORITY, this);
}
DataObjectPropertiesProvider.$inject = [ 'propertiesPanel', 'translate', 'moddle', 'commandStack', 'elementRegistry' ];
DataObjectPropertiesProvider.$inject = [
'propertiesPanel',
'translate',
'moddle',
'commandStack',
'elementRegistry',
];
/**
* Create a group on the main panel with a select box (for choosing the Data Object to connect)
@ -38,10 +63,10 @@ function createDataObjectSelector(element, translate, moddle, commandStack) {
element,
component: DataObjectSelect,
isEdited: isTextFieldEntryEdited,
moddle: moddle,
commandStack: commandStack,
}
]
moddle,
commandStack,
},
],
};
}
@ -53,13 +78,19 @@ function createDataObjectSelector(element, translate, moddle, commandStack) {
* @param moddle
* @returns entries
*/
function createDataObjectEditor(element, translate, moddle, commandStack, elementRegistry) {
function createDataObjectEditor(
element,
translate,
moddle,
commandStack,
elementRegistry
) {
const dataObjectArray = {
id: 'editDataObjects',
element,
label: 'Data Objects',
component: ListGroup,
...DataObjectArray({ element, moddle, commandStack, elementRegistry })
...DataObjectArray({ element, moddle, commandStack, elementRegistry }),
};
if (dataObjectArray.items) {

View File

@ -1,49 +1,22 @@
import { HeaderButton, TextAreaEntry, TextFieldEntry, isTextFieldEntryEdited } from '@bpmn-io/properties-panel';
import {
HeaderButton,
TextAreaEntry,
isTextFieldEntryEdited,
} from '@bpmn-io/properties-panel';
import { useService } from 'bpmn-js-properties-panel';
export const SCRIPT_TYPE = {
bpmn: 'bpmn:script',
pre: 'spiffworkflow:preScript',
post: 'spiffworkflow:postScript'
post: 'spiffworkflow:postScript',
};
/**
* Generates a python script.
* @param element The elemment that should get the script task.
* @param scriptType The type of script -- can be a preScript, postScript or a BPMN:Script for script tags
* @param moddle For updating the underlying xml document when needed.
* @returns {[{component: (function(*)), isEdited: *, id: string, element},{component: (function(*)), isEdited: *, id: string, element}]}
*/
export default function(element, moddle, scriptType, label, description) {
return [
{
id: 'pythonScript_' + scriptType,
element,
targetTag: scriptType,
component: PythonScript,
isEdited: isTextFieldEntryEdited,
moddle: moddle,
label: label,
description: description
},
{
id: 'launchEditorButton' + scriptType,
target_tag: scriptType,
element,
component: LaunchEditorButton,
isEdited: isTextFieldEntryEdited,
moddle: moddle
},
];
}
function PythonScript(props) {
const { element, id } = props;
const type = props.targetTag;
const moddle = props.moddle;
const label = props.label;
const description = props.description;
const { type } = props;
const { moddle } = props;
const { label } = props;
const { description } = props;
const translate = useService('translate');
const debounce = useService('debounceInput');
@ -72,31 +45,33 @@ function PythonScript(props) {
}
if (!bizObj.extensionElements) {
return null;
} else {
return bizObj.extensionElements.get("values").filter(function(e) {
}
return bizObj.extensionElements
.get('values')
.filter(function getInstanceOfType(e) {
return e.$instanceOf(type);
})[0];
}
};
const getValue = () => {
const scriptObj = getScriptObject()
const scriptObj = getScriptObject();
if (scriptObj) {
return scriptObj.script;
} else {
return ""
}
return '';
};
const setValue = value => {
const businessObject = element.businessObject;
let scriptObj = getScriptObject()
const setValue = (value) => {
const { businessObject } = element;
let scriptObj = getScriptObject();
// Create the script object if needed.
if (!scriptObj) {
scriptObj = moddle.create(type);
if (type !== SCRIPT_TYPE.bpmn) {
if (!businessObject.extensionElements) {
businessObject.extensionElements = moddle.create('bpmn:ExtensionElements');
businessObject.extensionElements = moddle.create(
'bpmn:ExtensionElements'
);
}
businessObject.extensionElements.get('values').push(scriptObj);
}
@ -104,26 +79,67 @@ function PythonScript(props) {
scriptObj.script = value;
};
return <TextAreaEntry
id={ id }
element={ element }
description={ translate(description) }
label={ translate(label) }
getValue={ getValue }
setValue={ setValue }
debounce={ debounce }
/>;
return (
<TextAreaEntry
id={id}
element={element}
description={translate(description)}
label={translate(label)}
getValue={getValue}
setValue={setValue}
debounce={debounce}
/>
);
}
function LaunchEditorButton(props) {
const { element, id, type } = props;
const { element, type } = props;
const eventBus = useService('eventBus');
const modeling = useService('modeling');
// fixme: add a call up date as a property
return <HeaderButton
className="spiffworkflow-properties-panel-button"
onClick={() => {
eventBus.fire('launch.script.editor', { element: element , type});
}}
>Launch Editor</HeaderButton>;
return (
<HeaderButton
className="spiffworkflow-properties-panel-button"
onClick={() => {
eventBus.fire('launch.script.editor', { element, type });
}}
>
Launch Editor
</HeaderButton>
);
}
/**
* Generates a python script.
* @param element The elemment that should get the script task.
* @param scriptType The type of script -- can be a preScript, postScript or a BPMN:Script for script tags
* @param moddle For updating the underlying xml document when needed.
* @returns {[{component: (function(*)), isEdited: *, id: string, element},{component: (function(*)), isEdited: *, id: string, element}]}
*/
export default function getEntries(
element,
moddle,
scriptType,
label,
description
) {
return [
{
id: `pythonScript_${scriptType}`,
element,
type: scriptType,
component: PythonScript,
isEdited: isTextFieldEntryEdited,
moddle,
label,
description,
},
{
id: `launchEditorButton${scriptType}`,
type: scriptType,
element,
component: LaunchEditorButton,
isEdited: isTextFieldEntryEdited,
moddle,
},
];
}

View File

@ -1,26 +1,34 @@
import RulesModule from 'diagram-js/lib/features/rules';
import IoPalette from './InputOutput/IoPalette';
import IoRules from './InputOutput/IoRules';
import IoInterceptor from './InputOutput/IoInterceptor';
import DataObjectInterceptor from './DataObject/DataObjectInterceptor';
import DataObjectRules from './DataObject/DataObjectRules';
import RulesModule from 'diagram-js/lib/features/rules';
import DataObjectRenderer from './DataObject/DataObjectRenderer';
import DataObjectPropertiesProvider from './DataObject/propertiesPanel/DataObjectPropertiesProvider';
import ExtensionsPropertiesProvider from './extensions/propertiesPanel/ExtensionsPropertiesProvider';
import MessagesPropertiesProvider from './messages/propertiesPanel/MessagesPropertiesProvider';
export default {
__depends__: [ RulesModule ],
__depends__: [RulesModule],
__init__: [
'dataObjectInterceptor', 'dataObjectRules', 'dataObjectPropertiesProvider',
'dataObjectInterceptor',
'dataObjectRules',
'dataObjectPropertiesProvider',
'extensionsPropertiesProvider',
'ioPalette', 'ioRules', 'ioInterceptor', 'dataObjectRenderer' ],
dataObjectInterceptor: [ 'type', DataObjectInterceptor ],
dataObjectRules:[ 'type', DataObjectRules ],
dataObjectRenderer: [ 'type', DataObjectRenderer ],
dataObjectPropertiesProvider: [ 'type', DataObjectPropertiesProvider ],
extensionsPropertiesProvider: [ 'type', ExtensionsPropertiesProvider ],
ioPalette: [ 'type', IoPalette ],
ioRules: [ 'type', IoRules ],
ioInterceptor: [ 'type', IoInterceptor ],
'messagesPropertiesProvider',
'ioPalette',
'ioRules',
'ioInterceptor',
'dataObjectRenderer',
],
dataObjectInterceptor: ['type', DataObjectInterceptor],
dataObjectRules: ['type', DataObjectRules],
dataObjectRenderer: ['type', DataObjectRenderer],
dataObjectPropertiesProvider: ['type', DataObjectPropertiesProvider],
extensionsPropertiesProvider: ['type', ExtensionsPropertiesProvider],
messagesPropertiesProvider: ['type', MessagesPropertiesProvider],
ioPalette: ['type', IoPalette],
ioRules: ['type', IoRules],
ioInterceptor: ['type', IoInterceptor],
};

View File

@ -0,0 +1,163 @@
import { is } from 'bpmn-js/lib/util/ModelUtil';
/**
* loops up until it can find the root.
* @param element
*/
export function getRoot(businessObject) {
// todo: Do we want businessObject to be a shape or moddle object?
if (businessObject.$type === 'bpmn:Definitions') {
return businessObject;
}
if (typeof businessObject.$parent !== 'undefined') {
return getRoot(businessObject.$parent);
}
return businessObject;
}
export function isMessageElement(shapeElement) {
return (
is(shapeElement, 'bpmn:SendTask') ||
is(shapeElement, 'bpmn:ReceiveTask') ||
isMessageEvent(shapeElement)
);
}
export function isMessageEvent(shapeElement) {
const { eventDefinitions } = shapeElement.businessObject;
if (eventDefinitions && eventDefinitions[0]) {
return eventDefinitions[0].$type === 'bpmn:MessageEventDefinition';
}
return false;
}
export function canReceiveMessage(shapeElement) {
if (is(shapeElement, 'bpmn:ReceiveTask')) {
return true;
}
if (isMessageEvent(shapeElement)) {
return (
is(shapeElement, 'bpmn:StartEvent') || is(shapeElement, 'bpmn:CatchEvent')
);
}
return false;
}
export function getMessageRefElement(shapeElement) {
if (isMessageEvent(shapeElement)) {
const messageEventDefinition =
shapeElement.businessObject.eventDefinitions[0];
if (messageEventDefinition && messageEventDefinition.messageRef) {
return messageEventDefinition.messageRef;
}
} else if (
isMessageElement(shapeElement) &&
shapeElement.businessObject.messageRef
) {
return shapeElement.businessObject.messageRef;
}
return null;
}
export function findFormalExpressions(shapeElement) {
const formalExpressions = [];
const messageRef = getMessageRefElement(shapeElement);
if (messageRef) {
const root = getRoot(shapeElement.businessObject);
if (root.$type === 'bpmn:Definitions') {
for (const childElement of root.rootElements) {
if (childElement.$type === 'bpmn:CorrelationProperty') {
const retrievalExpression = processCorrelationProperty(
childElement,
messageRef
);
// todo: is there a better test for this than length === 1?
if (retrievalExpression.length === 1) {
const formalExpression = {
correlationId: childElement.id,
expression: retrievalExpression[0],
};
formalExpressions.push(formalExpression);
}
}
}
}
}
return formalExpressions;
}
export function getMessageElementForShapeElement(shapeElement) {
const { businessObject } = shapeElement;
const taskMessage = getMessageRefElement(shapeElement);
const messages = findMessageModdleElements(businessObject);
if (taskMessage) {
for (const message of messages) {
if (message.id === taskMessage.id) {
return message;
}
}
}
return null;
}
function processCorrelationProperty(correlationProperty, message) {
const expressions = [];
for (const retrievalExpression of correlationProperty.correlationPropertyRetrievalExpression) {
if (
retrievalExpression.$type ===
'bpmn:CorrelationPropertyRetrievalExpression' &&
retrievalExpression.messageRef &&
retrievalExpression.messageRef.id === message.id &&
retrievalExpression.messagePath.body
) {
expressions.push(retrievalExpression.messagePath.body);
}
}
return expressions;
}
export function findCorrelationProperties(businessObject) {
const root = getRoot(businessObject);
const correlationProperties = [];
for (const rootElement of root.rootElements) {
if (rootElement.$type === 'bpmn:CorrelationProperty') {
correlationProperties.push(rootElement);
}
}
return correlationProperties;
}
export function findCorrelationKeys(businessObject) {
const root = getRoot(businessObject);
const correlationKeys = [];
for (const rootElement of root.rootElements) {
if (rootElement.$type === 'bpmn:Collaboration') {
const currentKeys = rootElement.correlationKeys;
for (const correlationKey in currentKeys) {
const currentCorrelation = rootElement.correlationKeys[correlationKey];
correlationKeys.push(currentCorrelation);
// const currentProperty = {};
// currentProperty.name = currentCorrelation.name;
// currentProperty.refs = [];
// for (const correlationProperty in currentCorrelation.correlationPropertyRef) {
// currentProperty.refs.push(
// currentCorrelation.correlationPropertyRef[correlationProperty]
// );
// }
// correlationKeys.push(currentProperty);
}
}
}
return correlationKeys;
}
export function findMessageModdleElements(businessObject) {
const messages = [];
const root = getRoot(businessObject);
for (const rootElement of root.rootElements) {
if (rootElement.$type === 'bpmn:Message') {
messages.push(rootElement);
}
}
return messages;
}

View File

@ -0,0 +1,6 @@
import MessagesPropertiesProvider from './propertiesPanel/MessagesPropertiesProvider';
export default {
__init__: ['messagesPropertiesProvider'],
messagesPropertiesProvider: ['type', MessagesPropertiesProvider],
};

View File

@ -0,0 +1,123 @@
import { useService } from 'bpmn-js-properties-panel';
import { SimpleEntry, TextFieldEntry } from '@bpmn-io/properties-panel';
import { findCorrelationKeys, getRoot } from '../MessageHelpers';
/**
* Provides a list of data objects, and allows you to add / remove data objects, and change their ids.
* @param props
* @constructor
*/
export function CorrelationKeysArray(props) {
const { element, moddle, commandStack } = props;
const correlationKeys = findCorrelationKeys(element.businessObject);
const items = correlationKeys.map((correlationKey, index) => {
const id = `correlationGroup-${index}`;
return {
id,
label: correlationKey.name,
entries: correlationGroup({
id,
element,
correlationKey,
commandStack,
}),
autoFocusEntry: id,
};
});
function add(event) {
event.stopPropagation();
if (element.type === 'bpmn:Collaboration') {
const newCorrelationKeyElement = moddle.create('bpmn:CorrelationKey');
newCorrelationKeyElement.name =
moddle.ids.nextPrefixed('CorrelationKey_');
const correlationKeyElements =
element.businessObject.get('correlationKeys');
correlationKeyElements.push(newCorrelationKeyElement);
commandStack.execute('element.updateProperties', {
element,
moddleElement: moddle,
properties: {
correlationKey: correlationKeyElements,
},
});
}
}
return { items, add };
}
// <bpmn:correlationKey name="lover"> <--- The correlationGroup
// <bpmn:correlationPropertyRef>lover_name</bpmn:correlationPropertyRef>
// <bpmn:correlationPropertyRef>lover_instrument</bpmn:correlationPropertyRef>
// </bpmn:correlationKey>
// <bpmn:correlationKey name="singer" />
function correlationGroup(props) {
const { correlationKey, commandStack } = props;
const id = `correlation-${correlationKey.name}`;
const entries = [
{
id: `${id}-${correlationKey.name}-key`,
component: CorrelationKeyTextField,
correlationKey,
commandStack,
},
];
(correlationKey.correlationPropertyRef || []).forEach(
(correlationProperty) => {
entries.push({
id: `${id}-${correlationProperty.id}-group`,
component: CorrelationPropertyText,
correlationProperty,
});
}
);
return entries;
}
function CorrelationKeyTextField(props) {
const { id, element, correlationKey, commandStack } = props;
const debounce = useService('debounceInput');
const setValue = (value) => {
commandStack.execute('element.updateModdleProperties', {
element,
moddleElement: correlationKey,
properties: {
name: value,
},
});
};
const getValue = () => {
return correlationKey.name;
};
return TextFieldEntry({
element,
id: `${id}-textField`,
getValue,
setValue,
debounce,
});
}
function CorrelationPropertyText(props) {
const { id, parameter, correlationProperty } = props;
const debounce = useService('debounceInput');
const getValue = () => {
return correlationProperty.id;
};
return SimpleEntry({
element: parameter,
id: `${id}-textField`,
label: correlationProperty.id,
getValue,
disabled: true,
debounce,
});
}

View File

@ -0,0 +1,108 @@
import { useService } from 'bpmn-js-properties-panel';
import {
isTextFieldEntryEdited,
ListGroup,
TextAreaEntry,
TextFieldEntry,
} from '@bpmn-io/properties-panel';
import { findFormalExpressions } from '../MessageHelpers';
/**
* Allows the creation, or editing of messageCorrelations at the bpmn:sendTask level of a BPMN document.
*/
export function CorrelationPropertiesArray(props) {
const { moddle } = props;
const { element } = props;
const { commandStack } = props;
// const { elementRegistry } = props;
const formalExpressions = findFormalExpressions(element);
const items = formalExpressions.map((formalExpression) => {
const id = `correlation-${formalExpression.correlationId}`;
const entries = MessageCorrelationGroup({
idPrefix: id,
formalExpression,
});
return {
id,
label: formalExpression.correlationId,
entries,
autoFocusEntry: id,
// remove: removeFactory({ element, correlationProperty, commandStack, elementRegistry })
};
});
function add(event) {
event.stopPropagation();
const newRetrievalExpression = moddle.create(
'bpmn:CorrelationPropertyRetrievalExpression'
);
const newElements = formalExpressions;
newRetrievalExpression.messageRef = element.businessObject.messageRef;
newElements.push(newRetrievalExpression);
commandStack.execute('element.updateModdleProperties', {
element,
moddleElement: element.businessObject,
});
}
return { items, add };
}
function MessageCorrelationGroup(props) {
const { idPrefix, formalExpression } = props;
return [
{
id: `${idPrefix}-group`,
component: MessageCorrelationTextField,
isEdited: isTextFieldEntryEdited,
idPrefix,
formalExpression,
},
];
}
function MessageCorrelationTextField(props) {
const { idPrefix, element, parameter, formalExpression } = props;
const commandStack = useService('commandStack');
const debounce = useService('debounceInput');
const setValue = (value) => {
commandStack.execute('element.updateModdleProperties', {
element,
moddleElement: formalExpression,
properties: {
id: value,
},
});
// Also update the label of all the references
// const references = findDataReferenceShapes(element, correlationProperty.id);
const references = ['hello1', 'hello2'];
for (const ref of references) {
commandStack.execute('element.updateProperties', {
element: ref,
moddleElement: ref.businessObject,
properties: {
name: value,
},
changed: [ref], // everything is already marked as changed, don't recalculate.
});
}
};
const getValue = (_parameter) => {
return formalExpression.expression;
};
return TextFieldEntry({
element: parameter,
id: `${idPrefix}-textField`,
label: 'Expression',
getValue,
setValue,
debounce,
});
}

View File

@ -0,0 +1,64 @@
import { useService } from 'bpmn-js-properties-panel';
import { TextAreaEntry } from '@bpmn-io/properties-panel';
import { getMessageElementForShapeElement } from '../MessageHelpers';
/**
* Allows the creation, or editing of messagePayload at the bpmn:sendTask level of a BPMN document.
*/
export function MessagePayload(props) {
const shapeElement = props.element;
const debounce = useService('debounceInput');
const messageElement = getMessageElementForShapeElement(shapeElement);
const disabled = !messageElement;
const getMessagePayloadObject = () => {
if (messageElement) {
const { extensionElements } = messageElement;
if (extensionElements) {
return messageElement.extensionElements
.get('values')
.filter(function getInstanceOfType(e) {
return e.$instanceOf('spiffworkflow:messagePayload');
})[0];
}
}
return null;
};
const getValue = () => {
const messagePayloadObject = getMessagePayloadObject();
if (messagePayloadObject) {
return messagePayloadObject.messagePayload;
}
return '';
};
const setValue = (value) => {
let messagePayloadObject = getMessagePayloadObject();
if (!messagePayloadObject) {
messagePayloadObject = messageElement.$model.create(
'spiffworkflow:messagePayload'
);
if (!messageElement.extensionElements) {
messageElement.extensionElements = messageElement.$model.create(
'bpmn:ExtensionElements'
);
}
messageElement.extensionElements.get('values').push(messagePayloadObject);
}
messagePayloadObject.messagePayload = value;
};
return (
<TextAreaEntry
id="messagePayload"
element={shapeElement}
description="The payload of the message."
label="Payload"
disabled={disabled}
getValue={getValue}
setValue={setValue}
debounce={debounce}
/>
);
}

View File

@ -0,0 +1,83 @@
import { useService } from 'bpmn-js-properties-panel';
import { SelectEntry } from '@bpmn-io/properties-panel';
import {
findMessageModdleElements,
getMessageRefElement,
isMessageEvent,
} from '../MessageHelpers';
/**
* Allows the selection, or creation, of Message at the Definitions level of a BPMN document.
*/
export function MessageSelect(props) {
const shapeElement = props.element;
const { commandStack } = props;
const debounce = useService('debounceInput');
const getValue = () => {
const messageRefElement = getMessageRefElement(shapeElement);
if (messageRefElement) {
return messageRefElement.id;
}
return '';
};
const setValue = (value) => {
/* Need to add the selected message as the messageRef on the current message task */
const { businessObject } = shapeElement;
const messages = findMessageModdleElements(shapeElement.businessObject);
for (const message of messages) {
if (message.id === value) {
if (isMessageEvent(shapeElement)) {
const messageEventDefinition = businessObject.eventDefinitions[0];
messageEventDefinition.messageRef = message;
// call this to update the other elements in the props panel like payload
commandStack.execute('element.updateModdleProperties', {
element: shapeElement,
moddleElement: businessObject,
});
} else if (
businessObject.$type === 'bpmn:ReceiveTask' ||
businessObject.$type === 'bpmn:SendTask'
) {
commandStack.execute('element.updateModdleProperties', {
element: shapeElement,
moddleElement: businessObject,
properties: {
messageRef: message,
},
});
commandStack.execute('element.updateProperties', {
element: shapeElement,
moddleElement: businessObject,
properties: {
messageRef: message,
},
});
}
}
}
};
const getOptions = (_value) => {
const messages = findMessageModdleElements(shapeElement.businessObject);
const options = [];
for (const message of messages) {
options.push({ label: message.name, value: message.id });
}
return options;
};
return (
<SelectEntry
id="selectMessage"
element={shapeElement}
description="Select the Message to associate with this task or event."
label="Which message is this associated with?"
getValue={getValue}
setValue={setValue}
getOptions={getOptions}
debounce={debounce}
/>
);
}

View File

@ -0,0 +1,66 @@
import { useService } from 'bpmn-js-properties-panel';
import { TextFieldEntry } from '@bpmn-io/properties-panel';
import { getMessageElementForShapeElement } from '../MessageHelpers';
/**
* Allows the creation, or editing of messageVariable at the bpmn:sendTask level of a BPMN document.
*/
export function MessageVariable(props) {
const shapeElement = props.element;
const debounce = useService('debounceInput');
const messageElement = getMessageElementForShapeElement(shapeElement);
const disabled = !messageElement;
const getMessageVariableObject = () => {
if (messageElement) {
const { extensionElements } = messageElement;
if (extensionElements) {
return messageElement.extensionElements
.get('values')
.filter(function getInstanceOfType(e) {
return e.$instanceOf('spiffworkflow:messageVariable');
})[0];
}
}
return null;
};
const getValue = () => {
const messageVariableObject = getMessageVariableObject();
if (messageVariableObject) {
return messageVariableObject.messageVariable;
}
return '';
};
const setValue = (value) => {
let messageVariableObject = getMessageVariableObject();
if (!messageVariableObject) {
messageVariableObject = messageElement.$model.create(
'spiffworkflow:messageVariable'
);
if (!messageElement.extensionElements) {
messageElement.extensionElements = messageElement.$model.create(
'bpmn:ExtensionElements'
);
}
messageElement.extensionElements
.get('values')
.push(messageVariableObject);
}
messageVariableObject.messageVariable = value;
};
return (
<TextFieldEntry
id="messageVariable"
element={shapeElement}
description="The name of the variable where we should store payload."
label="Variable Name"
disabled={disabled}
getValue={getValue}
setValue={setValue}
debounce={debounce}
/>
);
}

View File

@ -0,0 +1,151 @@
import { ListGroup, isTextFieldEntryEdited } from '@bpmn-io/properties-panel';
import { is } from 'bpmn-js/lib/util/ModelUtil';
import { CorrelationKeysArray } from './CorrelationKeysArray';
import { MessageSelect } from './MessageSelect';
import { MessagePayload } from './MessagePayload';
import { MessageVariable } from './MessageVariable';
import { CorrelationPropertiesArray } from './CorrelationPropertiesArray';
import { isMessageElement, canReceiveMessage } from '../MessageHelpers';
const LOW_PRIORITY = 500;
export default function MessagesPropertiesProvider(
propertiesPanel,
translate,
moddle,
commandStack,
elementRegistry
) {
this.getGroups = function getGroupsCallback(element) {
return function pushGroup(groups) {
if (is(element, 'bpmn:Collaboration')) {
groups.push(
createCollaborationGroup(
element,
translate,
moddle,
commandStack,
elementRegistry
)
);
} else if (isMessageElement(element)) {
const messageIndex = findEntry(groups, 'message');
if (messageIndex) {
groups.splice(messageIndex, 1);
}
groups.push(
createMessageGroup(
element,
translate,
moddle,
commandStack,
elementRegistry
)
);
}
return groups;
};
};
function findEntry(entries, entryId) {
let entryIndex = null;
entries.forEach(function (value, index) {
if (value.id === entryId) {
entryIndex = index;
}
});
return entryIndex;
}
propertiesPanel.registerProvider(LOW_PRIORITY, this);
}
MessagesPropertiesProvider.$inject = [
'propertiesPanel',
'translate',
'moddle',
'commandStack',
'elementRegistry',
];
/**
* Adds a group to the properties panel for the script task that allows you
* to set the script.
* @param element
* @param translate
* @returns The components to add to the properties panel. */
function createCollaborationGroup(
element,
translate,
moddle,
commandStack,
elementRegistry
) {
return {
id: 'correlation_keys',
label: translate('Correlation Keys'),
component: ListGroup,
...CorrelationKeysArray({ element, moddle, commandStack, elementRegistry }),
};
}
/**
* Adds a group to the properties panel for editing messages for the SendTask
* @param element
* @param translate
* @returns The components to add to the properties panel. */
function createMessageGroup(
element,
translate,
moddle,
commandStack,
elementRegistry
) {
const entries = [
{
id: 'selectMessage',
element,
component: MessageSelect,
isEdited: isTextFieldEntryEdited,
moddle,
commandStack,
},
];
if (canReceiveMessage(element)) {
entries.push({
id: 'messageVariable',
element,
component: MessageVariable,
isEdited: isTextFieldEntryEdited,
moddle,
commandStack,
});
} else {
entries.push({
id: 'messagePayload',
element,
component: MessagePayload,
isEdited: isTextFieldEntryEdited,
moddle,
commandStack,
});
}
entries.push({
id: 'correlationProperties',
label: translate('Correlation Properties'),
component: ListGroup,
...CorrelationPropertiesArray({
element,
moddle,
commandStack,
elementRegistry,
}),
});
return {
id: 'messages',
label: translate('Message'),
entries,
};
}

View File

@ -26,6 +26,28 @@
}
]
},
{
"name": "messagePayload",
"superClass": [ "Element" ],
"properties": [
{
"name": "messagePayload",
"isBody": true,
"type": "String"
}
]
},
{
"name": "messageVariable",
"superClass": [ "Element" ],
"properties": [
{
"name": "messageVariable",
"isBody": true,
"type": "String"
}
]
},
{
"name": "calledDecisionId",
"superClass": [ "Element" ],

1264
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -8,7 +8,8 @@
"build:watch": "webpack --watch",
"dev": "run-p build:watch serve",
"serve": "sirv public --dev",
"lint": "eslint .",
"lint": "./node_modules/.bin/eslint src *.js",
"lint:fix": "./node_modules/.bin/eslint --fix src *.js",
"start": "run-s build serve",
"test": "karma start karma.conf.js"
},
@ -43,7 +44,14 @@
"chai": "^4.3.6",
"copy-webpack-plugin": "^11.0.0",
"eslint": "^8.18.0",
"eslint_d": "^12.2.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-bpmn-io": "^0.14.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-jsx-a11y": "^6.6.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-sonarjs": "^0.13.0",
"file-saver": "^2.0.5",
"karma": "^6.3.4",
"karma-chrome-launcher": "^3.1.1",
@ -55,6 +63,7 @@
"mocha": "^10.0.0",
"mocha-test-container-support": "^0.2.0",
"npm-run-all": "^4.1.5",
"prettier": "^2.7.1",
"raw-loader": "^4.0.2",
"sinon": "^14.0.0",
"sinon-chai": "^3.7.0",
@ -64,8 +73,9 @@
"webpack-cli": "^4.9.2"
},
"dependencies": {
"@bpmn-io/properties-panel": "^0.18.0",
"bpmn-js": "^9.2.2",
"bpmn-js-properties-panel": "^1.1.1",
"bpmn-js-properties-panel": "^1.2.0",
"diagram-js": "^8.5.0",
"inherits": "^2.0.4",
"inherits-browser": "^0.0.1",

132
test/spec/MessagesSpec.js Normal file
View File

@ -0,0 +1,132 @@
import TestContainer from 'mocha-test-container-support';
import {
BpmnPropertiesPanelModule,
BpmnPropertiesProviderModule,
} from 'bpmn-js-properties-panel';
import {
bootstrapPropertiesPanel,
expectSelected,
findEntry,
findGroupEntry,
// findInput,
findSelect,
findTextarea,
findButtonByClass,
pressButton,
findDivByClass,
} from './helpers';
import spiffModdleExtension from '../../app/spiffworkflow/moddle/spiffworkflow.json';
import messages from '../../app/spiffworkflow/messages';
describe('Messages should work', function () {
const xml = require('./bpmn/collaboration.bpmn').default;
let container;
beforeEach(function () {
container = TestContainer.get(this);
});
beforeEach(
bootstrapPropertiesPanel(xml, {
container,
debounceInput: false,
additionalModules: [
messages,
BpmnPropertiesPanelModule,
BpmnPropertiesProviderModule,
],
moddleExtensions: {
spiffworkflow: spiffModdleExtension,
},
})
);
it('should allow you to see the collaborations section', async function () {
// THEN - a select Data Object section should appear in the properties panel
const entry = findGroupEntry('correlation_keys', container);
expect(entry).to.exist;
});
it('should show a Message Properties group when a send task is selected', async function () {
// Select the send Task
const send_shape = await expectSelected('ActivitySendLetter');
expect(send_shape, "Can't find Send Task").to.exist;
// THEN - a select Data Object section should appear in the properties panel
const entry = findGroupEntry('messages', container);
expect(entry, "Can't find the message group in the properties panel").to
.exist;
});
it('should show a list of messages in a drop down inside the message group', async function () {
// Select the send Task
const send_shape = await expectSelected('ActivitySendLetter');
expect(send_shape, "Can't find Send Task").to.exist;
// THEN - there are two options to choose from.
const entry = findEntry('selectMessage', container);
expect(entry, "Can't find the message select list").to.exist;
// AND - There should be two entries in it, one for each message.
const selector = findSelect(entry);
expect(selector).to.exist;
expect(selector.length).to.equal(2);
});
it('should show the payload inside the message group', async function () {
// Select the second Task
const send_shape = await expectSelected('ActivitySendLetter');
expect(send_shape, "Can't find Send Task").to.exist;
// THEN - there is a payload.
const payload = findEntry('messagePayload', container);
expect(payload, "Can't find the message payload").to.exist;
const textArea = findTextarea(
'bio-properties-panel-messagePayload',
payload
);
expect(textArea, "Can't find the payload textarea").to.exist;
expect(textArea.value, "Can't find payload value").to.exist;
expect(textArea.value).to.include("'to': { 'name': my_lover_variable }");
});
it('should show the correlations inside the message group', async function () {
// Select the second Task
const send_shape = await expectSelected('ActivitySendLetter');
expect(send_shape, "Can't find Send Task").to.exist;
// THEN - there are correlations.
const correlations = findGroupEntry('messageCorrelations', container);
expect(correlations, "Can't find the message correlations").to.exist;
});
// it('should add a new correlation when clicked', async function () {
// // Select the second Task
// const send_shape = await expectSelected('ActivitySendLetter');
// expect(send_shape, "Can't find Send Task").to.exist;
//
// const buttonClass =
// 'bio-properties-panel-group-header-button bio-properties-panel-add-entry';
// const button = findButtonByClass(buttonClass, container);
// pressButton(button);
//
// console.log(button);
// });
//
// it('should add a new Correlation Key when clicked', async function () {
// const divClass = 'bio-properties-panel-list';
// const divs = findDivByClass(divClass, container);
//
// const buttonClass =
// 'bio-properties-panel-group-header-button bio-properties-panel-add-entry';
// const button = findButtonByClass(buttonClass, container);
// pressButton(button);
//
// // THEN - a select Data Object section should appear in the properties panel
// const entry = findGroupEntry('correlation_keys', container);
// expect(entry).to.exist;
//
// const divs2 = findDivByClass(divClass, container);
// });
});

View File

@ -0,0 +1,146 @@
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:spiffworkflow="http://spiffworkflow.org/bpmn/schema/1.0/core" id="Definitions_96f6665" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="3.0.0-dev">
<bpmn:collaboration id="Collaboration_0oye1os">
<bpmn:participant id="message_initiator" name="Message Initiator" processRef="message_send_process" />
<bpmn:participant id="message_receiver" name="Message Receiver" processRef="message_receiver_process" />
<bpmn:messageFlow id="message_send_flow" name="Message Send Flow" sourceRef="send_message" targetRef="receive_message" />
<bpmn:messageFlow id="message_response_flow" name="Message Response Flow" sourceRef="respond_to_message" targetRef="receive_message_response" />
<bpmn:correlationKey name="message_correlation_key">
<bpmn:correlationPropertyRef>message_correlation_property</bpmn:correlationPropertyRef>
</bpmn:correlationKey>
</bpmn:collaboration>
<bpmn:correlationProperty id="message_correlation_property" name="Message Correlation Property">
<bpmn:correlationPropertyRetrievalExpression messageRef="message_send">
<bpmn:formalExpression>to</bpmn:formalExpression>
</bpmn:correlationPropertyRetrievalExpression>
<bpmn:correlationPropertyRetrievalExpression messageRef="message_response">
<bpmn:formalExpression>from.name</bpmn:formalExpression>
</bpmn:correlationPropertyRetrievalExpression>
</bpmn:correlationProperty>
<bpmn:process id="message_send_process" name="Message Send Process" isExecutable="true">
<bpmn:startEvent id="StartEvent_1">
<bpmn:outgoing>Flow_176e02g</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:sequenceFlow id="Flow_037vpjk" sourceRef="send_message" targetRef="receive_message_response" />
<bpmn:sequenceFlow id="Flow_1qgz6p0" sourceRef="receive_message_response" targetRef="Event_0kndoyu" />
<bpmn:sequenceFlow id="Flow_176e02g" sourceRef="StartEvent_1" targetRef="send_message" />
<bpmn:sendTask id="send_message" name="Send Message" messageRef="message_send">
<bpmn:incoming>Flow_176e02g</bpmn:incoming>
<bpmn:outgoing>Flow_037vpjk</bpmn:outgoing>
</bpmn:sendTask>
<bpmn:intermediateCatchEvent id="receive_message_response" name="Receive Message Response">
<bpmn:incoming>Flow_037vpjk</bpmn:incoming>
<bpmn:outgoing>Flow_1qgz6p0</bpmn:outgoing>
<bpmn:messageEventDefinition id="MessageEventDefinition_1l3n0zr" messageRef="message_response" />
</bpmn:intermediateCatchEvent>
<bpmn:endEvent id="Event_0kndoyu">
<bpmn:incoming>Flow_1qgz6p0</bpmn:incoming>
</bpmn:endEvent>
</bpmn:process>
<bpmn:message id="message_send" name="Message Send">
<bpmn:extensionElements>
<spiffworkflow:messagePayload>{"to": "the_recipient1" }</spiffworkflow:messagePayload>
</bpmn:extensionElements>
</bpmn:message>
<bpmn:message id="message_response" name="Message Response">
<bpmn:extensionElements>
<spiffworkflow:messagePayload>{"from": {"name": "the_sender"}}</spiffworkflow:messagePayload>
</bpmn:extensionElements>
</bpmn:message>
<bpmn:process id="message_receiver_process" name="Message Receiver Process">
<bpmn:startEvent id="receive_message" name="Receive Message">
<bpmn:outgoing>Flow_0505x87</bpmn:outgoing>
<bpmn:messageEventDefinition id="MessageEventDefinition_0h33u2n" messageRef="message_send" />
</bpmn:startEvent>
<bpmn:endEvent id="Event_0q5otqd">
<bpmn:incoming>Flow_1273yit</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="Flow_0505x87" sourceRef="receive_message" targetRef="respond_to_message" />
<bpmn:sequenceFlow id="Flow_1273yit" sourceRef="respond_to_message" targetRef="Event_0q5otqd" />
<bpmn:intermediateThrowEvent id="respond_to_message" name="Respond to Message">
<bpmn:incoming>Flow_0505x87</bpmn:incoming>
<bpmn:outgoing>Flow_1273yit</bpmn:outgoing>
<bpmn:messageEventDefinition id="MessageEventDefinition_0kakria" />
</bpmn:intermediateThrowEvent>
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Collaboration_0oye1os">
<bpmndi:BPMNShape id="Participant_0bjh770_di" bpmnElement="message_initiator" isHorizontal="true">
<dc:Bounds x="120" y="52" width="600" height="250" />
<bpmndi:BPMNLabel />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_176e02g_di" bpmnElement="Flow_176e02g">
<di:waypoint x="215" y="177" />
<di:waypoint x="280" y="177" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1qgz6p0_di" bpmnElement="Flow_1qgz6p0">
<di:waypoint x="478" y="177" />
<di:waypoint x="552" y="177" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_037vpjk_di" bpmnElement="Flow_037vpjk">
<di:waypoint x="380" y="177" />
<di:waypoint x="442" y="177" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
<dc:Bounds x="179" y="159" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0vm33bu_di" bpmnElement="send_message">
<dc:Bounds x="280" y="137" width="100" height="80" />
<bpmndi:BPMNLabel />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_0yt48xb_di" bpmnElement="receive_message_response">
<dc:Bounds x="442" y="159" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="417" y="129" width="88" height="27" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_0kndoyu_di" bpmnElement="Event_0kndoyu">
<dc:Bounds x="552" y="159" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Participant_0mr0gg1_di" bpmnElement="message_receiver" isHorizontal="true">
<dc:Bounds x="120" y="350" width="600" height="250" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_0505x87_di" bpmnElement="Flow_0505x87">
<di:waypoint x="248" y="480" />
<di:waypoint x="372" y="480" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1273yit_di" bpmnElement="Flow_1273yit">
<di:waypoint x="408" y="480" />
<di:waypoint x="532" y="480" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="Event_052nccg_di" bpmnElement="receive_message">
<dc:Bounds x="212" y="462" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="187" y="505" width="88" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_0q5otqd_di" bpmnElement="Event_0q5otqd">
<dc:Bounds x="532" y="462" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_1p63v3w_di" bpmnElement="respond_to_message">
<dc:Bounds x="372" y="462" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="362" y="505" width="57" height="27" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_1ueajoz_di" bpmnElement="message_send_flow">
<di:waypoint x="300" y="217" />
<di:waypoint x="300" y="340" />
<di:waypoint x="230" y="340" />
<di:waypoint x="230" y="462" />
<bpmndi:BPMNLabel>
<dc:Bounds x="303" y="315" width="74" height="27" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1n96n67_di" bpmnElement="message_response_flow">
<di:waypoint x="391" y="462" />
<di:waypoint x="400" y="329" />
<di:waypoint x="460" y="329" />
<di:waypoint x="460" y="195" />
<bpmndi:BPMNLabel>
<dc:Bounds x="462" y="315" width="76" height="27" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>

View File

@ -0,0 +1,195 @@
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:spiffworkflow="http://spiffworkflow.org/bpmn/schema/1.0/core" xmlns:modeler="http://camunda.org/schema/modeler/1.0" id="Definitions_0qmxumb" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.0.0" modeler:executionPlatform="Camunda Platform" modeler:executionPlatformVersion="7.17.0">
<bpmn:collaboration id="my_collaboration">
<bpmn:participant id="buddy" name="Buddy" processRef="process_buddy" />
<bpmn:participant id="Person" name="Person" processRef="random_person_process" />
<bpmn:participant id="Participant_1tlkvw1" name="Tom Petty" processRef="Process_04o9jmt" />
<bpmn:messageFlow id="love_letter_flow" name="Love Letter Flow" sourceRef="ActivitySendLetter" targetRef="Event_0ym6ptw" />
<bpmn:messageFlow id="Flow_10ya1ap" sourceRef="Activity_0ra5uc1" targetRef="Participant_1tlkvw1" />
<bpmn:messageFlow id="Flow_0vonyt2" sourceRef="Participant_1tlkvw1" targetRef="Event_06829ki" />
<bpmn:messageFlow id="Flow_0wwbhd6" sourceRef="Event_0e1t8xh" targetRef="EventReceiveLetter" />
<bpmn:correlationKey name="lover">
<bpmn:correlationPropertyRef>lover_name</bpmn:correlationPropertyRef>
<bpmn:correlationPropertyRef>lover_instrument</bpmn:correlationPropertyRef>
</bpmn:correlationKey>
<bpmn:correlationKey name="singer" />
</bpmn:collaboration>
<bpmn:message id="love_letter" name="Love Letter">
<bpmn:extensionElements>
<spiffworkflow:messagePayload>
{
'to': { 'name': my_lover_variable }
}
</spiffworkflow:messagePayload>
</bpmn:extensionElements>
</bpmn:message>
<bpmn:message id="love_letter_response" name="Love Letter Response" />
<bpmn:correlationProperty id="lover_instrument" name="Lover&#39;s Instrument">
<bpmn:correlationPropertyRetrievalExpression messageRef="love_letter">
<bpmn:formalExpression>lover.instrument</bpmn:formalExpression>
</bpmn:correlationPropertyRetrievalExpression>
<bpmn:correlationPropertyRetrievalExpression messageRef="love_letter_response">
<bpmn:formalExpression>from.instrument</bpmn:formalExpression>
</bpmn:correlationPropertyRetrievalExpression>
</bpmn:correlationProperty>
<bpmn:correlationProperty id="lover_name" name="Lover&#39;s Name">
<bpmn:correlationPropertyRetrievalExpression messageRef="love_letter">
<bpmn:formalExpression>lover.name</bpmn:formalExpression>
</bpmn:correlationPropertyRetrievalExpression>
<bpmn:correlationPropertyRetrievalExpression messageRef="love_letter_response">
<bpmn:formalExpression>from.name</bpmn:formalExpression>
</bpmn:correlationPropertyRetrievalExpression>
<bpmn:correlationPropertyRetrievalExpression>
<bpmn:formalExpression>heartbreaker</bpmn:formalExpression>
</bpmn:correlationPropertyRetrievalExpression>
</bpmn:correlationProperty>
<bpmn:correlationProperty id="singer_name" name="Singer&#39;s Name">
<bpmn:correlationPropertyRetrievalExpression messageRef="love_letter_response">
<bpmn:formalExpression>to.name</bpmn:formalExpression>
</bpmn:correlationPropertyRetrievalExpression>
</bpmn:correlationProperty>
<bpmn:process id="process_buddy" name="Process Buddy" isExecutable="true">
<bpmn:startEvent id="StartEvent_1">
<bpmn:outgoing>Flow_1bl6jeh</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:sendTask id="ActivitySendLetter" name="Send Letter" messageRef="love_letter">
<bpmn:incoming>Flow_1bl6jeh</bpmn:incoming>
<bpmn:outgoing>Flow_0tp8uut</bpmn:outgoing>
</bpmn:sendTask>
<bpmn:intermediateCatchEvent id="EventReceiveLetter" name="receive Letter">
<bpmn:incoming>Flow_0tp8uut</bpmn:incoming>
<bpmn:outgoing>Flow_1ai45pq</bpmn:outgoing>
<bpmn:messageEventDefinition id="medllr" messageRef="love_letter_response" />
</bpmn:intermediateCatchEvent>
<bpmn:endEvent id="Event_01h5zqa">
<bpmn:incoming>Flow_0rygg2d</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sendTask id="Activity_0ra5uc1" name="Get support">
<bpmn:incoming>Flow_1ai45pq</bpmn:incoming>
<bpmn:outgoing>Flow_1f0m6hd</bpmn:outgoing>
</bpmn:sendTask>
<bpmn:intermediateCatchEvent id="Event_06829ki">
<bpmn:incoming>Flow_1f0m6hd</bpmn:incoming>
<bpmn:outgoing>Flow_0rygg2d</bpmn:outgoing>
<bpmn:messageEventDefinition id="MessageEventDefinition_07bwnfa" />
</bpmn:intermediateCatchEvent>
<bpmn:sequenceFlow id="Flow_1f0m6hd" sourceRef="Activity_0ra5uc1" targetRef="Event_06829ki" />
<bpmn:sequenceFlow id="Flow_1ai45pq" sourceRef="EventReceiveLetter" targetRef="Activity_0ra5uc1" />
<bpmn:sequenceFlow id="Flow_0tp8uut" sourceRef="ActivitySendLetter" targetRef="EventReceiveLetter" />
<bpmn:sequenceFlow id="Flow_1bl6jeh" sourceRef="StartEvent_1" targetRef="ActivitySendLetter" />
<bpmn:sequenceFlow id="Flow_0rygg2d" sourceRef="Event_06829ki" targetRef="Event_01h5zqa" />
</bpmn:process>
<bpmn:process id="random_person_process" name="Process" isExecutable="true">
<bpmn:startEvent id="Event_0ym6ptw">
<bpmn:outgoing>Flow_1bnzzx2</bpmn:outgoing>
<bpmn:messageEventDefinition id="MessageEventDefinition_05bnll8" />
</bpmn:startEvent>
<bpmn:endEvent id="Event_0yy6dsf">
<bpmn:incoming>Flow_11malws</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="Flow_1bnzzx2" sourceRef="Event_0ym6ptw" targetRef="Event_0e1t8xh" />
<bpmn:sequenceFlow id="Flow_11malws" sourceRef="Event_0e1t8xh" targetRef="Event_0yy6dsf" />
<bpmn:intermediateThrowEvent id="Event_0e1t8xh">
<bpmn:incoming>Flow_1bnzzx2</bpmn:incoming>
<bpmn:outgoing>Flow_11malws</bpmn:outgoing>
<bpmn:messageEventDefinition id="MessageEventDefinition_145e86u" />
</bpmn:intermediateThrowEvent>
</bpmn:process>
<bpmn:process id="Process_04o9jmt" isExecutable="false" />
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="my_collaboration">
<bpmndi:BPMNShape id="Participant_12ffz3p_di" bpmnElement="buddy" isHorizontal="true">
<dc:Bounds x="129" y="190" width="721" height="200" />
<bpmndi:BPMNLabel />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_0rygg2d_di" bpmnElement="Flow_0rygg2d">
<di:waypoint x="718" y="265" />
<di:waypoint x="782" y="265" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1bl6jeh_di" bpmnElement="Flow_1bl6jeh">
<di:waypoint x="215" y="265" />
<di:waypoint x="270" y="265" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0tp8uut_di" bpmnElement="Flow_0tp8uut">
<di:waypoint x="370" y="265" />
<di:waypoint x="432" y="265" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1ai45pq_di" bpmnElement="Flow_1ai45pq">
<di:waypoint x="468" y="265" />
<di:waypoint x="540" y="265" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1f0m6hd_di" bpmnElement="Flow_1f0m6hd">
<di:waypoint x="640" y="265" />
<di:waypoint x="682" y="265" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
<dc:Bounds x="179" y="247" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0p9c4se_di" bpmnElement="ActivitySendLetter">
<dc:Bounds x="270" y="225" width="100" height="80" />
<bpmndi:BPMNLabel />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_0s2n1j8_di" bpmnElement="EventReceiveLetter">
<dc:Bounds x="432" y="247" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="416" y="223" width="67" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_01h5zqa_di" bpmnElement="Event_01h5zqa">
<dc:Bounds x="782" y="247" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_07t6p94_di" bpmnElement="Activity_0ra5uc1">
<dc:Bounds x="540" y="225" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_1f1k5np_di" bpmnElement="Event_06829ki">
<dc:Bounds x="682" y="247" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Participant_0nbivcp_di" bpmnElement="Person" isHorizontal="true">
<dc:Bounds x="129" y="430" width="721" height="160" />
<bpmndi:BPMNLabel />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_1bnzzx2_di" bpmnElement="Flow_1bnzzx2">
<di:waypoint x="328" y="530" />
<di:waypoint x="412" y="530" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_11malws_di" bpmnElement="Flow_11malws">
<di:waypoint x="448" y="530" />
<di:waypoint x="572" y="530" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="Event_09ldq03_di" bpmnElement="Event_0ym6ptw">
<dc:Bounds x="292" y="512" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_0yy6dsf_di" bpmnElement="Event_0yy6dsf">
<dc:Bounds x="572" y="512" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_12u2p44_di" bpmnElement="Event_0e1t8xh">
<dc:Bounds x="412" y="512" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Participant_1tlkvw1_di" bpmnElement="Participant_1tlkvw1" isHorizontal="true">
<dc:Bounds x="129" y="80" width="721" height="60" />
<bpmndi:BPMNLabel />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_11c08m8_di" bpmnElement="love_letter_flow">
<di:waypoint x="310" y="305" />
<di:waypoint x="310" y="512" />
<bpmndi:BPMNLabel>
<dc:Bounds x="219" y="377" width="82" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_10ya1ap_di" bpmnElement="Flow_10ya1ap">
<di:waypoint x="590" y="225" />
<di:waypoint x="590" y="140" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0vonyt2_di" bpmnElement="Flow_0vonyt2">
<di:waypoint x="700" y="140" />
<di:waypoint x="700" y="247" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0wwbhd6_di" bpmnElement="Flow_0wwbhd6">
<di:waypoint x="430" y="512" />
<di:waypoint x="430" y="398" />
<di:waypoint x="450" y="398" />
<di:waypoint x="450" y="283" />
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>

View File

@ -0,0 +1,221 @@
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:spiffworkflow="http://spiffworkflow.org/bpmn/schema/1.0/core" xmlns:modeler="http://camunda.org/schema/modeler/1.0" id="Definitions_0qmxumb" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.0.0" modeler:executionPlatform="Camunda Platform" modeler:executionPlatformVersion="7.17.0">
<bpmn:collaboration id="my_collaboration">
<bpmn:participant id="buddy" name="Alpha" processRef="process_buddy" />
<bpmn:participant id="Person" name="Beta" processRef="random_person_process" />
<bpmn:messageFlow id="love_letter_flow" name="Message Flow" sourceRef="ActivitySendLetter" targetRef="Event_0ym6ptw" />
<bpmn:messageFlow id="Flow_0zpmqjr" name="Response Flow" sourceRef="Event_0e1t8xh" targetRef="Activity_1dagl6a" />
<bpmn:correlationKey name="invoice">
<bpmn:correlationPropertyRef>invoice_id</bpmn:correlationPropertyRef>
<bpmn:correlationPropertyRef>invoice_date</bpmn:correlationPropertyRef>
<bpmn:correlationPropertyRef>invoice_total</bpmn:correlationPropertyRef>
</bpmn:correlationKey>
<bpmn:correlationKey name="payment">
<bpmn:correlationPropertyRef>payment_id</bpmn:correlationPropertyRef>
<bpmn:correlationPropertyRef>payment_date</bpmn:correlationPropertyRef>
<bpmn:correlationPropertyRef>payment_total</bpmn:correlationPropertyRef>
</bpmn:correlationKey>
</bpmn:collaboration>
<bpmn:message id="send_invoice" name="Send Invoice">
<bpmn:extensionElements>
<spiffworkflow:messagePayload>
{
'invoice': { 'id': my_invoice_id, 'date': my_invoice_date, 'total': my_invoice_total }
}
</spiffworkflow:messagePayload>
</bpmn:extensionElements>
</bpmn:message>
<bpmn:message id="send_payment" name="Send Payment">
<bpmn:extensionElements>
<spiffworkflow:messagePayload>
{ 'payment':
{
'id': my_payment_id,
'date': my_payment_date,
'total': my_payment_total,
'invoice_id': invoice_id,
'invoice_date': invoice_data,
'invoice_amount': invoice_amount,
}
}
</spiffworkflow:messagePayload>
</bpmn:extensionElements>
</bpmn:message>
<bpmn:correlationProperty id="invoice_id" name="Invoice ID">
<bpmn:correlationPropertyRetrievalExpression messageRef="send_invoice">
<bpmn:formalExpression>invoice.invoice_id</bpmn:formalExpression>
</bpmn:correlationPropertyRetrievalExpression>
<bpmn:correlationPropertyRetrievalExpression messageRef="send_payment">
<bpmn:formalExpression>payment.invoice_id</bpmn:formalExpression>
</bpmn:correlationPropertyRetrievalExpression>
</bpmn:correlationProperty>
<bpmn:correlationProperty id="invoice_total" name="Invoice Total">
<bpmn:correlationPropertyRetrievalExpression messageRef="send_invoice">
<bpmn:formalExpression>invoice.total</bpmn:formalExpression>
</bpmn:correlationPropertyRetrievalExpression>
<bpmn:correlationPropertyRetrievalExpression messageRef="send_payment">
<bpmn:formalExpression>payment.invoice_amount</bpmn:formalExpression>
</bpmn:correlationPropertyRetrievalExpression>
</bpmn:correlationProperty>
<bpmn:correlationProperty id="invoice_date" name="Invoice Date">
<bpmn:correlationPropertyRetrievalExpression messageRef="send_invoice">
<bpmn:formalExpression>invoice.date</bpmn:formalExpression>
</bpmn:correlationPropertyRetrievalExpression>
<bpmn:correlationPropertyRetrievalExpression messageRef="send_payment">
<bpmn:formalExpression>payment.invoice_date</bpmn:formalExpression>
</bpmn:correlationPropertyRetrievalExpression>
</bpmn:correlationProperty>
<bpmn:correlationProperty id="payment_date" name="Payment Date">
<bpmn:correlationPropertyRetrievalExpression messageRef="send_payment">
<bpmn:formalExpression>payment.date</bpmn:formalExpression>
</bpmn:correlationPropertyRetrievalExpression>
</bpmn:correlationProperty>
<bpmn:correlationProperty id="payment_total" name="Payment Total">
<bpmn:correlationPropertyRetrievalExpression messageRef="send_payment">
<bpmn:formalExpression>payment.total</bpmn:formalExpression>
</bpmn:correlationPropertyRetrievalExpression>
</bpmn:correlationProperty>
<bpmn:correlationProperty id="payment_id" name="Payment ID">
<bpmn:correlationPropertyRetrievalExpression messageRef="send_payment">
<bpmn:formalExpression>payment.id</bpmn:formalExpression>
</bpmn:correlationPropertyRetrievalExpression>
</bpmn:correlationProperty>
<bpmn:process id="process_buddy" name="Process Buddy" isExecutable="true">
<bpmn:startEvent id="StartEvent_1">
<bpmn:outgoing>Flow_1bl6jeh</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:sendTask id="ActivitySendLetter" name="Send Message" messageRef="love_letter">
<bpmn:incoming>Flow_1bl6jeh</bpmn:incoming>
<bpmn:outgoing>Flow_1vgtrb2</bpmn:outgoing>
</bpmn:sendTask>
<bpmn:sequenceFlow id="Flow_1bl6jeh" sourceRef="StartEvent_1" targetRef="ActivitySendLetter" />
<bpmn:sequenceFlow id="Flow_1vgtrb2" sourceRef="ActivitySendLetter" targetRef="Activity_1dagl6a" />
<bpmn:endEvent id="Event_01h5zqa">
<bpmn:incoming>Flow_1f0m6hd</bpmn:incoming>
</bpmn:endEvent>
<bpmn:receiveTask id="Activity_1dagl6a" name="Reveive Response">
<bpmn:incoming>Flow_1vgtrb2</bpmn:incoming>
<bpmn:outgoing>Flow_1ygtaxw</bpmn:outgoing>
</bpmn:receiveTask>
<bpmn:sequenceFlow id="Flow_1f0m6hd" sourceRef="Activity_0ra5uc1" targetRef="Event_01h5zqa" />
<bpmn:sequenceFlow id="Flow_1ygtaxw" sourceRef="Activity_1dagl6a" targetRef="Activity_0ra5uc1" />
<bpmn:manualTask id="Activity_0ra5uc1" name="Display Stuff">
<bpmn:incoming>Flow_1ygtaxw</bpmn:incoming>
<bpmn:outgoing>Flow_1f0m6hd</bpmn:outgoing>
</bpmn:manualTask>
</bpmn:process>
<bpmn:process id="random_person_process" name="Process" isExecutable="true">
<bpmn:startEvent id="Event_0ym6ptw">
<bpmn:outgoing>Flow_1bnzzx2</bpmn:outgoing>
<bpmn:messageEventDefinition id="MessageEventDefinition_05bnll8" />
</bpmn:startEvent>
<bpmn:sequenceFlow id="Flow_11malws" sourceRef="Event_0e1t8xh" targetRef="Event_0yy6dsf" />
<bpmn:sequenceFlow id="Flow_1bnzzx2" sourceRef="Event_0ym6ptw" targetRef="Activity_15kdfc4" />
<bpmn:sequenceFlow id="Flow_07sdx2y" sourceRef="Activity_15kdfc4" targetRef="Event_0e1t8xh" />
<bpmn:endEvent id="Event_0yy6dsf">
<bpmn:incoming>Flow_11malws</bpmn:incoming>
</bpmn:endEvent>
<bpmn:intermediateThrowEvent id="Event_0e1t8xh">
<bpmn:incoming>Flow_07sdx2y</bpmn:incoming>
<bpmn:outgoing>Flow_11malws</bpmn:outgoing>
<bpmn:messageEventDefinition id="MessageEventDefinition_145e86u" />
</bpmn:intermediateThrowEvent>
<bpmn:scriptTask id="Activity_15kdfc4" name="Do Something">
<bpmn:incoming>Flow_1bnzzx2</bpmn:incoming>
<bpmn:outgoing>Flow_07sdx2y</bpmn:outgoing>
</bpmn:scriptTask>
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="my_collaboration">
<bpmndi:BPMNShape id="Participant_12ffz3p_di" bpmnElement="buddy" isHorizontal="true">
<dc:Bounds x="129" y="190" width="889" height="290" />
<bpmndi:BPMNLabel />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_1vgtrb2_di" bpmnElement="Flow_1vgtrb2">
<di:waypoint x="370" y="265" />
<di:waypoint x="510" y="265" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1bl6jeh_di" bpmnElement="Flow_1bl6jeh">
<di:waypoint x="215" y="265" />
<di:waypoint x="270" y="265" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1f0m6hd_di" bpmnElement="Flow_1f0m6hd">
<di:waypoint x="770" y="265" />
<di:waypoint x="882" y="265" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1ygtaxw_di" bpmnElement="Flow_1ygtaxw">
<di:waypoint x="610" y="265" />
<di:waypoint x="670" y="265" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
<dc:Bounds x="179" y="247" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0p9c4se_di" bpmnElement="ActivitySendLetter">
<dc:Bounds x="270" y="225" width="100" height="80" />
<bpmndi:BPMNLabel />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_01h5zqa_di" bpmnElement="Event_01h5zqa">
<dc:Bounds x="882" y="247" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_021bozj_di" bpmnElement="Activity_1dagl6a">
<dc:Bounds x="510" y="225" width="100" height="80" />
<bpmndi:BPMNLabel />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_05js9ii_di" bpmnElement="Activity_0ra5uc1">
<dc:Bounds x="670" y="225" width="100" height="80" />
<bpmndi:BPMNLabel />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Participant_0nbivcp_di" bpmnElement="Person" isHorizontal="true">
<dc:Bounds x="129" y="520" width="889" height="160" />
<bpmndi:BPMNLabel />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_11malws_di" bpmnElement="Flow_11malws">
<di:waypoint x="578" y="620" />
<di:waypoint x="702" y="620" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1bnzzx2_di" bpmnElement="Flow_1bnzzx2">
<di:waypoint x="328" y="620" />
<di:waypoint x="370" y="620" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_07sdx2y_di" bpmnElement="Flow_07sdx2y">
<di:waypoint x="470" y="620" />
<di:waypoint x="542" y="620" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="Event_09ldq03_di" bpmnElement="Event_0ym6ptw">
<dc:Bounds x="292" y="602" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_0yy6dsf_di" bpmnElement="Event_0yy6dsf">
<dc:Bounds x="702" y="602" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_12u2p44_di" bpmnElement="Event_0e1t8xh">
<dc:Bounds x="542" y="602" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0itanit_di" bpmnElement="Activity_15kdfc4">
<dc:Bounds x="370" y="580" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_11c08m8_di" bpmnElement="love_letter_flow">
<di:waypoint x="310" y="305" />
<di:waypoint x="310" y="602" />
<bpmndi:BPMNLabel>
<dc:Bounds x="225" y="411" width="71" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0zpmqjr_di" bpmnElement="Flow_0zpmqjr">
<di:waypoint x="560" y="602" />
<di:waypoint x="560" y="305" />
<bpmndi:BPMNLabel>
<dc:Bounds x="582" y="410" width="76" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>

View File

@ -12,11 +12,13 @@ import { bootstrapBpmnJS, inject, insertCSS } from 'bpmn-js/test/helper';
import {getBusinessObject} from 'bpmn-js/lib/util/ModelUtil';
import {createMoveEvent} from 'diagram-js/lib/features/mouse/Mouse';
let PROPERTIES_PANEL_CONTAINER;
export let PROPERTIES_PANEL_CONTAINER;
export let CONTAINER;
export function bootstrapPropertiesPanel(diagram, options, locals) {
return async function() {
let container = options.container;
CONTAINER = container;
if (!container) {
container = TestContainer.get(this);
}
@ -109,10 +111,18 @@ export function findInput(type, container) {
return domQuery(`input[type='${ type }']`, container);
}
export function findTextarea(id, container) {
return domQuery(`textarea[id='${ id }']`, container);
}
export function findButton(id, container) {
return domQuery(`button[id='${ id }']`, container);
}
export function findButtonByClass(buttonClass, container) {
return domQuery(`button[class='${ buttonClass }']`, container)
}
export function findSelect(container) {
return domQuery('select', container);
}
@ -125,6 +135,10 @@ export function pressButton(button) {
fireEvent.click(button);
}
export function findDivByClass(divClass, container) {
return domQuery(`div[class='${ divClass }']`, container)
}