feat(context-pad): show delete only if allowed by rules
Related to bpmn-io/diagram-js#131
This commit is contained in:
parent
eb75fda7e0
commit
9322a6a1e6
|
@ -3,6 +3,7 @@
|
|||
|
||||
var assign = require('lodash/object/assign'),
|
||||
forEach = require('lodash/collection/forEach'),
|
||||
isArray = require('lodash/lang/isArray'),
|
||||
is = require('../../util/ModelUtil').is,
|
||||
isAny = require('../modeling/util/ModelingUtil').isAny,
|
||||
getChildLanes = require('../modeling/util/LaneUtil').getChildLanes,
|
||||
|
@ -14,7 +15,7 @@ var assign = require('lodash/object/assign'),
|
|||
*/
|
||||
function ContextPadProvider(contextPad, modeling, elementFactory,
|
||||
connect, create, bpmnReplace,
|
||||
canvas) {
|
||||
canvas, rules) {
|
||||
|
||||
contextPad.registerProvider(this);
|
||||
|
||||
|
@ -27,6 +28,7 @@ function ContextPadProvider(contextPad, modeling, elementFactory,
|
|||
this._create = create;
|
||||
this._bpmnReplace = bpmnReplace;
|
||||
this._canvas = canvas;
|
||||
this._rules = rules;
|
||||
}
|
||||
|
||||
ContextPadProvider.$inject = [
|
||||
|
@ -36,7 +38,8 @@ ContextPadProvider.$inject = [
|
|||
'connect',
|
||||
'create',
|
||||
'bpmnReplace',
|
||||
'canvas'
|
||||
'canvas',
|
||||
'rules'
|
||||
];
|
||||
|
||||
module.exports = ContextPadProvider;
|
||||
|
@ -51,7 +54,8 @@ ContextPadProvider.prototype.getContextPadEntries = function(element) {
|
|||
connect = this._connect,
|
||||
create = this._create,
|
||||
bpmnReplace = this._bpmnReplace,
|
||||
canvas = this._canvas;
|
||||
canvas = this._canvas,
|
||||
rules = this._rules;
|
||||
|
||||
var actions = {};
|
||||
|
||||
|
@ -270,18 +274,27 @@ ContextPadProvider.prototype.getContextPadEntries = function(element) {
|
|||
});
|
||||
}
|
||||
|
||||
// Delete Element Entry
|
||||
assign(actions, {
|
||||
'delete': {
|
||||
group: 'edit',
|
||||
className: 'bpmn-icon-trash',
|
||||
title: 'Remove',
|
||||
action: {
|
||||
click: removeElement,
|
||||
dragstart: removeElement
|
||||
// delete element entry, only show if allowed by rules
|
||||
var deleteAllowed = rules.allowed('elements.delete', { elements: [ element ]});
|
||||
|
||||
if (isArray(deleteAllowed)) {
|
||||
// was the element returned as a deletion candidate?
|
||||
deleteAllowed = deleteAllowed[0] === element;
|
||||
}
|
||||
|
||||
if (deleteAllowed) {
|
||||
assign(actions, {
|
||||
'delete': {
|
||||
group: 'edit',
|
||||
className: 'bpmn-icon-trash',
|
||||
title: 'Remove',
|
||||
action: {
|
||||
click: removeElement,
|
||||
dragstart: removeElement
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return actions;
|
||||
};
|
||||
|
|
|
@ -13,14 +13,15 @@ var contextPadModule = require('../../../../lib/features/context-pad'),
|
|||
coreModule = require('../../../../lib/core'),
|
||||
modelingModule = require('../../../../lib/features/modeling'),
|
||||
popupModule = require('diagram-js/lib/features/popup-menu'),
|
||||
replaceModule = require('diagram-js/lib/features/replace');
|
||||
replaceModule = require('diagram-js/lib/features/replace'),
|
||||
rulesModule = require('./rules');
|
||||
|
||||
|
||||
describe('features - context-pad', function() {
|
||||
|
||||
var diagramXML = require('../../../fixtures/bpmn/simple.bpmn');
|
||||
|
||||
var testModules = [ contextPadModule, coreModule, modelingModule, popupModule, replaceModule ];
|
||||
var testModules = [ contextPadModule, coreModule, modelingModule, popupModule, replaceModule, rulesModule ];
|
||||
|
||||
beforeEach(bootstrapViewer(diagramXML, { modules: testModules }));
|
||||
|
||||
|
@ -34,6 +35,121 @@ describe('features - context-pad', function() {
|
|||
});
|
||||
|
||||
|
||||
describe('remove action rules', function () {
|
||||
|
||||
var deleteAction;
|
||||
|
||||
beforeEach(inject(function (contextPad) {
|
||||
|
||||
deleteAction = function(element) {
|
||||
return domQuery('[data-action="delete"]', contextPad.getPad(element).html);
|
||||
};
|
||||
}));
|
||||
|
||||
|
||||
it('should add delete action by default', inject(function (elementRegistry, contextPad) {
|
||||
|
||||
// given
|
||||
var element = elementRegistry.get('StartEvent_1');
|
||||
|
||||
// when
|
||||
contextPad.open(element);
|
||||
|
||||
// then
|
||||
expect(deleteAction(element)).to.exist;
|
||||
}));
|
||||
|
||||
|
||||
it('should include delete action when rule returns true', inject(function (elementRegistry, contextPad, customRules) {
|
||||
|
||||
// given
|
||||
customRules.addRule('elements.delete', function() {
|
||||
return true;
|
||||
});
|
||||
|
||||
var element = elementRegistry.get('StartEvent_1');
|
||||
|
||||
// when
|
||||
contextPad.open(element);
|
||||
|
||||
// then
|
||||
expect(deleteAction(element)).to.exist;
|
||||
}));
|
||||
|
||||
|
||||
it('should NOT include delete action when rule returns false', inject(function(elementRegistry, contextPad, customRules) {
|
||||
|
||||
// given
|
||||
customRules.addRule('elements.delete', function() {
|
||||
return false;
|
||||
});
|
||||
|
||||
var element = elementRegistry.get('StartEvent_1');
|
||||
|
||||
// when
|
||||
contextPad.open(element);
|
||||
|
||||
// then
|
||||
expect(deleteAction(element)).to.not.exist;
|
||||
}));
|
||||
|
||||
|
||||
it('should call rules with [ element ]', inject(function(elementRegistry, contextPad, customRules) {
|
||||
|
||||
// given
|
||||
var element = elementRegistry.get('StartEvent_1');
|
||||
|
||||
customRules.addRule('elements.delete', function(context) {
|
||||
|
||||
// element array is actually passed
|
||||
expect(context.elements).to.eql([ element ]);
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
// then
|
||||
expect(function() {
|
||||
contextPad.open(element);
|
||||
}).not.to.throw;
|
||||
}));
|
||||
|
||||
|
||||
it('should include delete action when [ element ] is returned from rule', inject(function(elementRegistry, contextPad, customRules) {
|
||||
|
||||
// given
|
||||
customRules.addRule('elements.delete', function(context) {
|
||||
return context.elements;
|
||||
});
|
||||
|
||||
var element = elementRegistry.get('StartEvent_1');
|
||||
|
||||
// when
|
||||
contextPad.open(element);
|
||||
|
||||
// then
|
||||
expect(deleteAction(element)).to.exist;
|
||||
}));
|
||||
|
||||
|
||||
it('should NOT include delete action when [ ] is returned from rule', inject(function(elementRegistry, contextPad, customRules) {
|
||||
|
||||
// given
|
||||
customRules.addRule('elements.delete', function() {
|
||||
return [];
|
||||
});
|
||||
|
||||
var element = elementRegistry.get('StartEvent_1');
|
||||
|
||||
// when
|
||||
contextPad.open(element);
|
||||
|
||||
// then
|
||||
expect(deleteAction(element)).to.not.exist;
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe('should show replace popup menu in the correct position ', function() {
|
||||
|
||||
var container;
|
||||
|
@ -66,5 +182,7 @@ describe('features - context-pad', function() {
|
|||
expect(replaceMenuRect.left).to.be.at.most(padMenuRect.left);
|
||||
expect(replaceMenuRect.top).to.be.at.most(padMenuRect.bottom + padding);
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
'use strict';
|
||||
|
||||
var inherits = require('inherits');
|
||||
|
||||
var RuleProvider = require('diagram-js/lib/features/rules/RuleProvider');
|
||||
|
||||
function CustomRules(eventBus) {
|
||||
RuleProvider.call(this, eventBus);
|
||||
}
|
||||
|
||||
CustomRules.$inject = [ 'eventBus' ];
|
||||
|
||||
inherits(CustomRules, RuleProvider);
|
||||
|
||||
module.exports = CustomRules;
|
|
@ -0,0 +1,4 @@
|
|||
module.exports = {
|
||||
__init__: [ 'customRules' ],
|
||||
customRules: [ 'type', require('./CustomRules') ]
|
||||
};
|
Loading…
Reference in New Issue