425 lines
10 KiB
JavaScript
425 lines
10 KiB
JavaScript
/**(function() {
|
|
|
|
'use strict';**/
|
|
var $ = require('jquery'),
|
|
_ = require('lodash'),
|
|
BpmnViewer = require('bpmn-js'),
|
|
Diffing = require('bpmn-js-diffing');
|
|
var bpmnModeler=null;
|
|
function createViewer(side) {
|
|
return new BpmnViewer({
|
|
container: '#canvas-' + side,
|
|
height: '100%',
|
|
width: '100%'
|
|
});
|
|
}
|
|
|
|
function syncViewers(a, b) {
|
|
|
|
var changing;
|
|
|
|
function update(viewer) {
|
|
return function(e) {
|
|
if (changing) {
|
|
return;
|
|
}
|
|
|
|
changing = true;
|
|
viewer.get('canvas').viewbox(e.viewbox);
|
|
changing = false;
|
|
};
|
|
}
|
|
|
|
function syncViewbox(a, b) {
|
|
a.on('canvas.viewbox.changed', update(b));
|
|
}
|
|
|
|
syncViewbox(a, b);
|
|
syncViewbox(b, a);
|
|
}
|
|
|
|
function createViewers(left, right) {
|
|
|
|
var sides = {};
|
|
|
|
sides[left] = createViewer(left);
|
|
sides[right] = createViewer(right);
|
|
|
|
// sync navigation
|
|
syncViewers(sides[left], sides[right]);
|
|
|
|
return sides;
|
|
}
|
|
|
|
|
|
var viewers = createViewers('left', 'right');
|
|
|
|
function getViewer(side) {
|
|
return viewers[side];
|
|
}
|
|
|
|
function isLoaded(v) {
|
|
return v.loading !== undefined && !v.loading;
|
|
}
|
|
|
|
function allDiagramsLoaded() {
|
|
return _.every(viewers, isLoaded);
|
|
}
|
|
|
|
function setLoading(viewer, loading) {
|
|
viewer.loading = loading;
|
|
}
|
|
|
|
|
|
function clearDiffs(viewer) {
|
|
viewer.get('overlays').remove({ type: 'diff' });
|
|
|
|
// TODO(nre): expose as external API
|
|
_.forEach(viewer.get('elementRegistry')._elementMap, function(container) {
|
|
var gfx = container.gfx;
|
|
|
|
gfx
|
|
.removeClass('diff-added')
|
|
.removeClass('diff-changed')
|
|
.removeClass('diff-removed')
|
|
.removeClass('diff-layout-changed');
|
|
});
|
|
|
|
}
|
|
|
|
|
|
function diagramLoading(side, viewer) {
|
|
|
|
setLoading(viewer, true);
|
|
|
|
var loaded = _.filter(viewers, isLoaded);
|
|
|
|
// clear diffs on loaded
|
|
_.forEach(loaded, function(v) {
|
|
clearDiffs(v);
|
|
});
|
|
}
|
|
|
|
function diagramLoaded(err, side, viewer) {
|
|
if (err) {
|
|
console.error('load error', err);
|
|
}
|
|
|
|
setLoading(viewer, err);
|
|
|
|
if (allDiagramsLoaded()) {
|
|
|
|
// sync viewboxes
|
|
var other = getViewer(side == 'left' ? 'right' : 'left');
|
|
viewer.get('canvas').viewbox(other.get('canvas').viewbox());
|
|
|
|
showDiff(getViewer('left'), getViewer('right'));
|
|
}
|
|
}
|
|
|
|
|
|
// we use $.ajax to load the diagram.
|
|
// make sure you run the application via web-server (ie. connect (node) or asdf (ruby))
|
|
|
|
function loadDiagram(side, diagram) {
|
|
var viewer = getViewer(side);
|
|
function done(err) {
|
|
diagramLoaded(err, side, viewer);
|
|
}
|
|
diagramLoading(side, viewer);
|
|
if (diagram.xml) {
|
|
viewer.importXML(diagram.xml, done);
|
|
bpmnModeler=viewer;
|
|
return;
|
|
}
|
|
|
|
$.get(diagram.url, function(xml) {
|
|
viewer.importXML(xml, done);
|
|
});
|
|
}
|
|
function showDiff(viewerOld, viewerNew) {
|
|
var result = Diffing.diff (viewerOld.definitions, viewerNew.definitions);
|
|
|
|
|
|
$.each(result._removed, function(i, obj) {
|
|
highlight(viewerOld, i, 'diff-removed');
|
|
addMarker(viewerOld, i, 'marker-removed', '−');
|
|
});
|
|
|
|
|
|
$.each(result._added, function(i, obj) {
|
|
highlight(viewerNew, i, 'diff-added');
|
|
addMarker(viewerNew, i, 'marker-added', '+');
|
|
});
|
|
|
|
|
|
$.each(result._layoutChanged, function(i, obj) {
|
|
highlight(viewerOld, i, 'diff-layout-changed');
|
|
addMarker(viewerOld, i, 'marker-layout-changed', '⇨');
|
|
|
|
highlight(viewerNew, i, 'diff-layout-changed');
|
|
addMarker(viewerNew, i, 'marker-layout-changed', '⇨');
|
|
});
|
|
|
|
|
|
$.each(result._changed, function(i, obj) {
|
|
|
|
highlight(viewerOld, i, 'diff-changed');
|
|
addMarker(viewerOld, i, 'marker-changed', '✎');
|
|
|
|
highlight(viewerNew, i, 'diff-changed');
|
|
addMarker(viewerNew, i, 'marker-changed', '✎');
|
|
|
|
var details = '<table ><tr><th>Attribute</th><th>old</th><th>new</th></tr>';
|
|
$.each(obj.attrs, function(attr, changes) {
|
|
details = details + '<tr>' +
|
|
'<td>' + attr + '</td><td>' + changes.oldValue + '</td>' +
|
|
'<td>' + changes.newValue + '</td>' +
|
|
'</tr>';
|
|
});
|
|
|
|
details = details + '</table></div>';
|
|
|
|
viewerOld.get('elementRegistry').getGraphicsByElement(i).click (function (event) {
|
|
$('#changeDetailsOld_' + i).toggle();
|
|
});
|
|
|
|
var detailsOld = '<div id="changeDetailsOld_' + i + '" class="changeDetails">' + details;
|
|
// attach an overlay to a node
|
|
/** viewerOld.get('overlays').add(i, 'diff', {
|
|
position: {
|
|
bottom: -5,
|
|
left: 0
|
|
},
|
|
html: detailsOld
|
|
});**/
|
|
|
|
$('#changeDetailsOld_' + i).toggle();
|
|
|
|
viewerNew.get('elementRegistry').getGraphicsByElement(i).click (function (event) {
|
|
$('#changeDetailsNew_' + i).toggle();
|
|
});
|
|
|
|
var detailsNew = '<div id="changeDetailsNew_' + i + '" class="changeDetails">' + details;
|
|
|
|
// attach an overlay to a node
|
|
/** viewerNew.get('overlays').add(i, 'diff', {
|
|
position: {
|
|
bottom: -5,
|
|
left: 0
|
|
},
|
|
html: detailsNew
|
|
});**/
|
|
|
|
$('#changeDetailsNew_' + i).toggle();
|
|
});
|
|
|
|
// create Table Overview of Changes
|
|
showChangesOverview (result, viewerOld, viewerNew);
|
|
|
|
}
|
|
|
|
|
|
//loadDiagram('left', { url: '../resources/pizza-collaboration/old.bpmn' });
|
|
//loadDiagram('right', { url: '../resources/pizza-collaboration/new.bpmn' });
|
|
|
|
|
|
function openDiagram(xml, side) {
|
|
loadDiagram(side, { xml: xml });
|
|
}
|
|
|
|
function openFile(file, target, done) {
|
|
var reader = new FileReader();
|
|
|
|
reader.onload = function(e) {
|
|
var xml = e.target.result;
|
|
done(xml, target);
|
|
};
|
|
|
|
reader.readAsText(file);
|
|
}
|
|
|
|
|
|
$('.drop-zone').each(function() {
|
|
var node = this,
|
|
element = $(node);
|
|
|
|
element.append('<div class="drop-marker" />');
|
|
|
|
function removeMarker() {
|
|
$('.drop-zone').removeClass('dropping');
|
|
}
|
|
|
|
function handleFileSelect(e) {
|
|
e.stopPropagation();
|
|
e.preventDefault();
|
|
|
|
var files = e.dataTransfer.files;
|
|
openFile(files[0], element.attr('target'), openDiagram);
|
|
|
|
removeMarker();
|
|
}
|
|
|
|
function handleDragOver(e) {
|
|
removeMarker();
|
|
|
|
e.stopPropagation();
|
|
e.preventDefault();
|
|
|
|
element.addClass('dropping');
|
|
|
|
e.dataTransfer.dropEffect = 'copy';
|
|
}
|
|
|
|
function handleDragLeave(e) {
|
|
removeMarker();
|
|
}
|
|
|
|
node.addEventListener('dragover', handleDragOver, false);
|
|
node.ownerDocument.body.addEventListener('dragover', handleDragLeave, false);
|
|
|
|
node.addEventListener('drop', handleFileSelect, false);
|
|
});
|
|
|
|
$('.file').on('change', function(e) {
|
|
openFile(e.target.files[0], $(this).attr('target'), openDiagram);
|
|
});
|
|
|
|
|
|
function addMarker(viewer, elementId, className, symbol) {
|
|
|
|
var overlays = viewer.get('overlays');
|
|
|
|
try {
|
|
// attach an overlay to a node
|
|
overlays.add(elementId, 'diff', {
|
|
position: {
|
|
top: -12,
|
|
right: 12
|
|
},
|
|
html: '<span class="marker ' + className + '">' + symbol + '</span>'
|
|
});
|
|
} catch (e) {
|
|
// fuck you, haha
|
|
}
|
|
}
|
|
|
|
function highlight(viewer, elementId, marker) {
|
|
viewer.get('canvas').addMarker(elementId, marker);
|
|
}
|
|
|
|
function unhighlight(viewer, elementId, marker) {
|
|
viewer.get('canvas').removeMarker(elementId, marker);
|
|
}
|
|
|
|
$('#changes-overview .show-hide-toggle').click(function () {
|
|
$('#changes-overview').toggleClass('collapsed');
|
|
});
|
|
|
|
|
|
function showChangesOverview (result, viewerOld, viewerNew) {
|
|
|
|
$('#changes-overview table').remove();
|
|
|
|
var changesTable = $(
|
|
'<table>' +
|
|
'<thead><tr><th></th><th>环节名称</th><th>环节类型</th><th>比对结果</th></tr></thead>' +
|
|
'</table>');
|
|
|
|
var count = 0;
|
|
|
|
function addRow(element, type, label) {
|
|
var html =
|
|
'<tr class="entry">' +
|
|
'<td>' + (count++) + '</td><td>' + (element.name || '') + '</td>' +
|
|
'<td>' + element.$type.replace('bpmn:', '') + '</td>' +
|
|
'<td><span class="status">' + label + '</span></td>' +
|
|
'</tr>';
|
|
|
|
var row = $(html).data({
|
|
changed: type,
|
|
element: element.id
|
|
}).addClass(type).appendTo(changesTable);
|
|
}
|
|
|
|
$.each(result._removed, function(i, obj) {
|
|
addRow(obj, 'removed', '刪除');
|
|
});
|
|
|
|
$.each(result._added, function(i, obj) {
|
|
addRow(obj, 'added', '新增');
|
|
});
|
|
|
|
$.each(result._changed, function(i, obj) {
|
|
addRow(obj.model, 'changed', '修改');
|
|
});
|
|
|
|
$.each(result._layoutChanged, function(i, obj) {
|
|
addRow(obj, 'layout-changed', '布局调整');
|
|
});
|
|
|
|
changesTable.appendTo('#changes-overview .changes');
|
|
|
|
|
|
var HIGHLIGHT_CLS = 'highlight';
|
|
|
|
$('#changes-overview tr.entry').each(function() {
|
|
|
|
var row = $(this);
|
|
|
|
var id = row.data('element');
|
|
var changed = row.data('changed');
|
|
|
|
row.hover(function() {
|
|
|
|
if (changed == 'removed') {
|
|
highlight(viewerOld, id, HIGHLIGHT_CLS);
|
|
} else if (changed == 'added') {
|
|
highlight(viewerNew, id, HIGHLIGHT_CLS);
|
|
} else {
|
|
highlight(viewerOld, id, HIGHLIGHT_CLS);
|
|
highlight(viewerNew, id, HIGHLIGHT_CLS);
|
|
}
|
|
}, function() {
|
|
|
|
if (changed == 'removed') {
|
|
unhighlight(viewerOld, id, HIGHLIGHT_CLS);
|
|
} else if (changed == 'added') {
|
|
unhighlight(viewerNew, id, HIGHLIGHT_CLS);
|
|
} else {
|
|
unhighlight(viewerOld, id, HIGHLIGHT_CLS);
|
|
unhighlight(viewerNew, id, HIGHLIGHT_CLS);
|
|
}
|
|
});
|
|
|
|
row.click(function() {
|
|
|
|
var containerWidth = $('.di-container').width();
|
|
var containerHeight = $('.di-container').height();
|
|
|
|
var viewer = (changed == 'removed' ? viewerOld : viewerNew);
|
|
|
|
var element = viewer.get('elementRegistry').getById(id);
|
|
|
|
var x, y;
|
|
|
|
if (element.waypoints) {
|
|
x = element.waypoints[0].x;
|
|
y = element.waypoints[0].y;
|
|
} else {
|
|
x = element.x + element.width / 2;
|
|
y = element.y + element.height / 2;
|
|
}
|
|
console.log(222);
|
|
viewer.get('canvas').viewbox({
|
|
x: x - (containerWidth / 2),
|
|
y: y - ((containerHeight / 2) - 100),
|
|
width: containerWidth,
|
|
height: containerHeight
|
|
});
|
|
});
|
|
|
|
});
|
|
}
|
|
|
|
/**})();**/ |