瀏覽代碼

10.0.5 release

Former-commit-id: 19ca5f87a315ac37bd80613b5746816fb697c6b6
Gaudenz Alder 6 年之前
父節點
當前提交
8934f2c4b6

+ 4 - 0
ChangeLog

@@ -1,3 +1,7 @@
+19-DEC-2018: 10.0.5
+
+- Fixes for collaborative editing
+
 19-DEC-2018: 10.0.4
 
 - Fixes for night mode and responsive UI

+ 1 - 1
VERSION

@@ -1 +1 @@
-10.0.4
+10.0.5

+ 1 - 1
src/main/webapp/cache.manifest

@@ -1,7 +1,7 @@
 CACHE MANIFEST
 
 # THIS FILE WAS GENERATED. DO NOT MODIFY!
-# 12/19/2018 11:31 AM
+# 12/19/2018 05:08 PM
 
 app.html
 index.html?offline=1

File diff suppressed because it is too large
+ 361 - 360
src/main/webapp/js/app.min.js


File diff suppressed because it is too large
+ 18 - 18
src/main/webapp/js/atlas-viewer.min.js


File diff suppressed because it is too large
+ 644 - 643
src/main/webapp/js/atlas.min.js


+ 62 - 23
src/main/webapp/js/diagramly/DiffSync.js

@@ -31,7 +31,7 @@ EditorUi.prototype.viewStateWhitelist = ['background', 'backgroundImage', 'foldi
 /**
  * Removes all labels, user objects and styles from the given node in-place.
  */
-EditorUi.prototype.patchPages = function(pages, diff, markPages, shadow)
+EditorUi.prototype.patchPages = function(pages, diff, markPages, shadow, updateEdgeParents)
 {
 	var shadowLookup = {};
 	var newPages = [];
@@ -48,11 +48,6 @@ EditorUi.prototype.patchPages = function(pages, diff, markPages, shadow)
 		}
 	}
 	
-	for (var i = 0; i < pages.length; i++)
-	{
-		lookup[pages[i].getId()] = pages[i];
-	}
-	
 	if (diff[EditorUi.DIFF_REMOVE] != null)
 	{
 		for (var i = 0; i < diff[EditorUi.DIFF_REMOVE].length; i++)
@@ -82,30 +77,38 @@ EditorUi.prototype.patchPages = function(pages, diff, markPages, shadow)
 		}
 	}
 	
-	// Restores existing order
-	var prev = '';
-	
-	for (var i = 0; i < pages.length; i++)
-	{
-		var pageId = pages[i].getId();
+	// Restores existing order and creates lookup
+  	if (pages != null)
+  	{
+		var prev = '';
 		
-		if (moved[prev] == null && !removed[pages[i].getId()] &&
-			(diff[EditorUi.DIFF_UPDATE] == null ||
-			diff[EditorUi.DIFF_UPDATE][pageId] == null ||
-			diff[EditorUi.DIFF_UPDATE][pageId].previous == null))
+		for (var i = 0; i < pages.length; i++)
 		{
-			moved[prev] = pageId;
+			var pageId = pages[i].getId();
+			lookup[pageId] = pages[i];
+			
+			if (moved[prev] == null && !removed[pageId] &&
+				(diff[EditorUi.DIFF_UPDATE] == null ||
+				diff[EditorUi.DIFF_UPDATE][pageId] == null ||
+				diff[EditorUi.DIFF_UPDATE][pageId].previous == null))
+			{
+				moved[prev] = pageId;
+			}
+			
+			prev = pageId;
 		}
-		
-		prev = pageId;
-	}
+  	}
+  	
+  	// FIXME: Workaround for possible duplicate pages
+  	var added = {};
 	
 	var addPage = mxUtils.bind(this, function(page)
 	{
 		var id = (page != null) ? page.getId() : '';
 		
-		if (page != null)
+		if (page != null && !added[id])
 		{
+			added[id] = true;
 			newPages.push(page);
 			var pageDiff = (diff[EditorUi.DIFF_UPDATE] != null) ?
 					diff[EditorUi.DIFF_UPDATE][id] : null;
@@ -126,7 +129,7 @@ EditorUi.prototype.patchPages = function(pages, diff, markPages, shadow)
 				
 				if (pageDiff.cells != null)
 				{
-					this.patchPage(page, pageDiff.cells, shadowLookup[page.getId()]);
+					this.patchPage(page, pageDiff.cells, shadowLookup[page.getId()], updateEdgeParents);
 				}
 				
 				if (markPages && (pageDiff.cells != null ||
@@ -300,7 +303,7 @@ EditorUi.prototype.createParentLookup = function(model, diff)
 /**
  * Removes all labels, user objects and styles from the given node in-place.
  */
-EditorUi.prototype.patchPage = function(page, diff, shadowPage)
+EditorUi.prototype.patchPage = function(page, diff, shadowPage, updateEdgeParents)
 {
 	var model = (page == this.currentPage) ? this.editor.graph.model : new mxGraphModel(page.root);
 	var shadowModel = (shadowPage != null) ? new mxGraphModel(shadowPage.root) : null;
@@ -309,6 +312,11 @@ EditorUi.prototype.patchPage = function(page, diff, shadowPage)
 	model.beginUpdate();
 	try
 	{
+		// Disables update of edge parents during update to avoid interference with
+		// remote updated edge parents
+		var prev = model.maintainEdgeParent;
+		model.maintainEdgeParent = false;
+
 		// Handles new root cells
 		var temp = parentLookup[''];
 		var cellDiff = (temp != null && temp.inserted != null) ? temp.inserted[''] : null;
@@ -378,6 +386,15 @@ EditorUi.prototype.patchPage = function(page, diff, shadowPage)
 				}
 			}
 		}
+
+		// Only updates edge parents if there are possible changes which is the case
+		// for patching the local pages in the case where the file was modified
+		model.maintainEdgeParent = prev;
+		
+		if (updateEdgeParents)
+		{
+			model.updateEdgeParents(model.root);
+		}
 	}
 	finally
 	{
@@ -527,6 +544,18 @@ EditorUi.prototype.patchCell = function(model, cell, diff, shadowCell)
 			model.setCollapsed(cell, diff.collapsed == 1);
 		}
 
+		if (diff.vertex != null)
+		{
+			// Changes vertex state in-place
+			cell.vertex = diff.vertex == 1;
+		}
+
+		if (diff.edge != null)
+		{
+			// Changes edge state in-place
+			cell.edge = diff.edge == 1;
+		}
+		
 		if (diff.connectable != null)
 		{
 			// Changes connectable state in-place
@@ -991,6 +1020,16 @@ EditorUi.prototype.diffCell = function(oldCell, newCell)
 		diff['collapsed'] = (newCell.collapsed) ? 1 : 0;
 	}
 
+	if (oldCell.vertex != newCell.vertex)
+	{
+		diff['vertex'] = (newCell.vertex) ? 1 : 0;
+	}
+	
+	if (oldCell.edge != newCell.edge)
+	{
+		diff['edge'] = (newCell.edge) ? 1 : 0;
+	}
+
 	if (oldCell.connectable != newCell.connectable)
 	{
 		diff['connectable'] = (newCell.connectable) ? 1 : 0;

+ 20 - 5
src/main/webapp/js/diagramly/DrawioFile.js

@@ -337,16 +337,31 @@ DrawioFile.prototype.checksumError = function(error, patches)
 			this.stats.uptime = Math.round((new Date().getTime() -
 				new Date(this.stats.start).getTime()) / 1000);
 		}
-	
+		
+		var data = mxUtils.getPrettyXml(file);
+		
+		if (data != null && data.length > 10000)
+		{
+			data = this.ui.editor.graph.compress(data) + '\n';
+		}
+
+		var json = JSON.stringify(patches, null, 2);
+		
+		if (json != null && json.length > 10000)
+		{
+			json = this.ui.editor.graph.compress(json);
+		}
+		
 		EditorUi.sendReport('Checksum Error ' + new Date().toISOString() + ':\n\n' +
 			'File=' + this.getId() + ' (' + this.getMode() + ')\n' +
 			((this.sync != null) ? ('Client=' + this.sync.clientId + '\n') : '') +
 			'User=' + uid + '\n' +
 			'Size=' + this.getSize() + '\n' +
 			'Sync=' + DrawioFile.SYNC + '\n\n' +
-			'Stats:\n' + JSON.stringify(this.stats, null, 2) + '\n' +
-			'Data:\n' + mxUtils.getPrettyXml(file) + '\n' +
-			'Patches:\n' + JSON.stringify(patches, null, 2));
+			'Stats:\n' + JSON.stringify(this.stats, null, 2) + '\n\n' +
+			'Data:\n' + data + '\n' +
+			'Patches:\n' + json + '\n\n' +
+			'Stack:\n' + new Error().stack);
 	}
 	catch (e)
 	{
@@ -507,7 +522,7 @@ DrawioFile.prototype.patch = function(patches, shadow)
 			for (var i = 0; i < patches.length; i++)
 			{
 				this.ui.pages = this.ui.patchPages(this.ui.pages,
-					patches[i], true, shadow);
+					patches[i], true, shadow, this.isModified());
 			}
 		}
 		finally

+ 3 - 2
src/main/webapp/js/diagramly/EditorUi.js

@@ -1753,7 +1753,7 @@
             
             if ((/^https?:\/\//.test(realUrl)) && !this.isCorsEnabledForUrl(realUrl))
             {
-                realUrl = PROXY_URL + '?url=' + encodeURIComponent(desc.url);
+                realUrl = PROXY_URL + '?url=' + encodeURIComponent(realUrl);
             }
 
             // LATER: Remove cache-control header
@@ -3405,11 +3405,12 @@
 		div.style.position = 'absolute';
 		div.style.overflow = 'hidden';
 		div.style.borderWidth = '3px';
-
+		
 		var elt2 = document.createElement('a');
 		elt2.className = 'geTitle';
 		elt2.style.height = '100%';
 		elt2.style.paddingTop = '9px';
+		elt2.innerHTML = '<span style="font-size:18px;margin-right:5px;">+</span>';
 
 		mxUtils.write(elt2, mxResources.get('moreShapes') + '...');
 

+ 16 - 18
src/main/webapp/js/diagramly/Pages.js

@@ -848,30 +848,28 @@ EditorUi.prototype.removePage = function(page)
 		{
 			var next = this.currentPage;
 			
-			if (next == page)
+			if (next == page && this.pages.length > 1)
 			{
-				if (this.pages.length > 1)
+				var tmp = mxUtils.indexOf(this.pages, page);
+				
+				if (tmp == this.pages.length - 1)
 				{
-					var tmp = mxUtils.indexOf(this.pages, page);
-					
-					if (tmp == this.pages.length - 1)
-					{
-						tmp--;
-					}
-					else
-					{
-						tmp++;
-					}
-					
-					next = this.pages[tmp];
+					tmp--;
 				}
 				else
 				{
-					// Removes label with incorrect page number to force
-					// default page name which is OK for a single page
-					next = this.insertPage();
-					graph.model.execute(new RenamePage(this, next, mxResources.get('pageWithNumber', [1])));
+					tmp++;
 				}
+				
+				next = this.pages[tmp];
+			}
+			else if (this.pages.length <= 1)
+			{
+				// Removes label with incorrect page number to force
+				// default page name which is OK for a single page
+				next = this.insertPage();
+				graph.model.execute(new RenamePage(this, next,
+					mxResources.get('pageWithNumber', [1])));
 			}
 			
 			// Uses model to fire event to trigger autosave

File diff suppressed because it is too large
+ 1 - 1
src/main/webapp/js/embed-static.min.js


File diff suppressed because it is too large
+ 1 - 1
src/main/webapp/js/reader.min.js


File diff suppressed because it is too large
+ 18 - 18
src/main/webapp/js/viewer.min.js


+ 229 - 1
src/main/webapp/plugins/random.js

@@ -163,6 +163,234 @@ Draw.loadPlugin(function(ui)
 		}
 	});
 	
+	// Adds resource for action
+	mxResources.parse('placeChildren=Place children...');
+
+	// Adds action
+	ui.actions.addAction('placeChildren', function()
+	{
+		var graph = ui.editor.graph;
+		var cells = graph.getSelectionCells().slice();
+		
+		if (cells.length > 1)
+		{
+
+			var counter = 0;
+			var delay = parseInt(prompt('Delay (ms)', defaultDelay));
+			var max = parseInt(prompt('Cycles', defaultMax));
+			
+			
+			function schedule()
+			{
+				var jitter = 1 + 0.3 * (Math.random() - 0.5);
+				
+				window.setTimeout(function()
+				{
+					// assuming parent is the first cell selected
+					var parentA = cells[0];
+					var parentB = cells[1];
+					
+					var childrenA = parentA.children;
+					var childrenB = parentB.children;
+					
+					var numberA = (childrenA != null)? childrenA.length: 0;
+					var numberB = (childrenB != null)? childrenB.length: 0;
+					
+					var n = 0;
+					
+					if (childrenA != null && childrenA.length > 1 || childrenB != null && childrenB.length > 1)
+					{
+						graph.getModel().beginUpdate();
+						try
+						{
+							// first, remove a few children from each parent
+							childrenA = parentA.children;
+							childrenB = parentB.children;
+							numberA = (childrenA != null)? childrenA.length: 0;
+							numberB = (childrenB != null)? childrenB.length: 0;
+							
+							// 1st parent
+							n = Math.floor(Math.random() * 4); // how many to delete? at least 1 should remain
+							n = Math.min(n, Math.max(0, numberA - 2));
+							console.log(counter + " - removing " + n + " children from parent A");
+							for (var i = 0; i < n;  i++)
+							{
+								childrenA = parentA.children;
+								numberA = (childrenA != null)? childrenA.length: 0;
+								if (numberA > 0)
+								{
+									var k = Math.floor(Math.random() * numberA);
+									parentA.remove(k);
+								}
+							}
+							
+							// 2nd parent
+							n = Math.floor(Math.random() * 4); // how many to delete? at least 1 should remain
+							n = Math.min(n, Math.max(0, numberB - 2));
+							console.log(counter + " - removing " + n + " children from parent B");
+							for (var i = 0; i < n;  i++)
+							{
+								childrenB = parentB.children;
+								numberB = (childrenB != null)? childrenB.length: 0;
+								if (numberB > 0)
+								{
+									var k = Math.floor(Math.random() * numberB);
+									parentB.remove(k);
+								}
+							}
+							
+							// second, insert a few children to each parent
+							childrenA = parentA.children;
+							childrenB = parentB.children;
+							numberA = (childrenA != null)? childrenA.length: 0;
+							numberB = (childrenB != null)? childrenB.length: 0;
+							
+							// 1st parent
+							n = Math.floor(Math.random() * 4); // how many to insert?
+							console.log(counter + " - inserting " + n + " children into parent A");
+							for (var i = 0; i < n;  i++)
+							{
+								childrenA = parentA.children;
+								numberA = (childrenA != null)? childrenA.length: 0;
+								if (numberA > 0)
+								{
+									var k = Math.floor(Math.random() * numberA);
+									var x = Math.floor(Math.random() * 200);
+									var y = Math.floor(Math.random() * 50);
+									var number = Math.floor(Math.random() * 9000 + 1000);
+									var child = graph.insertVertex(parentA, null, number.toString(), x, y, 120, 30);
+									parentA.insert(child, k);
+								}
+							}
+							
+							// 2nd parent
+							n = Math.floor(Math.random() * 4); // how many to insert?
+							console.log(counter + " - inserting " + n + " children into parent B");
+							for (var i = 0; i < n;  i++)
+							{
+								childrenB = parentB.children;
+								numberB = (childrenB != null)? childrenB.length: 0;
+								if (numberB > 0)
+								{
+									var k = Math.floor(Math.random() * numberB);
+									var x = Math.floor(Math.random() * 200);
+									var y = Math.floor(Math.random() * 50);
+									var number = Math.floor(Math.random() * 9000 + 1000);
+									var child = graph.insertVertex(parentB, null, number.toString(), x, y, 120, 30);
+									parentB.insert(child, k);
+								}
+							}
+							
+							// third, shuffle children in each parent
+							childrenA = parentA.children;
+							childrenB = parentB.children;
+							numberA = (childrenA != null)? childrenA.length: 0;
+							numberB = (childrenB != null)? childrenB.length: 0;
+							
+							// 1st parent
+							n = Math.floor(Math.random() * numberA); // how many to shuffle?
+							console.log(counter + " - moving " + n + " children inside parent A");
+							for (var i = 0; i < n;  i++)
+							{
+								childrenA = parentA.children;
+								numberA = (childrenA != null)? childrenA.length: 0;
+								if (numberA > 0)
+								{
+									var k = Math.floor(Math.random() * numberA);  // from index
+									var l = Math.floor(Math.random() * numberA);  // to index
+									var child = parentA.getChildAt(k);
+									parentA.insert(child, l);
+								}
+							}
+							
+							// 2nd parent
+							n = Math.floor(Math.random() * numberB); // how many to shuffle?
+							console.log(counter + " - moving " + n + " children inside parent B");
+							for (var i = 0; i < n;  i++)
+							{
+								childrenB = parentB.children;
+								numberB = (childrenB != null)? childrenB.length: 0;
+								if (numberB > 0)
+								{
+									var k = Math.floor(Math.random() * numberB);  // from index
+									var l = Math.floor(Math.random() * numberB);  // to index
+									var child = parentB.getChildAt(k);
+									parentB.insert(child, l);
+								}
+							}
+							
+							// fourth, exchange a few children between both parents
+							childrenA = parentA.children;
+							childrenB = parentB.children;
+							numberA = (childrenA != null)? childrenA.length: 0;
+							numberB = (childrenB != null)? childrenB.length: 0;
+							
+							// permute children
+							var passes = Math.floor(Math.random() * numberA) + 1;
+							console.log(counter + " - swapping " + passes + " children from parent A to parent B");
+							
+							for (var i = 0; i < passes; i++)
+							{
+								// which child to select from parent A
+								var k = Math.floor(Math.random() * numberA);
+								// where to insert it to parent B
+								var l = Math.floor(Math.random() * (numberB + 1));
+								graph.model.add(parentB, childrenA[k], l);
+								
+								numberA -= 1;
+								numberB += 1;
+							}
+
+							var passes = Math.floor(Math.random() * numberB) + 1;
+							console.log(counter + " - swapping " + passes + " children from parent B to parent A");
+							
+							for (var i = 0; i < passes; i++)
+							{
+								// which child to select from parent A
+								var k = Math.floor(Math.random() * numberB);
+								// where to insert it to parent B
+								var l = Math.floor(Math.random() * (numberA + 1));
+								graph.model.add(parentA, childrenB[k], l);
+								numberA += 1;
+								numberB -= 1;
+							}
+						}
+						finally
+						{
+							graph.getModel().endUpdate();
+						}
+					}
+
+					if (ui.dialog != null)
+					{
+						console.log('swapChildren halted');
+					}
+					else
+					{
+						ui.saveFile(null, function()
+						{
+							if (counter++ < max && ui.dialog == null)
+							{
+								console.log('swapChildren', counter);
+								schedule();
+							}
+							else
+							{
+								console.log('swapChildren halted');
+							}
+						});
+					}
+				}, delay * jitter);
+			}
+			
+			schedule();
+		}
+		else
+		{
+			ui.alert(mxResources.get('nothingIsSelected'));
+		}
+	});
+	
 	// Adds resource for action
 	mxResources.parse('reorderChildren=Reorder children...');
 
@@ -247,6 +475,6 @@ Draw.loadPlugin(function(ui)
 	{
 		oldFunct.apply(this, arguments);
 		
-		ui.menus.addMenuItems(menu, ['-', 'randomLabel', 'reorderChildren', 'swapChildren'], parent);
+		ui.menus.addMenuItems(menu, ['-', 'randomLabel', 'reorderChildren', 'swapChildren', 'placeChildren'], parent);
 	};
 });