Skip to content

Commit

Permalink
fix: pasting compensation activity without boundary event
Browse files Browse the repository at this point in the history
Closes #2070
  • Loading branch information
abdul99ahad authored and nikku committed Sep 9, 2024
1 parent afdd676 commit 4359f18
Show file tree
Hide file tree
Showing 5 changed files with 195 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ All notable changes to [bpmn-js](https://github.com/bpmn-io/bpmn-js) are documen

___Note:__ Yet to be released changes appear here._

* `FIX`: pasting compensation activity without boundary event ([#2070](https://github.com/bpmn-io/bpmn-js/issues/2070))
* `FIX`: lane resize constraints for se and nw direction ([#2209](https://github.com/bpmn-io/bpmn-js/issues/2209))

## 17.9.2
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import inherits from 'inherits-browser';

import CommandInterceptor from 'diagram-js/lib/command/CommandInterceptor';

import { getBusinessObject, is } from '../../../util/ModelUtil';

import { hasEventDefinition } from '../../../util/DiUtil';

/**
* @typedef {import('diagram-js/lib/core/EventBus').default} EventBus
* @typedef {import('../../rules/BpmnRules').default} BpmnRules
* @typedef {import('../Modeling').default} Modeling
*/


/**
* A behavior that sets the property of Compensation Activity after paste operation
*
* @param {EventBus} eventBus
* @param {Modeling} modeling
*/
export default function SetCompensationActivityAfterPasteBehavior(eventBus, modeling) {

CommandInterceptor.call(this, eventBus);

this.postExecuted('elements.create', function(event) {
const context = event.context,
elements = context.elements;

// check if compensation activity is connected to compensation boundary event
for (const element of elements) {
if (isForCompensation(element) && !isConnectedToCompensationBoundaryEvent(element)) {
modeling.updateProperties(element, { isForCompensation: undefined });
}
}
});
}

inherits(SetCompensationActivityAfterPasteBehavior, CommandInterceptor);

SetCompensationActivityAfterPasteBehavior.$inject = [
'eventBus',
'modeling'
];


// helpers //////////////////////

function isForCompensation(element) {
const bo = getBusinessObject(element);
return bo && bo.isForCompensation;
}

function isCompensationBoundaryEvent(element) {
return element && is(element, 'bpmn:BoundaryEvent') &&
hasEventDefinition(element, 'bpmn:CompensateEventDefinition');
}

function isConnectedToCompensationBoundaryEvent(element) {
const compensationAssociations = element.incoming.filter(
connection => isCompensationBoundaryEvent(connection.source)
);
if (compensationAssociations.length > 0) {
return true;
}
return false;
}
7 changes: 5 additions & 2 deletions lib/features/modeling/behavior/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import ToggleElementCollapseBehaviour from './ToggleElementCollapseBehaviour';
import UnclaimIdBehavior from './UnclaimIdBehavior';
import UnsetDefaultFlowBehavior from './UnsetDefaultFlowBehavior';
import UpdateFlowNodeRefsBehavior from './UpdateFlowNodeRefsBehavior';
import SetCompensationActivityAfterPasteBehavior from './SetCompensationActivityAfterPasteBehavior';

/**
* @type { import('didi').ModuleDeclaration }
Expand Down Expand Up @@ -83,7 +84,8 @@ export default {
'toggleElementCollapseBehaviour',
'unclaimIdBehavior',
'updateFlowNodeRefsBehavior',
'unsetDefaultFlowBehavior'
'unsetDefaultFlowBehavior',
'setCompensationActivityAfterPasteBehavior'
],
adaptiveLabelPositioningBehavior: [ 'type', AdaptiveLabelPositioningBehavior ],
appendBehavior: [ 'type', AppendBehavior ],
Expand Down Expand Up @@ -124,5 +126,6 @@ export default {
toggleElementCollapseBehaviour : [ 'type', ToggleElementCollapseBehaviour ],
unclaimIdBehavior: [ 'type', UnclaimIdBehavior ],
unsetDefaultFlowBehavior: [ 'type', UnsetDefaultFlowBehavior ],
updateFlowNodeRefsBehavior: [ 'type', UpdateFlowNodeRefsBehavior ]
updateFlowNodeRefsBehavior: [ 'type', UpdateFlowNodeRefsBehavior ],
setCompensationActivityAfterPasteBehavior: [ 'type', SetCompensationActivityAfterPasteBehavior ]
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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" id="Definitions_1" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.25.0">
<bpmn:process id="Process_1" isExecutable="false">
<bpmn:startEvent id="Event_0wuaar2">
<bpmn:outgoing>Flow_1ank1yi</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:task id="Compensation_Boundary_Task">
<bpmn:incoming>Flow_1ank1yi</bpmn:incoming>
</bpmn:task>
<bpmn:sequenceFlow id="Flow_1ank1yi" sourceRef="Event_0wuaar2" targetRef="Compensation_Boundary_Task" />
<bpmn:boundaryEvent id="Compensation_Boundary_Event" attachedToRef="Compensation_Boundary_Task">
<bpmn:compensateEventDefinition id="CompensateEventDefinition_0ibh5ku" />
</bpmn:boundaryEvent>
<bpmn:task id="Compensation_Activity" isForCompensation="true" />
<bpmn:association id="Association_0x72gur" associationDirection="One" sourceRef="Compensation_Boundary_Event" targetRef="Compensation_Activity" />
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">
<bpmndi:BPMNShape id="Event_0wuaar2_di" bpmnElement="Event_0wuaar2">
<dc:Bounds x="152" y="112" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Compensation_Boundary_Task_di" bpmnElement="Compensation_Boundary_Task">
<dc:Bounds x="240" y="90" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Compensation_Activity_di" bpmnElement="Compensation_Activity">
<dc:Bounds x="370" y="210" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Association_0x72gur_di" bpmnElement="Association_0x72gur">
<di:waypoint x="300" y="188" />
<di:waypoint x="300" y="250" />
<di:waypoint x="370" y="250" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="Event_0njauji_di" bpmnElement="Compensation_Boundary_Event">
<dc:Bounds x="282" y="152" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_1ank1yi_di" bpmnElement="Flow_1ank1yi">
<di:waypoint x="188" y="130" />
<di:waypoint x="240" y="130" />
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import {
bootstrapModeler,
inject
} from 'test/TestHelper';

import modelingModule from 'lib/features/modeling';
import coreModule from 'lib/core';
import { is } from 'lib/util/ModelUtil';
import copyPasteModule from 'lib/features/copy-paste';

import diagramXML from './SetCompensationActivityAfterPasteBehaviorSpec.bpmn';


describe('features/modeling/behavior - compensation activity after paste', function() {

const testModules = [
copyPasteModule,
coreModule,
modelingModule
];

beforeEach(bootstrapModeler(diagramXML, { modules: testModules }));


describe('copy/paste compensation activity', function() {

it('without boundary event', inject(function(canvas, elementRegistry, copyPaste) {

// given
copyPaste.copy([ elementRegistry.get('Compensation_Activity') ]);

// when
var copiedElements = copyPaste.paste({
element: canvas.getRootElement(),
point: {
x: 100,
y: 100
}
});

// then
expect(copiedElements).to.have.lengthOf(1);
const taskElement = copiedElements.find(element => is(element, 'bpmn:Task'));
expect(taskElement.businessObject.isForCompensation).to.be.false;
}));


it('with boundary event', inject(function(canvas, elementRegistry, copyPaste) {

// given
copyPaste.copy([
elementRegistry.get('Compensation_Boundary_Task'),
elementRegistry.get('Compensation_Activity') ]);

// when
var copiedElements = copyPaste.paste({
element: canvas.getRootElement(),
point: {
x: 100,
y: 100
}
});

// then
expect(copiedElements).to.have.lengthOf(4);
expect(copiedElements.filter(element => is(element, 'bpmn:Association'))).to.have.length(1);
expect(copiedElements.filter(element => is(element, 'bpmn:BoundaryEvent'))).to.have.length(1);
expect(copiedElements.filter(element => is(element, 'bpmn:Task'))).to.have.length(2);

// verify that for every Task element, if businessObject.isForCompensation exists, it should be true
copiedElements.filter(element => is(element, 'bpmn:Task')).forEach(taskElement => {
if (Object.prototype.hasOwnProperty.call(taskElement.businessObject, 'isForCompensation')) {
expect(taskElement.businessObject.isForCompensation).to.be.true;
}
});
}));

});

});

0 comments on commit 4359f18

Please sign in to comment.