Skip to content

Commit

Permalink
feat: support multiple propertiesProviders
Browse files Browse the repository at this point in the history
This adds the PropertiesPanel#registerProvider method that allows users
to register custom properties providers.

A provider must have one of the following signatures:

({ getTabs: (element) => any[] }) // returns / overrides existing tabs

({ getTabs: (element) => (any[]) => any[] }); // may modify the existing
tabs (i.e. monkey patch) and return the updated tabs

Related to camunda/camunda-modeler#1992
  • Loading branch information
nikku authored and fake-join[bot] committed Mar 2, 2021
1 parent 1bf944a commit 8bcc06a
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 6 deletions.
66 changes: 60 additions & 6 deletions lib/PropertiesPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ var getBusinessObject = require('bpmn-js/lib/util/ModelUtil').getBusinessObject;
var HIDE_CLASS = 'bpp-hidden';
var DEBOUNCE_DELAY = 300;

var DEFAULT_PRIORITY = 1000;

function isToggle(node) {
return node.type === 'checkbox' || node.type === 'radio';
Expand Down Expand Up @@ -223,34 +224,56 @@ function extractGroups(tabs) {
* @constructor
*
* @param {Object} config
* @param {didi.Injector} injector
* @param {EventBus} eventBus
* @param {Modeling} modeling
* @param {PropertiesProvider} propertiesProvider
* @param {Canvas} canvas
* @param {CommandStack} commandStack
*/
function PropertiesPanel(config, eventBus, modeling, propertiesProvider, commandStack, canvas) {
function PropertiesPanel(config, injector, eventBus, modeling, commandStack, canvas) {

this._eventBus = eventBus;
this._modeling = modeling;
this._commandStack = commandStack;
this._canvas = canvas;
this._propertiesProvider = propertiesProvider;

var propertiesProvider = injector.get('propertiesProvider', false);

if (propertiesProvider) {
this.registerProvider(propertiesProvider);
}

this._init(config);
}

PropertiesPanel.$inject = [
'config.propertiesPanel',
'injector',
'eventBus',
'modeling',
'propertiesProvider',
'commandStack',
'canvas'
];

module.exports = PropertiesPanel;

/**
* @param {number} [priority]
* @param { { getTabs: any[] | (any) => (any[]) => any[]) } } provider
*/
PropertiesPanel.prototype.registerProvider = function(priority, provider) {

if (!provider) {
provider = priority;
priority = DEFAULT_PRIORITY;
}

this._eventBus.on('propertiesPanel.getProviders', priority, function(event) {
event.providers.push(provider);
});

this._eventBus.fire('propertiesPanel.providersChanged');
};

PropertiesPanel.prototype._init = function(config) {

Expand Down Expand Up @@ -340,7 +363,10 @@ PropertiesPanel.prototype._init = function(config) {
}
});

eventBus.on('elementTemplates.changed', function() {
eventBus.on([
'elementTemplates.changed',
'propertiesPanel.providersChanged'
], function() {
var current = self._current;
var element = current && current.element;

Expand Down Expand Up @@ -460,6 +486,34 @@ PropertiesPanel.prototype.activateTab = function(tabId) {
}
};

PropertiesPanel.prototype._getProviders = function() {

var event = this._eventBus.createEvent({
type: 'propertiesPanel.getProviders',
providers: []
});

this._eventBus.fire(event);

return event.providers;
};

PropertiesPanel.prototype._getTabs = function(element) {
var providers = this._getProviders();

// loop through all providers and their entries.
// group entries by id so that overriding an entry is possible
return reduce(providers, function(tabs, provider) {
var tabsOrUpdater = provider.getTabs(element);

if (isFunction(tabsOrUpdater)) {
return tabsOrUpdater(tabs);
} else {
return tabsOrUpdater;
}
}, []);
};

/**
* Update properties panel to show properties of element. Create new properties panel if no previous
* properties panel, element has changed or element has not changed but entries have.
Expand All @@ -474,7 +528,7 @@ PropertiesPanel.prototype.update = function(element) {
}

// (2) Get tabs
var tabs = this._propertiesProvider.getTabs(element);
var tabs = this._getTabs(element);

var activeTabId,
activeTabNode;
Expand Down
45 changes: 45 additions & 0 deletions test/spec/PropertiesPanelSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,7 @@ describe('properties-panel', function() {
it('should paste to [contenteditable] as plain text');
});


describe('integration test', function() {

describe('validation', function() {
Expand Down Expand Up @@ -639,6 +640,50 @@ describe('properties-panel', function() {

});
});


describe('properties providers', function() {

it('should register provider', inject(
function(propertiesPanel) {

// given

// when
// high priority provider
propertiesPanel.registerProvider(1500, {
getTabs: function(element) {
expect(element).to.exist;

return function(tabs) {
expect(tabs).to.be.empty;
};
}
});

// default priority provider
propertiesPanel.registerProvider({
getTabs: function(element) {
expect(element).to.exist;

return function(tabs) {
expect(tabs).to.have.length(3);

// clear tabs
return [];
};
}
});

propertiesPanel.attachTo(container);

// then
expect(document.querySelectorAll('.bpp-properties-tab', container)).to.be.empty;
}
));

});

});

// helper //////////////////////////
Expand Down

0 comments on commit 8bcc06a

Please sign in to comment.