Selaa lähdekoodia

20.4.2 release

David Benson 3 vuotta sitten
vanhempi
commit
dc89d67cf6
89 muutettua tiedostoa jossa 9641 lisäystä ja 8842 poistoa
  1. 22 0
      ChangeLog
  2. 1 1
      VERSION
  3. 0 6
      src/main/java/com/mxgraph/online/ProxyServlet.java
  4. 2949 2936
      src/main/webapp/js/app.min.js
  5. 27 9
      src/main/webapp/js/diagramly/App.js
  6. 2 2
      src/main/webapp/js/diagramly/Devel.js
  7. 51 78
      src/main/webapp/js/diagramly/Dialogs.js
  8. 66 113
      src/main/webapp/js/diagramly/DrawioFile.js
  9. 6 56
      src/main/webapp/js/diagramly/DrawioFileSync.js
  10. 39 32
      src/main/webapp/js/diagramly/Editor.js
  11. 158 29
      src/main/webapp/js/diagramly/EditorUi.js
  12. 18 17
      src/main/webapp/js/diagramly/Menus.js
  13. 1 1
      src/main/webapp/js/diagramly/Settings.js
  14. 10 10
      src/main/webapp/js/diagramly/sidebar/Sidebar-C4.js
  15. 2 6
      src/main/webapp/js/diagramly/sidebar/Sidebar-Rack.js
  16. 66 3
      src/main/webapp/js/diagramly/sidebar/Sidebar-Sysml.js
  17. 3 1
      src/main/webapp/js/grapheditor/Editor.js
  18. 82 1
      src/main/webapp/js/grapheditor/EditorUi.js
  19. 137 11
      src/main/webapp/js/grapheditor/Format.js
  20. 2 2
      src/main/webapp/js/grapheditor/Menus.js
  21. 2758 2732
      src/main/webapp/js/integrate.min.js
  22. 19 6
      src/main/webapp/js/shapes-14-6-5.min.js
  23. 1408 1388
      src/main/webapp/js/viewer-static.min.js
  24. 1389 1382
      src/main/webapp/js/viewer.min.js
  25. 3 3
      src/main/webapp/mxgraph/mxClient.js
  26. 2 0
      src/main/webapp/resources/dia.txt
  27. 2 0
      src/main/webapp/resources/dia_am.txt
  28. 2 0
      src/main/webapp/resources/dia_ar.txt
  29. 2 0
      src/main/webapp/resources/dia_bg.txt
  30. 2 0
      src/main/webapp/resources/dia_bn.txt
  31. 2 0
      src/main/webapp/resources/dia_bs.txt
  32. 2 0
      src/main/webapp/resources/dia_ca.txt
  33. 2 0
      src/main/webapp/resources/dia_cs.txt
  34. 2 0
      src/main/webapp/resources/dia_da.txt
  35. 2 0
      src/main/webapp/resources/dia_de.txt
  36. 2 0
      src/main/webapp/resources/dia_el.txt
  37. 2 0
      src/main/webapp/resources/dia_eo.txt
  38. 2 0
      src/main/webapp/resources/dia_es.txt
  39. 2 0
      src/main/webapp/resources/dia_et.txt
  40. 2 0
      src/main/webapp/resources/dia_eu.txt
  41. 2 0
      src/main/webapp/resources/dia_fa.txt
  42. 2 0
      src/main/webapp/resources/dia_fi.txt
  43. 2 0
      src/main/webapp/resources/dia_fil.txt
  44. 13 11
      src/main/webapp/resources/dia_fr.txt
  45. 2 0
      src/main/webapp/resources/dia_gl.txt
  46. 2 0
      src/main/webapp/resources/dia_gu.txt
  47. 2 0
      src/main/webapp/resources/dia_he.txt
  48. 2 0
      src/main/webapp/resources/dia_hi.txt
  49. 2 0
      src/main/webapp/resources/dia_hr.txt
  50. 2 0
      src/main/webapp/resources/dia_hu.txt
  51. 2 0
      src/main/webapp/resources/dia_i18n.txt
  52. 2 0
      src/main/webapp/resources/dia_id.txt
  53. 2 0
      src/main/webapp/resources/dia_it.txt
  54. 2 0
      src/main/webapp/resources/dia_ja.txt
  55. 2 0
      src/main/webapp/resources/dia_kn.txt
  56. 2 0
      src/main/webapp/resources/dia_ko.txt
  57. 2 0
      src/main/webapp/resources/dia_lt.txt
  58. 2 0
      src/main/webapp/resources/dia_lv.txt
  59. 2 0
      src/main/webapp/resources/dia_ml.txt
  60. 2 0
      src/main/webapp/resources/dia_mr.txt
  61. 2 0
      src/main/webapp/resources/dia_ms.txt
  62. 2 0
      src/main/webapp/resources/dia_my.txt
  63. 2 0
      src/main/webapp/resources/dia_nl.txt
  64. 2 0
      src/main/webapp/resources/dia_no.txt
  65. 2 0
      src/main/webapp/resources/dia_pl.txt
  66. 2 0
      src/main/webapp/resources/dia_pt-br.txt
  67. 2 0
      src/main/webapp/resources/dia_pt.txt
  68. 2 0
      src/main/webapp/resources/dia_ro.txt
  69. 2 0
      src/main/webapp/resources/dia_ru.txt
  70. 2 0
      src/main/webapp/resources/dia_si.txt
  71. 2 0
      src/main/webapp/resources/dia_sk.txt
  72. 2 0
      src/main/webapp/resources/dia_sl.txt
  73. 2 0
      src/main/webapp/resources/dia_sr.txt
  74. 2 0
      src/main/webapp/resources/dia_sv.txt
  75. 2 0
      src/main/webapp/resources/dia_sw.txt
  76. 2 0
      src/main/webapp/resources/dia_ta.txt
  77. 2 0
      src/main/webapp/resources/dia_te.txt
  78. 2 0
      src/main/webapp/resources/dia_th.txt
  79. 2 0
      src/main/webapp/resources/dia_tr.txt
  80. 2 0
      src/main/webapp/resources/dia_uk.txt
  81. 2 0
      src/main/webapp/resources/dia_vi.txt
  82. 2 0
      src/main/webapp/resources/dia_zh-tw.txt
  83. 2 0
      src/main/webapp/resources/dia_zh.txt
  84. 1 1
      src/main/webapp/service-worker.js
  85. 1 1
      src/main/webapp/service-worker.js.map
  86. 125 0
      src/main/webapp/shapes/mxSysML.js
  87. 151 0
      src/main/webapp/shapes/rack/mxRack.js
  88. 3 3
      src/main/webapp/styles/dark.css
  89. 14 1
      src/main/webapp/styles/grapheditor.css

+ 22 - 0
ChangeLog

@@ -1,3 +1,25 @@
+19-OCT-2022: 20.4.2
+
+- Fixes draggable elements problem in Chrome [3112]
+
+13-OCT-2022: 20.4.1
+
+- Adds Gliffy file size error message [DS-920]
+- Only hides current menu for mouse down event types [DS-921]
+- Fixes possible #ERROR fill for invalid fillStyles [DS-922]
+- Bugfixes for Rack Cabinet shape [3052]
+- Fixes DOM for empty status message
+- Fixes status alert style in dark mode
+- Fixes spaces, missing HTML tag in C4 shapes [3082]
+- Uses data attribute for status event handling code [DS-923]
+- Uses svg icons, fixes revisions dialog for mobile
+- Adds new port shape to the SysML library [3015]
+- Inverts order of toolbar items in revision dialog
+- Adds editing for relative positions in Arrange tab
+- Fixes possible overflow of library preview [3080]
+- Handles data-effect attribute for status bar items
+- Fixes key insert position if mouse outside diagram [DS-924]
+
 29-SEP-2022: 20.4.0
 
 - [conf cloud] Fixed bug that instances without configuration store diagrams as compressed XML [DID-6387]

+ 1 - 1
VERSION

@@ -1 +1 @@
-20.4.0
+20.4.2

+ 0 - 6
src/main/java/com/mxgraph/online/ProxyServlet.java

@@ -78,12 +78,6 @@ public class ProxyServlet extends HttpServlet
 
 			try(OutputStream out = response.getOutputStream())
 			{
-				if ("draw.io".equals(ua))
-				{
-					log.log(Level.SEVERE, "Infinite loop detected, proxy should not call itself");
-					throw new UnsupportedContentException();
-				}
-
 				request.setCharacterEncoding("UTF-8");
 				response.setCharacterEncoding("UTF-8");
 

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 2949 - 2936
src/main/webapp/js/app.min.js


+ 27 - 9
src/main/webapp/js/diagramly/App.js

@@ -5855,6 +5855,9 @@ App.prototype.updateButtonContainer = function()
 	}
 };
 
+/**
+ * For testing use notifs = [{timestamp: Date.now(), content: 'Test'}]
+ */
 App.prototype.fetchAndShowNotification = function(target, subtarget)
 {
 	if (this.fetchingNotif)
@@ -5991,21 +5994,36 @@ App.prototype.showNotification = function(notifs, lsReadFlag)
 	{
 		this.notificationBtn = document.createElement('div');
 		this.notificationBtn.className = 'geNotification-box';
-		
-		if (uiTheme == 'min')
+
+		var notifCount = document.createElement('span');
+		notifCount.className = 'geNotification-count';
+		this.notificationBtn.appendChild(notifCount);
+				
+		if (Editor.currentTheme == 'simple' ||
+			Editor.currentTheme == 'min')
 		{
-			this.notificationBtn.style.width = '30px';
-			this.notificationBtn.style.top = '4px';
+			if (Editor.currentTheme != 'min' ||
+				urlParams['sketch'] == '1')
+			{
+				this.notificationBtn.style.width = '30px';
+				notifCount.style.marginRight = '-10px';
+			}
+			
+			if (Editor.currentTheme == 'simple' ||
+				urlParams['sketch'] == '1')
+			{
+				this.notificationBtn.style.top = '7px';
+			}
+			else
+			{
+				this.notificationBtn.style.top = '4px';
+			}
 		}
 		else if (urlParams['atlas'] == '1')
 		{
 			this.notificationBtn.style.top = '2px';
 		}
 		
-		var notifCount = document.createElement('span');
-		notifCount.className = 'geNotification-count';
-		this.notificationBtn.appendChild(notifCount);
-		
 		var notifBell = document.createElement('div');
 		notifBell.className = 'geNotification-bell';
 		notifBell.style.opacity = uiTheme == 'min'? '0.5' : '';
@@ -6927,7 +6945,7 @@ App.prototype.updateHeader = function()
 			mxEvent.consume(evt);
 		}));
 		
-		if (urlParams['live-ui'] != '1' && uiTheme != 'atlas' && urlParams['embed'] != '1')
+		if (!Editor.enableSimpleTheme && uiTheme != 'atlas' && urlParams['embed'] != '1')
 		{
 			this.darkModeElement = this.toggleFormatElement.cloneNode(true);
 			this.darkModeElement.setAttribute('title', mxResources.get('theme'));

+ 2 - 2
src/main/webapp/js/diagramly/Devel.js

@@ -32,8 +32,8 @@ if (!mxIsElectron && location.protocol !== 'http:')
 			'; ';
 
 		var styleHashes = '\'sha256-pVoUz0B9cDvBP/6KP+5uOMqPh1c14hF0KFqSELqeyNQ=\' ' + // index.html
-			'\'sha256-cR/4glxXXRQGG5dXHk8/3xDJi1TSbDRy/iDCenCAUtI=\' ' + // Minimal.js/Light
-			'\'sha256-F2GX+Xo20+2dLG42hJFsFOmMgHcYXVoslaChl+VtVnM=\' ' + // Minimal.js/Dark
+			'\'sha256-fz76QL1MJQS5qXbiXMmitTofZw/gTcjkFzzC/oUlp4c=\' ' + // Minimal.js/Light
+			'\'sha256-8pjr3H3fIwNWNcaaqjCv/GeVTzj2XsEz9vqCQrX/5aE=\' ' + // Minimal.js/Dark
 			'\'sha256-7kY8ozVqKLIIBwZ24dhdmZkM26PsOlZmEi72RhmZKoM=\' ' + // mxTooltipHandler.js
 			'\'sha256-kuk5TvxZ/Kwuobo4g6uasb1xRQwr1+nfa1A3YGePO7U=\' ' + // MathJax
 			'\'sha256-ByOXYIXIkfNC3flUR/HoxR4Ak0pjOEF1q8XmtuIa6po=\' ' + // purify.min.js

+ 51 - 78
src/main/webapp/js/diagramly/Dialogs.js

@@ -5751,7 +5751,7 @@ var RevisionDialog = function(editorUi, revs, restoreFn)
 	var container = document.createElement('div');
 	container.style.position = 'absolute';
 	container.style.border = '1px solid lightGray';
-	container.style.left = '199px';
+	container.style.left = '200px';
 	container.style.width = '470px';
 	container.style.height = '376px';
 	container.style.overflow = 'hidden';
@@ -5854,78 +5854,50 @@ var RevisionDialog = function(editorUi, revs, restoreFn)
 	var currentRev = null;
 	var currentDoc = null;
 	var currentXml = null;
-	
-	var zoomInBtn = mxUtils.button('', function()
+
+	var zoomInBtn = editorUi.createToolbarButton(Editor.zoomInImage, mxResources.get('zoomIn'), function()
 	{
 		if (currentDoc != null)
 		{
 			graph.zoomIn();
 		}
-	});
-	zoomInBtn.className = 'geSprite geSprite-zoomin';
-	zoomInBtn.setAttribute('title', mxResources.get('zoomIn'));
-	zoomInBtn.style.outline = 'none';
-	zoomInBtn.style.border = 'none';
-	zoomInBtn.style.margin = '2px';
+	}, 20);
+
 	zoomInBtn.setAttribute('disabled', 'disabled');
-	mxUtils.setOpacity(zoomInBtn, 20);
-	
-	var zoomOutBtn = mxUtils.button('', function()
+
+	var zoomOutBtn = editorUi.createToolbarButton(Editor.zoomOutImage, mxResources.get('zoomOut'), function()
 	{
 		if (currentDoc != null)
 		{
 			graph.zoomOut();
 		}
-	});
-	zoomOutBtn.className = 'geSprite geSprite-zoomout';
-	zoomOutBtn.setAttribute('title', mxResources.get('zoomOut'));
-	zoomOutBtn.style.outline = 'none';
-	zoomOutBtn.style.border = 'none';
-	zoomOutBtn.style.margin = '2px';
+	}, 20);
+
 	zoomOutBtn.setAttribute('disabled', 'disabled');
-	mxUtils.setOpacity(zoomOutBtn, 20);
 
-	var zoomFitBtn = mxUtils.button('', function()
+	var zoomFitBtn = editorUi.createToolbarButton(Editor.zoomFitImage, mxResources.get('fit'), function()
 	{
 		if (currentDoc != null)
 		{
-			graph.maxFitScale = 8;
-			graph.fit(8);
+			if (graph.view.scale == 1)
+			{
+				graph.maxFitScale = 8;
+				graph.fit(8);
+			}
+			else
+			{
+				graph.zoomActual();
+			}
+
 			graph.center();
 		}
-	});
-	zoomFitBtn.className = 'geSprite geSprite-fit';
-	zoomFitBtn.setAttribute('title', mxResources.get('fit'));
-	zoomFitBtn.style.outline = 'none';
-	zoomFitBtn.style.border = 'none';
-	zoomFitBtn.style.margin = '2px';
+	}, 20);
+
 	zoomFitBtn.setAttribute('disabled', 'disabled');
-	mxUtils.setOpacity(zoomFitBtn, 20);
-	
-	var zoomActualBtn = mxUtils.button('', function()
-	{
-		if (currentDoc != null)
-		{
-			graph.zoomActual();
-			graph.center();
-		}
-	});
-	zoomActualBtn.className = 'geSprite geSprite-actualsize';
-	zoomActualBtn.setAttribute('title', mxResources.get('actualSize'));
-	zoomActualBtn.style.outline = 'none';
-	zoomActualBtn.style.border = 'none';
-	zoomActualBtn.style.margin = '2px';
-	zoomActualBtn.setAttribute('disabled', 'disabled');
-	mxUtils.setOpacity(zoomActualBtn, 20);
 
 	// Gesture listener added below to handle pressed state
-	var compareBtn = mxUtils.button('', function() { });
-	compareBtn.className = 'geSprite geSprite-middle';
-	compareBtn.setAttribute('title', mxResources.get('compare'));
-	compareBtn.style.outline = 'none';
-	compareBtn.style.border = 'none';
-	compareBtn.style.margin = '2px';
-	mxUtils.setOpacity(compareBtn, 60);
+	var compareBtn = editorUi.createToolbarButton(Editor.compareImage, mxResources.get('zoomOut'), null, 20);
+	compareBtn.setAttribute('disabled', 'disabled');
 	
 	var cmpContainer = container.cloneNode(false);
 	cmpContainer.style.pointerEvent = 'none';
@@ -5941,6 +5913,19 @@ var RevisionDialog = function(editorUi, revs, restoreFn)
 	cmpGraph.maxFitScale = null;
 	cmpGraph.centerZoom = true;
 
+	var fileInfo = document.createElement('div');
+	fileInfo.style.position = 'absolute';
+	fileInfo.style.textAlign = 'left';
+	fileInfo.style.color = 'gray';
+	fileInfo.style.marginTop = '8px';
+	fileInfo.style.backgroundColor = 'transparent';
+	fileInfo.style.top = '440px';
+	fileInfo.style.left = '32px';
+	fileInfo.style.maxWidth = '380px';
+	fileInfo.style.cursor = 'default';
+
+	var prevFileInfo = null;
+
 	mxEvent.addGestureListeners(compareBtn, function(e)
 	{
 		// Gets current state of page with given ID
@@ -5954,7 +5939,8 @@ var RevisionDialog = function(editorUi, revs, restoreFn)
 		}
 		else
 		{
-			fileInfo.style.display = 'none';
+			prevFileInfo = fileInfo.innerHTML;
+			fileInfo.innerHTML = mxResources.get('current');
 			container.style.display = 'none';
 			cmpContainer.style.display = '';
 			cmpContainer.style.backgroundColor = container.style.backgroundColor;
@@ -5972,23 +5958,12 @@ var RevisionDialog = function(editorUi, revs, restoreFn)
 
 		if (container.style.display == 'none')
 		{
-			fileInfo.style.display = '';
 			container.style.display = '';
+			fileInfo.innerHTML = prevFileInfo;
 			cmpContainer.style.display = 'none';
 		}
 	});
 
-	var fileInfo = document.createElement('div');
-	fileInfo.style.position = 'absolute';
-	fileInfo.style.textAlign = 'right';
-	fileInfo.style.color = 'gray';
-	fileInfo.style.marginTop = '10px';
-	fileInfo.style.backgroundColor = 'transparent';
-	fileInfo.style.top = '440px';
-	fileInfo.style.right = '32px';
-	fileInfo.style.maxWidth = '380px';
-	fileInfo.style.cursor = 'default';
-
 	var downloadBtn = mxUtils.button(mxResources.get('download'), function()
 	{
 		if (currentDoc != null)
@@ -6088,11 +6063,12 @@ var RevisionDialog = function(editorUi, revs, restoreFn)
 	
 	var pageSelect = document.createElement('select');
 	pageSelect.setAttribute('disabled', 'disabled');
-	pageSelect.style.maxWidth = '80px';
+	pageSelect.style.userSelect = 'none';
+	pageSelect.style.maxWidth = '100px';
 	pageSelect.style.position = 'relative';
 	pageSelect.style.top = '-2px';
 	pageSelect.style.verticalAlign = 'bottom';
-	pageSelect.style.marginRight = '6px';
+	pageSelect.style.marginLeft = '10px';
 	pageSelect.style.display = 'none';
 	
 	var pageSelectFunction = null;
@@ -6146,7 +6122,8 @@ var RevisionDialog = function(editorUi, revs, restoreFn)
 	var buttons = document.createElement('div');
 	buttons.style.position = 'absolute';
 	buttons.style.top = '482px';
-	buttons.style.width = '640px';
+	buttons.style.right = '28px';
+	buttons.style.left = '32px';
 	buttons.style.textAlign = 'right';
 
 	var tb = document.createElement('div');
@@ -6154,8 +6131,8 @@ var RevisionDialog = function(editorUi, revs, restoreFn)
 	tb.style.backgroundColor = 'transparent';
 	tb.style.padding = '2px';
 	tb.style.border = 'none';
-	tb.style.left = '199px';
 	tb.style.top = '442px';
+	tb.style.right = '28px';
 	
 	var currentElt = null;
 
@@ -6343,7 +6320,6 @@ var RevisionDialog = function(editorUi, revs, restoreFn)
 							zoomInBtn.removeAttribute('disabled');
 							zoomOutBtn.removeAttribute('disabled');
 							zoomFitBtn.removeAttribute('disabled');
-							zoomActualBtn.removeAttribute('disabled');
 							compareBtn.removeAttribute('disabled');
 							
 							if (file == null || !file.isRestricted())
@@ -6361,7 +6337,6 @@ var RevisionDialog = function(editorUi, revs, restoreFn)
 							mxUtils.setOpacity(zoomInBtn, 60);
 							mxUtils.setOpacity(zoomOutBtn, 60);
 							mxUtils.setOpacity(zoomFitBtn, 60);
-							mxUtils.setOpacity(zoomActualBtn, 60);
 							mxUtils.setOpacity(compareBtn, 60);
 						}
 						else
@@ -6369,6 +6344,7 @@ var RevisionDialog = function(editorUi, revs, restoreFn)
 							pageSelect.style.display = 'none';
 							pageSelect.innerText = '';
 							fileInfo.innerText = '';
+							errorNode.innerText = '';
 							mxUtils.write(fileInfo, mxResources.get('errorLoadingFile'));
 							mxUtils.write(errorNode, mxResources.get('errorLoadingFile'));
 						}
@@ -6401,7 +6377,6 @@ var RevisionDialog = function(editorUi, revs, restoreFn)
 							downloadBtn.setAttribute('disabled', 'disabled');
 							zoomInBtn.setAttribute('disabled', 'disabled');
 							zoomOutBtn.setAttribute('disabled', 'disabled');
-							zoomActualBtn.setAttribute('disabled', 'disabled');
 							zoomFitBtn.setAttribute('disabled', 'disabled');
 							compareBtn.setAttribute('disabled', 'disabled');
 
@@ -6412,7 +6387,6 @@ var RevisionDialog = function(editorUi, revs, restoreFn)
 							mxUtils.setOpacity(zoomInBtn, 20);
 							mxUtils.setOpacity(zoomOutBtn, 20);
 							mxUtils.setOpacity(zoomFitBtn, 20);
-							mxUtils.setOpacity(zoomActualBtn, 20);
 							mxUtils.setOpacity(compareBtn, 20);
 
 							spinner.spin(container);
@@ -6505,12 +6479,11 @@ var RevisionDialog = function(editorUi, revs, restoreFn)
 	});
 	closeBtn.className = 'geBtn';
 
-	tb.appendChild(pageSelect);
-	tb.appendChild(zoomInBtn);
+	tb.appendChild(compareBtn);
 	tb.appendChild(zoomOutBtn);
-	tb.appendChild(zoomActualBtn);
 	tb.appendChild(zoomFitBtn);
-	tb.appendChild(compareBtn);
+	tb.appendChild(zoomInBtn);
+	tb.appendChild(pageSelect);
 
 	if (editorUi.editor.cancelFirst)
 	{
@@ -8009,7 +7982,7 @@ var MoreShapesDialog = function(editorUi, expanded, entries)
 									}
 									else if (entry.image != null)
 									{
-										preview.innerHTML += '<img border="0" src="' + entry.image + '"/>';
+										preview.innerHTML += '<img border="0" style="max-width:100%;" src="' + entry.image + '"/>';
 									}
 									else if (entry.desc == null)
 									{

+ 66 - 113
src/main/webapp/js/diagramly/DrawioFile.js

@@ -1687,19 +1687,8 @@ DrawioFile.prototype.addAllSavedStatus = function(status)
 	if (this.ui.statusContainer != null && this.ui.getCurrentFile() == this)
 	{
 		status = (status != null) ? status : mxUtils.htmlEntities(mxResources.get(this.allChangesSavedKey));
-		this.ui.editor.setStatus('<div title="'+ status + '">' + status + '</div>');
-		var links = this.ui.statusContainer.getElementsByTagName('div');
-		
-		if (links.length > 0 && this.isRevisionHistorySupported())
-		{
-			links[0].style.cursor = 'pointer';
-			links[0].style.textDecoration = 'underline';
-			
-			mxEvent.addListener(links[0], 'click', mxUtils.bind(this, function()
-			{
-				this.ui.actions.get('revisionHistory').funct();
-			}));
-		}
+		var rev = (this.isRevisionHistorySupported()) ? 'data-action="revisionHistory" ' : '';
+		this.ui.editor.setStatus('<div ' + rev + 'title="'+ status + '">' + status + '</div>');
 	}
 };
 
@@ -1775,22 +1764,11 @@ DrawioFile.prototype.addUnsavedStatus = function(err)
 		if (err instanceof Error && err.message != null && err.message != '')
 		{
 			var status = mxUtils.htmlEntities(mxResources.get('unsavedChanges'));
-			
-			this.ui.editor.setStatus('<div title="'+ status + '" class="geStatusAlert">' +
-				status + ' (' + mxUtils.htmlEntities(err.message) + ')</div>');
-
-			// Installs click handler for error message
-			var links = this.ui.statusContainer.getElementsByTagName('div');
-			
-			if (links != null && links.length > 0)
-			{
-				links[0].style.cursor = 'pointer';
-
-				mxEvent.addListener(links[0], 'click', mxUtils.bind(this, function()
-				{
-					this.ui.showError(mxResources.get('unsavedChanges'), mxUtils.htmlEntities(err.message));
-				}));
-			}
+			this.ui.editor.setStatus('<div title="'+ status + '" data-title="' +
+				mxUtils.htmlEntities(mxResources.get('unsavedChanges')) +
+				'" data-message="' + mxUtils.htmlEntities(err.message) +
+				'" class="geStatusAlert">' + status + ' (' +
+				mxUtils.htmlEntities(err.message) + ')</div>');
 		}
 		else
 		{
@@ -1814,30 +1792,12 @@ DrawioFile.prototype.addUnsavedStatus = function(err)
 
 			var status = mxUtils.htmlEntities(mxResources.get('unsavedChangesClickHereToSave')) +
 				((msg != null && msg != '') ? ' (' + mxUtils.htmlEntities(msg) + ')' : '');
-			this.ui.editor.setStatus('<div title="'+ status + '" class="geStatusAlertOrange">' + status +
+			var action = 'data-action="' + ((this.ui.mode == null || !this.isEditable()) ?
+				'saveAs' : 'save') + '"';
+			this.ui.editor.setStatus('<div ' + action + ' title="' +
+				status + '" class="geStatusAlertOrange">' + status +
 				' <img src="' + Editor.saveImage + '"/></div>');
 			
-			// Installs click handler for saving
-			var links = this.ui.statusContainer.getElementsByTagName('div');
-			
-			if (links != null && links.length > 0)
-			{
-				links[0].style.cursor = 'pointer';
-
-				mxEvent.addListener(links[0], 'click', mxUtils.bind(this, function()
-				{
-					this.ui.actions.get((this.ui.mode == null || !this.isEditable()) ?
-						'saveAs' : 'save').funct();
-				}));
-			}
-			else
-			{
-				var status = mxUtils.htmlEntities(mxResources.get('unsavedChanges'));
-				
-				this.ui.editor.setStatus('<div title="'+ status + '" class="geStatusAlert">' + status +
-					' (' + mxUtils.htmlEntities(err.message) + ')</div>');
-			}
-			
 			if (EditorUi.enableDrafts && (this.getMode() == null || EditorUi.isElectronApp))
 			{
 				this.lastDraftSave = this.lastDraftSave || Date.now();
@@ -1870,7 +1830,7 @@ DrawioFile.prototype.addUnsavedStatus = function(err)
  * Halts all timers and shows a conflict status message. The optional error
  * handler is invoked first.
  */
-DrawioFile.prototype.addConflictStatus = function(fn, message)
+DrawioFile.prototype.addConflictStatus = function(message, fn)
 {
 	if (this.invalidChecksum && message == null)
 	{
@@ -1878,39 +1838,22 @@ DrawioFile.prototype.addConflictStatus = function(fn, message)
 	}
 
 	this.setConflictStatus(mxUtils.htmlEntities(mxResources.get('fileChangedSync')) +
-		((message != null && message != '') ? ' (' + mxUtils.htmlEntities(message) + ')' : ''));
+		((message != null && message != '') ? ' (' +
+		mxUtils.htmlEntities(message) + ')' : ''), fn);
 	this.ui.spinner.stop();
 	this.clearAutosave();
-
-	var links = (this.ui.statusContainer != null) ? this.ui.statusContainer.getElementsByTagName('div') : null;
-	
-	if (links != null && links.length > 0)
-	{
-		links[0].style.cursor = 'pointer';
-
-		mxEvent.addListener(links[0], 'click', mxUtils.bind(this, function(evt)
-		{
-			if (mxEvent.getSource(evt).nodeName != 'IMG')
-			{
-				fn();
-			}
-		}));
-	}
-	else
-	{
-		this.ui.alert(mxUtils.htmlEntities(mxResources.get('fileChangedSync')), fn);
-	}
 };
 
 /**
  * Halts all timers and shows a conflict status message. The optional error
  * handler is invoked first.
  */
-DrawioFile.prototype.setConflictStatus = function(message)
+DrawioFile.prototype.setConflictStatus = function(message, fn)
 {
-	this.ui.editor.setStatus('<div title="'+ message + '" class="geStatusAlert">' + message +
-		' <a href="https://www.diagrams.net/doc/faq/synchronize" title="' + mxResources.get('help') +
-		'" target="_blank">' + '<img src="' + Editor.helpImage + '"/></a></div>');
+	this.ui.editor.setStatus('<div title="'+ message + '" ' + ((fn != null) ?
+		'data-action="statusFunction"' : '') + ' class="geStatusAlert">' + message +
+		'<img data-link="https://www.diagrams.net/doc/faq/synchronize" src="' +
+		Editor.helpImage + '" style="cursor:help;"/></div>', fn);
 };
 
 /**
@@ -1933,10 +1876,10 @@ DrawioFile.prototype.showRefreshDialog = function(success, error, message)
 	else
 	{
 		// Allows for escape key to be pressed while dialog is showing
-		this.addConflictStatus(mxUtils.bind(this, function()
+		this.addConflictStatus(message, mxUtils.bind(this, function()
 		{
 			this.showRefreshDialog(success, error);
-		}), message);
+		}));
 		
 		this.ui.showError(mxResources.get('warning') + ' (' + message + ')',
 			mxResources.get('fileChangedSyncDialog'),
@@ -2210,12 +2153,12 @@ DrawioFile.prototype.handleConflictError = function(err, manual)
 	}
 	else
 	{
-		this.addConflictStatus(mxUtils.bind(this, function()
+		this.addConflictStatus(this.getErrorMessage(err), mxUtils.bind(this, function()
 		{
 			this.ui.editor.setStatus(mxUtils.htmlEntities(
 				mxResources.get('updatingDocument')));
 			this.synchronizeFile(success, error);
-		}), this.getErrorMessage(err));
+		}));
 	}
 };
 
@@ -2437,54 +2380,64 @@ DrawioFile.prototype.autosave = function(delay, maxDelay, success, error)
 	// Starts new timer or executes immediately if not unsaved for maxDelay
 	var thread = window.setTimeout(mxUtils.bind(this, function()
 	{
-		this.lastAutosave = null;
-		
-		if (this.autosaveThread == thread)
-		{
-			this.autosaveThread = null;
-		}
-
-		EditorUi.debug('DrawioFile.autosave', [this], 'thread', thread,
-			'modified', this.isModified(), 'now', this.isAutosaveNow(),
-			'saving', this.savingFile);
-		
-		// Workaround for duplicate save if UI is blocking
-		// after save while pending autosave triggers
-		if (this.isModified() && this.isAutosaveNow())
+		try
 		{
-			var rev = this.isAutosaveRevision();
+			this.lastAutosave = null;
 			
-			if (rev)
+			if (this.autosaveThread == thread)
 			{
-				this.lastAutosaveRevision = new Date().getTime();
+				this.autosaveThread = null;
 			}
+
+			EditorUi.debug('DrawioFile.autosave', [this], 'thread', thread,
+				'modified', this.isModified(), 'now', this.isAutosaveNow(),
+				'saving', this.savingFile);
 			
-			this.save(rev, mxUtils.bind(this, function(resp)
+			// Workaround for duplicate save if UI is blocking
+			// after save while pending autosave triggers
+			if (this.isModified() && this.isAutosaveNow())
 			{
-				this.autosaveCompleted();
+				var rev = this.isAutosaveRevision();
 				
-				if (success != null)
+				if (rev)
 				{
-					success(resp);
+					this.lastAutosaveRevision = new Date().getTime();
 				}
-			}), mxUtils.bind(this, function(resp)
+				
+				this.save(rev, mxUtils.bind(this, function(resp)
+				{
+					this.autosaveCompleted();
+					
+					if (success != null)
+					{
+						success(resp);
+					}
+				}), mxUtils.bind(this, function(resp)
+				{
+					if (error != null)
+					{
+						error(resp);
+					}
+				}));
+			}
+			else
 			{
-				if (error != null)
+				if (!this.isModified())
 				{
-					error(resp);
+					this.ui.editor.setStatus('');
 				}
-			}));
+				
+				if (success != null)
+				{
+					success(null);
+				}
+			}
 		}
-		else
+		catch (e)
 		{
-			if (!this.isModified())
-			{
-				this.ui.editor.setStatus('');
-			}
-			
-			if (success != null)
+			if (error != null)
 			{
-				success(null);
+				error(e);
 			}
 		}
 	}), tmp);

+ 6 - 56
src/main/webapp/js/diagramly/DrawioFileSync.js

@@ -234,12 +234,7 @@ DrawioFileSync.prototype.syncChangeCounter = 0;
 /**
  * Specifies if notifications should be sent and received for changes.
  */
-DrawioFileSync.prototype.enabled = true;
-
-/**
- * True if a change event is fired for a remote change.
- */
-DrawioFileSync.prototype.updateStatusInterval = 10000;
+ DrawioFileSync.prototype.enabled = true;
 
 /**
  * Holds the channel ID for sending and receiving change notifications.
@@ -627,9 +622,7 @@ DrawioFileSync.prototype.updateStatus = function()
 				str = mxResources.get('lessThanAMinute');
 			}
 			
-			var history = this.file.isRevisionHistorySupported();
-
-			// Consumed and displays last message
+			// Consumes and displays last message
 			var msg = this.lastMessage;
 			this.lastMessage = null;
 			
@@ -639,55 +632,12 @@ DrawioFileSync.prototype.updateStatus = function()
 			}
 
 			var label = mxResources.get('lastChange', [str]);
-			
-			this.ui.editor.setStatus('<div title="'+ mxUtils.htmlEntities(label) + '">' + mxUtils.htmlEntities(label) + '</div>' +
+			var rev = (this.file.isRevisionHistorySupported()) ? 'data-action="revisionHistory" ' : '';
+			this.ui.editor.setStatus('<div ' + rev + 'title="'+ mxUtils.htmlEntities(label) + '">' + mxUtils.htmlEntities(label) + '</div>' +
 				(this.file.isEditable() ? '' : '<div class="geStatusAlert">' + mxUtils.htmlEntities(mxResources.get('readOnly')) + '</div>') +
 				(this.isConnected() ? '' : '<div class="geStatusAlert">' + mxUtils.htmlEntities(mxResources.get('disconnected')) + '</div>') +
-				((msg != null) ? ' <span title="' + mxUtils.htmlEntities(msg) + '">(' + mxUtils.htmlEntities(msg) + ')</span>' : ''));
-			var links = this.ui.statusContainer.getElementsByTagName('div');
-			
-			if (links.length > 0 && history)
-			{
-				links[0].style.display = 'inline-block';
+				((msg != null) ? ' <div data-effect="fade" title="' + mxUtils.htmlEntities(msg) + '">(' + mxUtils.htmlEntities(msg) + ')</div>' : ''));
 
-				if (history)
-				{
-					links[0].style.cursor = 'pointer';
-					links[0].style.textDecoration = 'underline';
-					
-					mxEvent.addListener(links[0], 'click', mxUtils.bind(this, function()
-					{
-						this.ui.actions.get('revisionHistory').funct();
-					}));
-				}
-			}
-
-			// Fades in/out last message
-			var spans = this.ui.statusContainer.getElementsByTagName('span');
-			
-			if (spans.length > 0)
-			{
-				var temp = spans[0];
-				temp.style.opacity = '0';
-				mxUtils.setPrefixedStyle(temp.style, 'transition', 'all 0.2s ease');
-				
-				window.setTimeout(mxUtils.bind(this, function()
-				{
-					mxUtils.setOpacity(temp, 100);
-					mxUtils.setPrefixedStyle(temp.style, 'transition', 'all 1s ease');
-					
-					window.setTimeout(mxUtils.bind(this, function()
-					{
-						mxUtils.setOpacity(temp, 0);
-
-						window.setTimeout(mxUtils.bind(this, function()
-						{
-							this.updateStatus();
-						}), 1000);
-					}), this.updateStatusInterval / 2);
-				}), 0);
-			}
-			
 			this.resetUpdateStatusThread();
 		}
 		else
@@ -712,7 +662,7 @@ DrawioFileSync.prototype.resetUpdateStatusThread = function()
 		this.updateStatusThread = window.setInterval(mxUtils.bind(this, function()
 		{
 			this.updateStatus();
-		}), this.updateStatusInterval);
+		}), Editor.updateStatusInterval);
 	}
 };
 

+ 39 - 32
src/main/webapp/js/diagramly/Editor.js

@@ -18,34 +18,6 @@
 		html4.ATTRIBS['font::data-font-src'] = 0;
 	}
 
-	/**
-	 * Specifies the app name. Default is document.title.
-	 */
-	Editor.prototype.appName = 'diagrams.net';
-		
-	/**
-	 * Known file types.
-	 */
-	Editor.prototype.diagramFileTypes = [
-		{description: 'diagramXmlDesc', extension: 'drawio', mimeType: 'text/xml'},
-		{description: 'diagramPngDesc', extension: 'png', mimeType: 'image/png'},
-		{description: 'diagramSvgDesc', extension: 'svg', mimeType: 'image/svg'},
-		{description: 'diagramHtmlDesc', extension: 'html', mimeType: 'text/html'},
-		{description: 'diagramXmlDesc', extension: 'xml', mimeType: 'text/xml'}];
-
-	/**
-	 * Known file types.
-	 */
-	Editor.prototype.libraryFileTypes = [{description: 'Library (.drawiolib, .xml)', extensions: ['drawiolib', 'xml']}];
-
-	/**
-	 * Additional help text for special file extensions.
-	 */
-	Editor.prototype.fileExtensions = [
-		{ext: 'html', title: 'filetypeHtml'},
-		{ext: 'png', title: 'filetypePng'},
-		{ext: 'svg', title: 'filetypeSvg'}];
-	
 	/**
 	 * Definitions for sketch font styles.
 	 */
@@ -139,10 +111,6 @@
 	 */
 	Editor.svgBrokenImage = Graph.createSvgImage(10, 10, '<rect x="0" y="0" width="10" height="10" stroke="#000" fill="transparent"/><path d="m 0 0 L 10 10 L 0 10 L 10 0" stroke="#000" fill="transparent"/>');
 
-	/**
-	 * Error image for not found images
-	 */	
-
 	/**
 	 * Error image for not found images
 	 */	
@@ -167,6 +135,12 @@
 	 * Specifies if custom properties should be enabled.
 	 */
 	Editor.enableCustomProperties = true;
+		
+	/**
+	 * Specifies if the simple theme should be enabled. This theme can be used
+	 * at runtime in the kennedy theme.
+	 */
+	Editor.enableSimpleTheme = urlParams['live-ui'] == '1';
 	
 	/**
 	 * Sets the default value for including a copy of the diagram.
@@ -2104,6 +2078,39 @@
 		return rtn.join('');
 	};
 
+	/**
+	 * Interval for updating the file status.
+	 */
+	Editor.updateStatusInterval = 10000;
+
+	/**
+	 * Specifies the app name. Default is document.title.
+	 */
+	Editor.prototype.appName = 'diagrams.net';
+		
+	 /**
+	  * Known file types.
+	  */
+	Editor.prototype.diagramFileTypes = [
+		{description: 'diagramXmlDesc', extension: 'drawio', mimeType: 'text/xml'},
+		{description: 'diagramPngDesc', extension: 'png', mimeType: 'image/png'},
+		{description: 'diagramSvgDesc', extension: 'svg', mimeType: 'image/svg'},
+		{description: 'diagramHtmlDesc', extension: 'html', mimeType: 'text/html'},
+		{description: 'diagramXmlDesc', extension: 'xml', mimeType: 'text/xml'}];
+
+	 /**
+	  * Known file types.
+	  */
+	Editor.prototype.libraryFileTypes = [{description: 'Library (.drawiolib, .xml)', extensions: ['drawiolib', 'xml']}];
+ 
+	 /**
+	  * Additional help text for special file extensions.
+	  */
+	Editor.prototype.fileExtensions = [
+		{ext: 'html', title: 'filetypeHtml'},
+		{ext: 'png', title: 'filetypePng'},
+		{ext: 'svg', title: 'filetypeSvg'}];
+	
 	/**
 	 * General timeout is 25 seconds.
 	 */

+ 158 - 29
src/main/webapp/js/diagramly/EditorUi.js

@@ -8614,6 +8614,8 @@
 						else if (done != null)
 						{
 							done(null);
+							this.showError(mxResources.get('error'), xhr.status == 413? mxResources.get('diagramTooLarge') :
+													mxResources.get('unknownError'));
 						}
 					}
 				});
@@ -10671,7 +10673,6 @@
 					window.setTimeout(mxUtils.bind(this, function()
 					{
 						this.fireEvent(new mxEventObject('currentThemeChanged'));
-						this.editor.fireEvent(new mxEventObject('statusChanged'));
 
 						// Restores scroll position
 						this.editor.graph.refresh();
@@ -10830,7 +10831,7 @@
 			this.createShapesWindow();
 			this.sidebarContainer.style.left = '0px';
 			this.sidebarContainer.style.top = '0px';
-			this.sidebarContainer.style.bottom = '0px';
+			this.sidebarContainer.style.bottom = '63px';
 			this.sidebarContainer.style.width = '100%';
 		}
 
@@ -11146,8 +11147,8 @@
 				this.sketchPickerMenuElt = document.createElement('div');
 				this.sketchPickerMenuElt.className = 'geToolbarContainer';
 				this.sketchPickerMenuElt.style.cssText = 'position:absolute;left:10px;border-radius:4px;' +
-					'padding:0px 4px 4px;white-space:nowrap;' +
-					'z-index:1;transform:translate(0, -50%);top:50%;user-select:none;width:40px;';
+					'padding:0px 4px 4px;white-space:nowrap;max-height:100%;width:48px;z-index:1;' +
+					'box-sizing:border-box;transform:translate(0, -50%);top:50%;user-select:none;';
 
 				var picker = this.sketchPickerMenuElt;
 				mxUtils.setPrefixedStyle(picker.style, 'transition', 'transform .3s ease-out');
@@ -11278,12 +11279,13 @@
 					{
 						mxUtils.setPrefixedStyle(picker.style, 'transform', 'translate(0, -50%)');
 						picker.style.padding = '8px 6px 4px';
-						picker.style.width = '40px';
+						picker.style.width = '48px';
 						picker.style.top = '50%';
 						picker.style.bottom = '';
 						picker.style.height = '';
 						foldImg.style.backgroundImage = 'url(' + mxWindow.prototype.normalizeImage + ')';
 						foldImg.setAttribute('title', 'Minimize'/*TODO:mxResources.get('minimize')*/);
+						foldImg.style.width = '100%';
 						foldImg.style.height = '14px';
 						collapsed = false;
 						initPicker();
@@ -11293,13 +11295,13 @@
 						picker.innerText = '';
 						picker.appendChild(foldImg);
 						mxUtils.setPrefixedStyle(picker.style, 'transform', 'translate(0, 0)');
+						picker.style.width = 'auto';
 						picker.style.bottom = '12px';
 						picker.style.padding = '0px';
-						picker.style.height = '24px';
-						picker.style.width = '24px';
 						picker.style.top = '';
 						foldImg.style.backgroundImage = 'url(' + Editor.plusImage + ')';
 						foldImg.setAttribute('title', mxResources.get('insert'));
+						foldImg.style.width = '24px';
 						foldImg.style.height = '24px';
 						collapsed = true;
 					}
@@ -11331,16 +11333,24 @@
 					'min-width:40px;justify-content:flex-end;align-items:center;';
 				this.sketchWrapperElt.appendChild(this.sketchMenubarElt);
 
-				if (urlParams['embed'] != '1' && this.getServiceName() != 'atlassian')
+				// Moves menu away if picker overlaps
+				var refreshMenu = mxUtils.bind(this, function()
 				{
-					this.installStatusMinimizer(this.sketchMenubarElt);
-				}
+					var overflow = (this.sketchPickerMenuElt.offsetTop -
+						this.sketchPickerMenuElt.offsetHeight / 2 < 58);
+					this.sketchMainMenuElt.style.left = (overflow) ? '70px' : '10px';
+					this.sketchMenubarElt.style.maxWidth = (overflow) ? 
+						'calc(100% - 230px)' : 'calc(100% - 170px)';
+					
+				});
+
+				refreshMenu();
+				mxEvent.addListener(window, 'resize', refreshMenu);
 			}
 
 			if (this.statusContainer != null)
 			{
 				this.statusContainer.style.flexShrink = '1';
-				this.statusContainer.style.overflow = 'hidden';
 				this.sketchMenubarElt.appendChild(this.statusContainer);
 			}
 
@@ -11406,17 +11416,18 @@
 	/**
 	 * Overrides image dialog to add image search and Google+.
 	 */
-	EditorUi.prototype.createMenu = function(key, img)
+	EditorUi.prototype.createMenu = function(key, img, className)
 	{
+		className = (className != null) ? className : 'geToolbarButton';
 		var menu = this.menus.get(key);
 		var elt = this.menubar.addMenu(mxResources.get(key), menu.funct);
 		
-		elt.className = 'geToolbarButton';
+		elt.className = className;
 		elt.style.display = 'inline-block';
 		elt.style.cursor = 'pointer';
 		elt.style.height = '24px';
 		elt.setAttribute('title', mxResources.get(key));
-		this.menus.menuCreated(menu, elt, 'geToolbarButton');
+		this.menus.menuCreated(menu, elt, className);
 		
 		if (img != null)
 		{
@@ -11432,13 +11443,14 @@
 	};
 
 	/**
-	 * Overrides image dialog to add image search and Google+.
+	 * Create toolbar button.
 	 */
-	EditorUi.prototype.createMenuItem = function(key, img, ignoreState)
+	EditorUi.prototype.createToolbarButton = function(img, title, fn, size)
 	{
+		size = (size != null) ? size : 24;
 		var btn = document.createElement('a');
-		btn.className = 'geToolbarButton';
-		btn.setAttribute('title', mxResources.get(key));
+		btn.className = 'geToolbarButton geAdaptiveAsset';
+		btn.setAttribute('title', title);
 		btn.style.backgroundImage = 'url(' + img + ')';
 		btn.style.backgroundPosition = 'center center';
 		btn.style.backgroundRepeat = 'no-repeat';
@@ -11446,12 +11458,10 @@
 		btn.style.display = 'inline-block';
 		btn.style.cursor = 'pointer';
 		btn.style.marginLeft = '6px';
-		btn.style.width = '24px';
-		btn.style.height = '24px';
-
-		var action = this.actions.get(key);
+		btn.style.width = size + 'px';
+		btn.style.height = size + 'px';
 
-		if (action != null)
+		if (fn != null)
 		{
 			// Prevents focus
 			mxEvent.addListener(btn, (mxClient.IS_POINTER) ? 'pointerdown' : 'mousedown',
@@ -11464,12 +11474,27 @@
 			{
 				if (btn.getAttribute('disabled') != 'disabled')
 				{
-					action.funct(evt);
+					fn(evt);
 				}
 				
 				mxEvent.consume(evt);
 			});
-	
+		}
+
+		return btn;
+	};
+
+	/**
+	 * Overrides image dialog to add image search and Google+.
+	 */
+	EditorUi.prototype.createMenuItem = function(key, img, ignoreState)
+	{
+		var action = this.actions.get(key);
+		var fn = (action != null) ? action.funct : null;
+		var btn = this.createToolbarButton(img, mxResources.get(key), fn);
+
+		if (action != null)
+		{
 			if (!ignoreState)
 			{
 				function updateState()
@@ -11593,6 +11618,96 @@
 		}
 	};
 
+	/**
+	 * 
+	 */
+	EditorUi.prototype.createShapesPanel = function(container)
+	{
+		var div = document.createElement('div');
+		div.style.cssText = 'position:absolute;left:0;right:0;border-top:1px solid lightgray;' +
+			'height:24px;bottom:31px;text-align:center;cursor:pointer;padding:6px 0 0 0;';
+		div.className = 'geTitle';
+		var span = document.createElement('span');
+		span.style.fontSize = '18px';
+		span.style.marginRight = '5px';
+		span.innerHTML = '+';
+		div.appendChild(span);
+		mxUtils.write(div, mxResources.get('moreShapes'));
+		container.appendChild(div);
+		
+		mxEvent.addListener(div, 'click', mxUtils.bind(this, function()
+		{
+			this.actions.get('shapes').funct();
+		}));
+
+		// var menuObj = new Menubar(this, container);
+
+		var addMenu = mxUtils.bind(this, function(id, label)
+		{
+			var elt = this.createMenu(id, null, 'geTitle');
+
+			elt.style.cssText = 'position:absolute;border-top:1px solid lightgray;' +
+				'width:50%;height:24px;bottom:0px;text-align:center;cursor:pointer;' +
+				'padding:6px 0 0 0;cusor:pointer;';
+			container.appendChild(elt);
+
+			return elt;
+		});
+		
+		if (Editor.enableCustomLibraries && (urlParams['embed'] != '1' || urlParams['libraries'] == '1'))
+		{
+			// Defined in native apps together with openLibrary
+			if (this.actions.get('newLibrary') != null)
+			{
+				var div = document.createElement('div');
+				div.style.cssText = 'position:absolute;left:0px;width:50%;border-top:1px solid lightgray;' +
+					'height:30px;bottom:0px;text-align:center;cursor:pointer;padding:0px;';
+				div.className = 'geTitle';
+				var span = document.createElement('span');
+				span.style.cssText = 'position:relative;top:6px;';
+				mxUtils.write(span, mxResources.get('newLibrary'));
+				div.appendChild(span);
+				container.appendChild(div);
+				
+				mxEvent.addListener(div, 'click', this.actions.get('newLibrary').funct);
+				
+				var div = div.cloneNode(false);
+				div.style.left = '50%';
+				div.style.borderLeft = '1px solid lightgray';
+				var span = span.cloneNode(false);
+				mxUtils.write(span, mxResources.get('openLibrary'));
+				div.appendChild(span);
+				container.appendChild(div);
+				
+				mxEvent.addListener(div, 'click', this.actions.get('openLibrary').funct);
+			}
+			else
+			{
+				var elt = addMenu('newLibrary', mxResources.get('newLibrary'));
+				elt.style.boxSizing = 'border-box';
+				elt.style.paddingRight = '6px';
+				elt.style.paddingLeft = '6px';
+				elt.style.height = '32px';
+				elt.style.left = '0';
+				
+				var elt = addMenu('openLibraryFrom', mxResources.get('openLibraryFrom'));
+				elt.style.borderLeft = '1px solid lightgray';
+				elt.style.boxSizing = 'border-box';
+				elt.style.paddingRight = '6px';
+				elt.style.paddingLeft = '6px';
+				elt.style.height = '32px';
+				elt.style.left = '50%';
+			}
+		}
+		else
+		{
+			div.style.bottom = '0';
+		}
+
+		container.appendChild(this.sidebarContainer);
+		container.style.overflow = 'hidden';
+	};
+
 	/**
 	 * Overrides image dialog to add image search and Google+.
 	 */
@@ -11610,7 +11725,7 @@
 					Math.max(30, (this.diagramContainer.parentNode.clientHeight - h) / 2) : 56,
 				w - 6, h - 6, mxUtils.bind(this, function(container)
 			{
-				container.appendChild(this.sidebarContainer);
+				this.createShapesPanel(container);
 			}));
 			
 			this.sidebarWindow.window.addListener(mxEvent.SHOW, mxUtils.bind(this, function()
@@ -11673,6 +11788,7 @@
 			'html body.geEditor .geTabContainer div { border-color: #e5e5e5 !important; }'
 			) +
 			// End of custom styles
+			'html body .geStatus > *:not([class]) { vertical-align:top; }' +
 			'html > body > div > a.geItem { background-color: #ffffff; color: #707070; border-top: 1px solid lightgray; border-left: 1px solid lightgray; }' +
 			'html body .geMenubarContainer { border-bottom:1px solid lightgray;background-color:#ffffff; }' +
 			'html body .mxWindow button.geBtn { font-size:12px !important; margin-left: 0; }' +
@@ -12756,6 +12872,11 @@
 													{
 														this.openLocalFile(req.getText(), null, true);
 													}
+													else
+													{
+														this.showError(mxResources.get('error'), req.getStatus() == 413? mxResources.get('diagramTooLarge') :
+																			mxResources.get('unknownError'));
+													}
 												}));
 											}
 										}
@@ -14401,10 +14522,18 @@
 					// Asynchronous parsing via server
 					this.parseFileData(data, mxUtils.bind(this, function(xhr)
 					{
-						if (xhr.readyState == 4 && xhr.status >= 200 && xhr.status <= 299 &&
-							xhr.responseText.substring(0, 13) == '<mxGraphModel')
+						if (xhr.readyState == 4)
 						{
-							doLoad(xhr.responseText, evt);
+							if (xhr.status >= 200 && xhr.status <= 299 &&
+								xhr.responseText.substring(0, 13) == '<mxGraphModel')
+							{
+								doLoad(xhr.responseText, evt);
+							}
+							else
+							{
+								this.handleError({message: xhr.status == 413? mxResources.get('diagramTooLarge') : 
+										mxResources.get('unknownError')});
+							}
 						}
 					}), '');
 				}

+ 18 - 17
src/main/webapp/js/diagramly/Menus.js

@@ -1268,8 +1268,10 @@
 			{
 				var menubar = menusCreateMenuBar.apply(this, arguments);
 				
-				if (menubar != null && urlParams['embed'] != '1' &&
-					uiTheme != 'atlas' && urlParams['live-ui'] == '1')
+				if (menubar != null && Editor.enableSimpleTheme &&
+					editorUi.getServiceName() != 'atlassian' &&
+					urlParams['embed'] != '1' &&
+					uiTheme != 'atlas')
 				{
 					var themeMenu = this.get('appearance');
 					
@@ -1282,7 +1284,6 @@
 						elt.style.backgroundRepeat = 'no-repeat';
 						elt.style.backgroundSize = '100% 100%';
 						elt.style.display = 'inline-block';
-						elt.style.verticalAlign = 'top';
 						elt.style.marginLeft = '2px';
 						elt.style.cursor = 'pointer';
 						elt.style.zIndex = '1';
@@ -2923,7 +2924,7 @@
 				this.addMenuItems(menu, ['toggleDarkMode'], parent);
 			}
 
-			this.addMenuItems(menu, ['toggleSimpleMode', 'toggleSketchMode'], parent);
+			this.addMenuItems(menu, ['toggleSimpleMode'], parent);
 		})));
 
 		this.put('theme', new Menu(mxUtils.bind(this, function(menu, parent)
@@ -3316,8 +3317,8 @@
 			{
     			graph.startEditingAtCell(insertVertex('Text', 40, 20, 'text;html=1;resizable=0;autosize=1;' +
     				'align=center;verticalAlign=middle;points=[];fillColor=none;strokeColor=none;rounded=0;',
-					(evt != null && !mxEvent.isControlDown(evt) && !mxEvent.isMetaDown(evt)) ?
-						graph.getInsertPoint() : null));
+					(evt != null && !mxEvent.isControlDown(evt) && !mxEvent.isMetaDown(evt) &&
+					graph.isMouseInsertPoint()) ? graph.getInsertPoint() : null));
 			}
 		}, null, null, Editor.ctrlKey + '+Shift+X/A')).isEnabled = isGraphEnabled;
 		
@@ -3326,8 +3327,8 @@
 			if (graph.isEnabled() && !graph.isCellLocked(graph.getDefaultParent()))
 			{
     	    	insertVertex('', 120, 60, 'whiteSpace=wrap;html=1;', (evt != null &&
-					!mxEvent.isControlDown(evt) && !mxEvent.isMetaDown(evt)) ?
-						graph.getInsertPoint() : null);
+					!mxEvent.isControlDown(evt) && !mxEvent.isMetaDown(evt) &&
+					graph.isMouseInsertPoint()) ? graph.getInsertPoint() : null);
 			}
 		}, null, null, 'D')).isEnabled = isGraphEnabled;
 		
@@ -3338,8 +3339,8 @@
     	    	insertVertex('', 140, 160, 'shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;' +
 					'fontColor=#000000;darkOpacity=0.05;fillColor=#FFF9B2;strokeColor=none;fillStyle=solid;' +
 					'direction=west;gradientDirection=north;gradientColor=#FFF2A1;shadow=1;size=20;pointerEvents=1;',
-					(evt != null && !mxEvent.isControlDown(evt) && !mxEvent.isMetaDown(evt)) ?
-						graph.getInsertPoint() : null);
+					(evt != null && !mxEvent.isControlDown(evt) && !mxEvent.isMetaDown(evt) &&
+					graph.isMouseInsertPoint()) ? graph.getInsertPoint() : null);
 			}
 		}, null, null, 'S')).isEnabled = isGraphEnabled;
 
@@ -3348,8 +3349,8 @@
 			if (graph.isEnabled() && !graph.isCellLocked(graph.getDefaultParent()))
 			{
     	    	insertVertex('', 80, 80, 'ellipse;whiteSpace=wrap;html=1;', (evt != null &&
-					!mxEvent.isControlDown(evt) && !mxEvent.isMetaDown(evt)) ?
-						graph.getInsertPoint() : null);
+					!mxEvent.isControlDown(evt) && !mxEvent.isMetaDown(evt) &&
+					graph.isMouseInsertPoint()) ? graph.getInsertPoint() : null);
 			}
 		}, null, null, 'F')).isEnabled = isGraphEnabled;
 		
@@ -3358,8 +3359,8 @@
 			if (graph.isEnabled() && !graph.isCellLocked(graph.getDefaultParent()))
 			{
     	    	insertVertex('', 80, 80, 'rhombus;whiteSpace=wrap;html=1;', (evt != null &&
-					!mxEvent.isControlDown(evt) && !mxEvent.isMetaDown(evt)) ?
-						graph.getInsertPoint() : null);
+					!mxEvent.isControlDown(evt) && !mxEvent.isMetaDown(evt) &&
+					graph.isMouseInsertPoint()) ? graph.getInsertPoint() : null);
 			}
 		})).isEnabled = isGraphEnabled;
 
@@ -3368,8 +3369,8 @@
 			if (graph.isEnabled() && !graph.isCellLocked(graph.getDefaultParent()))
 			{
     	    	insertEdge('', graph.defaultEdgeLength, 'edgeStyle=none;orthogonalLoop=1;jettySize=auto;html=1;',
-					(evt != null && !mxEvent.isControlDown(evt) && !mxEvent.isMetaDown(evt)) ?
-						graph.getInsertPoint() : null);
+					(evt != null && !mxEvent.isControlDown(evt) && !mxEvent.isMetaDown(evt) &&
+					graph.isMouseInsertPoint()) ? graph.getInsertPoint() : null);
 			}
 		}, null, null, 'C')).isEnabled = isGraphEnabled;
 
@@ -3474,7 +3475,7 @@
 				editorUi.showImportCsvDialog();
 			}, parent, null, isGraphEnabled());
 			
-			if (uiTheme == 'min')
+			if (Editor.currentTheme == 'simple' || Editor.currentTheme == 'min')
 			{
 				this.addMenuItems(menu, ['-', 'createShape',
 					'editDiagram'], parent);

+ 1 - 1
src/main/webapp/js/diagramly/Settings.js

@@ -264,7 +264,7 @@ var mxSettings =
 			recentColors: [],
 			formatWidth: mxSettings.defaultFormatWidth,
 			createTarget: urlParams['sketch'] == '1' ||
-				urlParams['live-ui'] == '1',
+				Editor.enableSimpleTheme,
 			pageFormat: mxGraph.prototype.pageFormat,
 			search: true,
 			showStartScreen: true,

+ 10 - 10
src/main/webapp/js/diagramly/sidebar/Sidebar-C4.js

@@ -14,7 +14,7 @@
 			this.addEntry(dt + 'person', function()
 		   	{
 			    var bg = new mxCell('', 
-			    		new mxGeometry(0, 0, w * 2, h * 1.8), 'html=1;fontSize=11;dashed=0;whitespace=wrap;fillColor=#083F75;strokeColor=#06315C;fontColor=#ffffff;shape=mxgraph.c4.person2;align=center;metaEdit=1;points=[[0.5,0,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0]];resizable=0;');
+			    		new mxGeometry(0, 0, w * 2, h * 1.8), 'html=1;fontSize=11;dashed=0;whiteSpace=wrap;fillColor=#083F75;strokeColor=#06315C;fontColor=#ffffff;shape=mxgraph.c4.person2;align=center;metaEdit=1;points=[[0.5,0,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0]];resizable=0;');
 		    	bg.vertex = true;
 		    	bg.setValue(mxUtils.createXmlDocument().createElement('object'));
 		    	bg.setAttribute('placeholders', '1');
@@ -28,7 +28,7 @@
 			this.addEntry(dt + 'external person', function()
 		   	{
 			    var bg = new mxCell('', 
-			    		new mxGeometry(0, 0, w * 2, h * 1.8), 'html=1;fontSize=11;dashed=0;whitespace=wrap;fillColor=#6C6477;strokeColor=#4D4D4D;fontColor=#ffffff;shape=mxgraph.c4.person2;align=center;metaEdit=1;points=[[0.5,0,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0]];resizable=0;');
+			    		new mxGeometry(0, 0, w * 2, h * 1.8), 'html=1;fontSize=11;dashed=0;whiteSpace=wrap;fillColor=#6C6477;strokeColor=#4D4D4D;fontColor=#ffffff;shape=mxgraph.c4.person2;align=center;metaEdit=1;points=[[0.5,0,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0]];resizable=0;');
 		    	bg.vertex = true;
 		    	bg.setValue(mxUtils.createXmlDocument().createElement('object'));
 		    	bg.setAttribute('placeholders', '1');
@@ -90,10 +90,10 @@
 		    	bg.setValue(mxUtils.createXmlDocument().createElement('object'));
 		    	bg.setAttribute('placeholders', '1');
 		        bg.setAttribute('c4Type', 'Container name');
-		        bg.setAttribute('c4Container', 'Container ');
+		        bg.setAttribute('c4Container', 'Container');
 		        bg.setAttribute('c4Technology', 'e.g. Oracle Database 12');
 		        bg.setAttribute('c4Description', 'Description of storage type container role/responsibility.');
-		    	bg.setAttribute('label', '<font style="font-size: 16px"><b>%c4Type%</font><div>[%c4Container%:&nbsp;%c4Technology%]</div><br><div><font style="font-size: 11px"><font color="#E6E6E6">%c4Description%</font></div>');
+		    	bg.setAttribute('label', '<font style="font-size: 16px"><b>%c4Type%</b></font><div>[%c4Container%:&nbsp;%c4Technology%]</div><br><div><font style="font-size: 11px"><font color="#E6E6E6">%c4Description%</font></div>');
 			    
 			   	return sb.createVertexTemplateFromCells([bg], bg.geometry.width, bg.geometry.height, 'Data Container');
 			}),				
@@ -105,10 +105,10 @@
 		    	bg.setValue(mxUtils.createXmlDocument().createElement('object'));
 		    	bg.setAttribute('placeholders', '1');
 		        bg.setAttribute('c4Type', 'Container name');
-		        bg.setAttribute('c4Container', 'Container ');
+		        bg.setAttribute('c4Container', 'Container');
 		        bg.setAttribute('c4Technology', 'e.g. Micronaut, etc.');
 		        bg.setAttribute('c4Description', 'Description of microservice type container role/responsibility.');
-		    	bg.setAttribute('label', '<font style="font-size: 16px"><b>%c4Type%</font><div>[%c4Container%:&nbsp;%c4Technology%]</div><br><div><font style="font-size: 11px"><font color="#E6E6E6">%c4Description%</font></div>');
+		    	bg.setAttribute('label', '<font style="font-size: 16px"><b>%c4Type%</b></font><div>[%c4Container%:&nbsp;%c4Technology%]</div><br><div><font style="font-size: 11px"><font color="#E6E6E6">%c4Description%</font></div>');
 			    
 			   	return sb.createVertexTemplateFromCells([bg], bg.geometry.width, bg.geometry.height, 'Microservice Container');
 			}),				
@@ -120,10 +120,10 @@
 		    	bg.setValue(mxUtils.createXmlDocument().createElement('object'));
 		    	bg.setAttribute('placeholders', '1');
 		        bg.setAttribute('c4Type', 'Container name');
-		        bg.setAttribute('c4Container', 'Container ');
+		        bg.setAttribute('c4Container', 'Container');
 		        bg.setAttribute('c4Technology', 'e.g. Apache Kafka, etc.');
 		        bg.setAttribute('c4Description', 'Description of message bus type container role/responsibility.');
-		    	bg.setAttribute('label', '<font style="font-size: 16px"><b>%c4Type%</font><div>[%c4Container%:&nbsp;%c4Technology%]</div><br><div><font style="font-size: 11px"><font color="#E6E6E6">%c4Description%</font></div>');
+		    	bg.setAttribute('label', '<font style="font-size: 16px"><b>%c4Type%</b></font><div>[%c4Container%:&nbsp;%c4Technology%]</div><br><div><font style="font-size: 11px"><font color="#E6E6E6">%c4Description%</font></div>');
 			    
 			   	return sb.createVertexTemplateFromCells([bg], bg.geometry.width, bg.geometry.height, 'Message Bus Container');
 			}),				
@@ -135,10 +135,10 @@
 		    	bg.setValue(mxUtils.createXmlDocument().createElement('object'));
 		    	bg.setAttribute('placeholders', '1');
 		        bg.setAttribute('c4Type', 'Container name');
-		        bg.setAttribute('c4Container', 'Container ');
+		        bg.setAttribute('c4Container', 'Container');
 		        bg.setAttribute('c4Technology', 'e.g. JavaScript, Angular etc.');
 		        bg.setAttribute('c4Description', 'Description of web browser container role/responsibility.');
-		    	bg.setAttribute('label', '<font style="font-size: 16px"><b>%c4Type%</font><div>[%c4Container%:&nbsp;%c4Technology%]</div><br><div><font style="font-size: 11px"><font color="#E6E6E6">%c4Description%</font></div>');
+		    	bg.setAttribute('label', '<font style="font-size: 16px"><b>%c4Type%</b></font><div>[%c4Container%:&nbsp;%c4Technology%]</div><br><div><font style="font-size: 11px"><font color="#E6E6E6">%c4Description%</font></div>');
 			    
 			   	return sb.createVertexTemplateFromCells([bg], bg.geometry.width, bg.geometry.height, 'Web Browser Container');
 			}),				

+ 2 - 6
src/main/webapp/js/diagramly/sidebar/Sidebar-Rack.js

@@ -55,12 +55,8 @@
 		
 		this.addPaletteFunctions('rackGeneral', 'Rack / General', false,
 		[
-			this.createVertexTemplateEntry(s + 'shape=mxgraph.rackGeneral.container;fillColor2=#f4f4f4;container=1;collapsible=0;childLayout=rack;allowGaps=1;marginLeft=9;marginRight=9;marginTop=21;marginBottom=22;textColor=#666666;numDisp=off;', 180, 228.6, '', 'Rack Cabinet', null, null, dt + 'cabinet'),
-			this.createVertexTemplateEntry(s + 'shape=mxgraph.rackGeneral.container;fillColor2=#f4f4f4;container=1;collapsible=0;childLayout=rack;allowGaps=1;marginLeft=33;marginRight=9;marginTop=21;marginBottom=22;textColor=#666666;numDisp=ascend;', 210, 228.6, '', 'Numbered Rack Cabinet', null, null, dt + 'cabinet numbered'),
-			this.createVertexTemplateEntry(s + 'shape=mxgraph.rackGeneral.container;container=1;collapsible=0;childLayout=rack;allowGaps=1;marginLeft=9;marginRight=9;marginTop=21;marginBottom=22;textColor=#666666;numDisp=off;', 180, 228.6, '', 'Rack Cabinet', null, null, dt + 'cabinet'),
-			this.createVertexTemplateEntry(s + 'shape=mxgraph.rackGeneral.container;container=1;collapsible=0;childLayout=rack;allowGaps=1;marginLeft=33;marginRight=9;marginTop=21;marginBottom=22;textColor=#666666;numDisp=ascend;', 210, 228.6, '', 'Numbered Rack Cabinet', null, null, dt + 'cabinet numbered'),
-//			this.createVertexTemplateEntry(s + 'shape=mxgraph.rackGeneral.rackCabinet;fillColor2=#f4f4f4;container=1;collapsible=0;childLayout=rack;allowGaps=1;marginLeft=9;marginRight=9;marginTop=21;marginBottom=22;textColor=#666666;numDisp=off;', 180, 219, '', 'Rack Cabinet', null, null, dt + 'cabinet'),
-//			this.createVertexTemplateEntry(s + 'shape=mxgraph.rackGeneral.rackCabinet;fillColor2=#f4f4f4;container=1;collapsible=0;childLayout=rack;allowGaps=1;marginLeft=33;marginRight=9;marginTop=21;marginBottom=22;textColor=#666666;numDisp=ascend;', 204, 219, '', 'Numbered Rack Cabinet', null, null, dt + 'cabinet numbered'),
+			this.createVertexTemplateEntry(s + 'shape=mxgraph.rackGeneral.rackCabinet2;fillColor2=#f4f4f4;container=1;collapsible=0;childLayout=rack;allowGaps=1;marginLeft=9;marginRight=9;marginTop=21;marginBottom=22;textColor=#666666;numDisp=off;', 180, 219, '', 'Rack Cabinet', null, null, dt + 'cabinet'),
+			this.createVertexTemplateEntry(s + 'shape=mxgraph.rackGeneral.rackCabinet2;fillColor2=#f4f4f4;container=1;collapsible=0;childLayout=rack;allowGaps=1;marginLeft=33;marginRight=9;marginTop=21;marginBottom=22;textColor=#666666;numDisp=ascend;', 204, 219, '', 'Numbered Rack Cabinet', null, null, dt + 'cabinet numbered'),
 			this.createVertexTemplateEntry(sr + 'text;', 160, 15, '', 'Spacing', null, null, dt + 'spacing'),
 			this.createVertexTemplateEntry(sr + 'shape=mxgraph.rackGeneral.plate;fillColor=#e8e8e8;', 160, 15, '', 'Cover Plate', null, null, dt + 'cover plate'),
 			this.createVertexTemplateEntry(sr + 'shape=mxgraph.rack.general.1u_rack_server;', 160, 15, '', 'Server', null, null, dt + 'server'),

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 66 - 3
src/main/webapp/js/diagramly/sidebar/Sidebar-Sysml.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 3 - 1
src/main/webapp/js/grapheditor/Editor.js


+ 82 - 1
src/main/webapp/js/grapheditor/EditorUi.js

@@ -4590,6 +4590,49 @@ EditorUi.prototype.createStatusContainer = function()
 	var container = document.createElement('a');
 	container.className = 'geItem geStatus';
 
+	// Handles data-action attribute
+	mxEvent.addListener(container, 'click', mxUtils.bind(this, function(evt)
+	{
+		var elt = mxEvent.getSource(evt);
+		var name = elt.getAttribute('data-action');
+
+		// Make generic
+		if (name == 'statusFunction' && this.editor.statusFunction != null)
+		{
+			this.editor.statusFunction();
+		}
+		else if (name != null)
+		{
+			var action = this.actions.get(name);
+
+			if (action != null)
+			{
+				action.funct();
+			}
+		}
+		else
+		{
+			var title = elt.getAttribute('data-title');
+			var msg = elt.getAttribute('data-message');
+
+			if (title != null && msg != null)
+			{
+				this.showError(title, msg);
+			}
+			else
+			{
+				var link = elt.getAttribute('data-link');
+
+				if (link != null)
+				{
+					this.editor.graph.openLink(link);
+				}
+			}
+		}
+
+		mxEvent.consume(evt);
+	}));
+
 	return container;
 };
 
@@ -4601,12 +4644,50 @@ EditorUi.prototype.setStatusText = function(value)
 	this.statusContainer.innerHTML = value;
 
 	// Wraps simple status messages in a div for styling
-	if (this.statusContainer.getElementsByTagName('div').length == 0)
+	if (this.statusContainer.getElementsByTagName('div').length == 0 &&
+		value != null && value.length > 0)
 	{
 		this.statusContainer.innerText = '';
 		var div = this.createStatusDiv(value);
 		this.statusContainer.appendChild(div);
 	}
+
+	// Handles data-effect attribute
+	var spans = this.statusContainer.querySelectorAll('[data-effect="fade"]');
+
+	if (spans != null)
+	{
+		for (var i = 0; i < spans.length; i++)
+		{
+			(function(temp)
+			{
+				mxUtils.setOpacity(temp, 0);
+				mxUtils.setPrefixedStyle(temp.style, 'transform', 'scaleX(0)');
+				mxUtils.setPrefixedStyle(temp.style, 'transition', 'all 0.2s ease');
+				
+				window.setTimeout(mxUtils.bind(this, function()
+				{
+					mxUtils.setOpacity(temp, 100);
+					mxUtils.setPrefixedStyle(temp.style, 'transform', 'scaleX(1)');
+					mxUtils.setPrefixedStyle(temp.style, 'transition', 'all 1s ease');
+					
+					window.setTimeout(mxUtils.bind(this, function()
+					{
+						mxUtils.setPrefixedStyle(temp.style, 'transform', 'scaleX(0)');
+						mxUtils.setOpacity(temp, 0);
+		
+						window.setTimeout(mxUtils.bind(this, function()
+						{
+							if (temp.parentNode != null)
+							{
+								temp.parentNode.removeChild(temp);
+							}
+						}), 1000);
+					}), Editor.updateStatusInterval / 2);
+				}), 0);
+			})(spans[i]);
+		}
+	}		
 };
 
 /**

+ 137 - 11
src/main/webapp/js/grapheditor/Format.js

@@ -1271,6 +1271,53 @@ BaseFormatPanel.prototype.addUnitInput = function(container, unit, right, width,
 	return input;
 };
 
+/**
+ * 
+ */
+BaseFormatPanel.prototype.addGenericInput = function(container, unit, left, width, readFn, writeFn)
+{
+	var graph = this.editorUi.editor.graph;
+
+	var update = function()
+	{
+		writeFn(input.value);
+	};
+
+	var input = this.addUnitInput(container, unit, left, width, update);
+
+	var listener = mxUtils.bind(this, function(sender, evt, force)
+	{
+		if (force || input != document.activeElement)
+		{
+			input.value = readFn() + unit;
+		}
+	});
+	
+	mxEvent.addListener(input, 'keydown', function(e)
+	{
+		if (e.keyCode == 13)
+		{
+			graph.container.focus();
+			mxEvent.consume(e);
+		}
+		else if (e.keyCode == 27)
+		{
+			listener(null, null, true);
+			graph.container.focus();
+			mxEvent.consume(e);
+		}
+	});
+	
+	graph.getModel().addListener(mxEvent.CHANGE, listener);
+	this.listeners.push({destroy: function() { graph.getModel().removeListener(listener); }});
+	listener();
+
+	mxEvent.addListener(input, 'blur', update);
+	mxEvent.addListener(input, 'change', update);
+
+	return input;
+};
+
 /**
  * 
  */
@@ -1378,6 +1425,8 @@ BaseFormatPanel.prototype.addLabel = function(div, title, right, width)
 	label.style.marginTop = '6px';
 	label.style.textAlign = 'center';
 	div.appendChild(label);
+
+	return label;
 };
 
 /**
@@ -2286,7 +2335,7 @@ ArrangePanel.prototype.addGeometry = function(container)
 	span.style.fontWeight = 'bold';
 	mxUtils.write(span, mxResources.get('position'));
 	div2.appendChild(span);
-	
+
 	var left = this.addUnitInput(div2, this.getUnit(), 87, 52, function()
 	{
 		leftUpdate.apply(this, arguments);
@@ -2298,8 +2347,77 @@ ArrangePanel.prototype.addGeometry = function(container)
 
 	mxUtils.br(div2);
 
-	this.addLabel(div2, mxResources.get('left'), 87);
-	this.addLabel(div2, mxResources.get('top'), 16);
+	if (rect.movable)
+	{
+		if (rect.edges.length == 0 && rect.vertices.length == 1)
+		{
+			var geo = graph.getCellGeometry(rect.vertices[0]);
+
+			if (geo != null && geo.relative)
+			{
+				mxUtils.br(div2);
+
+				var span = document.createElement('div');
+				span.style.position = 'absolute';
+				span.style.width = '70px';
+				span.style.marginTop = '0px';
+				mxUtils.write(span, mxResources.get('relative'));
+				div2.appendChild(span);
+
+				this.addGenericInput(div2, '%', 87, 52, function()
+				{
+					return (Math.round(geo.x * 1000) / 10);
+				}, function(value)
+				{
+					value = parseFloat(value);
+					
+					if (!isNaN(value))
+					{
+						model.beginUpdate();
+						try
+						{
+							geo = geo.clone();
+							geo.x = parseFloat(value) / 100;
+							model.setGeometry(rect.vertices[0], geo);
+						}
+						finally
+						{
+							model.endUpdate();
+						}
+					}
+				});
+
+				this.addGenericInput(div2, '%', 16, 52, function()
+				{
+					return (Math.round(geo.y * 1000) / 10);
+				}, function(value)
+				{
+					value = parseFloat(value);
+					
+					if (!isNaN(value))
+					{
+						model.beginUpdate();
+						try
+						{
+							geo = geo.clone();
+							geo.y = parseFloat(value) / 100;
+							model.setGeometry(rect.vertices[0], geo);
+						}
+						finally
+						{
+							model.endUpdate();
+						}
+					}
+				});
+
+				mxUtils.br(div2);
+			}
+		}
+		container.appendChild(div2);
+	}
+
+	this.addLabel(div2, mxResources.get('left'), 87).style.marginTop = '8px';
+	this.addLabel(div2, mxResources.get('top'), 16).style.marginTop = '8px';
 	
 	var listener = mxUtils.bind(this, function(sender, evt, force)
 	{
@@ -2407,7 +2525,8 @@ ArrangePanel.prototype.addGeometry = function(container)
 				}));
 				
 				btn.setAttribute('title', mxResources.get('center'));
-				btn.style.width = '210px';
+				btn.style.width = '134px';
+				btn.style.left = '89px';
 				btn.style.position = 'absolute';
 				mxUtils.br(div2);
 				mxUtils.br(div2);
@@ -4431,7 +4550,8 @@ StyleFormatPanel.prototype.addEditOps = function(div)
 			this.editorUi.actions.get('editStyle').funct();
 		}));
 		
-		btn.setAttribute('title', mxResources.get('editStyle') + ' (' + this.editorUi.actions.get('editStyle').shortcut + ')');
+		btn.setAttribute('title', mxResources.get('editStyle') + ' (' +
+			this.editorUi.actions.get('editStyle').shortcut + ')');
 		btn.style.width = '210px';
 		btn.style.marginBottom = '2px';
 		
@@ -4514,7 +4634,8 @@ StyleFormatPanel.prototype.addFill = function(container)
 	}, function(color)
 	{
 		graph.updateCellStyles({'gradientColor': color}, graph.getSelectionCells());
-	}, graph.getDefaultColor(ss.style, mxConstants.STYLE_GRADIENTCOLOR, graph.shapeForegroundColor, graph.shapeBackgroundColor));
+	}, graph.getDefaultColor(ss.style, mxConstants.STYLE_GRADIENTCOLOR,
+		graph.shapeForegroundColor, graph.shapeBackgroundColor));
 
 	var fillKey = (ss.style.shape == 'image') ? mxConstants.STYLE_IMAGE_BACKGROUND : mxConstants.STYLE_FILLCOLOR;
 
@@ -4522,7 +4643,8 @@ StyleFormatPanel.prototype.addFill = function(container)
 		fillKey, 'default', null, mxUtils.bind(this, function(color)
 	{
 		graph.setCellStyles(fillKey, color, ss.cells);
-	}), graph.getDefaultColor(ss.style, fillKey, graph.shapeBackgroundColor, graph.shapeForegroundColor));
+	}), graph.getDefaultColor(ss.style, fillKey, graph.shapeBackgroundColor,
+		graph.shapeForegroundColor));
 
 	fillPanel.style.fontWeight = 'bold';
 	var tmpColor = mxUtils.getValue(ss.style, fillKey, null);
@@ -4581,7 +4703,8 @@ StyleFormatPanel.prototype.addFill = function(container)
 	var listener = mxUtils.bind(this, function()
 	{
 		ss = ui.getSelectionState();
-		var value = mxUtils.getValue(ss.style, mxConstants.STYLE_GRADIENT_DIRECTION, mxConstants.DIRECTION_SOUTH);
+		var value = mxUtils.getValue(ss.style, mxConstants.STYLE_GRADIENT_DIRECTION,
+			mxConstants.DIRECTION_SOUTH);
 		var fillStyle = mxUtils.getValue(ss.style, 'fillStyle', 'auto');
 		
 		// Handles empty string which is not allowed as a value
@@ -4595,7 +4718,8 @@ StyleFormatPanel.prototype.addFill = function(container)
 		
 		var fillColor = mxUtils.getValue(ss.style, fillKey, null);
 		
-		if (!ss.fill || fillColor == null || fillColor == mxConstants.NONE || ss.style.shape == 'filledEdge')
+		if (!ss.fill || fillColor == null || fillColor == mxConstants.NONE ||
+			ss.style.shape == 'filledEdge')
 		{
 			fillStyleSelect.style.display = 'none';
 			gradientPanel.style.display = 'none';
@@ -4623,7 +4747,8 @@ StyleFormatPanel.prototype.addFill = function(container)
 				fillStyleSelect.value = fillStyle;
 			}
 
-			fillStyleSelect.style.display = ss.style.sketch == '1' || gradientSelect.style.display == 'none'? '' : 'none';
+			fillStyleSelect.style.display = ss.style.sketch == '1' ||
+				gradientSelect.style.display == 'none'? '' : 'none';
 			gradientPanel.style.display = (!ss.containsImage && (ss.style.sketch != '1' ||
 				fillStyle == 'solid' || fillStyle == 'auto')) ? '' : 'none';
 		}
@@ -4657,7 +4782,8 @@ StyleFormatPanel.prototype.addFill = function(container)
 	
 	for (var i = 0; i < custom.length; i++)
 	{
-		container.appendChild(this.createCellColorOption(custom[i].title, custom[i].key, custom[i].defaultValue));
+		container.appendChild(this.createCellColorOption(custom[i].title,
+			custom[i].key, custom[i].defaultValue));
 	}
 	
 	return container;

+ 2 - 2
src/main/webapp/js/grapheditor/Menus.js

@@ -1797,8 +1797,8 @@ Menubar.prototype.addMenuHandler = function(elt, funct)
         mxEvent.addListener(elt, (mxClient.IS_POINTER) ? 'pointerdown' : 'mousedown',
         	mxUtils.bind(this, function(evt)
 		{
-			if (!this.editorUi.menusautoPopup && this.editorUi.currentMenu != null &&
-				this.editorUi.currentMenuElt != elt)
+			if (!this.editorUi.menus.autoPopup && this.editorUi.currentMenu != null &&
+				this.editorUi.currentMenuElt != elt && mxEvent.isMouseEvent(evt))
 			{
 				this.editorUi.hideCurrentMenu();
 			}

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 2758 - 2732
src/main/webapp/js/integrate.min.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 19 - 6
src/main/webapp/js/shapes-14-6-5.min.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1408 - 1388
src/main/webapp/js/viewer-static.min.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1389 - 1382
src/main/webapp/js/viewer.min.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 3 - 3
src/main/webapp/mxgraph/mxClient.js


+ 2 - 0
src/main/webapp/resources/dia.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_am.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_ar.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_bg.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_bn.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_bs.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_ca.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=Si aquesta instància inclou més de 100.000 pàgines, é
 choosePageIDsFile=Trieu el fitxer csv d'identificadors de pàgina actuals
 chooseDrawioPsgesFile=Trieu pàgines amb el fitxer csv de diagrames draw.io
 private=Privat
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_cs.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_da.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_de.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_el.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_eo.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_es.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_et.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_eu.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=Instantzia honek 100.000 orrialde baino gehiago baditu, a
 choosePageIDsFile=Aukeratu uneko orriaren IDak csv fitxategia
 chooseDrawioPsgesFile=Aukeratu draw.io diagramak csv fitxategia duten orrialdeak
 private=Pribatua
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_fa.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_fi.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=Jos tämä ilmentymä sisältää yli 100 000 sivua, on n
 choosePageIDsFile=Valitse nykyisten sivutunnusten csv-tiedosto
 chooseDrawioPsgesFile=Valitse sivut draw.io-kaavioiden csv-tiedostolla
 private=Yksityinen
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_fil.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 13 - 11
src/main/webapp/resources/dia_fr.txt

@@ -344,7 +344,7 @@ formatVssx=VSSX
 formatXmlPlain=XML (Texte normal)
 formatXml=XML
 forum=Forum d'aide
-freehand=Freehand
+freehand=Main levée
 fromTemplate=Depuis un modèle
 fromTemplateUrl=A partir d'une URL de modèle
 fromText=A partir d'un texte
@@ -429,7 +429,7 @@ ios=iOS
 italic=Italique
 kennedy=Kennedy
 keyboardShortcuts=Raccourcis clavier
-labels=Labels
+labels=Étiquettes
 layers=Couches
 landscape=Paysage
 language=Langue
@@ -702,8 +702,8 @@ simple=Simple
 simpleArrow=Flèche simple
 simpleViewer=Affichage simple
 size=Taille
-sketch=Sketch
-snapToGrid=Snap to Grid
+sketch=Croquis
+snapToGrid=Accrocher à la grille
 solid=Uni
 sourceSpacing=Espacement de la source
 south=Sud
@@ -839,8 +839,8 @@ folderEmpty=Dossier vide
 recent=Récent
 sharedWithMe=Partagé avec moi
 sharepointSites=Sharepoint Sites
-errorFetchingFolder=Error fetching folder items
-errorAuthOD=Error authenticating to OneDrive
+errorFetchingFolder=Erreur de récupération des éléments du dossier
+errorAuthOD=Erreur d'authentification à OneDrive
 officeMainHeader=Adds draw.io diagrams to your document.
 officeStepsHeader=This add-in performs the following steps:
 officeStep1=Connects to Microsoft OneDrive, Google Drive or your device.
@@ -859,7 +859,7 @@ selectChildren=Sélectionner les enfants
 selectSiblings=Sélectionner les co-latéraux
 selectParent=Sélectionner le parent
 selectDescendants=Sélectionner les descendants
-lastSaved=Last saved {1} ago
+lastSaved=Dernière sauvegarde il y a {1}
 resolve=Résoudre
 reopen=Ré-ouvrir
 showResolved=Show Resolved
@@ -876,7 +876,7 @@ confAnchor=Confluence Page Anchor
 confTimeout=The connection has timed out
 confSrvTakeTooLong=The server at {1} is taking too long to respond.
 confCannotInsertNew=Cannot insert draw.io diagram to a new Confluence page
-confSaveTry=Please save the page and try again.
+confSaveTry=Veuillez sauvegarder la page et réessayer.
 confCannotGetID=Unable to determine page ID
 confContactAdmin=Please contact your Confluence administrator.
 readErr=Lire l'erreur
@@ -1062,7 +1062,7 @@ invalidSel=Invalid selection
 diagNameEmptyErr=Diagram name cannot be empty
 openDiagram=Open Diagram
 newDiagram=New diagram
-editable=Editable
+editable=Modifiable
 confAReimportStarted=Re-import {1} diagrams started...
 spaceFilter=Filter by spaces
 curViewState=Current Viewer State
@@ -1169,8 +1169,8 @@ diagramEdited={1} diagram "{2}" edited
 confDraftPermissionErr=Draft cannot be written. Do you have attachment write/read permission on this page?
 confDraftTooBigErr=Draft size is too large. Pease check "Attachment Maximum Size" of "Attachment Settings" in Confluence Configuration?
 owner=Propriétaire
-repository=Repository
-branch=Branch
+repository=Dépôt
+branch=Branche
 meters=Mètres
 teamsNoEditingMsg=Editor functionality is only available in Desktop environment (in MS Teams App or a web browser)
 contactOwner=Contacter le propriétaire
@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Privé
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_gl.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_gu.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_he.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_hi.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_hr.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_hu.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_i18n.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=confAHugeInstancesDesc
 choosePageIDsFile=choosePageIDsFile
 chooseDrawioPsgesFile=chooseDrawioPsgesFile
 private=private
+diagramTooLarge=diagramTooLarge
+selectAdminUsers=selectAdminUsers

+ 2 - 0
src/main/webapp/resources/dia_id.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_it.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_ja.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_kn.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_ko.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_lt.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_lv.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_ml.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_mr.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_ms.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_my.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_nl.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=Als dit exemplaar meer dan 100.000 pagina's bevat, is het
 choosePageIDsFile=Kies het huidige pagina-ID's csv-bestand
 chooseDrawioPsgesFile=Kies pagina's met draw.io diagrammen csv-bestand
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_no.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_pl.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_pt-br.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_pt.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_ro.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_ru.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_si.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_sk.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_sl.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_sr.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_sv.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_sw.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_ta.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_te.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_th.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_tr.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_uk.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_vi.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_zh-tw.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

+ 2 - 0
src/main/webapp/resources/dia_zh.txt

@@ -1209,3 +1209,5 @@ confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to
 choosePageIDsFile=Choose current page IDs csv file
 chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
 private=Private
+diagramTooLarge=The diagram is too large, please reduce its size and try again.
+selectAdminUsers=Select Admin Users

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
src/main/webapp/service-worker.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
src/main/webapp/service-worker.js.map


+ 125 - 0
src/main/webapp/shapes/mxSysML.js

@@ -3142,3 +3142,128 @@ mxShapeSysMLUseCaseExtensionPoints.prototype.getConstraints = function(style, w,
 	
 	return (constr);
 };
+
+//**********************************************************************************************************************************************************
+//Port
+//**********************************************************************************************************************************************************
+/**
+* Extends mxShape.
+*/
+function mxShapeSysMLPort(bounds, fill, stroke, strokewidth)
+{
+	mxShape.call(this);
+	this.bounds = bounds;
+	this.fill = fill;
+	this.stroke = stroke;
+	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
+};
+
+/**
+* Extends mxShape.
+*/
+mxUtils.extend(mxShapeSysMLPort, mxShape);
+
+mxShapeSysMLPort.prototype.cst = {
+		PORT : 'mxgraph.sysml.port'
+};
+
+mxShapeSysMLPort.prototype.customProperties = [
+	{name: 'sysMLPortType', dispName: 'Port Type', type: 'enum',
+		enumList:[
+			{val:'empty', dispName:'Empty'},
+			{val:'flowN', dispName:'Flow Up'},
+			{val:'flowE', dispName:'Flow Right'},
+			{val:'flowS', dispName:'Flow Down'},
+			{val:'flowW', dispName:'Flow Left'},
+			{val:'doubleH', dispName:'Double Horizontal'},
+			{val:'doubleV', dispName:'Double Vertical'}
+		]}
+];
+
+/**
+* Function: paintVertexShape
+* 
+* Paints the vertex shape.
+*/
+mxShapeSysMLPort.prototype.paintVertexShape = function(c, x, y, w, h)
+{
+	c.translate(x, y);
+	c.rect(0, 0, w, h);
+	c.fillAndStroke();
+	var portType = mxUtils.getValue(this.style, 'sysMLPortType', 'empty');
+	
+	switch (portType)
+	{
+		case 'flowN' :
+				c.begin();
+				c.moveTo(0.25 * w, 0.5 * h);
+				c.lineTo(0.5 * w, 0.25 * h);
+				c.lineTo(0.75 * w, 0.5 * h);
+				c.moveTo(0.5 * w, 0.25 * h);
+				c.lineTo(0.5 * w, 0.75 * h);
+				c.stroke();
+			break;
+		case 'flowE' :
+				c.begin();
+				c.moveTo(0.5 * w, 0.25 * h);
+				c.lineTo(0.75 * w, 0.5 * h);
+				c.lineTo(0.5 * w, 0.75 * h);
+				c.moveTo(0.75 * w, 0.5 * h);
+				c.lineTo(0.25 * w, 0.5 * h);
+				c.stroke();
+			break;
+		case 'flowS' :
+				c.begin();
+				c.moveTo(0.25 * w, 0.5 * h);
+				c.lineTo(0.5 * w, 0.75 * h);
+				c.lineTo(0.75 * w, 0.5 * h);
+				c.moveTo(0.5 * w, 0.75 * h);
+				c.lineTo(0.5 * w, 0.25 * h);
+				c.stroke();
+			break;
+		case 'flowW' :
+				c.begin();
+				c.moveTo(0.5 * w, 0.25 * h);
+				c.lineTo(0.25 * w, 0.5 * h);
+				c.lineTo(0.5 * w, 0.75 * h);
+				c.moveTo(0.25 * w, 0.5 * h);
+				c.lineTo(0.75 * w, 0.5 * h);
+				c.stroke();
+			break;
+		case 'doubleH' :
+				c.begin();
+				c.moveTo(0.6 * w, 0.25 * h);
+				c.lineTo(0.85 * w, 0.5 * h);
+				c.lineTo(0.6 * w, 0.75 * h);
+				c.moveTo(0.4 * w, 0.25 * h);
+				c.lineTo(0.15 * w, 0.5 * h);
+				c.lineTo(0.4 * w, 0.75 * h);
+				c.stroke();
+			break;
+		case 'doubleV' :
+				c.begin();
+				c.moveTo(0.25 * w, 0.6 * h);
+				c.lineTo(0.5 * w, 0.85 * h);
+				c.lineTo(0.75 * w, 0.6 * h);
+				c.moveTo(0.25 * w, 0.4 * h);
+				c.lineTo(0.5 * w, 0.15 * h);
+				c.lineTo(0.75 * w, 0.4 * h);
+				c.stroke();
+			break;
+	}
+};
+
+mxCellRenderer.registerShape(mxShapeSysMLPort.prototype.cst.PORT, mxShapeSysMLPort);
+
+mxShapeSysMLPort.prototype.getConstraints = function(style, w, h)
+{
+	var constr = [];
+
+	constr.push(new mxConnectionConstraint(new mxPoint(0.5, 0), false));
+	constr.push(new mxConnectionConstraint(new mxPoint(0.5, 1), false));
+	constr.push(new mxConnectionConstraint(new mxPoint(0, 0.5), false));
+	constr.push(new mxConnectionConstraint(new mxPoint(1, 0.5), false));
+
+	return (constr);
+};
+

+ 151 - 0
src/main/webapp/shapes/rack/mxRack.js

@@ -657,6 +657,156 @@ mxRackRackCabinet.prototype.sideText = function(c, h, unitNum, unitH, fontSize,
 	c.stroke();
 };
 
+//**********************************************************************************************************************************************************
+//Rack Cabinet
+//**********************************************************************************************************************************************************
+/**
+ * Extends mxShape.
+ */
+function mxRackRackCabinet2(bounds, fill, stroke, strokewidth)
+{
+	mxShape.call(this);
+	this.bounds = bounds;
+	this.fill = fill;
+	this.stroke = stroke;
+	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
+};
+
+/**
+ * Extends mxShape.
+ */
+mxUtils.extend(mxRackRackCabinet2, mxShape);
+
+mxRackRackCabinet2.prototype.cst = 
+{
+		SHAPE_RACK_RACK_CABINET : 'mxgraph.rackGeneral.rackCabinet2',
+		UNIT_NUM : 'unitNum',
+		UNIT_HEIGHT : 'rackUnitSize',
+		TEXT_COLOR : 'textColor',
+		NUM_DIR : 'numDir',
+		NUMBER_DISPLAY : 'numDisp',
+		ON : 'on',
+		OFF : 'off',
+		DIR_ASC : 'ascend',
+		DIR_DESC : 'descend',
+		TEXT_SIZE : 'textSize'
+};
+
+mxRackRackCabinet2.prototype.customProperties = [
+	{name: 'unitNum', dispName: 'Number of units', type: 'int', defVal: 12},
+	{name: 'startUnit', dispName: 'Starting unit', type: 'int', defVal: 1},
+	{name: 'rackUnitSize', dispName: 'Unit height', type: 'float', defVal: 14.8},
+	{name: 'fillColor2', dispName: 'Panel Color', type: 'color', defVal: '#ffffff'},
+	{name: 'textColor', dispName: 'Number text color', type: 'color', defVal: '#666666'},
+	{name: 'textSize', dispName: 'Text size', type: 'float', defVal: '12'},
+	{name: 'numDisp', dispName: 'Display Numbers', type: 'enum', defVal: 'descend',
+		enumList: [{val: 'off', dispName: 'Off'}, {val: 'ascend', dispName: 'Ascending'}, {val: 'descend', dispName: 'Descending'}],
+		onChange: function(graph, newValue)
+		{
+			graph.setCellStyles('marginLeft', (newValue == 'off') ? 9 : 33, graph.getSelectionCells());
+		}
+	}
+];
+
+
+/**
+ * Function: paintVertexShape
+ * 
+ * Paints the vertex shape.
+ */
+mxRackRackCabinet2.prototype.paintVertexShape = function(c, x, y, w, h)
+{
+	var unitNum = parseFloat(mxUtils.getValue(this.style, mxRackRackCabinet2.prototype.cst.UNIT_NUM, '12'));
+	var unitH = parseFloat(mxUtils.getValue(this.style, mxRackRackCabinet2.prototype.cst.UNIT_HEIGHT, '14.8'));
+	var fontSize = parseFloat(mxUtils.getValue(this.style, mxRackRackCabinet2.prototype.cst.TEXT_SIZE, '12'));
+	var numDisp = mxUtils.getValue(this.style, mxRackRackCabinet2.prototype.cst.NUMBER_DISPLAY, mxRackRackCabinet2.prototype.cst.ON);
+
+	if (numDisp !== mxRackRackCabinet2.prototype.cst.OFF)
+	{
+		c.translate(x + fontSize * 2, y);
+		w = w - fontSize * 2;
+	}
+	else
+	{
+		c.translate(x, y);
+	};
+
+	var h = unitNum * unitH + 42;
+	this.background(c, w, h);
+	c.setShadow(false);
+	this.foreground(c, w, h);
+
+	if (numDisp !== mxRackRackCabinet2.prototype.cst.OFF)
+	{
+		this.sideText(c, h, unitNum, unitH, fontSize, numDisp);
+	};
+};
+
+mxRackRackCabinet2.prototype.background = function(c, w, h)
+{
+	var fillC = mxUtils.getValue(this.style, 'fillColor2', '#ffffff');
+	c.setFillColor(fillC);
+	c.rect(0, 0, w, h);
+	c.fillAndStroke();
+};
+
+mxRackRackCabinet2.prototype.foreground = function(c, w, h)
+{
+	var fillC = mxUtils.getValue(this.style, mxConstants.STYLE_FILLCOLOR, '#f4f4f4');
+	c.setFillColor(fillC);
+	c.rect(0, 0, w, 21);
+	c.fillAndStroke();
+	c.rect(0, h - 21, w, 21);
+	c.fillAndStroke();
+	c.rect(0, 21, 9, h - 42);
+	c.fillAndStroke();
+	c.rect(w - 9, 21, 9, h - 42);
+	c.fillAndStroke();
+	c.ellipse(2.5, 7.5, 6, 6);
+	c.stroke();
+	c.ellipse(w - 8.5, 7.5, 6, 6);
+	c.stroke();
+	c.ellipse(2.5, h - 13.5, 6, 6);
+	c.stroke();
+	c.ellipse(w - 8.5, h - 13.5, 6, 6);
+	c.stroke();
+};
+
+mxRackRackCabinet2.prototype.sideText = function(c, h, unitNum, unitH, fontSize, numDisp)
+{
+	var fontColor = mxUtils.getValue(this.style, mxRackRackCabinet2.prototype.cst.TEXT_COLOR, '#666666');
+	var startUnit = mxUtils.getValue(this.style, 'startUnit', 1);
+	c.setFontSize(fontSize);
+	c.setFontColor(fontColor);
+
+	if (numDisp === mxRackRackCabinet2.prototype.cst.DIR_ASC)
+	{
+		for (var i = 0; i < unitNum; i++)
+		{
+			c.text(-fontSize, 21 + unitH * 0.5 + i * unitH, 0, 0, (i + startUnit).toString(), mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
+		};
+	}
+	else if (numDisp === mxRackRackCabinet2.prototype.cst.DIR_DESC || numDisp === mxRackRackCabinet2.prototype.cst.DIR_ON)
+	{
+		for (var i = 0; i < unitNum; i++)
+		{
+			c.text(-fontSize, h - 21 - unitH * 0.5 - i * unitH, 0, 0, (i + startUnit).toString(), mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
+		};
+	};
+
+	c.setStrokeColor(fontColor);
+
+	c.begin();
+
+	for (var i = 0; i < unitNum + 1; i++)
+	{
+		c.moveTo(-2 * fontSize, 21 + i * unitH);
+		c.lineTo(0, 21 + i * unitH);
+	};
+
+	c.stroke();
+};
+
 //**********************************************************************************************************************************************************
 //1U Horizontal Cable Duct
 //**********************************************************************************************************************************************************
@@ -1261,6 +1411,7 @@ mxRackCabinetLeg.prototype.background = function(c, w, h)
 
 // New generic unit size implementations
 mxCellRenderer.registerShape(mxRackContainer.prototype.cst.SHAPE_RACK_CONTAINER, mxRackContainer);
+mxCellRenderer.registerShape(mxRackRackCabinet2.prototype.cst.SHAPE_RACK_RACK_CABINET, mxRackRackCabinet2);
 mxCellRenderer.registerShape(mxRackHorCableDuct.prototype.cst.SHAPE_RACK_HOR_CABLE_DUCT, mxRackHorCableDuct);
 mxCellRenderer.registerShape(mxRackHorRoutingBank.prototype.cst.SHAPE_RACK_HOR_ROUTING_BANK, mxRackHorRoutingBank);
 mxCellRenderer.registerShape(mxRackNeatPatch.prototype.cst.SHAPE_RACK_NEAT_PATCH, mxRackNeatPatch);

+ 3 - 3
src/main/webapp/styles/dark.css

@@ -33,7 +33,7 @@ html body, html body .geFooterContainer, html body #geFooterItem1, html body tex
 	background:#2a2a2a;
 	color:#cccccc;
 }
-html body a {
+html body a :not(.geStatus *) {
 	color:#337ab7;
 }
 html body div.mxRubberband {
@@ -168,12 +168,12 @@ html .geEditor ::-webkit-scrollbar-thumb {
 html .geEditor ::-webkit-scrollbar-thumb:hover, .geHsplit:hover, .geVsplit:hover {
 	background-color:#a0a0a0;
 }
-html body .geStatusAlert {
+html body a.geStatus .geStatusAlert {
 	background-color:#a20025;
 	border:1px solid #bd002b;
 	color:#fff !important;
 }
-html body .geStatusAlert:hover {
+html body a.geStatus .geStatusAlert:hover {
 	background-color:#a20025;
 	border-color:#bd002b;
 }

+ 14 - 1
src/main/webapp/styles/grapheditor.css

@@ -94,8 +94,17 @@
 	font-size:12px;
 }
 a.geStatus {
+	white-space:nowrap;
+}
+a.geStatus:not(:empty) {
 	margin-right:8px;
 }
+.geStatus *[data-action] {
+	cursor:pointer;
+}
+.geStatus *[data-action]:not([class]) {
+	text-decoration:underline;
+}
 .geStatus img {
 	max-width:16px;
 	vertical-align:bottom;
@@ -1930,4 +1939,8 @@ table.geProperties tr td {
 
 .geMaximized #max-button {
   display: none;
-}
+}
+[draggable="true"] {
+    transform: translate(0, 0);
+    z-index: 0;
+}