feat(Viewer): allow to select diagram to view
This introduces a new parameter to `Viewer#importXML` which enables to choose the diagram to display. ``` var viewer = new Viewer({ container: container }); viewer.importXML(xml, diagramId, done); ``` Closes #87
This commit is contained in:
parent
0c71ad30a0
commit
1c0585aaaf
|
@ -6,6 +6,8 @@
|
|||
*/
|
||||
import {
|
||||
assign,
|
||||
find,
|
||||
isFunction,
|
||||
isNumber,
|
||||
omit
|
||||
} from 'min-dash';
|
||||
|
@ -66,6 +68,26 @@ function ensureUnit(val) {
|
|||
return val + (isNumber(val) ? 'px' : '');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Find BPMNDiagram in definitions by ID
|
||||
*
|
||||
* @param {ModdleElement} definitions
|
||||
* @param {String} diagramId
|
||||
*
|
||||
* @return {Diagram|undefined}
|
||||
*/
|
||||
function findDiagram(definitions, diagramId) {
|
||||
if (!diagramId) {
|
||||
return;
|
||||
}
|
||||
|
||||
return find(definitions.diagrams, function(element) {
|
||||
return element.id === diagramId;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* A viewer for BPMN 2.0 diagrams.
|
||||
*
|
||||
|
@ -152,9 +174,15 @@ inherits(Viewer, Diagram);
|
|||
* You can use these events to hook into the life-cycle.
|
||||
*
|
||||
* @param {String} xml the BPMN 2.0 xml
|
||||
* @param {String} [diagramId] id of the diagram to render (if not provided, the first one will be rendered)
|
||||
* @param {Function} [done] invoked with (err, warnings=[])
|
||||
*/
|
||||
Viewer.prototype.importXML = function(xml, done) {
|
||||
Viewer.prototype.importXML = function(xml, diagramId, done) {
|
||||
|
||||
if (isFunction(diagramId)) {
|
||||
done = diagramId;
|
||||
diagramId = null;
|
||||
}
|
||||
|
||||
// done is optional
|
||||
done = done || function() {};
|
||||
|
@ -175,7 +203,8 @@ Viewer.prototype.importXML = function(xml, done) {
|
|||
context: context
|
||||
}) || definitions;
|
||||
|
||||
var parseWarnings = context.warnings;
|
||||
var parseWarnings = context.warnings,
|
||||
diagram;
|
||||
|
||||
if (err) {
|
||||
err = checkValidationError(err);
|
||||
|
@ -185,7 +214,17 @@ Viewer.prototype.importXML = function(xml, done) {
|
|||
return done(err, parseWarnings);
|
||||
}
|
||||
|
||||
self.importDefinitions(definitions, function(err, importWarnings) {
|
||||
diagram = findDiagram(definitions, diagramId);
|
||||
|
||||
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) {
|
||||
var allWarnings = [].concat(parseWarnings, importWarnings || []);
|
||||
|
||||
self._emit('import.done', { error: err, warnings: allWarnings });
|
||||
|
@ -346,7 +385,12 @@ Viewer.prototype.saveSVG = function(options, done) {
|
|||
*/
|
||||
|
||||
|
||||
Viewer.prototype.importDefinitions = function(definitions, done) {
|
||||
Viewer.prototype.importDefinitions = function(definitions, diagram, done) {
|
||||
|
||||
if (isFunction(diagram)) {
|
||||
done = diagram;
|
||||
diagram = null;
|
||||
}
|
||||
|
||||
// catch synchronous exceptions during #clear()
|
||||
try {
|
||||
|
@ -362,7 +406,7 @@ Viewer.prototype.importDefinitions = function(definitions, done) {
|
|||
}
|
||||
|
||||
// perform graphical import
|
||||
return importBpmnDiagram(this, definitions, done);
|
||||
return importBpmnDiagram(this, definitions, diagram, done);
|
||||
};
|
||||
|
||||
Viewer.prototype.getModules = function() {
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
import BpmnTreeWalker from './BpmnTreeWalker';
|
||||
|
||||
import {
|
||||
isFunction
|
||||
} from 'min-dash';
|
||||
|
||||
/**
|
||||
* Import the definitions into a diagram.
|
||||
|
@ -8,9 +11,16 @@ import BpmnTreeWalker from './BpmnTreeWalker';
|
|||
*
|
||||
* @param {Diagram} diagram
|
||||
* @param {ModdleElement} definitions
|
||||
* @param {ModdleElement} [selectedDiagram] the BPMNDiagram element selected to be rendered
|
||||
* (if not provided, the first one will be rendered)
|
||||
* @param {Function} done the callback, invoked with (err, [ warning ]) once the import is done
|
||||
*/
|
||||
export function importBpmnDiagram(diagram, definitions, done) {
|
||||
export function importBpmnDiagram(diagram, definitions, selectedDiagram, done) {
|
||||
|
||||
if (isFunction(selectedDiagram)) {
|
||||
done = selectedDiagram;
|
||||
selectedDiagram = null;
|
||||
}
|
||||
|
||||
var importer,
|
||||
eventBus,
|
||||
|
@ -24,8 +34,9 @@ export function importBpmnDiagram(diagram, definitions, done) {
|
|||
* all elements you encounter.
|
||||
*
|
||||
* @param {ModdleElement} definitions
|
||||
* @param {ModdleElement} selectedDiagram
|
||||
*/
|
||||
function render(definitions) {
|
||||
function render(definitions, selectedDiagram) {
|
||||
|
||||
var visitor = {
|
||||
|
||||
|
@ -46,7 +57,7 @@ export function importBpmnDiagram(diagram, definitions, done) {
|
|||
|
||||
// traverse BPMN 2.0 document model,
|
||||
// starting at definitions
|
||||
walker.handleDefinitions(definitions);
|
||||
walker.handleDefinitions(definitions, selectedDiagram);
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -56,7 +67,7 @@ export function importBpmnDiagram(diagram, definitions, done) {
|
|||
|
||||
eventBus.fire('import.render.start', { definitions: definitions });
|
||||
|
||||
render(definitions);
|
||||
render(definitions, selectedDiagram);
|
||||
|
||||
eventBus.fire('import.render.complete', {
|
||||
error: error,
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_0j4810n" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="3.0.1">
|
||||
<bpmn:process id="Process_1" isExecutable="true">
|
||||
<bpmn:startEvent id="StartEvent_1">
|
||||
<bpmn:outgoing>SequenceFlow_1</bpmn:outgoing>
|
||||
</bpmn:startEvent>
|
||||
<bpmn:sequenceFlow id="SequenceFlow_1" sourceRef="StartEvent_1" targetRef="Task_1" />
|
||||
<bpmn:userTask id="Task_1">
|
||||
<bpmn:incoming>SequenceFlow_1</bpmn:incoming>
|
||||
<bpmn:outgoing>SequenceFlow_2</bpmn:outgoing>
|
||||
</bpmn:userTask>
|
||||
<bpmn:sequenceFlow id="SequenceFlow_2" sourceRef="Task_1" targetRef="Task_2" />
|
||||
<bpmn:userTask id="Task_2">
|
||||
<bpmn:incoming>SequenceFlow_2</bpmn:incoming>
|
||||
<bpmn:outgoing>SequenceFlow_3</bpmn:outgoing>
|
||||
</bpmn:userTask>
|
||||
<bpmn:endEvent id="EndEvent_1">
|
||||
<bpmn:incoming>SequenceFlow_3</bpmn:incoming>
|
||||
</bpmn:endEvent>
|
||||
<bpmn:sequenceFlow id="SequenceFlow_3" sourceRef="Task_2" targetRef="EndEvent_1" />
|
||||
</bpmn:process>
|
||||
<bpmn:process id="Process_2" isExecutable="true">
|
||||
<bpmn:startEvent id="StartEvent_2" />
|
||||
<bpmn:intermediateThrowEvent id="IntermediateThrowEvent_1" />
|
||||
<bpmn:sequenceFlow id="SequenceFlow_4" sourceRef="StartEvent_2" targetRef="IntermediateThrowEvent_1" />
|
||||
<bpmn:endEvent id="EndEvent_2" />
|
||||
<bpmn:sequenceFlow id="SequenceFlow_5" sourceRef="IntermediateThrowEvent_1" targetRef="EndEvent_2" />
|
||||
</bpmn:process>
|
||||
<bpmndi:BPMNDiagram id="BPMNDiagram_2">
|
||||
<bpmndi:BPMNPlane id="BPMNPlane_2" bpmnElement="Process_2">
|
||||
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_2">
|
||||
<dc:Bounds x="156" y="81" width="36" height="36" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="_BPMNShape_IntermediateThrowEvent_1" bpmnElement="IntermediateThrowEvent_1">
|
||||
<dc:Bounds x="234" y="81" width="36" height="36" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="_BPMNShape_EndEvent_2" bpmnElement="EndEvent_2">
|
||||
<dc:Bounds x="328" y="81" width="36" height="36" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_4" bpmnElement="SequenceFlow_4">
|
||||
<di:waypoint x="192" y="99" />
|
||||
<di:waypoint x="234" y="99" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_5" bpmnElement="SequenceFlow_5">
|
||||
<di:waypoint x="270" y="99" />
|
||||
<di:waypoint x="328" y="99" />
|
||||
</bpmndi:BPMNEdge>
|
||||
</bpmndi:BPMNPlane>
|
||||
</bpmndi:BPMNDiagram>
|
||||
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">
|
||||
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_1" bpmnElement="StartEvent_1">
|
||||
<dc:Bounds x="156" y="103" width="36" height="36" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="_BPMNShape_Task_1" bpmnElement="Task_1">
|
||||
<dc:Bounds x="242" y="81" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="_BPMNShape_Task_2" bpmnElement="Task_2">
|
||||
<dc:Bounds x="392" y="81" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="_BPMNShape_EndEvent_1" bpmnElement="EndEvent_1">
|
||||
<dc:Bounds x="542" y="103" width="36" height="36" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_1" bpmnElement="SequenceFlow_1">
|
||||
<di:waypoint x="192" y="121" />
|
||||
<di:waypoint x="242" y="121" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_2" bpmnElement="SequenceFlow_2">
|
||||
<di:waypoint x="342" y="121" />
|
||||
<di:waypoint x="392" y="121" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_3" bpmnElement="SequenceFlow_3">
|
||||
<di:waypoint x="492" y="121" />
|
||||
<di:waypoint x="542" y="121" />
|
||||
</bpmndi:BPMNEdge>
|
||||
</bpmndi:BPMNPlane>
|
||||
</bpmndi:BPMNDiagram>
|
||||
</bpmn:definitions>
|
File diff suppressed because it is too large
Load Diff
|
@ -8,6 +8,10 @@ import Viewer from 'lib/Viewer';
|
|||
|
||||
import inherits from 'inherits';
|
||||
|
||||
import {
|
||||
isFunction
|
||||
} from 'min-dash';
|
||||
|
||||
|
||||
describe('Viewer', function() {
|
||||
|
||||
|
@ -18,10 +22,15 @@ describe('Viewer', function() {
|
|||
});
|
||||
|
||||
|
||||
function createViewer(xml, done) {
|
||||
function createViewer(xml, diagramId, done) {
|
||||
if (isFunction(diagramId)) {
|
||||
done = diagramId;
|
||||
diagramId = null;
|
||||
}
|
||||
|
||||
var viewer = new Viewer({ container: container });
|
||||
|
||||
viewer.importXML(xml, function(err, warnings) {
|
||||
viewer.importXML(xml, diagramId, function(err, warnings) {
|
||||
done(err, warnings, viewer);
|
||||
});
|
||||
}
|
||||
|
@ -670,6 +679,68 @@ describe('Viewer', function() {
|
|||
});
|
||||
});
|
||||
|
||||
|
||||
it('should import BPMN with multiple diagrams without diagram id specified', function(done) {
|
||||
|
||||
// given
|
||||
var xml = require('../fixtures/bpmn/multiple-diagrams.bpmn');
|
||||
|
||||
// when
|
||||
createViewer(xml, function(err) {
|
||||
|
||||
// then
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should import BPMN with multiple diagrams with diagram id specified', function(done) {
|
||||
|
||||
// given
|
||||
var xml = require('../fixtures/bpmn/multiple-diagrams.bpmn');
|
||||
|
||||
// when
|
||||
createViewer(xml, 'Diagram_80fecfcd-0165-4c36-90b6-3ea384265fe7', function(err) {
|
||||
|
||||
// then
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should complete with error if diagram of provided ID does not exist', function(done) {
|
||||
|
||||
// given
|
||||
var xml = require('../fixtures/bpmn/multiple-diagrams.bpmn');
|
||||
|
||||
// when
|
||||
createViewer(xml, 'Diagram_IDontExist', function(err) {
|
||||
|
||||
// then
|
||||
expect(err).to.exist;
|
||||
expect(err.message).to.eql('BPMNDiagram not found');
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should import BPMN with multiple diagrams when only xml is provided', function(done) {
|
||||
|
||||
// given
|
||||
var viewer = new Viewer({ container: container });
|
||||
|
||||
var xml = require('../fixtures/bpmn/multiple-diagrams.bpmn');
|
||||
|
||||
// when
|
||||
viewer.importXML(xml);
|
||||
|
||||
// then
|
||||
viewer.on('import.done', function(event) {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
|
|
@ -18,7 +18,8 @@ import {
|
|||
} from 'diagram-js/lib/util/GraphicsUtil';
|
||||
|
||||
import {
|
||||
find
|
||||
find,
|
||||
isFunction
|
||||
} from 'min-dash';
|
||||
|
||||
import { is } from 'lib/util/ModelUtil';
|
||||
|
@ -40,12 +41,22 @@ describe('import - Importer', function() {
|
|||
});
|
||||
|
||||
|
||||
function runImport(diagram, xml, done) {
|
||||
function runImport(diagram, xml, diagramId, done) {
|
||||
|
||||
if (isFunction(diagramId)) {
|
||||
done = diagramId;
|
||||
diagramId = null;
|
||||
}
|
||||
|
||||
var moddle = new BpmnModdle();
|
||||
|
||||
moddle.fromXML(xml, function(err, definitions) {
|
||||
importBpmnDiagram(diagram, definitions, done);
|
||||
|
||||
var selectedDiagram = find(definitions.diagrams, function(element) {
|
||||
return element.id === diagramId;
|
||||
});
|
||||
|
||||
importBpmnDiagram(diagram, definitions, selectedDiagram, done);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -394,7 +405,79 @@ describe('import - Importer', function() {
|
|||
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should import single diagram from multiple diagrams 2', function(done) {
|
||||
|
||||
// given
|
||||
var xml = require('../../fixtures/bpmn/import/multiple-diagrams.bpmn');
|
||||
|
||||
var events = [];
|
||||
|
||||
// log events
|
||||
diagram.get('eventBus').on('bpmnElement.added', function(e) {
|
||||
events.push({
|
||||
type: 'add',
|
||||
semantic: e.element.businessObject.id,
|
||||
di: e.element.businessObject.di.id,
|
||||
diagramElement: e.element && e.element.id
|
||||
});
|
||||
});
|
||||
|
||||
// when
|
||||
runImport(diagram, xml, 'BPMNDiagram_2', function(err, warnings) {
|
||||
|
||||
// then
|
||||
expect(events).to.eql([
|
||||
{ type: 'add', semantic: 'Process_2', di: 'BPMNPlane_2', diagramElement: 'Process_2' },
|
||||
{ type: 'add', semantic: 'StartEvent_2', di: '_BPMNShape_StartEvent_2', diagramElement: 'StartEvent_2' },
|
||||
{ type: 'add', semantic: 'IntermediateThrowEvent_1', di: '_BPMNShape_IntermediateThrowEvent_1', diagramElement: 'IntermediateThrowEvent_1' },
|
||||
{ type: 'add', semantic: 'EndEvent_2', di: '_BPMNShape_EndEvent_2', diagramElement: 'EndEvent_2' },
|
||||
{ type: 'add', semantic: 'SequenceFlow_4', di: 'BPMNEdge_SequenceFlow_4', diagramElement: 'SequenceFlow_4' },
|
||||
{ type: 'add', semantic: 'SequenceFlow_5', di: 'BPMNEdge_SequenceFlow_5', diagramElement: 'SequenceFlow_5' }
|
||||
]);
|
||||
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should import single diagram from multiple diagrams 1', function(done) {
|
||||
|
||||
// given
|
||||
var xml = require('../../fixtures/bpmn/import/multiple-diagrams.bpmn');
|
||||
|
||||
var events = [];
|
||||
|
||||
// log events
|
||||
diagram.get('eventBus').on('bpmnElement.added', function(e) {
|
||||
events.push({
|
||||
type: 'add',
|
||||
semantic: e.element.businessObject.id,
|
||||
di: e.element.businessObject.di.id,
|
||||
diagramElement: e.element && e.element.id
|
||||
});
|
||||
});
|
||||
|
||||
// when
|
||||
runImport(diagram, xml, 'BPMNDiagram_1', function(err, warnings) {
|
||||
|
||||
// then
|
||||
expect(events).to.eql([
|
||||
{ type: 'add', semantic: 'Process_1', di: 'BPMNPlane_1', diagramElement: 'Process_1' },
|
||||
{ type: 'add', semantic: 'StartEvent_1', di: '_BPMNShape_StartEvent_1', diagramElement: 'StartEvent_1' },
|
||||
{ type: 'add', semantic: 'Task_1', di: '_BPMNShape_Task_1', diagramElement: 'Task_1' },
|
||||
{ type: 'add', semantic: 'Task_2', di: '_BPMNShape_Task_2', diagramElement: 'Task_2' },
|
||||
{ type: 'add', semantic: 'EndEvent_1', di: '_BPMNShape_EndEvent_1', diagramElement: 'EndEvent_1' },
|
||||
{ type: 'add', semantic: 'SequenceFlow_1', di: 'BPMNEdge_SequenceFlow_1', diagramElement: 'SequenceFlow_1' },
|
||||
{ type: 'add', semantic: 'SequenceFlow_2', di: 'BPMNEdge_SequenceFlow_2', diagramElement: 'SequenceFlow_2' },
|
||||
{ type: 'add', semantic: 'SequenceFlow_3', di: 'BPMNEdge_SequenceFlow_3', diagramElement: 'SequenceFlow_3' }
|
||||
]);
|
||||
|
||||
done(err);
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue