feat(Viewer): add #open method

This adds a method to switch displayed diagram without reimporting
xml via

```
var viewer = new Viewer({ container: container });
viewer.importXML(xml, diagramId, done);

var diagrams = viewer.getDefinitions().diagrams;
viewer.open(diagrams[1], done);
```
This commit is contained in:
Valerio Spadaro 2019-04-11 14:05:26 +02:00 committed by Nico Rehwaldt
parent 1c0585aaaf
commit 3f0583ad5f
2 changed files with 191 additions and 38 deletions

View File

@ -76,16 +76,16 @@ function ensureUnit(val) {
* @param {ModdleElement} definitions
* @param {String} diagramId
*
* @return {Diagram|undefined}
* @return {Diagram|null}
*/
function findDiagram(definitions, diagramId) {
if (!diagramId) {
return;
return null;
}
return find(definitions.diagrams, function(element) {
return element.id === diagramId;
});
}) || null;
}
/**
@ -203,8 +203,7 @@ Viewer.prototype.importXML = function(xml, diagramId, done) {
context: context
}) || definitions;
var parseWarnings = context.warnings,
diagram;
var parseWarnings = context.warnings;
if (err) {
err = checkValidationError(err);
@ -214,17 +213,9 @@ Viewer.prototype.importXML = function(xml, diagramId, done) {
return done(err, parseWarnings);
}
diagram = findDiagram(definitions, diagramId);
self._setDefinitions(definitions);
if (diagramId && !diagram) {
err = new Error('BPMNDiagram not found');
self._emit('import.done', { error: err, warnings: parseWarnings || [] });
return done(err);
}
self.importDefinitions(definitions, diagram, function(err, importWarnings) {
self.open(diagramId, function(err, importWarnings) {
var allWarnings = [].concat(parseWarnings, importWarnings || []);
self._emit('import.done', { error: err, warnings: allWarnings });
@ -234,6 +225,60 @@ Viewer.prototype.importXML = function(xml, diagramId, done) {
});
};
/**
* Open diagram of previously imported XML.
*
* Once finished the viewer reports back the result to the
* provided callback function with (err, warnings).
*
* ## Life-Cycle Events
*
* During switch the viewer will fire life-cycle events:
*
* * import.render.start (graphical import start)
* * import.render.complete (graphical import finished)
*
* You can use these events to hook into the life-cycle.
*
* @param {String|Diagram} [diagram] id or the diagram to open
* @param {Function} [done] invoked with (err, warnings=[])
*/
Viewer.prototype.open = function(diagram, done) {
if (isFunction(diagram)) {
done = diagram;
diagram = null;
}
var definitions = this._definitions;
// done is optional
done = done || function() {};
if (!definitions) {
return done(new Error('no XML imported'));
}
if (typeof diagram === 'string') {
diagram = findDiagram(definitions, diagram);
if (!diagram) {
return done(new Error('no diagram to display'));
}
}
// catch synchronous exceptions during #clear()
try {
// clear existing rendered diagram
this.clear();
} catch (error) {
return done(error);
}
// perform graphical import
return importBpmnDiagram(this, definitions, diagram, done);
};
/**
* Export the currently displayed BPMN 2.0 diagram as
* a BPMN 2.0 XML document.
@ -385,28 +430,8 @@ Viewer.prototype.saveSVG = function(options, done) {
*/
Viewer.prototype.importDefinitions = function(definitions, diagram, done) {
if (isFunction(diagram)) {
done = diagram;
diagram = null;
}
// catch synchronous exceptions during #clear()
try {
if (this._definitions) {
// clear existing rendered diagram
this.clear();
}
// update definitions
this._definitions = definitions;
} catch (e) {
return done(e);
}
// perform graphical import
return importBpmnDiagram(this, definitions, diagram, done);
Viewer.prototype._setDefinitions = function(definitions) {
this._definitions = definitions;
};
Viewer.prototype.getModules = function() {

View File

@ -718,7 +718,7 @@ describe('Viewer', function() {
// then
expect(err).to.exist;
expect(err.message).to.eql('BPMNDiagram not found');
expect(err.message).to.eql('no diagram to display');
done();
});
@ -744,6 +744,134 @@ describe('Viewer', function() {
});
describe('#open', function() {
var diagramId1 = 'Diagram_80fecfcd-0165-4c36-90b6-3ea384265fe7',
diagramId2 = 'Diagram_94435ba7-4027-4df9-ad3b-df1f6e068e5e',
xml = require('../fixtures/bpmn/multiple-diagrams.bpmn');
it('should open another diagram', function(done) {
// when
createViewer(xml, diagramId1, function(err, warnings, viewer) {
// then
expect(err).not.to.exist;
expect(warnings).to.be.empty;
var definitions = viewer.getDefinitions();
expect(definitions).to.exist;
viewer.open(diagramId2, function(err, warnings) {
// then
expect(err).not.to.exist;
expect(warnings).to.be.empty;
var definitions = viewer.getDefinitions();
expect(definitions).to.exist;
done();
});
});
});
it('should complete with error if xml was not imported', function(done) {
// given
var viewer = new Viewer();
// when
viewer.open(function(err) {
// then
expect(err).to.exist;
expect(err.message).to.eql('no XML imported');
var definitions = viewer.getDefinitions();
expect(definitions).to.not.exist;
done();
});
});
it('should open with error if diagram does not exist', function(done) {
// when
createViewer(xml, diagramId1, function(err, warnings, viewer) {
// then
expect(err).not.to.exist;
expect(warnings).to.be.empty;
var definitions = viewer.getDefinitions();
expect(definitions).to.exist;
viewer.open('Diagram_IDontExist', function(err) {
// then
expect(err).to.exist;
expect(err.message).to.eql('no diagram to display');
// definitions stay the same
expect(viewer.getDefinitions()).to.eql(definitions);
done();
});
});
});
it('should emit <import.*> events', function(done) {
// given
var viewer = new Viewer({ container: container });
var events = [];
// when
viewer.importXML(xml, diagramId1, function(err) {
// when
viewer.on([
'import.parse.start',
'import.parse.complete',
'import.render.start',
'import.render.complete',
'import.done'
], function(e) {
// log event type + event arguments
events.push([
e.type,
Object.keys(e).filter(function(key) {
return key !== 'type';
})
]);
});
viewer.open(diagramId2, function(err) {
// then
expect(events).to.eql([
[ 'import.render.start', [ 'definitions' ] ],
[ 'import.render.complete', [ 'error', 'warnings' ] ]
]);
done(err);
});
});
});
});
describe('#saveXML', function() {
it('should export XML', function(done) {