diff --git a/lib/features/context-pad/ContextPadProvider.js b/lib/features/context-pad/ContextPadProvider.js index 2d2f4a1f..f055f546 100644 --- a/lib/features/context-pad/ContextPadProvider.js +++ b/lib/features/context-pad/ContextPadProvider.js @@ -1,7 +1,8 @@ import { assign, forEach, - isArray + isArray, + every } from 'min-dash'; import { @@ -86,9 +87,49 @@ ContextPadProvider.$inject = [ 'translate' ]; +ContextPadProvider.prototype.getMultiElementContextPadEntries = function(elements) { + var modeling = this._modeling; + + var actions = {}; + + if (this._isDeleteAllowed(elements)) { + assign(actions, { + 'delete': { + group: 'edit', + className: 'bpmn-icon-trash', + title: this._translate('Remove'), + action: { + click: function(event, elements) { + modeling.removeElements(elements.slice()); + } + } + } + }); + } + + return actions; +}; + +/** + * @param {djs.model.Base[]} elements + * @return {boolean} + */ +ContextPadProvider.prototype._isDeleteAllowed = function(elements) { + + var baseAllowed = this._rules.allowed('elements.delete', { + elements: elements + }); + + if (isArray(baseAllowed)) { + return every(baseAllowed, function(element) { + return includes(baseAllowed, element); + }); + } + + return baseAllowed; +}; ContextPadProvider.prototype.getContextPadEntries = function(element) { - var contextPad = this._contextPad, modeling = this._modeling, @@ -113,7 +154,7 @@ ContextPadProvider.prototype.getContextPadEntries = function(element) { connect.start(event, element); } - function removeElement(e) { + function removeElement(e, element) { modeling.removeElements([ element ]); } @@ -479,3 +520,7 @@ function isEventType(eventBo, type, definition) { return isType && isDefinition; } + +function includes(array, item) { + return array.indexOf(item) !== -1; +} \ No newline at end of file diff --git a/test/spec/features/context-pad/ContextPadProviderSpec.js b/test/spec/features/context-pad/ContextPadProviderSpec.js index 2ea5ce31..c17c7e51 100644 --- a/test/spec/features/context-pad/ContextPadProviderSpec.js +++ b/test/spec/features/context-pad/ContextPadProviderSpec.js @@ -51,8 +51,8 @@ describe('features - context-pad', function() { beforeEach(inject(function(contextPad) { - deleteAction = function(element) { - return padEntry(contextPad.getPad(element).html, 'delete'); + deleteAction = function(target) { + return padEntry(contextPad.getPad(target).html, 'delete'); }; })); @@ -165,6 +165,65 @@ describe('features - context-pad', function() { }) ); + + describe('multi-element', function() { + + it('should add delete action by default', inject( + function(elementRegistry, contextPad) { + + // given + var event = elementRegistry.get('StartEvent_1'), + task = elementRegistry.get('Task_1'); + + // when + contextPad.open([ event, task ]); + + // then + expect(deleteAction([ event, task ])).to.exist; + } + )); + + + it('should NOT add delete action when rule returns false', inject( + function(elementRegistry, contextPad, customRules) { + + // given + customRules.addRule('elements.delete', 1500, function() { + return false; + }); + + var event = elementRegistry.get('StartEvent_1'), + task = elementRegistry.get('Task_1'); + + // when + contextPad.open([ event, task ]); + + // then + expect(deleteAction([ event, task ])).not.to.exist; + } + )); + + + it('should trigger batch delete', inject( + function(elementRegistry, contextPad, customRules) { + + // given + var event = elementRegistry.get('StartEvent_1'), + task = elementRegistry.get('Task_1'); + + contextPad.open([ event, task ]); + + // when + contextPad.trigger('click', padEvent('delete')); + + // then + expect(elementRegistry.get('StartEvent_1')).not.to.exist; + expect(elementRegistry.get('Task_1')).not.to.exist; + } + )); + + }); + });