Browse Source

10.5.1 release

Gaudenz Alder 6 years ago
parent
commit
fc006c044d

+ 4 - 0
ChangeLog

@@ -1,3 +1,7 @@
+19-MAR-2019: 10.5.1
+
+- Adds comments for Confluence cloud
+
 18-MAR-2019: 10.5.0
 
 - Uses .drawio extension in desktop app

+ 1 - 1
VERSION

@@ -1 +1 @@
-10.5.0
+10.5.1

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

@@ -1,7 +1,7 @@
 CACHE MANIFEST
 
 # THIS FILE WAS GENERATED. DO NOT MODIFY!
-# 03/18/2019 05:24 PM
+# 03/19/2019 06:36 PM
 
 app.html
 index.html?offline=1

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


+ 57 - 4
src/main/webapp/js/diagramly/App.js

@@ -127,13 +127,37 @@ App = function(editor, container, lightbox)
 					console.log('Plugin Error:', e, App.DrawPlugins[i]);
 				}
 			}
+			finally
+			{
+				App.embedModePluginsCount--;
+				this.initializeEmbedMode();
+			}
 		}
 		
 		// Installs global callback for plugins
 		window.Draw.loadPlugin = mxUtils.bind(this, function(callback)
 		{
-			callback(this);
+			try
+			{
+				callback(this);
+			}
+			finally
+			{
+				App.embedModePluginsCount--;
+				this.initializeEmbedMode();
+			}
 		});
+		
+		//Set a timeout in case a plugin doesn't load quickly or doesn't load at all
+		setTimeout(mxUtils.bind(this, function()
+		{
+			//Force finish loading if its not yet called
+			if (App.embedModePluginsCount > 0)
+			{
+				App.embedModePluginsCount = 0;
+				this.initializeEmbedMode();
+			}
+		}), 5000); //5 sec timeout
 	}
 
 	this.load();
@@ -548,6 +572,7 @@ App.main = function(callback, createUi)
 							if (App.pluginsLoaded[plugins[i]] == null)
 							{
 								App.pluginsLoaded[plugins[i]] = true;
+								App.embedModePluginsCount++;
 								mxscript(plugins[i]);
 							}
 						}
@@ -771,7 +796,7 @@ App.main = function(callback, createUi)
 			console.error(e);
 		}
 	}
-
+	
 	// Sends load event if configuration is requested and waits for configure action
 	if (urlParams['configure'] == '1')
 	{
@@ -887,6 +912,7 @@ App.initPluginCallback = function()
  * 
  */
 App.pluginsLoaded = {};
+App.embedModePluginsCount = 0;
 
 /**
  * Queue for loading plugins and wait for UI instance
@@ -906,6 +932,7 @@ App.loadPlugins = function(plugins, useInclude)
 					if (App.pluginsLoaded[url] == null)
 					{
 						App.pluginsLoaded[url] = true;
+						App.embedModePluginsCount++;
 						
 						if (typeof window.drawDevUrl === 'undefined')
 						{
@@ -947,6 +974,26 @@ App.loadPlugins = function(plugins, useInclude)
 	}
 };
 
+/**
+ * Delay embed mode initialization until all plugins are loaded
+ */
+App.prototype.initializeEmbedMode = function()
+{
+	if (urlParams['embed'] == '1')
+	{
+		if (App.embedModePluginsCount > 0 || this.initEmbedDone)
+		{
+			return; //Wait for plugins to load, or this is a duplicate call due to timeout
+		}
+		else
+		{
+			this.initEmbedDone = true;
+		}
+		
+		EditorUi.prototype.initializeEmbedMode.apply(this, arguments);
+	}
+};
+
 /**
  * Translates this point by the given vector.
  * 
@@ -4357,7 +4404,7 @@ App.prototype.updateButtonContainer = function()
 		var file = this.getCurrentFile();
 		
 		// Comments
-		if (file != null && file.constructor == DriveFile)
+		if (this.commentsSupported())
 		{
 			if (this.commentButton == null)
 			{
@@ -4369,6 +4416,12 @@ App.prototype.updateButtonContainer = function()
 					'background-position:center center;background-repeat:no-repeat;background-image:' +
 					'url(' + Editor.commentImage + ');';
 				
+				if (uiTheme == 'atlas')
+				{
+					this.commentButton.style.marginRight = '10px';
+					this.commentButton.style.marginTop = '-3px';
+				}
+				
 				mxEvent.addListener(this.commentButton, 'click', mxUtils.bind(this, function()
 				{
 					this.actions.get('comments').funct();
@@ -4376,7 +4429,7 @@ App.prototype.updateButtonContainer = function()
 				
 				this.buttonContainer.appendChild(this.commentButton);
 				
-				if (uiTheme == 'dark')
+				if (uiTheme == 'dark' || uiTheme == 'atlas')
 				{
 					this.commentButton.style.filter = 'invert(100%)';
 				}

+ 97 - 26
src/main/webapp/js/diagramly/Dialogs.js

@@ -6271,6 +6271,8 @@ var FindWindow = function(ui, x, y, w, h)
 	
 	this.window.addListener('show', mxUtils.bind(this, function()
 	{
+		this.window.fit();
+		
 		if (this.window.isVisible())
 		{
 			searchInput.focus();
@@ -6289,6 +6291,36 @@ var FindWindow = function(ui, x, y, w, h)
 			graph.container.focus();
 		}
 	}));
+	
+	this.window.setLocation = function(x, y)
+	{
+		var iw = window.innerWidth || document.body.clientWidth || document.documentElement.clientWidth;
+		var ih = window.innerHeight || document.body.clientHeight || document.documentElement.clientHeight;
+		
+		x = Math.max(0, Math.min(x, iw - this.table.clientWidth));
+		y = Math.max(0, Math.min(y, ih - this.table.clientHeight - 48));
+
+		if (this.getX() != x || this.getY() != y)
+		{
+			mxWindow.prototype.setLocation.apply(this, arguments);
+		}
+	};
+	
+	var resizeListener = mxUtils.bind(this, function()
+	{
+		var x = this.window.getX();
+		var y = this.window.getY();
+		
+		this.window.setLocation(x, y);
+	});
+	
+	mxEvent.addListener(window, 'resize', resizeListener);
+
+	this.destroy = function()
+	{
+		mxEvent.removeListener(window, 'resize', resizeListener);
+		this.window.destroy();
+	}
 };
 
 /**
@@ -6418,6 +6450,8 @@ var TagsWindow = function(editorUi, x, y, w, h)
 	
 	this.window.addListener('show', mxUtils.bind(this, function()
 	{
+		this.window.fit();
+		
 		if (this.window.isVisible())
 		{
 			searchInput.focus();
@@ -6436,6 +6470,36 @@ var TagsWindow = function(editorUi, x, y, w, h)
 			graph.container.focus();
 		}
 	}));
+	
+	this.window.setLocation = function(x, y)
+	{
+		var iw = window.innerWidth || document.body.clientWidth || document.documentElement.clientWidth;
+		var ih = window.innerHeight || document.body.clientHeight || document.documentElement.clientHeight;
+		
+		x = Math.max(0, Math.min(x, iw - this.table.clientWidth));
+		y = Math.max(0, Math.min(y, ih - this.table.clientHeight - 48));
+
+		if (this.getX() != x || this.getY() != y)
+		{
+			mxWindow.prototype.setLocation.apply(this, arguments);
+		}
+	};
+	
+	var resizeListener = mxUtils.bind(this, function()
+	{
+		var x = this.window.getX();
+		var y = this.window.getY();
+		
+		this.window.setLocation(x, y);
+	});
+	
+	mxEvent.addListener(window, 'resize', resizeListener);
+
+	this.destroy = function()
+	{
+		mxEvent.removeListener(window, 'resize', resizeListener);
+		this.window.destroy();
+	}
 };
 
 /**
@@ -7032,7 +7096,7 @@ var PluginsDialog = function(editorUi)
 				{
 					return function()
 					{
-						editorUi.confirm(window.parent.mxResources.get('delete') + ' "' + plugins[index] + '"?', function()
+						editorUi.confirm(mxResources.get('delete') + ' "' + plugins[index] + '"?', function()
 						{
 							plugins.splice(index, 1);
 							refresh();
@@ -9566,10 +9630,8 @@ var BtnDialog = function(editorUi, peer, btnLbl, fn)
  */
 var CommentsWindow = function(editorUi, x, y, w, h)
 {
-	var file = editorUi.getCurrentFile();
-	var readOnly = !file.desc.canComment;
-	var canReplyToReplies = !readOnly;
-	var file = editorUi.getCurrentFile();
+	var readOnly = !editorUi.canComment();
+	var canReplyToReplies = editorUi.canReplyToReplies();
 	
 	var div = document.createElement('div');
 	div.className = 'geCommentsWin';
@@ -9609,6 +9671,22 @@ var CommentsWindow = function(editorUi, x, y, w, h)
 		link.style.filter = 'none';
 	}
 	
+	function updateNoComments()
+	{
+		var divs = listDiv.getElementsByTagName('div');
+		var visibleCount = 0;
+		
+		for (var i = 0; i < divs.length; i++)
+		{
+			if (divs[i].style.display != 'none' && divs[i].parentNode == listDiv)
+			{
+				visibleCount++;
+			}
+		}
+		
+		noComments.style.display = (visibleCount == 0) ? 'block' : 'none';
+	};
+	
 	function editComment(comment, cdiv, saveCallback, deleteOnCancel)
 	{
 		var commentTxt = cdiv.querySelector('.geCommentTxt');
@@ -9636,6 +9714,7 @@ var CommentsWindow = function(editorUi, x, y, w, h)
 			if (deleteOnCancel)
 			{
 				cdiv.parentNode.removeChild(cdiv);
+				updateNoComments();
 			}
 			else
 			{
@@ -9823,7 +9902,7 @@ var CommentsWindow = function(editorUi, x, y, w, h)
 		{
 			var pdiv = collectReplies().pdiv;
 			
-			var newReply = file.newComment(initContent, editorUi.getCurrentUser());
+			var newReply = editorUi.newComment(initContent, editorUi.getCurrentUser());
 			newReply.pCommentId = comment.id;
 			
 			if (comment.replies == null) comment.replies = [];
@@ -9976,18 +10055,7 @@ var CommentsWindow = function(editorUi, x, y, w, h)
 						}
 					}
 					
-					var divs = listDiv.getElementsByTagName('div');
-					var visibleCount = 0;
-					
-					for (var i = 0; i < divs.length; i++)
-					{
-						if (divs[i].style.display != 'none' && divs[i].parentNode == listDiv)
-						{
-							visibleCount++;
-						}
-					}
-					
-					noComments.style.display = (visibleCount == 0) ? 'block' : 'none';
+					updateNoComments();
 				};
 				
 				if (comment.isResolved)
@@ -10032,7 +10100,7 @@ var CommentsWindow = function(editorUi, x, y, w, h)
 		
 		mxEvent.addListener(addLink, 'click', function(evt)
 		{
-			var newComment = file.newComment('', editorUi.getCurrentUser());
+			var newComment = editorUi.newComment('', editorUi.getCurrentUser());
 			var newCommentDiv = addComment(newComment, comments, null, 0);
 			
 			function doAddComment()
@@ -10041,7 +10109,7 @@ var CommentsWindow = function(editorUi, x, y, w, h)
 				{
 					showBusy(newCommentDiv);
 					
-					file.addComment(newComment, function(id)
+					editorUi.addComment(newComment, function(id)
 					{
 						newComment.id = id;
 						comments.push(newComment);
@@ -10115,13 +10183,11 @@ var CommentsWindow = function(editorUi, x, y, w, h)
 		listDiv.innerHTML = '<div style="padding-top:10px;text-align:center;"><img src="/images/spin.gif" valign="middle"> ' +
 			mxUtils.htmlEntities(mxResources.get('loading')) + '...</div>';
 		
-		file = editorUi.getCurrentFile();
-		
-		canReplyToReplies = file.canReplyToReplies();
+		canReplyToReplies = editorUi.canReplyToReplies();
 		
-		if (file != null)
+		if (editorUi.commentsSupported())
 		{
-			file.getComments(function(list)
+			editorUi.getComments(function(list)
 			{
 				function sortReplies(replies)
 				{
@@ -10163,7 +10229,7 @@ var CommentsWindow = function(editorUi, x, y, w, h)
 		}
 		else
 		{
-			//TODO if file is null, close the dialog
+			//TODO if comments are not supported, close the dialog
 			listDiv.innerHTML = mxUtils.htmlEntities(mxResources.get('error'));
 		}
 	});
@@ -10218,6 +10284,11 @@ var CommentsWindow = function(editorUi, x, y, w, h)
 	this.window.setClosable(true);
 	this.window.setVisible(true);
 	
+	this.window.addListener(mxEvent.SHOW, mxUtils.bind(this, function()
+	{
+		this.window.fit();
+	}));
+	
 	this.window.setLocation = function(x, y)
 	{
 		var iw = window.innerWidth || document.body.clientWidth || document.documentElement.clientWidth;

+ 16 - 0
src/main/webapp/js/diagramly/DrawioFile.js

@@ -2025,6 +2025,14 @@ DrawioFile.prototype.destroy = function()
 	}
 };
 
+/**
+ * Are comments supported
+ */
+DrawioFile.prototype.commentsSupported = function()
+{
+	return false; //The default is false and files that support it must explicitly state that
+};
+
 /**
  * Get comments of the file
  */
@@ -2049,6 +2057,14 @@ DrawioFile.prototype.canReplyToReplies = function()
 	return true;
 };
 
+/**
+ * Can add comments (The permission to comment to this file)
+ */
+DrawioFile.prototype.canComment = function()
+{
+	return true;
+};
+
 /**
  * Get a new comment object
  */

+ 36 - 11
src/main/webapp/js/diagramly/DriveClient.js

@@ -1062,14 +1062,20 @@ DriveClient.prototype.saveFile = function(file, revision, success, errFn, noChec
 		{
 			if (!file.isConflict(e))
 			{
-				EditorUi.logEvent({category: 'ERROR-SAVE-FILE-' + file.getHash()  + '.' +
+				var err = 'error-' + (file.getErrorMessage(e) || 'unknown');
+
+				if (e != null && e.error != null && e.error.code != null)
+				{
+					err += '-code-' + e.error.code;
+				}
+				
+				EditorUi.logEvent({category: 'ERROR-SAVE-FILE-' + file.getHash() + '.' +
 					file.desc.headRevisionId + '.' + file.desc.modifiedDate,
-					action: 'error-' + file.getErrorMessage(e),
-					label: (this.user != null) ? this.user.id : 'unknown-user'} +
-					'.' + ((file.sync != null) ? file.sync.clientId : 'nosync'));
+					action: err, label: ((this.user != null) ? this.user.id : 'unknown-user') +
+					'.' + ((file.sync != null) ? file.sync.clientId : 'nosync')});
 			}
 		}
-		catch (e)
+		catch (ex)
 		{
 			// ignore
 		}
@@ -1202,22 +1208,41 @@ DriveClient.prototype.saveFile = function(file, revision, success, errFn, noChec
 							
 							if (delta <= 0 || etag0 == resp.etag || (revision && head0 == resp.headRevisionId))
 							{
-								error({message: mxResources.get('errorSavingFile')});
+								var reasons = [];
+								
+								if (delta <= 0)
+								{
+									reasons.push('invalid modified time');
+								}
+								
+								if (etag0 == resp.etag)
+								{
+									resons.push('stale etag');
+								}
+								
+								if (revision && head0 == resp.headRevisionId)
+								{
+									resons.push('stale revision');
+								}
+								
+								var temp = ': ' + reasons.join(', ');
+								error({message: mxResources.get('errorSavingFile') + temp}, resp);
 								
 								// Logs failed save
 								try
 								{
 									EditorUi.sendReport('Critical: Error saving to Google Drive ' +
-										new Date().toISOString() + ':' +
-										'\n\nBrowser=' + navigator.userAgent +
+										new Date().toISOString() + ':' + '\n\nBrowser=' + navigator.userAgent +
 										'\nFile=' + file.desc.id + ' ' + file.desc.mimeType +
 										'\nUser=' + ((this.user != null) ? this.user.id : 'unknown') +
 										 	'.' + ((file.sync != null) ? file.sync.clientId : 'nosync') +
-										'\nOld=' + head0 + ' ' + mod0 + ' etag-hash=' + this.ui.hashValue(etag0) +
-										'\nNew=' + resp.headRevisionId + ' ' + resp.modifiedDate + '  etag-hash=' + this.ui.hashValue(resp.etag))
+										'\nErrors=' + temp + '\nOld=' + head0 + ' ' + mod0 + ' etag-hash=' +
+										this.ui.hashValue(etag0) + '\nNew=' + resp.headRevisionId + ' ' +
+										resp.modifiedDate + ' etag-hash=' + this.ui.hashValue(resp.etag))
 									EditorUi.logError('Critical: Error saving to Google Drive ' + file.desc.id,
 										null, 'from-' + head0 + '.' + mod0 + '-' + this.ui.hashValue(etag0) +
-										'-to-' + resp.headRevisionId + '.' + resp.modifiedDate + '-' + this.ui.hashValue(resp.etag),
+										'-to-' + resp.headRevisionId + '.' + resp.modifiedDate + '-' +
+										this.ui.hashValue(resp.etag) + ((temp.length > 0) ? '-errors-' + temp : ''),
 										(this.user != null) ? this.user.id : 'unknown');
 								}
 								catch (e)

+ 16 - 0
src/main/webapp/js/diagramly/DriveFile.js

@@ -663,6 +663,14 @@ DriveFile.prototype.loadDescriptor = function(success, error)
 	this.ui.drive.loadDescriptor(this.getId(), success, error);
 };
 
+/**
+ * Are comments supported
+ */
+DriveFile.prototype.commentsSupported = function()
+{
+	return true;
+};
+
 /**
  * Get comments of the file
  */
@@ -726,6 +734,14 @@ DriveFile.prototype.canReplyToReplies = function()
 	return false;
 };
 
+/**
+ * Can add comments (The permission to comment to this file)
+ */
+DriveFile.prototype.canComment = function()
+{
+	return this.desc.canComment;
+};
+
 /**
  * Get a new comment object
  */

+ 89 - 1
src/main/webapp/js/diagramly/EditorUi.js

@@ -10368,7 +10368,7 @@
 						if (uiTheme == 'atlas')
 						{
 							this.buttonContainer.style.paddingRight = '12px';
-							this.buttonContainer.style.paddingTop = '12px';
+							this.buttonContainer.style.paddingTop = '6px';
 							this.buttonContainer.style.right = '25px';
 						}
 						else if (uiTheme != 'min')
@@ -12034,4 +12034,92 @@
 			sendResponse(null, 'Invalid Call: An error occured, ' + e.message);
 		}
 	};
+	
+	/**
+	 *
+	 * Comments: We need these functions as wrapper of File functions in order to facilitate overriding them if comments are needed without having a file
+	 * 			 (e.g. Confluence Plugin)
+	 * 
+	 */
+	
+	/**
+	 * Are comments supported
+	 */
+	EditorUi.prototype.commentsSupported = function()
+	{
+		var file = this.getCurrentFile();
+		
+		return file != null? file.commentsSupported() : false;
+	};
+
+	/**
+	 * Get comments
+	 */
+	EditorUi.prototype.getComments = function(success, error)
+	{
+		var file = this.getCurrentFile();
+		
+		if (file != null)
+		{
+			file.getComments(success, error);
+		}
+		else 
+		{
+			success([]); //placeholder
+		}
+	};
+
+	/**
+	 * Add a comment
+	 */
+	EditorUi.prototype.addComment = function(comment, success, error)
+	{
+		var file = this.getCurrentFile();
+		
+		if (file != null)
+		{
+			file.addComment(comment, success, error);
+		}
+		else 
+		{
+			success(Date.now()); //placeholder
+		}
+	};
+
+	/**
+	 * Can add a reply to a reply
+	 */
+	EditorUi.prototype.canReplyToReplies = function()
+	{
+		var file = this.getCurrentFile();
+			
+		return file != null? file.canReplyToReplies() : true;
+	};
+
+	/**
+	 * Can add comments (The permission to comment)
+	 */
+	EditorUi.prototype.canComment = function()
+	{
+		var file = this.getCurrentFile();
+		
+		return file != null? file.canComment() : true;
+	};
+
+	/**
+	 * Get a new comment object
+	 */
+	EditorUi.prototype.newComment = function(content, user)
+	{
+		var file = this.getCurrentFile();
+		
+		if (file != null)
+		{
+			return file.newComment(content, user)
+		}
+		else 
+		{
+			return new DrawioComment(this, null, content, Date.now(), Date.now(), false, user);
+		}
+	};
 })();

+ 2 - 6
src/main/webapp/js/diagramly/Menus.js

@@ -2833,9 +2833,7 @@
 		{
 			viewPanelsFunct.apply(this, arguments);
 			
-			var file = editorUi.getCurrentFile();
-			
-			if (file != null && file.constructor == DriveFile)
+			if (editorUi.commentsSupported())
 			{
 				editorUi.menus.addMenuItems(menu, ['comments'], parent);
 			}
@@ -2844,10 +2842,8 @@
 		// Overrides view menu to add search and scratchpad
 		this.put('view', new Menu(mxUtils.bind(this, function(menu, parent)
 		{
-			var file = editorUi.getCurrentFile();
-
 			this.addMenuItems(menu, ((this.editorUi.format != null) ? ['formatPanel'] : []).
-				concat(['outline', 'layers']).concat((file != null && file.constructor == DriveFile) ?
+				concat(['outline', 'layers']).concat((editorUi.commentsSupported()) ?
 				['comments', '-'] : ['-']));
 			
 			this.addMenuItems(menu, ['-', 'search'], parent);

+ 1 - 3
src/main/webapp/js/diagramly/Minimal.js

@@ -767,9 +767,7 @@ EditorUi.initMinimalTheme = function()
 
 			ui.menus.addMenuItems(menu, ['-', 'outline', 'layers'], parent);
 			
-			var file = ui.getCurrentFile();
-			
-			if (file != null && file.constructor == DriveFile)
+			if (ui.commentsSupported())
 			{
 				ui.menus.addMenuItems(menu, ['comments'], parent);
 			}

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

@@ -11,6 +11,8 @@
 		
 		this.addPaletteFunctions('rackGeneral', 'Rack / General', false,
 		[
+			this.createVertexTemplateEntry(s + 'shape=mxgraph.rackGeneral.container;fillColor2=#f4f4f4;fillColor=#ffffff;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;fillColor=#ffffff;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(sr + 'text;', 160, 15, '', 'Spacing', null, null, dt + 'spacing'),

+ 6 - 0
src/main/webapp/js/mxgraph/Dialogs.js

@@ -1929,6 +1929,7 @@ var OutlineWindow = function(editorUi, x, y, w, h)
 	
 	this.window.addListener(mxEvent.SHOW, mxUtils.bind(this, function()
 	{
+		this.window.fit();
 		outline.suspended = false;
 		outline.outline.refresh();
 		outline.update();
@@ -2609,6 +2610,11 @@ var LayersWindow = function(editorUi, x, y, w, h)
 	this.window.setResizable(true);
 	this.window.setClosable(true);
 	this.window.setVisible(true);
+
+	this.window.addListener(mxEvent.SHOW, mxUtils.bind(this, function()
+	{
+		this.window.fit();
+	}));
 	
 	// Make refresh available via instance
 	this.refreshLayers = refresh;

File diff suppressed because it is too large
+ 5 - 4
src/main/webapp/js/shapes.min.js


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


+ 107 - 0
src/main/webapp/plugins/cConf-1-4-8.js

@@ -99,6 +99,7 @@ Draw.loadPlugin(function(ui)
 		if (eventName == 'export')
 		{
 			msg.macroData = macroData;
+			msg.comments = confComments;
 		}
 
 		return msg;
@@ -246,4 +247,110 @@ Draw.loadPlugin(function(ui)
 	{
 		ui.format.refresh();
 	}
+	
+	//Comments
+
+	function setModified()
+	{
+		ui.editor.setStatus(mxUtils.htmlEntities(mxResources.get('unsavedChanges')));
+		ui.editor.setModified(true);	
+	};
+	
+	var confUser = null;
+	var confComments = null;
+	
+	ui.getCurrentUser = function()
+	{
+		if (confUser == null)
+		{
+			ui.remoteInvoke('getCurrentUser', null, null, function(user)
+			{
+				confUser = new DrawioUser(user.id, user.email, user.displayName, user.pictureUrl);
+			}, function()
+			{
+				//ignore such that next call we retry
+			});
+			
+			//Return a dummy user until we have the actual user in order for UI to be populated
+			return new DrawioUser(Date.now(), null, 'Anonymous');
+		}
+		
+		return confUser;
+	};
+	
+	
+	ui.commentsSupported = function()
+	{
+		return true;
+	};
+			
+	function confCommentToDrawio(cComment, pCommentId)
+	{
+		var comment = new DrawioComment(null, cComment.id, cComment.content, 
+				cComment.modifiedDate, cComment.createdDate, cComment.isResolved,
+				new DrawioUser(cComment.user.id, cComment.user.email,
+						cComment.user.displayName, cComment.user.pictureUrl), pCommentId);
+		
+		for (var i = 0; cComment.replies != null && i < cComment.replies.length; i++)
+		{
+			comment.addReplyDirect(confCommentToDrawio(cComment.replies[i], cComment.id));
+		}
+		
+		return comment;
+	};
+			
+	ui.getComments = function(success, error)
+	{
+		if (confComments == null)
+		{
+			ui.remoteInvoke('getComments', [macroData.contentId], null, function(comments)
+			{
+				confComments = [];
+				
+				for (var i = 0; i < comments.length; i++)
+				{
+					confComments.push(confCommentToDrawio(comments[i]));
+				}
+				
+				success(confComments);
+			}, error);
+		}
+		else
+		{
+			success(confComments);
+		}
+	};
+
+	ui.addComment = function(comment, success, error)
+	{
+		setModified();
+		success(confUser.id + ':' + Date.now()); 
+	};
+			
+	ui.newComment = function(content, user)
+	{
+		return new DrawioComment(null, null, content, Date.now(), Date.now(), false, user); //remove file information
+	};
+	
+	//In Confluence, comments are part of the file (specifically custom contents), so needs to mark as changed with every change
+	DrawioComment.prototype.addReply = function(reply, success, error, doResolve, doReopen)
+	{
+		setModified();
+		success();
+	};
+
+	DrawioComment.prototype.editComment = function(newContent, success, error)
+	{
+		setModified();
+		success();
+	};
+
+	DrawioComment.prototype.deleteComment = function(success, error)
+	{
+		setModified();
+		success();
+	};
+	
+	//Prefetch current user 
+	ui.getCurrentUser();
 });

+ 5 - 4
src/main/webapp/shapes/rack/mxRack.js

@@ -40,6 +40,7 @@ mxRackContainer.prototype.cst =
 };
 
 mxRackContainer.prototype.customProperties = [
+	{name: 'fillColor2', dispName: 'Cabinet Color', type: 'color'},
 	{name: 'textColor', dispName: 'Numbers Color', type: 'color'},
 	{name: 'numDisp', dispName: 'Display Numbers', type: 'enum',
 		enumList: [{val: 'off', dispName: 'Off'}, {val: 'ascend', dispName: 'Ascending'}, {val: 'descend', dispName: 'Descending'}],
@@ -59,6 +60,8 @@ mxRackContainer.prototype.paintVertexShape = function(c, x, y, w, h)
 {
 	var fontSize = 12;
 	var displayNumbers = mxUtils.getValue(this.style, mxRackContainer.prototype.cst.NUMBER_DISPLAY, mxRackContainer.prototype.cst.DIR_ASC);
+	var fillColor = mxUtils.getValue(this.style, mxConstants.STYLE_FILLCOLOR, '#ffffff');
+	var fillColor2 = mxUtils.getValue(this.style, 'fillColor2', '#f4f4f4');
 
 	if (displayNumbers !== mxRackContainer.prototype.cst.OFF)
 	{
@@ -70,8 +73,10 @@ mxRackContainer.prototype.paintVertexShape = function(c, x, y, w, h)
 		c.translate(x, y);
 	};
 
+	c.setFillColor(fillColor);
 	this.background(c, w, h, fontSize);
 	c.setShadow(false);
+	c.setFillColor(fillColor2);
 	this.foreground(c, w, h, fontSize);
 
 	if (displayNumbers !== mxRackContainer.prototype.cst.OFF && w > 18 + fontSize * 2)
@@ -82,7 +87,6 @@ mxRackContainer.prototype.paintVertexShape = function(c, x, y, w, h)
 
 mxRackContainer.prototype.background = function(c, w, h, fontSize)
 {
-	c.setFillColor('#ffffff');
 	c.rect(0, 0, w, h);
 	c.fillAndStroke();
 };
@@ -91,7 +95,6 @@ mxRackContainer.prototype.foreground = function(c, w, h, fontSize)
 {
 	if (w > 18 + fontSize * 2 && h > 42)
 	{
-		c.setFillColor('#f4f4f4');
 		c.rect(0, 0, w, 21);
 		c.fillAndStroke();
 		c.rect(0, h - 21, w, 21);
@@ -127,8 +130,6 @@ mxRackContainer.prototype.sideText = function(c, w, h, fontSize)
 		c.text(-fontSize, 21 + mxRackContainer.unitSize * 0.5 + i * mxRackContainer.unitSize, 0, 0, displayNumber, mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
 	}
 
-	c.setStrokeColor('#dddddd');
-
 	c.begin();
 
 	for (var i = 0; i < units + 1; i++)