feat(bpmn): make available BpmnRegistry in renderer
This commit upgrades the code base to the latest diagram-js changes and adds a component called BpmnRegistry that can be used to retrieve a certain BPMN/DI element from a shape/connection id. Related to #19
This commit is contained in:
parent
4c0c286ae7
commit
02313e6c1b
14
lib/Model.js
14
lib/Model.js
|
@ -24,8 +24,22 @@ function instance() {
|
|||
return INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a BPMN model tree from a given xml string.
|
||||
*
|
||||
* @param {String} xmlStr
|
||||
* @param {String} [typeName] name of the root element, defaults to 'bpmn:Definitions'
|
||||
* @param {Object} [options] to pass to the underlying reader
|
||||
* @param {Function} callback the callback that is invoked with (err, result, parseContext)
|
||||
*/
|
||||
function fromXML(xmlStr, typeName, options, callback) {
|
||||
|
||||
if (!_.isString(typeName)) {
|
||||
callback = options;
|
||||
options = typeName;
|
||||
typeName = 'bpmn:Definitions';
|
||||
}
|
||||
|
||||
if (_.isFunction(options)) {
|
||||
callback = options;
|
||||
options = {};
|
||||
|
|
|
@ -3,10 +3,12 @@ var Diagram = require('diagram-js');
|
|||
var bpmnModule = require('./di').defaultModule,
|
||||
Viewer = require('./Viewer');
|
||||
|
||||
require('./core/BpmnRegistry');
|
||||
|
||||
require('./draw/BpmnRenderer');
|
||||
|
||||
require('diagram-js/src/features/DragUI');
|
||||
require('diagram-js/src/features/SelectionUI');
|
||||
require('diagram-js/lib/features/dnd/Visuals');
|
||||
require('diagram-js/lib/features/selection/Visuals');
|
||||
|
||||
|
||||
function Modeler(container) {
|
||||
|
@ -20,7 +22,7 @@ Modeler.prototype.createDiagram = function() {
|
|||
return new Diagram({
|
||||
canvas: { container: this.container },
|
||||
modules: [ bpmnModule ],
|
||||
components: [ 'selectionUI', 'dragUI' ]
|
||||
components: [ 'selectionVisuals', 'dragVisuals', 'bpmnRegistry']
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
var _ = require('lodash');
|
||||
|
||||
function failSafeAsync(fn) {
|
||||
|
||||
return function() {
|
||||
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
|
||||
var done = args[args.length - 1];
|
||||
if (!done || !_.isFunction(done)) {
|
||||
done = function(e) {
|
||||
throw e;
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
fn.apply(this, args);
|
||||
} catch (e) {
|
||||
done(e);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.failSafeAsync = failSafeAsync;
|
|
@ -1,11 +1,12 @@
|
|||
var Diagram = require('diagram-js');
|
||||
|
||||
var Importer = require('./import/Importer'),
|
||||
Model = require('./Model');
|
||||
Model = require('./Model'),
|
||||
failSafeAsync = require('./Util').failSafeAsync;
|
||||
|
||||
|
||||
function initListeners(diagram, listeners) {
|
||||
var events = diagram.get('events');
|
||||
var events = diagram.get('eventBus');
|
||||
|
||||
listeners.forEach(function(l) {
|
||||
events.on(l.event, l.handler);
|
||||
|
@ -72,7 +73,7 @@ Viewer.prototype.saveSVG = function(options, done) {
|
|||
done(null, svg);
|
||||
};
|
||||
|
||||
Viewer.prototype.importDefinitions = function(definitions, done) {
|
||||
Viewer.prototype.importDefinitions = failSafeAsync(function(definitions, done) {
|
||||
|
||||
if (this.diagram) {
|
||||
this.clear();
|
||||
|
@ -85,7 +86,7 @@ Viewer.prototype.importDefinitions = function(definitions, done) {
|
|||
this.definitions = definitions;
|
||||
|
||||
Importer.importBpmnDiagram(this.diagram, definitions, done);
|
||||
};
|
||||
});
|
||||
|
||||
Viewer.prototype.createDiagram = function() {
|
||||
return new Diagram({ canvas: { container: this.container }});
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
var bpmnModule = require('../di').defaultModule;
|
||||
|
||||
|
||||
/**
|
||||
* @class
|
||||
*
|
||||
* A registry that keeps track of bpmn semantic / di elements and the
|
||||
* corresponding shapes.
|
||||
*
|
||||
* @param {EventBus} events
|
||||
* @param {ElementRegistry} elementRegistry
|
||||
*/
|
||||
function BpmnRegistry(events, elementRegistry) {
|
||||
|
||||
var elements = {
|
||||
di: {},
|
||||
semantic: {},
|
||||
diagramElement: {}
|
||||
};
|
||||
|
||||
events.on('bpmn.element.add', function(e) {
|
||||
var semantic = e.semantic,
|
||||
id = semantic.id;
|
||||
|
||||
elements.di[id] = e.di;
|
||||
elements.semantic[id] = e.semantic;
|
||||
elements.diagramElement[id] = e.diagramElement;
|
||||
});
|
||||
|
||||
events.on('bpmn.element.removed', function(e) {
|
||||
var semantic = e.semantic,
|
||||
id = semantic.id;
|
||||
|
||||
delete elements.di[id];
|
||||
delete elements.semantic[id];
|
||||
delete elements.diagramElement[id];
|
||||
});
|
||||
|
||||
function get(type) {
|
||||
var collection = elements[type];
|
||||
|
||||
return function(id) {
|
||||
return collection[id];
|
||||
};
|
||||
}
|
||||
|
||||
// API
|
||||
this.getSemantic = get('semantic');
|
||||
this.getDi = get('di');
|
||||
this.getDiagramElement = get('diagramElement');
|
||||
}
|
||||
|
||||
bpmnModule.type('bpmnRegistry', [ 'eventBus', 'elementRegistry', BpmnRegistry ]);
|
||||
|
||||
module.exports = BpmnRegistry;
|
|
@ -1,14 +1,14 @@
|
|||
var bpmnModule = require('../di').defaultModule;
|
||||
|
||||
require('diagram-js/src/core/Events');
|
||||
require('diagram-js/src/draw/Styles');
|
||||
require('diagram-js/lib/core/EventBus');
|
||||
require('diagram-js/lib/draw/Styles');
|
||||
|
||||
var DefaultRenderer = require('diagram-js/src/draw/Renderer');
|
||||
var DefaultRenderer = require('diagram-js/lib/draw/Renderer');
|
||||
|
||||
|
||||
var flattenPoints = DefaultRenderer.flattenPoints;
|
||||
|
||||
function BpmnRenderer(events, styles) {
|
||||
function BpmnRenderer(events, styles, bpmnRegistry) {
|
||||
|
||||
DefaultRenderer.apply(this, [ events, styles ]);
|
||||
|
||||
|
@ -394,6 +394,6 @@ function BpmnRenderer(events, styles) {
|
|||
BpmnRenderer.prototype = Object.create(DefaultRenderer.prototype);
|
||||
|
||||
|
||||
bpmnModule.type('renderer', [ 'events', 'styles', BpmnRenderer ]);
|
||||
bpmnModule.type('renderer', [ 'eventBus', 'styles', 'bpmnRegistry', BpmnRenderer ]);
|
||||
|
||||
module.exports = BpmnRenderer;
|
|
@ -1,12 +1,12 @@
|
|||
var _ = require('lodash');
|
||||
|
||||
var BpmnTreeWalker = require('./BpmnTreeWalker');
|
||||
var BpmnTreeWalker = require('./BpmnTreeWalker'),
|
||||
Util = require('../Util');
|
||||
|
||||
function importBpmnDiagram(diagram, definitions, done) {
|
||||
|
||||
var canvas = diagram.get('canvas');
|
||||
|
||||
var shapes = {};
|
||||
var events = diagram.get('eventBus');
|
||||
|
||||
var visitor = {
|
||||
|
||||
|
@ -14,6 +14,12 @@ function importBpmnDiagram(diagram, definitions, done) {
|
|||
|
||||
var shape;
|
||||
|
||||
function fire(type, shape) {
|
||||
events.fire('bpmn.element.' + type, {
|
||||
semantic: element, di: di, diagramElement: shape
|
||||
});
|
||||
}
|
||||
|
||||
if (di.$type === 'bpmndi:BPMNShape') {
|
||||
var bounds = di.bounds;
|
||||
|
||||
|
@ -24,6 +30,7 @@ function importBpmnDiagram(diagram, definitions, done) {
|
|||
parent: parent
|
||||
};
|
||||
|
||||
fire('add', shape);
|
||||
canvas.addShape(shape);
|
||||
} else {
|
||||
|
||||
|
@ -32,10 +39,12 @@ function importBpmnDiagram(diagram, definitions, done) {
|
|||
});
|
||||
|
||||
shape = { id: element.id, type: element.$type, waypoints: waypoints };
|
||||
|
||||
fire('add', shape);
|
||||
canvas.addConnection(shape);
|
||||
}
|
||||
|
||||
shapes[element.id] = shape;
|
||||
fire('added', shape);
|
||||
|
||||
return shape;
|
||||
},
|
||||
|
@ -46,10 +55,9 @@ function importBpmnDiagram(diagram, definitions, done) {
|
|||
};
|
||||
|
||||
var walker = new BpmnTreeWalker(visitor);
|
||||
|
||||
walker.handleDefinitions(definitions);
|
||||
|
||||
|
||||
done();
|
||||
}
|
||||
|
||||
module.exports.importBpmnDiagram = importBpmnDiagram;
|
||||
module.exports.importBpmnDiagram = Util.failSafeAsync(importBpmnDiagram);
|
|
@ -0,0 +1,71 @@
|
|||
var fs = require('fs');
|
||||
|
||||
var BpmnModel = require('../../../lib/Model'),
|
||||
Modeler = require('../../../lib/Modeler');
|
||||
|
||||
var Matchers = require('../Matchers');
|
||||
|
||||
describe('Modeler', function() {
|
||||
|
||||
var bpmnModel = BpmnModel.instance();
|
||||
|
||||
function read(xml, opts, callback) {
|
||||
return BpmnModel.fromXML(xml, 'bpmn:Definitions', opts, callback);
|
||||
}
|
||||
|
||||
|
||||
var container;
|
||||
|
||||
|
||||
beforeEach(Matchers.add);
|
||||
|
||||
beforeEach(function() {
|
||||
container = document.createElement('div');
|
||||
document.getElementsByTagName('body')[0].appendChild(container);
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
container.parentNode.removeChild(container);
|
||||
});
|
||||
|
||||
|
||||
it('should import simple process', function(done) {
|
||||
|
||||
var xml = fs.readFileSync('test/fixtures/bpmn/simple.bpmn', 'utf8');
|
||||
|
||||
var renderer = new Modeler(container);
|
||||
|
||||
renderer.importXML(xml, function(err) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should import empty definitions', function(done) {
|
||||
|
||||
var xml = fs.readFileSync('test/fixtures/bpmn/empty-definitions.bpmn', 'utf8');
|
||||
|
||||
var renderer = new Modeler(container);
|
||||
|
||||
renderer.importXML(xml, function(err) {
|
||||
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should handle errors', function(done) {
|
||||
|
||||
var xml = 'invalid stuff';
|
||||
|
||||
var renderer = new Modeler(container);
|
||||
|
||||
renderer.importXML(xml, function(err) {
|
||||
|
||||
expect(err).toBeDefined();
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
|
@ -5,7 +5,7 @@ var BpmnModel = require('../../../lib/Model'),
|
|||
|
||||
var Matchers = require('../Matchers');
|
||||
|
||||
describe('Importer', function() {
|
||||
describe('Viewer', function() {
|
||||
|
||||
var bpmnModel = BpmnModel.instance();
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
var fs = require('fs'),
|
||||
Diagram = require('diagram-js/lib/Diagram');
|
||||
|
||||
var BpmnModel = require('../../../../lib/Model');
|
||||
var Importer = require('../../../../lib/import/Importer');
|
||||
|
||||
var bpmnModule = require('../../../../lib/di').defaultModule;
|
||||
|
||||
require('../../../../lib/core/BpmnRegistry');
|
||||
require('../../../../lib/draw/BpmnRenderer');
|
||||
|
||||
var Matchers = require('../../Matchers');
|
||||
|
||||
describe('import/Importer', function() {
|
||||
|
||||
var bpmnModel = BpmnModel.instance();
|
||||
|
||||
function read(xml, opts, callback) {
|
||||
return BpmnModel.fromXML(xml, 'bpmn:Definitions', opts, callback);
|
||||
}
|
||||
|
||||
var container;
|
||||
|
||||
|
||||
beforeEach(Matchers.add);
|
||||
|
||||
beforeEach(function() {
|
||||
container = document.createElement('div');
|
||||
document.getElementsByTagName('body')[0].appendChild(container);
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
container.parentNode.removeChild(container);
|
||||
});
|
||||
|
||||
|
||||
function createDiagram() {
|
||||
return new Diagram({
|
||||
canvas: { container: container },
|
||||
modules: [ bpmnModule ],
|
||||
components: [ 'bpmnRegistry']
|
||||
});
|
||||
}
|
||||
|
||||
it('should fire bpmn.element.add during import', function(done) {
|
||||
|
||||
// given
|
||||
var xml = fs.readFileSync('test/fixtures/bpmn/simple.bpmn', 'utf8');
|
||||
|
||||
var diagram = createDiagram();
|
||||
|
||||
var events = [];
|
||||
|
||||
// log events
|
||||
diagram.get('eventBus').on('bpmn.element.add', function(e) {
|
||||
events.push({ type: 'add', semantic: e.semantic.id, di: e.di.id, diagramElement: e.diagramElement.id });
|
||||
});
|
||||
|
||||
BpmnModel.fromXML(xml, function(err, definitions) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
// when
|
||||
Importer.importBpmnDiagram(diagram, definitions, function(err) {
|
||||
|
||||
// then
|
||||
expect(events).toEqual([
|
||||
{ type: 'add', semantic: 'SubProcess_1', di: '_BPMNShape_SubProcess_2', diagramElement: 'SubProcess_1' },
|
||||
{ type: 'add', semantic: 'StartEvent_1', di: '_BPMNShape_StartEvent_2', diagramElement: 'StartEvent_1' },
|
||||
{ type: 'add', semantic: 'Task_1', di: '_BPMNShape_Task_2', diagramElement: 'Task_1' },
|
||||
{ type: 'add', semantic: 'SequenceFlow_1', di: 'BPMNEdge_SequenceFlow_1', diagramElement: 'SequenceFlow_1' }
|
||||
]);
|
||||
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
Loading…
Reference in New Issue