Skip to content

Commit

Permalink
feat(Viewer): allow to select diagram to view
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Valerio Spadaro authored and barmac committed Apr 16, 2019
1 parent 161a50f commit eb103b3
Show file tree
Hide file tree
Showing 6 changed files with 6,277 additions and 14 deletions.
54 changes: 49 additions & 5 deletions lib/Viewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
*/
import {
assign,
find,
isFunction,
isNumber,
omit
} from 'min-dash';
Expand Down Expand Up @@ -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.
*
Expand Down Expand Up @@ -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() {};
Expand All @@ -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);
Expand All @@ -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 });
Expand Down Expand Up @@ -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 {
Expand All @@ -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() {
Expand Down
19 changes: 15 additions & 4 deletions lib/import/Importer.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import BpmnTreeWalker from './BpmnTreeWalker';

import {
isFunction
} from 'min-dash';

/**
* Import the definitions into a diagram.
Expand All @@ -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,
Expand All @@ -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 = {

Expand All @@ -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 {
Expand All @@ -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,
Expand Down
78 changes: 78 additions & 0 deletions test/fixtures/bpmn/import/multiple-diagrams.bpmn
Original file line number Diff line number Diff line change
@@ -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>
Loading

0 comments on commit eb103b3

Please sign in to comment.