Fixes several bugs in the editor related to Data Objects:
1) Correctly position the label on new data objects 2) When a Data Object is removed, remove all its references as well. 3) Avoid duplicate names showing up in the Data Objects list. 4) Allow non-words in data object names.
This commit is contained in:
parent
1270ea4fb0
commit
782ad97076
|
@ -20,7 +20,10 @@ export function findDataObjects(parent) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
for (const element of process.flowElements) {
|
for (const element of process.flowElements) {
|
||||||
if (element.$type === 'bpmn:DataObject') {
|
if (
|
||||||
|
element.$type === 'bpmn:DataObject' &&
|
||||||
|
dataObjects.indexOf(element) < 0
|
||||||
|
) {
|
||||||
dataObjects.push(element);
|
dataObjects.push(element);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,7 +51,7 @@ export function findDataReferenceShapes(processShape, id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function idToHumanReadableName(id) {
|
export function idToHumanReadableName(id) {
|
||||||
const words = id.match(/[A-Za-z][a-z]*/g) || [];
|
const words = id.match(/[A-Za-z][a-z]*/g) || [id];
|
||||||
return words.map(capitalize).join(' ');
|
return words.map(capitalize).join(' ');
|
||||||
|
|
||||||
function capitalize(word) {
|
function capitalize(word) {
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
import CommandInterceptor from 'diagram-js/lib/command/CommandInterceptor';
|
import CommandInterceptor from 'diagram-js/lib/command/CommandInterceptor';
|
||||||
import { getDi, is } from 'bpmn-js/lib/util/ModelUtil';
|
import { getDi, is } from 'bpmn-js/lib/util/ModelUtil';
|
||||||
import {findDataObjects, findDataReferenceShapes, idToHumanReadableName} from './DataObjectHelpers';
|
import { remove as collectionRemove } from 'diagram-js/lib/util/Collections';
|
||||||
var HIGH_PRIORITY = 1500;
|
|
||||||
import {
|
import {
|
||||||
remove as collectionRemove,
|
findDataObjects,
|
||||||
} from 'diagram-js/lib/util/Collections';
|
findDataReferenceShapes,
|
||||||
|
idToHumanReadableName,
|
||||||
|
} from './DataObjectHelpers';
|
||||||
|
|
||||||
|
const HIGH_PRIORITY = 1500;
|
||||||
/**
|
/**
|
||||||
* This Command Interceptor functions like the BpmnUpdator in BPMN.js - It hooks into events
|
* This Command Interceptor functions like the BpmnUpdator in BPMN.js - It hooks into events
|
||||||
* from Diagram.js and updates the underlying BPMN model accordingly.
|
* from Diagram.js and updates the underlying BPMN model accordingly.
|
||||||
|
@ -17,7 +20,7 @@ import {
|
||||||
* 4) Don't allow someone to move a DataObjectReference from one process to another process.
|
* 4) Don't allow someone to move a DataObjectReference from one process to another process.
|
||||||
*/
|
*/
|
||||||
export default class DataObjectInterceptor extends CommandInterceptor {
|
export default class DataObjectInterceptor extends CommandInterceptor {
|
||||||
constructor(eventBus, bpmnFactory, bpmnUpdater) {
|
constructor(eventBus, bpmnFactory, commandStack) {
|
||||||
super(eventBus);
|
super(eventBus);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -27,7 +30,8 @@ export default class DataObjectInterceptor extends CommandInterceptor {
|
||||||
* we know where it is placed - as we want to reuse data objects of the parent when
|
* we know where it is placed - as we want to reuse data objects of the parent when
|
||||||
* possible */
|
* possible */
|
||||||
this.preExecute(['shape.create'], HIGH_PRIORITY, function (event) {
|
this.preExecute(['shape.create'], HIGH_PRIORITY, function (event) {
|
||||||
const context = event.context, shape = context.shape;
|
const { context } = event;
|
||||||
|
const { shape } = context;
|
||||||
if (is(shape, 'bpmn:DataObjectReference') && shape.type !== 'label') {
|
if (is(shape, 'bpmn:DataObjectReference') && shape.type !== 'label') {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
}
|
}
|
||||||
|
@ -37,10 +41,11 @@ export default class DataObjectInterceptor extends CommandInterceptor {
|
||||||
* Don't just create a new data object, use the first existing one if it already exists
|
* Don't just create a new data object, use the first existing one if it already exists
|
||||||
*/
|
*/
|
||||||
this.executed(['shape.create'], HIGH_PRIORITY, function (event) {
|
this.executed(['shape.create'], HIGH_PRIORITY, function (event) {
|
||||||
const context = event.context, shape = context.shape;
|
const { context } = event;
|
||||||
|
const { shape } = context;
|
||||||
if (is(shape, 'bpmn:DataObjectReference') && shape.type !== 'label') {
|
if (is(shape, 'bpmn:DataObjectReference') && shape.type !== 'label') {
|
||||||
let process = shape.parent.businessObject;
|
const process = shape.parent.businessObject;
|
||||||
let existingDataObjects = findDataObjects(process);
|
const existingDataObjects = findDataObjects(process);
|
||||||
let dataObject;
|
let dataObject;
|
||||||
if (existingDataObjects.length > 0) {
|
if (existingDataObjects.length > 0) {
|
||||||
dataObject = existingDataObjects[0];
|
dataObject = existingDataObjects[0];
|
||||||
|
@ -48,14 +53,30 @@ export default class DataObjectInterceptor extends CommandInterceptor {
|
||||||
dataObject = bpmnFactory.create('bpmn:DataObject');
|
dataObject = bpmnFactory.create('bpmn:DataObject');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the name of the reference to match the data object's id.
|
|
||||||
shape.businessObject.name = idToHumanReadableName(dataObject.id);
|
|
||||||
|
|
||||||
// set the reference to the DataObject
|
// set the reference to the DataObject
|
||||||
shape.businessObject.dataObjectRef = dataObject;
|
shape.businessObject.dataObjectRef = dataObject;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In order for the label to display correctly, we need to update it in POST step.
|
||||||
|
*/
|
||||||
|
this.postExecuted(['shape.create'], HIGH_PRIORITY, function (event) {
|
||||||
|
const { context } = event;
|
||||||
|
const { shape } = context;
|
||||||
|
// set the reference to the DataObject
|
||||||
|
// Update the name of the reference to match the data object's id.
|
||||||
|
if (is(shape, 'bpmn:DataObjectReference') && shape.type !== 'label') {
|
||||||
|
commandStack.execute('element.updateProperties', {
|
||||||
|
element: shape,
|
||||||
|
moddleElement: shape.businessObject,
|
||||||
|
properties: {
|
||||||
|
name: idToHumanReadableName(shape.businessObject.dataObjectRef.id),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Don't remove the associated DataObject, unless all references to that data object
|
* Don't remove the associated DataObject, unless all references to that data object
|
||||||
* Difficult to do given placement of this logic in the BPMN Updater, so we have
|
* Difficult to do given placement of this logic in the BPMN Updater, so we have
|
||||||
|
@ -97,4 +118,4 @@ export default class DataObjectInterceptor extends CommandInterceptor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DataObjectInterceptor.$inject = [ 'eventBus', 'bpmnFactory', 'bpmnUpdater' ];
|
DataObjectInterceptor.$inject = ['eventBus', 'bpmnFactory', 'commandStack'];
|
||||||
|
|
|
@ -78,17 +78,10 @@ function removeFactory(props) {
|
||||||
flowElements: without(process.get('flowElements'), dataObject),
|
flowElements: without(process.get('flowElements'), dataObject),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
// Also update the label of all the references
|
// When a data object is removed, remove all references as well.
|
||||||
const references = findDataReferenceShapes(element, dataObject.id);
|
const references = findDataReferenceShapes(element, dataObject.id);
|
||||||
for (const ref of references) {
|
for (const ref of references) {
|
||||||
commandStack.execute('element.updateProperties', {
|
commandStack.execute('shape.delete', { shape: ref });
|
||||||
element: ref,
|
|
||||||
moddleElement: ref.businessObject,
|
|
||||||
properties: {
|
|
||||||
name: '???',
|
|
||||||
},
|
|
||||||
changed: [ref], // everything is already marked as changed, don't recalculate.
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import {useService } from 'bpmn-js-properties-panel';
|
import {useService } from 'bpmn-js-properties-panel';
|
||||||
import { SelectEntry } from '@bpmn-io/properties-panel';
|
import { SelectEntry } from '@bpmn-io/properties-panel';
|
||||||
import {idToHumanReadableName} from '../DataObjectHelpers';
|
import {findDataObjects, idToHumanReadableName} from '../DataObjectHelpers';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds the value of the given type within the extensionElements
|
* Finds the value of the given type within the extensionElements
|
||||||
|
@ -54,13 +54,12 @@ export function DataObjectSelect(props) {
|
||||||
const getOptions = value => {
|
const getOptions = value => {
|
||||||
const businessObject = element.businessObject;
|
const businessObject = element.businessObject;
|
||||||
const parent = businessObject.$parent;
|
const parent = businessObject.$parent;
|
||||||
let options = []
|
let dataObjects = findDataObjects(parent);
|
||||||
for (const element of parent.flowElements) {
|
let options = [];
|
||||||
if (element.$type === 'bpmn:DataObject') {
|
dataObjects.forEach(dataObj => {
|
||||||
options.push({label: element.id, value: element.id})
|
options.push({label: dataObj.id, value: dataObj.id})
|
||||||
}
|
});
|
||||||
}
|
return options;
|
||||||
return options
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return <SelectEntry
|
return <SelectEntry
|
||||||
|
|
Loading…
Reference in New Issue