WIP
This commit is contained in:
parent
9d46ea3ba8
commit
30b5f1bfae
|
@ -22,11 +22,11 @@ export default class DataStoreInterceptor extends CommandInterceptor {
|
|||
constructor(eventBus, bpmnFactory, commandStack, bpmnUpdater) {
|
||||
super(eventBus);
|
||||
|
||||
/* The default behavior is to move the data object into whatever object the reference is being created in.
|
||||
* If a data object already has a parent, don't change it.
|
||||
/* The default behavior is to move the data store into whatever object the reference is being created in.
|
||||
* If a data store already has a parent, don't change it.
|
||||
*/
|
||||
bpmnUpdater.updateSemanticParent = (businessObject, parentBusinessObject) => {
|
||||
// Special case for participant - which is a valid place to drop a data object, but it needs to be added
|
||||
// Special case for participant - which is a valid place to drop a data store, but it needs to be added
|
||||
// to the particpant's Process (which isn't directly accessible in BPMN.io
|
||||
let realParent = parentBusinessObject;
|
||||
if (is(realParent, 'bpmn:Participant')) {
|
||||
|
@ -34,7 +34,7 @@ export default class DataStoreInterceptor extends CommandInterceptor {
|
|||
}
|
||||
|
||||
if (is(businessObject, 'bpmn:DataStoreReference')) {
|
||||
// For data object references, always update the flowElements when a parent is provided
|
||||
// For data store references, always update the flowElements when a parent is provided
|
||||
// The parent could be null if it's being deleted, and I could probably handle that here instead of
|
||||
// when the shape is deleted, but not interested in refactoring at the moment.
|
||||
if (realParent != null) {
|
||||
|
@ -45,7 +45,7 @@ export default class DataStoreInterceptor extends CommandInterceptor {
|
|||
}
|
||||
}
|
||||
} else if (is(businessObject, 'bpmn:DataStore')) {
|
||||
// For data objects, only update the flowElements for new data objects, and set the parent so it doesn't get moved.
|
||||
// For data stores, only update the flowElements for new data stores, and set the parent so it doesn't get moved.
|
||||
if (typeof (businessObject.$parent) === 'undefined') {
|
||||
const flowElements = realParent.get('flowElements');
|
||||
flowElements.push(businessObject);
|
||||
|
@ -60,7 +60,7 @@ export default class DataStoreInterceptor extends CommandInterceptor {
|
|||
* For DataStoreReferences only ...
|
||||
* Prevent this from calling the CreateDataStoreBehavior in BPMN-js, as it will
|
||||
* attempt to crete a dataStore immediately. We can't create the dataStore until
|
||||
* 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 stores of the parent when
|
||||
* possible */
|
||||
this.preExecute(['shape.create'], HIGH_PRIORITY, function (event) {
|
||||
const { context } = event;
|
||||
|
@ -71,7 +71,7 @@ export default class DataStoreInterceptor 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 store, use the first existing one if it already exists
|
||||
*/
|
||||
this.executed(['shape.create'], HIGH_PRIORITY, function (event) {
|
||||
const { context } = event;
|
||||
|
@ -98,7 +98,7 @@ export default class DataStoreInterceptor extends CommandInterceptor {
|
|||
const { context } = event;
|
||||
const { shape } = context;
|
||||
// set the reference to the DataStore
|
||||
// Update the name of the reference to match the data object's id.
|
||||
// Update the name of the reference to match the data store's id.
|
||||
if (is(shape, 'bpmn:DataStoreReference') && shape.type !== 'label') {
|
||||
commandStack.execute('element.updateProperties', {
|
||||
element: shape,
|
||||
|
@ -111,7 +111,7 @@ export default class DataStoreInterceptor extends CommandInterceptor {
|
|||
});
|
||||
|
||||
/**
|
||||
* Don't remove the associated DataStore, unless all references to that data object
|
||||
* Don't remove the associated DataStore, unless all references to that data store
|
||||
* Difficult to do given placement of this logic in the BPMN Updater, so we have
|
||||
* to manually handle the removal.
|
||||
*/
|
|
@ -0,0 +1,149 @@
|
|||
import { useService } from 'bpmn-js-properties-panel';
|
||||
import {
|
||||
isTextFieldEntryEdited,
|
||||
TextFieldEntry,
|
||||
} from '@bpmn-io/properties-panel';
|
||||
import { without } from 'min-dash';
|
||||
import { is } from 'bpmn-js/lib/util/ModelUtil';
|
||||
import {
|
||||
findDataStores,
|
||||
findDataStoreReferenceShapes,
|
||||
idToHumanReadableName,
|
||||
} from '../DataStoreHelpers';
|
||||
|
||||
/**
|
||||
* Provides a list of data objects, and allows you to add / remove data objects, and change their ids.
|
||||
* @param props
|
||||
* @constructor
|
||||
*/
|
||||
export function DataStoreArray(props) {
|
||||
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.
|
||||
if (is(element.businessObject, 'bpmn:Process') || is(element.businessObject, 'bpmn:SubProcess')) {
|
||||
process = element.businessObject;
|
||||
} else if (element.businessObject.processRef) {
|
||||
process = element.businessObject.processRef;
|
||||
}
|
||||
|
||||
const dataStores = findDataStores(process);
|
||||
const items = dataStores.map((dataStore, index) => {
|
||||
const id = `${process.id}-dataObj-${index}`;
|
||||
return {
|
||||
id,
|
||||
label: dataStore.id,
|
||||
entries: DataStoreGroup({
|
||||
idPrefix: id,
|
||||
element,
|
||||
dataStore,
|
||||
}),
|
||||
autoFocusEntry: `${id}-dataStore`,
|
||||
remove: removeFactory({
|
||||
element,
|
||||
dataStore,
|
||||
process,
|
||||
commandStack,
|
||||
elementRegistry,
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
||||
function add(event) {
|
||||
event.stopPropagation();
|
||||
const newDataStore = moddle.create('bpmn:DataStore');
|
||||
const newElements = process.get('flowElements');
|
||||
newDataStore.id = moddle.ids.nextPrefixed('DataStore_');
|
||||
newDataStore.$parent = process;
|
||||
newElements.push(newDataStore);
|
||||
commandStack.execute('element.updateModdleProperties', {
|
||||
element,
|
||||
moddleElement: process,
|
||||
properties: {
|
||||
flowElements: newElements,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return { items, add };
|
||||
}
|
||||
|
||||
function removeFactory(props) {
|
||||
const { element, dataStore, process, commandStack } = props;
|
||||
|
||||
return function (event) {
|
||||
event.stopPropagation();
|
||||
commandStack.execute('element.updateModdleProperties', {
|
||||
element,
|
||||
moddleElement: process,
|
||||
properties: {
|
||||
flowElements: without(process.get('flowElements'), dataStore),
|
||||
},
|
||||
});
|
||||
// When a data object is removed, remove all references as well.
|
||||
const references = findDataStoreReferenceShapes(element.children, dataStore.id);
|
||||
for (const ref of references) {
|
||||
commandStack.execute('shape.delete', { shape: ref });
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function DataStoreGroup(props) {
|
||||
const { idPrefix, dataStore } = props;
|
||||
|
||||
return [
|
||||
{
|
||||
id: `${idPrefix}-dataStore`,
|
||||
component: DataStoreTextField,
|
||||
isEdited: isTextFieldEntryEdited,
|
||||
idPrefix,
|
||||
dataStore,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
function DataStoreTextField(props) {
|
||||
const { idPrefix, element, parameter, dataStore } = props;
|
||||
|
||||
const commandStack = useService('commandStack');
|
||||
const debounce = useService('debounceInput');
|
||||
|
||||
const setValue = (value) => {
|
||||
commandStack.execute('element.updateModdleProperties', {
|
||||
element,
|
||||
moddleElement: dataStore,
|
||||
properties: {
|
||||
id: value,
|
||||
},
|
||||
});
|
||||
|
||||
// Also update the label of all the references
|
||||
const references = findDataStoreReferenceShapes(element.children, dataStore.id);
|
||||
for (const ref of references) {
|
||||
commandStack.execute('element.updateProperties', {
|
||||
element: ref,
|
||||
moddleElement: ref.businessObject,
|
||||
properties: {
|
||||
name: idToHumanReadableName(value),
|
||||
},
|
||||
changed: [ref], // everything is already marked as changed, don't recalculate.
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const getValue = () => {
|
||||
return dataStore.id;
|
||||
};
|
||||
|
||||
return TextFieldEntry({
|
||||
element: parameter,
|
||||
id: `${idPrefix}-id`,
|
||||
label: 'Data Store Id',
|
||||
getValue,
|
||||
setValue,
|
||||
debounce,
|
||||
});
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
import { is, isAny } from 'bpmn-js/lib/util/ModelUtil';
|
||||
import { ListGroup, isTextFieldEntryEdited } from '@bpmn-io/properties-panel';
|
||||
import { DataStoreSelect } from './DataStoreSelect';
|
||||
import { DataStoreArray } from './DataStoreArray';
|
||||
|
||||
const LOW_PRIORITY = 500;
|
||||
|
||||
export default function DataStorePropertiesProvider(
|
||||
propertiesPanel,
|
||||
translate,
|
||||
moddle,
|
||||
commandStack,
|
||||
elementRegistry
|
||||
) {
|
||||
this.getGroups = function (element) {
|
||||
return function (groups) {
|
||||
if (is(element, 'bpmn:DataStoreReference')) {
|
||||
groups.push(
|
||||
createDataStoreSelector(element, translate, moddle, commandStack)
|
||||
);
|
||||
}
|
||||
if (
|
||||
isAny(element, ['bpmn:Process', 'bpmn:Participant']) ||
|
||||
(is(element, 'bpmn:SubProcess') && !element.collapsed)
|
||||
) {
|
||||
groups.push(
|
||||
createDataStoreEditor(
|
||||
element,
|
||||
translate,
|
||||
moddle,
|
||||
commandStack,
|
||||
elementRegistry
|
||||
)
|
||||
);
|
||||
}
|
||||
return groups;
|
||||
};
|
||||
};
|
||||
propertiesPanel.registerProvider(LOW_PRIORITY, this);
|
||||
}
|
||||
|
||||
DataStorePropertiesProvider.$inject = [
|
||||
'propertiesPanel',
|
||||
'translate',
|
||||
'moddle',
|
||||
'commandStack',
|
||||
'elementRegistry',
|
||||
];
|
||||
|
||||
/**
|
||||
* Create a group on the main panel with a select box (for choosing the Data Object to connect)
|
||||
* @param element
|
||||
* @param translate
|
||||
* @param moddle
|
||||
* @returns entries
|
||||
*/
|
||||
function createDataStoreSelector(element, translate, moddle, commandStack) {
|
||||
return {
|
||||
id: 'data_object_properties',
|
||||
label: translate('Data Object Properties'),
|
||||
entries: [
|
||||
{
|
||||
id: 'selectDataStore',
|
||||
element,
|
||||
component: DataStoreSelect,
|
||||
isEdited: isTextFieldEntryEdited,
|
||||
moddle,
|
||||
commandStack,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a group on the main panel with a select box (for choosing the Data Object to connect) AND a
|
||||
* full Data Object Array for modifying all the data objects.
|
||||
* @param element
|
||||
* @param translate
|
||||
* @param moddle
|
||||
* @returns entries
|
||||
*/
|
||||
function createDataStoreEditor(
|
||||
element,
|
||||
translate,
|
||||
moddle,
|
||||
commandStack,
|
||||
elementRegistry
|
||||
) {
|
||||
const dataStoreArray = {
|
||||
id: 'editDataStores',
|
||||
element,
|
||||
label: 'Data Stores',
|
||||
component: ListGroup,
|
||||
...DataStoreArray({ element, moddle, commandStack, elementRegistry }),
|
||||
};
|
||||
|
||||
if (dataStoreArray.items) {
|
||||
return dataStoreArray;
|
||||
}
|
||||
}
|
|
@ -6,6 +6,10 @@ import DataObjectInterceptor from './DataObject/DataObjectInterceptor';
|
|||
import DataObjectRules from './DataObject/DataObjectRules';
|
||||
import DataObjectRenderer from './DataObject/DataObjectRenderer';
|
||||
import DataObjectPropertiesProvider from './DataObject/propertiesPanel/DataObjectPropertiesProvider';
|
||||
import DataStoreInterceptor from './DataStore/DataStoreInterceptor';
|
||||
import DataStoreRules from './DataStore/DataStoreRules';
|
||||
import DataStoreRenderer from './DataStore/DataStoreRenderer';
|
||||
import DataStorePropertiesProvider from './DataStore/propertiesPanel/DataStorePropertiesProvider';
|
||||
import ConditionsPropertiesProvider from './conditions/propertiesPanel/ConditionsPropertiesProvider';
|
||||
import ExtensionsPropertiesProvider from './extensions/propertiesPanel/ExtensionsPropertiesProvider';
|
||||
import MessagesPropertiesProvider from './messages/propertiesPanel/MessagesPropertiesProvider';
|
||||
|
@ -22,6 +26,11 @@ export default {
|
|||
'dataObjectInterceptor',
|
||||
'dataObjectRules',
|
||||
'dataObjectPropertiesProvider',
|
||||
'dataObjectRenderer',
|
||||
'dataStoreInterceptor',
|
||||
'dataStoreRules',
|
||||
'dataStorePropertiesProvider',
|
||||
'dataStoreRenderer',
|
||||
'conditionsPropertiesProvider',
|
||||
'extensionsPropertiesProvider',
|
||||
'messagesPropertiesProvider',
|
||||
|
@ -32,7 +41,6 @@ export default {
|
|||
'ioPalette',
|
||||
'ioRules',
|
||||
'ioInterceptor',
|
||||
'dataObjectRenderer',
|
||||
'multiInstancePropertiesProvider',
|
||||
'standardLoopPropertiesProvider',
|
||||
],
|
||||
|
@ -40,6 +48,10 @@ export default {
|
|||
dataObjectRules: ['type', DataObjectRules],
|
||||
dataObjectRenderer: ['type', DataObjectRenderer],
|
||||
dataObjectPropertiesProvider: ['type', DataObjectPropertiesProvider],
|
||||
dataStoreInterceptor: ['type', DataStoreInterceptor],
|
||||
dataStoreRules: ['type', DataStoreRules],
|
||||
dataStoreRenderer: ['type', DataStoreRenderer],
|
||||
dataStorePropertiesProvider: ['type', DataStorePropertiesProvider],
|
||||
conditionsPropertiesProvider: ['type', ConditionsPropertiesProvider],
|
||||
extensionsPropertiesProvider: ['type', ExtensionsPropertiesProvider],
|
||||
signalPropertiesProvider: ['type', SignalPropertiesProvider],
|
||||
|
|
Loading…
Reference in New Issue