diff --git a/lib/camunda-cloud/Modeler.js b/lib/camunda-cloud/Modeler.js index a1450b72..971b1870 100644 --- a/lib/camunda-cloud/Modeler.js +++ b/lib/camunda-cloud/Modeler.js @@ -4,8 +4,6 @@ import BaseModeler from '../base/Modeler'; import behaviorsModule from 'camunda-bpmn-js-behaviors/lib/camunda-cloud'; -import rulesModule from './features/rules'; - import { ZeebePropertiesProviderModule as zeebePropertiesProviderModule, ZeebeTooltipProvider @@ -70,7 +68,6 @@ Modeler.prototype._addElementTemplateChooserModule = function(options) { Modeler.prototype._camundaCloudModules = [ ...commonModules, behaviorsModule, - rulesModule, zeebePropertiesProviderModule, cloudElementTemplatesPropertiesProvider, createAppendAnythingModule, diff --git a/lib/camunda-cloud/features/rules/BpmnRules.js b/lib/camunda-cloud/features/rules/BpmnRules.js deleted file mode 100644 index 1791d2fe..00000000 --- a/lib/camunda-cloud/features/rules/BpmnRules.js +++ /dev/null @@ -1,161 +0,0 @@ -import BpmnRules from 'bpmn-js/lib/features/rules/BpmnRules'; - -import { - find -} from 'min-dash'; - -import { - isLabel -} from 'bpmn-js/lib/util/LabelUtil'; - -import { - is, - getBusinessObject -} from 'bpmn-js/lib/util/ModelUtil'; - - -import { - isEventSubProcess -} from 'bpmn-js/lib/util/DiUtil'; - -import { - getBoundaryAttachment as isBoundaryAttachment -} from 'bpmn-js/lib/features/snapping/BpmnSnappingUtil'; - -/** - * @typedef {import('diagram-js/lib/core/EventBus').default} EventBus - * - * @typedef {import('bpmn-js/lib/model/Types').Element} Element - * @typedef {import('bpmn-js/lib/model/Types').Shape} Shape - * - * @typedef {import('diagram-js/lib/util/Types').Point} Point - */ - -const HIGH_PRIORITY = 5000; - -/** - * Zeebe rule provider that allows to create boundary events with catch events - * - * See {@link CustomRules} for the default implementation - * of BPMN 2.0 modeling rules provided by bpmn-js. - */ -export default class CustomRules extends BpmnRules { - - /** - * @param {EventBus} eventBus - */ - constructor(eventBus) { - super(eventBus); - } - - init() { - super.init(); - - this.addRule('shape.attach', HIGH_PRIORITY,(context) => { - return canAttach( - context.shape, - context.target, - null, - context.position); - }); - } -} - -CustomRules.$inject = [ 'eventBus' ]; - -/** - * Zeebe-specific rule that allows attaching intermediate events. - * - * @param {Element} elements - * @param {Shape} target - * @param {Element} source - * @param {Point} position - * - * @return {boolean|'attach'} - */ -function canAttach(elements, target, source, position) { - function isBoundaryEvent(element) { - return !isLabel(element) && is(element, 'bpmn:BoundaryEvent'); - } - - /** - * In Zeebe we treat IntermediateCatchEvents as boundary events too, - * this must be reflected in the rules. - */ - function isBoundaryCandidate(element) { - return isBoundaryEvent(element) || ( - ( - is(element, 'bpmn:IntermediateCatchEvent') || - is(element, 'bpmn:IntermediateThrowEvent') - ) && !element.parent - ); - } - - function isForCompensation(e) { - return getBusinessObject(e).isForCompensation; - } - - function isReceiveTaskAfterEventBasedGateway(element) { - return ( - is(element, 'bpmn:ReceiveTask') && - find(element.incoming, function(incoming) { - return is(incoming.source, 'bpmn:EventBasedGateway'); - }) - ); - } - - if (!Array.isArray(elements)) { - elements = [ elements ]; - } - - // disallow appending as boundary event - if (source) { - return false; - } - - // only (re-)attach one element at a time - if (elements.length !== 1) { - return false; - } - - const element = elements[0]; - - // do not attach labels - if (isLabel(element)) { - return false; - } - - // only handle boundary events - if (!isBoundaryCandidate(element)) { - return false; - } - - // allow default move operation - if (!target) { - return true; - } - - // disallow drop on event sub processes - if (isEventSubProcess(target)) { - return false; - } - - // only allow drop on non compensation activities - if (!is(target, 'bpmn:Activity') || isForCompensation(target)) { - return false; - } - - // only attach to subprocess border - if (position && !isBoundaryAttachment(position, target)) { - return false; - } - - // do not attach on receive tasks after event based gateways - if (isReceiveTaskAfterEventBasedGateway(target)) { - return false; - } - - return 'attach'; -} - -CustomRules.canAttach = canAttach; \ No newline at end of file diff --git a/lib/camunda-cloud/features/rules/index.js b/lib/camunda-cloud/features/rules/index.js deleted file mode 100644 index 59289540..00000000 --- a/lib/camunda-cloud/features/rules/index.js +++ /dev/null @@ -1,6 +0,0 @@ -import BpmnRules from './BpmnRules'; - -export default { - __init__: [ 'bpmnRules' ], - bpmnRules: [ 'type', BpmnRules ] -}; \ No newline at end of file diff --git a/test/camunda-cloud/features/rules/BpmnRulesSpec.js b/test/camunda-cloud/features/rules/BpmnRulesSpec.js deleted file mode 100644 index 57b2f5e8..00000000 --- a/test/camunda-cloud/features/rules/BpmnRulesSpec.js +++ /dev/null @@ -1,229 +0,0 @@ - -import { - bootstrapCamundaCloudModeler, - getBpmnJS, - inject -} from 'test/TestHelper'; - -import { - isString -} from 'min-dash'; - -import coreModule from 'bpmn-js/lib/core'; - -import modelingModule from 'bpmn-js/lib/features/modeling'; - -import contextPadModule from 'bpmn-js/lib/features/context-pad'; - -import paletteModule from 'bpmn-js/lib/features/palette'; - -import rulesModule from 'lib/camunda-cloud/features/rules'; - -import diagramXML from 'test/fixtures/diagram.bpmn'; - -const testModules = [ - coreModule, - paletteModule, - contextPadModule, - modelingModule, - rulesModule -]; - -describe('camunda-cloud/features - BpmnRules', function() { - - describe('event create', function() { - - beforeEach(bootstrapCamundaCloudModeler(diagramXML, { modules: testModules })); - - it('should attach IntermediateThrowEvent to Task', inject(function(elementFactory) { - - // given - const eventShape = elementFactory.createShape({ - type: 'bpmn:IntermediateThrowEvent' - }); - - // then - expectCanAttach([ eventShape ], 'ServiceTask_1', { - attach: 'attach' - }); - })); - - - it('should attach MessageEvent to Task', inject(function(elementFactory, bpmnFactory) { - - // given - const messageEventDefinition = bpmnFactory.create('bpmn:MessageEventDefinition'); - - const messageIntermediateCatchEvent = bpmnFactory.create('bpmn:IntermediateCatchEvent', { - eventDefinitions: [ messageEventDefinition ] - }); - - const eventShape = elementFactory.createShape({ - id: messageIntermediateCatchEvent.id, - businessObject: messageIntermediateCatchEvent - }); - - // then - expectCanAttach([ eventShape ], 'ServiceTask_1', { - attach: 'attach' - }); - - })); - - - it('should attach TimerEvent to Task', inject(function(elementFactory, bpmnFactory) { - - // given - const timerEventDefinition = bpmnFactory.create('bpmn:TimerEventDefinition'); - - const timerIntermediateCatchEvent = bpmnFactory.create('bpmn:IntermediateCatchEvent', { - eventDefinitions: [ timerEventDefinition ] - }); - - const eventShape = elementFactory.createShape({ - id: timerIntermediateCatchEvent.id, - businessObject: timerIntermediateCatchEvent - }); - - // then - expectCanAttach([ eventShape ], 'ServiceTask_1', { - attach: 'attach' - }); - - })); - - - it('should NOT attach non-boundary to Task', inject(function(elementFactory) { - - // given - const taskShape = elementFactory.createShape({ - type: 'bpmn:ReceiveTask' - }); - - // then - expectCanAttach([ taskShape ], 'ServiceTask_1', { - attach: false - }); - })); - - - it('should NOT attach multiple at a time to Task', inject(function(elementFactory) { - - // given - const eventShape1 = elementFactory.createShape({ - type: 'bpmn:IntermediateThrowEvent' - }); - - const eventShape2 = elementFactory.createShape({ - type: 'bpmn:IntermediateThrowEvent' - }); - - // then - expectCanAttach([ eventShape1, eventShape2 ], 'ServiceTask_1', { - attach: false - }); - })); - - - it('should NOT attach label to Task', inject(function(elementFactory) { - - // given - const labelElement = elementFactory.createShape({ - type: 'bpmn:FlowNode', - labelTarget: {} - }); - - // then - expectCanAttach([ labelElement ], 'ServiceTask_1', { - attach: false - }); - })); - - - it('should NOT attach to non compensation activity', inject(function(elementFactory) { - - // given - const eventShape = elementFactory.createShape({ - type: 'bpmn:IntermediateThrowEvent' - }); - - // then - expectCanAttach([ eventShape ], 'MessageEvent_1', { - attach: false - }); - })); - - - it('should NOT attach to ReceiveTask after EventBasedGateway ', inject(function(elementFactory) { - - // given - const eventShape = elementFactory.createShape({ - type: 'bpmn:IntermediateThrowEvent' - }); - - // then - expectCanAttach([ eventShape ], 'MessageTask_2', { - attach: false - }); - })); - - - it('should NOT attach BoundaryEvent to EventSubProcess ', inject(function(elementFactory) { - - // given - const eventShape = elementFactory.createShape({ - type: 'bpmn:BoundaryEvent' - }); - - // then - expectCanAttach([ eventShape ], 'EventSubProcess1', { - attach: false - }); - })); - - - }); - -}); - - -// helper ////////// - -/** - * Retrieve element, resolving an ID with - * the actual element. - */ -const get = (element) => { - - let actualElement; - - if (isString(element)) { - actualElement = getBpmnJS().invoke(function(elementRegistry) { - return elementRegistry.get(element); - }); - - if (!actualElement) { - throw new Error('element #' + element + ' not found'); - } - - return actualElement; - } - - return element; -}; - -const expectCanAttach = (elements, target, rules) => { - - let results = {}; - - getBpmnJS().invoke(function(bpmnRules) { - - target = get(target); - - if ('attach' in rules) { - results.attach = bpmnRules.canAttach(elements, target); - } - }); - - expect(results).to.eql(rules); -};