10.5.7 release
This commit is contained in:
parent
767b3021e7
commit
f3565a9b43
12 changed files with 2117 additions and 1992 deletions
|
@ -1,3 +1,8 @@
|
|||
26-MAR-2019: 10.5.7
|
||||
|
||||
- Adds comments in Confluence cloud viewer
|
||||
- Improves Google file not found dialog
|
||||
|
||||
25-MAR-2019: 10.5.6
|
||||
|
||||
- Adds file ID and mime type in GDriveConnector macro editor
|
||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
10.5.6
|
||||
10.5.7
|
|
@ -192,6 +192,8 @@
|
|||
<file name="Pages.js" />
|
||||
<file name="Trees.js" />
|
||||
<file name="Minimal.js" />
|
||||
<file name="DrawioComment.js" />
|
||||
<file name="DrawioUser.js" />
|
||||
</sources>
|
||||
|
||||
<sources dir="${basedir}">
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
CACHE MANIFEST
|
||||
|
||||
# THIS FILE WAS GENERATED. DO NOT MODIFY!
|
||||
# 03/25/2019 08:30 PM
|
||||
# 03/25/2019 10:19 PM
|
||||
|
||||
app.html
|
||||
index.html?offline=1
|
||||
|
|
BIN
src/main/webapp/images/save.png
Normal file
BIN
src/main/webapp/images/save.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 691 B |
1219
src/main/webapp/js/app.min.js
vendored
1219
src/main/webapp/js/app.min.js
vendored
File diff suppressed because it is too large
Load diff
|
@ -762,132 +762,6 @@ var SplashDialog = function(editorUi)
|
|||
this.container = div;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
var ConfirmDialog = function(editorUi, message, okFn, cancelFn, okLabel, cancelLabel, okImg, cancelImg, showRememberOption, imgSrc)
|
||||
{
|
||||
var div = document.createElement('div');
|
||||
div.style.textAlign = 'center';
|
||||
|
||||
var p2 = document.createElement('div');
|
||||
p2.style.padding = '6px';
|
||||
p2.style.overflow = 'auto';
|
||||
p2.style.maxHeight = '44px';
|
||||
p2.style.lineHeight = '1.2em';
|
||||
|
||||
if (mxClient.IS_QUIRKS)
|
||||
{
|
||||
p2.style.height = '60px';
|
||||
}
|
||||
|
||||
mxUtils.write(p2, message);
|
||||
div.appendChild(p2);
|
||||
|
||||
if (imgSrc != null)
|
||||
{
|
||||
var p3 = document.createElement('div');
|
||||
p3.style.padding = '6px 0 6px 0';
|
||||
var img = document.createElement('img');
|
||||
img.setAttribute('src', imgSrc);
|
||||
p3.appendChild(img);
|
||||
div.appendChild(p3);
|
||||
}
|
||||
|
||||
var btns = document.createElement('div');
|
||||
btns.style.textAlign = 'center';
|
||||
btns.style.whiteSpace = 'nowrap';
|
||||
|
||||
var cb = document.createElement('input');
|
||||
cb.setAttribute('type', 'checkbox');
|
||||
|
||||
var cancelBtn = mxUtils.button(cancelLabel || mxResources.get('cancel'), function()
|
||||
{
|
||||
editorUi.hideDialog();
|
||||
|
||||
if (cancelFn != null)
|
||||
{
|
||||
cancelFn(cb.checked);
|
||||
}
|
||||
});
|
||||
cancelBtn.className = 'geBtn';
|
||||
|
||||
if (cancelImg != null)
|
||||
{
|
||||
cancelBtn.innerHTML = cancelImg + '<br>' + cancelBtn.innerHTML;
|
||||
cancelBtn.style.paddingBottom = '8px';
|
||||
cancelBtn.style.paddingTop = '8px';
|
||||
cancelBtn.style.height = 'auto';
|
||||
cancelBtn.style.width = '40%';
|
||||
}
|
||||
|
||||
if (editorUi.editor.cancelFirst)
|
||||
{
|
||||
btns.appendChild(cancelBtn);
|
||||
}
|
||||
|
||||
var okBtn = mxUtils.button(okLabel || mxResources.get('ok'), function()
|
||||
{
|
||||
editorUi.hideDialog();
|
||||
|
||||
if (okFn != null)
|
||||
{
|
||||
okFn(cb.checked);
|
||||
}
|
||||
});
|
||||
btns.appendChild(okBtn);
|
||||
|
||||
if (okImg != null)
|
||||
{
|
||||
okBtn.innerHTML = okImg + '<br>' + okBtn.innerHTML + '<br>';
|
||||
okBtn.style.paddingBottom = '8px';
|
||||
okBtn.style.paddingTop = '8px';
|
||||
okBtn.style.height = 'auto';
|
||||
okBtn.className = 'geBtn';
|
||||
okBtn.style.width = '40%';
|
||||
}
|
||||
else
|
||||
{
|
||||
okBtn.className = 'geBtn gePrimaryBtn';
|
||||
}
|
||||
|
||||
if (!editorUi.editor.cancelFirst)
|
||||
{
|
||||
btns.appendChild(cancelBtn);
|
||||
}
|
||||
|
||||
div.appendChild(btns);
|
||||
|
||||
if (showRememberOption)
|
||||
{
|
||||
btns.style.marginTop = '10px';
|
||||
var p2 = document.createElement('p');
|
||||
p2.style.marginTop = '20px';
|
||||
p2.appendChild(cb);
|
||||
var span = document.createElement('span');
|
||||
mxUtils.write(span, ' ' + mxResources.get('rememberThisSetting'));
|
||||
p2.appendChild(span);
|
||||
div.appendChild(p2);
|
||||
|
||||
mxEvent.addListener(span, 'click', function(evt)
|
||||
{
|
||||
cb.checked = !cb.checked;
|
||||
mxEvent.consume(evt);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
btns.style.marginTop = '12px';
|
||||
}
|
||||
|
||||
this.init = function()
|
||||
{
|
||||
okBtn.focus();
|
||||
};
|
||||
|
||||
this.container = div;
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructs a new embed dialog
|
||||
*/
|
||||
|
@ -9624,698 +9498,3 @@ var BtnDialog = function(editorUi, peer, btnLbl, fn)
|
|||
|
||||
this.container = div;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
var CommentsWindow = function(editorUi, x, y, w, h)
|
||||
{
|
||||
var readOnly = !editorUi.canComment();
|
||||
var canReplyToReplies = editorUi.canReplyToReplies();
|
||||
|
||||
var div = document.createElement('div');
|
||||
div.className = 'geCommentsWin';
|
||||
div.style.background = (Dialog.backdropColor == 'white') ? 'whiteSmoke' : Dialog.backdropColor;
|
||||
|
||||
var tbarHeight = (!EditorUi.compactUi) ? '30px' : '26px';
|
||||
|
||||
var listDiv = document.createElement('div');
|
||||
listDiv.className = 'geCommentsList';
|
||||
listDiv.style.backgroundColor = (Dialog.backdropColor == 'white') ? 'whiteSmoke' : Dialog.backdropColor;
|
||||
listDiv.style.bottom = (parseInt(tbarHeight) + 7) + 'px';
|
||||
div.appendChild(listDiv);
|
||||
|
||||
var noComments = document.createElement('span');
|
||||
noComments.style.cssText = 'display:none;padding-top:10px;text-align:center;';
|
||||
mxUtils.write(noComments, mxResources.get('noCommentsFound'));
|
||||
|
||||
var selectionComment = null;
|
||||
|
||||
var ldiv = document.createElement('div');
|
||||
|
||||
ldiv.className = 'geToolbarContainer geCommentsToolbar';
|
||||
ldiv.style.height = tbarHeight;
|
||||
ldiv.style.padding = (!EditorUi.compactUi) ? '1px' : '4px 0px 3px 0px';
|
||||
ldiv.style.backgroundColor = (Dialog.backdropColor == 'white') ? 'whiteSmoke' : Dialog.backdropColor;
|
||||
|
||||
if (mxClient.IS_QUIRKS)
|
||||
{
|
||||
ldiv.style.filter = 'none';
|
||||
}
|
||||
|
||||
var link = document.createElement('a');
|
||||
link.className = 'geButton';
|
||||
|
||||
if (mxClient.IS_QUIRKS)
|
||||
{
|
||||
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');
|
||||
var actionsDiv = cdiv.querySelector('.geCommentActionsList');
|
||||
|
||||
var textArea = document.createElement('textarea');
|
||||
textArea.className = 'geCommentEditTxtArea';
|
||||
textArea.style.minHeight = commentTxt.offsetHeight + 'px';
|
||||
textArea.value = commentTxt.innerHTML;
|
||||
cdiv.insertBefore(textArea, commentTxt);
|
||||
|
||||
var btnDiv = document.createElement('div');
|
||||
btnDiv.className = 'geCommentEditBtns';
|
||||
|
||||
function reset()
|
||||
{
|
||||
cdiv.removeChild(textArea);
|
||||
cdiv.removeChild(btnDiv);
|
||||
actionsDiv.style.display = 'block';
|
||||
commentTxt.style.display = 'block';
|
||||
};
|
||||
|
||||
var cancelBtn = mxUtils.button(mxResources.get('cancel'), function()
|
||||
{
|
||||
if (deleteOnCancel)
|
||||
{
|
||||
cdiv.parentNode.removeChild(cdiv);
|
||||
updateNoComments();
|
||||
}
|
||||
else
|
||||
{
|
||||
reset();
|
||||
}
|
||||
});
|
||||
|
||||
cancelBtn.className = 'geCommentEditBtn';
|
||||
btnDiv.appendChild(cancelBtn);
|
||||
|
||||
var saveBtn = mxUtils.button(mxResources.get('save'), function()
|
||||
{
|
||||
commentTxt.innerHTML = '';
|
||||
comment.content = textArea.value;
|
||||
mxUtils.write(commentTxt, comment.content);
|
||||
reset();
|
||||
saveCallback(comment);
|
||||
});
|
||||
|
||||
// Updates modified state and handles placeholder text
|
||||
mxEvent.addListener(textArea, 'keydown', mxUtils.bind(this, function(evt)
|
||||
{
|
||||
if (!mxEvent.isConsumed(evt))
|
||||
{
|
||||
if ((mxEvent.isControlDown(evt) || (mxClient.IS_MAC &&
|
||||
mxEvent.isMetaDown(evt))) && evt.keyCode == 13 /* Ctrl+Enter */)
|
||||
{
|
||||
saveBtn.click();
|
||||
mxEvent.consume(evt);
|
||||
}
|
||||
else if (evt.keyCode == 27 /* Escape */)
|
||||
{
|
||||
cancelBtn.click();
|
||||
mxEvent.consume(evt);
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
// Focused to include in viewport before focusin textbox
|
||||
saveBtn.focus();
|
||||
saveBtn.className = 'geCommentEditBtn gePrimaryBtn';
|
||||
btnDiv.appendChild(saveBtn);
|
||||
|
||||
cdiv.insertBefore(btnDiv, commentTxt);
|
||||
actionsDiv.style.display = 'none';
|
||||
commentTxt.style.display = 'none';
|
||||
textArea.focus();
|
||||
};
|
||||
|
||||
function writeCommentDate(comment, dateDiv)
|
||||
{
|
||||
dateDiv.innerHTML = '';
|
||||
var str = editorUi.timeSince(new Date(comment.modifiedDate));
|
||||
|
||||
if (str == null)
|
||||
{
|
||||
str = mxResources.get('lessThanAMinute');
|
||||
}
|
||||
|
||||
mxUtils.write(dateDiv, mxResources.get('timeAgo', [str], '{1} ago'));
|
||||
};
|
||||
|
||||
function showBusy(commentDiv)
|
||||
{
|
||||
var busyImg = document.createElement('img');
|
||||
busyImg.className = 'geCommentBusyImg';
|
||||
busyImg.src= '/images/spin.gif';
|
||||
commentDiv.appendChild(busyImg);
|
||||
commentDiv.busyImg = busyImg;
|
||||
};
|
||||
|
||||
function showError(commentDiv)
|
||||
{
|
||||
commentDiv.style.border = '1px solid red';
|
||||
commentDiv.removeChild(commentDiv.busyImg);
|
||||
};
|
||||
|
||||
function showDone(commentDiv)
|
||||
{
|
||||
commentDiv.style.border = '';
|
||||
commentDiv.removeChild(commentDiv.busyImg);
|
||||
};
|
||||
|
||||
function addComment(comment, parentArr, parent, level, showResolved)
|
||||
{
|
||||
//Skip resolved comments if showResolved is not set
|
||||
if (!showResolved && comment.isResolved)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
noComments.style.display = 'none';
|
||||
|
||||
var cdiv = document.createElement('div');
|
||||
cdiv.className = 'geCommentContainer';
|
||||
cdiv.setAttribute('data-commentId', comment.id);
|
||||
cdiv.style.marginLeft = (level * 20 + 5) + 'px';
|
||||
|
||||
if (comment.isResolved && uiTheme != 'dark')
|
||||
{
|
||||
cdiv.style.backgroundColor = 'ghostWhite';
|
||||
}
|
||||
|
||||
var headerDiv = document.createElement('div');
|
||||
headerDiv.className = 'geCommentHeader';
|
||||
|
||||
var userImg = document.createElement('img');
|
||||
userImg.className = 'geCommentUserImg';
|
||||
userImg.src = comment.user.pictureUrl || Editor.userImage;
|
||||
headerDiv.appendChild(userImg);
|
||||
|
||||
var headerTxt = document.createElement('div');
|
||||
headerTxt.className = 'geCommentHeaderTxt';
|
||||
headerDiv.appendChild(headerTxt);
|
||||
|
||||
var usernameDiv = document.createElement('div');
|
||||
usernameDiv.className = 'geCommentUsername';
|
||||
mxUtils.write(usernameDiv, comment.user.displayName || '');
|
||||
headerTxt.appendChild(usernameDiv);
|
||||
|
||||
var dateDiv = document.createElement('div');
|
||||
dateDiv.className = 'geCommentDate';
|
||||
dateDiv.setAttribute('data-commentId', comment.id);
|
||||
writeCommentDate(comment, dateDiv);
|
||||
headerTxt.appendChild(dateDiv);
|
||||
cdiv.appendChild(headerDiv);
|
||||
|
||||
var commentTxtDiv = document.createElement('div');
|
||||
commentTxtDiv.className = 'geCommentTxt';
|
||||
mxUtils.write(commentTxtDiv, comment.content || '');
|
||||
cdiv.appendChild(commentTxtDiv);
|
||||
|
||||
var actionsDiv = document.createElement('div');
|
||||
actionsDiv.className = 'geCommentActions';
|
||||
var actionsList = document.createElement('ul');
|
||||
actionsList.className = 'geCommentActionsList';
|
||||
actionsDiv.appendChild(actionsList);
|
||||
|
||||
function addAction(name, evtHandler, hide)
|
||||
{
|
||||
var action = document.createElement('li');
|
||||
action.className = 'geCommentAction';
|
||||
var actionLnk = document.createElement('a');
|
||||
actionLnk.className = 'geCommentActionLnk';
|
||||
mxUtils.write(actionLnk, name);
|
||||
action.appendChild(actionLnk);
|
||||
|
||||
mxEvent.addListener(actionLnk, 'click', function(evt)
|
||||
{
|
||||
evtHandler(evt, comment);
|
||||
evt.preventDefault();
|
||||
mxEvent.consume(evt);
|
||||
});
|
||||
|
||||
actionsList.appendChild(action);
|
||||
|
||||
if (hide) action.style.display = 'none';
|
||||
};
|
||||
|
||||
function collectReplies()
|
||||
{
|
||||
var replies = [];
|
||||
var pdiv = cdiv;
|
||||
|
||||
function collectReplies(comment)
|
||||
{
|
||||
replies.push(pdiv);
|
||||
|
||||
if (comment.replies != null)
|
||||
{
|
||||
for (var i = 0; i < comment.replies.length; i++)
|
||||
{
|
||||
pdiv = pdiv.nextSibling;
|
||||
collectReplies(comment.replies[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
collectReplies(comment);
|
||||
|
||||
return {pdiv: pdiv, replies: replies};
|
||||
};
|
||||
|
||||
function addReply(initContent, editIt, saveCallback, doResolve, doReopen)
|
||||
{
|
||||
var pdiv = collectReplies().pdiv;
|
||||
|
||||
var newReply = editorUi.newComment(initContent, editorUi.getCurrentUser());
|
||||
newReply.pCommentId = comment.id;
|
||||
|
||||
if (comment.replies == null) comment.replies = [];
|
||||
|
||||
var replyComment = addComment(newReply, comment.replies, pdiv, level + 1);
|
||||
|
||||
function doAddReply()
|
||||
{
|
||||
showBusy(replyComment);
|
||||
|
||||
comment.addReply(newReply, function(id)
|
||||
{
|
||||
newReply.id = id;
|
||||
comment.replies.push(newReply);
|
||||
showDone(replyComment);
|
||||
|
||||
if (saveCallback) saveCallback();
|
||||
|
||||
}, function(err)
|
||||
{
|
||||
doEdit();
|
||||
showError(replyComment);
|
||||
editorUi.handleError(err, null, null, null,
|
||||
mxUtils.htmlEntities(mxResources.get('objectNotFound')));
|
||||
}, doResolve, doReopen);
|
||||
};
|
||||
|
||||
function doEdit()
|
||||
{
|
||||
editComment(newReply, replyComment, function(newReply)
|
||||
{
|
||||
doAddReply();
|
||||
}, true);
|
||||
};
|
||||
|
||||
if (editIt)
|
||||
{
|
||||
doEdit();
|
||||
}
|
||||
else
|
||||
{
|
||||
doAddReply();
|
||||
}
|
||||
};
|
||||
|
||||
if (!readOnly && (level == 0 || canReplyToReplies))
|
||||
{
|
||||
addAction(mxResources.get('reply'), function()
|
||||
{
|
||||
addReply('', true);
|
||||
}, comment.isResolved);
|
||||
}
|
||||
|
||||
var user = editorUi.getCurrentUser();
|
||||
|
||||
if (user != null && user.id == comment.user.id && !readOnly)
|
||||
{
|
||||
addAction(mxResources.get('edit'), function()
|
||||
{
|
||||
function doEditComment()
|
||||
{
|
||||
editComment(comment, cdiv, function()
|
||||
{
|
||||
showBusy(cdiv);
|
||||
|
||||
comment.editComment(comment.content, function()
|
||||
{
|
||||
showDone(cdiv);
|
||||
}, function(err)
|
||||
{
|
||||
showError(cdiv);
|
||||
doEditComment();
|
||||
editorUi.handleError(err, null, null, null,
|
||||
mxUtils.htmlEntities(mxResources.get('objectNotFound')));
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
doEditComment();
|
||||
}, comment.isResolved);
|
||||
|
||||
addAction(mxResources.get('delete'), function()
|
||||
{
|
||||
editorUi.confirm(mxResources.get('areYouSure'), function()
|
||||
{
|
||||
showBusy(cdiv);
|
||||
|
||||
comment.deleteComment(function()
|
||||
{
|
||||
var replies = collectReplies(comment).replies;
|
||||
|
||||
for (var i = 0; i < replies.length; i++)
|
||||
{
|
||||
listDiv.removeChild(replies[i]);
|
||||
}
|
||||
|
||||
for (var i = 0; i < parentArr.length; i++)
|
||||
{
|
||||
if (parentArr[i] == comment)
|
||||
{
|
||||
parentArr.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
noComments.style.display = (listDiv.getElementsByTagName('div').length == 0) ? 'block' : 'none';
|
||||
}, function(err)
|
||||
{
|
||||
showError(cdiv);
|
||||
editorUi.handleError(err, null, null, null,
|
||||
mxUtils.htmlEntities(mxResources.get('objectNotFound')));
|
||||
});
|
||||
});
|
||||
}, comment.isResolved);
|
||||
}
|
||||
|
||||
if (!readOnly && level == 0) //Resolve is a top-level action only
|
||||
{
|
||||
function toggleResolve(evt)
|
||||
{
|
||||
function doToggle()
|
||||
{
|
||||
var resolveActionLnk = evt.target;
|
||||
resolveActionLnk.innerHTML = '';
|
||||
|
||||
comment.isResolved = !comment.isResolved;
|
||||
mxUtils.write(resolveActionLnk, comment.isResolved? mxResources.get('reopen') : mxResources.get('resolve'));
|
||||
var actionsDisplay = comment.isResolved? 'none' : '';
|
||||
var replies = collectReplies(comment).replies;
|
||||
|
||||
|
||||
var color = (uiTheme == 'dark') ? 'transparent' : (comment.isResolved? 'ghostWhite' : 'white');
|
||||
|
||||
for (var i = 0; i < replies.length; i++)
|
||||
{
|
||||
replies[i].style.backgroundColor = color;
|
||||
|
||||
var forOpenActions = replies[i].querySelectorAll('.geCommentAction');
|
||||
|
||||
for (var j = 0; j < forOpenActions.length; j ++)
|
||||
{
|
||||
if (forOpenActions[j] == resolveActionLnk.parentNode) continue;
|
||||
|
||||
forOpenActions[j].style.display = actionsDisplay;
|
||||
}
|
||||
|
||||
if (!resolvedChecked)
|
||||
{
|
||||
replies[i].style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
updateNoComments();
|
||||
};
|
||||
|
||||
if (comment.isResolved)
|
||||
{
|
||||
addReply(mxResources.get('reOpened') + ': ', true, doToggle, false, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
addReply(mxResources.get('markedAsResolved'), false, doToggle, true);
|
||||
}
|
||||
};
|
||||
|
||||
addAction(comment.isResolved? mxResources.get('reopen') : mxResources.get('resolve'), toggleResolve);
|
||||
}
|
||||
|
||||
cdiv.appendChild(actionsDiv);
|
||||
|
||||
if (parent != null)
|
||||
{
|
||||
listDiv.insertBefore(cdiv, parent.nextSibling);
|
||||
}
|
||||
else
|
||||
{
|
||||
listDiv.appendChild(cdiv);
|
||||
}
|
||||
|
||||
for (var i = 0; comment.replies != null && i < comment.replies.length; i++)
|
||||
{
|
||||
var reply = comment.replies[i];
|
||||
reply.isResolved = comment.isResolved; //copy isResolved to child comments (replies)
|
||||
addComment(reply, comment.replies, null, level + 1, showResolved);
|
||||
}
|
||||
|
||||
return cdiv;
|
||||
};
|
||||
|
||||
if (!readOnly)
|
||||
{
|
||||
var addLink = link.cloneNode();
|
||||
addLink.innerHTML = '<div class="geSprite geSprite-plus" style="display:inline-block;"></div>';
|
||||
addLink.setAttribute('title', mxResources.get('create') + '...');
|
||||
|
||||
mxEvent.addListener(addLink, 'click', function(evt)
|
||||
{
|
||||
var newComment = editorUi.newComment('', editorUi.getCurrentUser());
|
||||
var newCommentDiv = addComment(newComment, comments, null, 0);
|
||||
|
||||
function doAddComment()
|
||||
{
|
||||
editComment(newComment, newCommentDiv, function(newComment)
|
||||
{
|
||||
showBusy(newCommentDiv);
|
||||
|
||||
editorUi.addComment(newComment, function(id)
|
||||
{
|
||||
newComment.id = id;
|
||||
comments.push(newComment);
|
||||
showDone(newCommentDiv);
|
||||
}, function(err)
|
||||
{
|
||||
showError(newCommentDiv);
|
||||
doAddComment();
|
||||
editorUi.handleError(err, null, null, null,
|
||||
mxUtils.htmlEntities(mxResources.get('objectNotFound')));
|
||||
});
|
||||
}, true);
|
||||
}
|
||||
|
||||
doAddComment();
|
||||
evt.preventDefault();
|
||||
mxEvent.consume(evt);
|
||||
});
|
||||
|
||||
ldiv.appendChild(addLink);
|
||||
}
|
||||
|
||||
var resolvedLink = link.cloneNode();
|
||||
resolvedLink.innerHTML = '<img src="/images/check.png" style="width: 16px; padding: 2px;">';
|
||||
resolvedLink.setAttribute('title', mxResources.get('showResolved'));
|
||||
var resolvedChecked = false;
|
||||
|
||||
if (uiTheme == 'dark')
|
||||
{
|
||||
resolvedLink.style.filter = 'invert(100%)';
|
||||
}
|
||||
|
||||
mxEvent.addListener(resolvedLink, 'click', function(evt)
|
||||
{
|
||||
resolvedChecked = !resolvedChecked;
|
||||
|
||||
this.className = resolvedChecked? 'geButton geCheckedBtn' : 'geButton';
|
||||
refresh();
|
||||
|
||||
evt.preventDefault();
|
||||
mxEvent.consume(evt);
|
||||
});
|
||||
|
||||
ldiv.appendChild(resolvedLink);
|
||||
|
||||
var refreshLink = link.cloneNode();
|
||||
refreshLink.innerHTML = '<img src="/images/update16.png" style="width: 16px; padding: 2px;">';
|
||||
refreshLink.setAttribute('title', mxResources.get('refresh'));
|
||||
|
||||
if (uiTheme == 'dark')
|
||||
{
|
||||
refreshLink.style.filter = 'invert(100%)';
|
||||
}
|
||||
|
||||
mxEvent.addListener(refreshLink, 'click', function(evt)
|
||||
{
|
||||
refresh();
|
||||
|
||||
evt.preventDefault();
|
||||
mxEvent.consume(evt);
|
||||
});
|
||||
|
||||
ldiv.appendChild(refreshLink);
|
||||
|
||||
div.appendChild(ldiv);
|
||||
|
||||
var comments = [];
|
||||
|
||||
var refresh = mxUtils.bind(this, function()
|
||||
{
|
||||
listDiv.innerHTML = '<div style="padding-top:10px;text-align:center;"><img src="/images/spin.gif" valign="middle"> ' +
|
||||
mxUtils.htmlEntities(mxResources.get('loading')) + '...</div>';
|
||||
|
||||
canReplyToReplies = editorUi.canReplyToReplies();
|
||||
|
||||
if (editorUi.commentsSupported())
|
||||
{
|
||||
editorUi.getComments(function(list)
|
||||
{
|
||||
function sortReplies(replies)
|
||||
{
|
||||
if (replies != null)
|
||||
{
|
||||
//Sort replies old to new
|
||||
replies.sort(function(r1, r2)
|
||||
{
|
||||
return new Date(r1.modifiedDate) - new Date(r2.modifiedDate);
|
||||
});
|
||||
|
||||
for (var i = 0; i < replies.length; i++)
|
||||
{
|
||||
sortReplies(replies[i].replies);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//Sort comments old to new
|
||||
list.sort(function(c1, c2)
|
||||
{
|
||||
return new Date(c1.modifiedDate) - new Date(c2.modifiedDate);
|
||||
});
|
||||
|
||||
listDiv.innerHTML = '';
|
||||
listDiv.appendChild(noComments);
|
||||
noComments.style.display = 'block';
|
||||
comments = list;
|
||||
|
||||
for (var i = 0; i < comments.length; i++)
|
||||
{
|
||||
sortReplies(comments[i].replies);
|
||||
addComment(comments[i], comments, null, 0, resolvedChecked);
|
||||
}
|
||||
}, function()
|
||||
{
|
||||
listDiv.innerHTML = mxUtils.htmlEntities(mxResources.get('error'));
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
//TODO if comments are not supported, close the dialog
|
||||
listDiv.innerHTML = mxUtils.htmlEntities(mxResources.get('error'));
|
||||
}
|
||||
});
|
||||
|
||||
refresh();
|
||||
|
||||
this.refreshComments = refresh;
|
||||
|
||||
//Refresh the modified date of each comment if the window is visible
|
||||
var refreshCommentsTime = mxUtils.bind(this, function()
|
||||
{
|
||||
if (!this.window.isVisible()) return; //only update if it is visible
|
||||
|
||||
var modDateDivs = listDiv.querySelectorAll('.geCommentDate');
|
||||
var modDateDivsMap = {};
|
||||
|
||||
for (var i = 0; i < modDateDivs.length; i++)
|
||||
{
|
||||
var div = modDateDivs[i];
|
||||
modDateDivsMap[div.getAttribute('data-commentId')] = div;
|
||||
}
|
||||
|
||||
function processComment(comment)
|
||||
{
|
||||
var div = modDateDivsMap[comment.id];
|
||||
|
||||
if (div == null) return; //resolved comments
|
||||
|
||||
writeCommentDate(comment, div);
|
||||
|
||||
for (var i = 0; comment.replies != null && i < comment.replies.length; i++)
|
||||
{
|
||||
processComment(comment.replies[i]);
|
||||
}
|
||||
};
|
||||
|
||||
for (var i = 0; i < comments.length; i++)
|
||||
{
|
||||
processComment(comments[i]);
|
||||
}
|
||||
});
|
||||
|
||||
//Periodically refresh time every one minute
|
||||
setInterval(refreshCommentsTime, 60000);
|
||||
this.refreshCommentsTime = refreshCommentsTime;
|
||||
|
||||
this.window = new mxWindow(mxResources.get('comments'), div, x, y, w, h, true, true);
|
||||
this.window.minimumSize = new mxRectangle(0, 0, 300, 200);
|
||||
this.window.destroyOnClose = false;
|
||||
this.window.setMaximizable(false);
|
||||
this.window.setResizable(true);
|
||||
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;
|
||||
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();
|
||||
}
|
||||
};
|
||||
|
|
|
@ -2035,6 +2035,22 @@ DrawioFile.prototype.commentsSupported = function()
|
|||
return false; //The default is false and files that support it must explicitly state that
|
||||
};
|
||||
|
||||
/**
|
||||
* Show refresh button?
|
||||
*/
|
||||
DrawioFile.prototype.commentsRefreshNeeded = function()
|
||||
{
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Show save button?
|
||||
*/
|
||||
DrawioFile.prototype.commentsSaveNeeded = function()
|
||||
{
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get comments of the file
|
||||
*/
|
||||
|
|
|
@ -42,6 +42,11 @@
|
|||
*/
|
||||
Editor.commentImage = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNMjEuOTkgNGMwLTEuMS0uODktMi0xLjk5LTJINGMtMS4xIDAtMiAuOS0yIDJ2MTJjMCAxLjEuOSAyIDIgMmgxNGw0IDQtLjAxLTE4ek0xOCAxNEg2di0yaDEydjJ6bTAtM0g2VjloMTJ2MnptMC0zSDZWNmgxMnYyeiIvPjxwYXRoIGQ9Ik0wIDBoMjR2MjRIMHoiIGZpbGw9Im5vbmUiLz48L3N2Zz4=';
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
Editor.commentImageInverted = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABLElEQVRYR+2Wvy4FQRjFf4dINAq9XqtSaVRqXArPINEodUqlhxC5/pU6nYdQSHQeQTRHNtmVuXuXrIxv1k1sN5vMOb85c75kxMCfBvZnCsD2ErAGzAfAvUt6THUnAGwfAWfAQoB5I3kh6aBZfALYXgGeg80b31VJT9UiBRgB48CTp9Lbku7aAPvAZSGAHUm3swEgKWtUbbsj1f4JDA4AbGb24iErgUzzr7bvSrrpVcKgK5ghgKAO9E/gvwNBJRxJuu41BUEd+BFARA3+JsAWcB9x3A7NzgSqt+ALsFwAYhqgMrW9Ub8J14G5QJBugAhD2yfAaUt7T9LVxBhGmDeato/rZJtfZQHq600hygPUEIfAOTAMQALxWrQD7X7ZXpT0VqyE3xU868n9G5PzASPvpiHavBAUAAAAAElFTkSuQmCC';
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
|
@ -3567,25 +3567,44 @@
|
|||
else
|
||||
{
|
||||
msg = (notFoundMessage != null) ? notFoundMessage :
|
||||
mxUtils.htmlEntities(mxResources.get('fileNotFoundOrDenied'));
|
||||
mxUtils.htmlEntities(mxResources.get('fileNotFoundOrDenied') +
|
||||
((this.drive != null && this.drive.user != null) ? ' (' + this.drive.user.displayName +
|
||||
', ' + this.drive.user.email+ ')' : ''));
|
||||
}
|
||||
|
||||
var id = window.location.hash;
|
||||
|
||||
if (id != null && id.substring(0, 2) == '#G' && resp != null && resp.error != null &&
|
||||
((resp.error.errors != null && resp.error.errors.length > 0 &&
|
||||
resp.error.errors[0].reason == 'fileAccess') ||
|
||||
// #U handles case where we tried to fallback to Google File and
|
||||
// hash property still shows the public URL we tried to load
|
||||
if (id != null && (id.substring(0, 2) == '#G' ||
|
||||
id.substring(0, 45) == '#Uhttps%3A%2F%2Fdrive.google.com%2Fuc%3Fid%3D') &&
|
||||
((resp != null && resp.error != null && ((resp.error.errors != null &&
|
||||
resp.error.errors.length > 0 && resp.error.errors[0].reason == 'fileAccess') ||
|
||||
(resp.error.data != null && resp.error.data.length > 0 &&
|
||||
resp.error.data[0].reason == 'fileAccess')))
|
||||
resp.error.data[0].reason == 'fileAccess'))) ||
|
||||
e.code == 404 || e.status == 404))
|
||||
{
|
||||
id = id.substring(2);
|
||||
id = (id.substring(0, 2) == '#U') ? id.substring(45, id.lastIndexOf('%26ex')) : id.substring(2);
|
||||
|
||||
// Special case where the button must have a different label and function
|
||||
this.showError(title, msg, mxResources.get('cancel'), null, retry,
|
||||
mxResources.get('tryOpeningViaThisPage'), mxUtils.bind(this, function()
|
||||
this.showError(title, msg, mxResources.get('openInNewWindow'), mxUtils.bind(this, function()
|
||||
{
|
||||
this.editor.graph.openLink('https://drive.google.com/open?id=' + id);
|
||||
this.handleError(resp, title, fn, invokeFnOnClose, notFoundMessage)
|
||||
}), retry, mxResources.get('changeUser'), mxUtils.bind(this, function()
|
||||
{
|
||||
if (this.spinner.spin(document.body, mxResources.get('loading')))
|
||||
{
|
||||
this.editor.graph.openLink('https://drive.google.com/open?id=' + id);
|
||||
}), null, null, 380);
|
||||
this.drive.clearUserId();
|
||||
gapi.auth.signOut();
|
||||
|
||||
// Reload page to reset client auth
|
||||
window.location.reload();
|
||||
}
|
||||
}), mxResources.get('cancel'), mxUtils.bind(this, function()
|
||||
{
|
||||
window.location.hash = '';
|
||||
}), 480, 150);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -12073,6 +12092,26 @@
|
|||
return file != null? file.commentsSupported() : false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Show refresh button?
|
||||
*/
|
||||
EditorUi.prototype.commentsRefreshNeeded = function()
|
||||
{
|
||||
var file = this.getCurrentFile();
|
||||
|
||||
return file != null? file.commentsRefreshNeeded() : true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Show save button?
|
||||
*/
|
||||
EditorUi.prototype.commentsSaveNeeded = function()
|
||||
{
|
||||
var file = this.getCurrentFile();
|
||||
|
||||
return file != null? file.commentsSaveNeeded() : false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get comments
|
||||
*/
|
||||
|
@ -12144,3 +12183,849 @@
|
|||
}
|
||||
};
|
||||
})();
|
||||
|
||||
/**
|
||||
* Comments Window, It is used by both editor and viewer. So, it is here in a common place
|
||||
*/
|
||||
var CommentsWindow = function(editorUi, x, y, w, h, saveCallback)
|
||||
{
|
||||
var readOnly = !editorUi.canComment();
|
||||
var canReplyToReplies = editorUi.canReplyToReplies();
|
||||
|
||||
var div = document.createElement('div');
|
||||
div.className = 'geCommentsWin';
|
||||
div.style.background = (Dialog.backdropColor == 'white') ? 'whiteSmoke' : Dialog.backdropColor;
|
||||
|
||||
var tbarHeight = (!EditorUi.compactUi) ? '30px' : '26px';
|
||||
|
||||
var listDiv = document.createElement('div');
|
||||
listDiv.className = 'geCommentsList';
|
||||
listDiv.style.backgroundColor = (Dialog.backdropColor == 'white') ? 'whiteSmoke' : Dialog.backdropColor;
|
||||
listDiv.style.bottom = (parseInt(tbarHeight) + 7) + 'px';
|
||||
div.appendChild(listDiv);
|
||||
|
||||
var noComments = document.createElement('span');
|
||||
noComments.style.cssText = 'display:none;padding-top:10px;text-align:center;';
|
||||
mxUtils.write(noComments, mxResources.get('noCommentsFound'));
|
||||
|
||||
var selectionComment = null;
|
||||
|
||||
var ldiv = document.createElement('div');
|
||||
|
||||
ldiv.className = 'geToolbarContainer geCommentsToolbar';
|
||||
ldiv.style.height = tbarHeight;
|
||||
ldiv.style.padding = (!EditorUi.compactUi) ? '1px' : '4px 0px 3px 0px';
|
||||
ldiv.style.backgroundColor = (Dialog.backdropColor == 'white') ? 'whiteSmoke' : Dialog.backdropColor;
|
||||
|
||||
if (mxClient.IS_QUIRKS)
|
||||
{
|
||||
ldiv.style.filter = 'none';
|
||||
}
|
||||
|
||||
var link = document.createElement('a');
|
||||
link.className = 'geButton';
|
||||
|
||||
if (mxClient.IS_QUIRKS)
|
||||
{
|
||||
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');
|
||||
var actionsDiv = cdiv.querySelector('.geCommentActionsList');
|
||||
|
||||
var textArea = document.createElement('textarea');
|
||||
textArea.className = 'geCommentEditTxtArea';
|
||||
textArea.style.minHeight = commentTxt.offsetHeight + 'px';
|
||||
textArea.value = commentTxt.innerHTML;
|
||||
cdiv.insertBefore(textArea, commentTxt);
|
||||
|
||||
var btnDiv = document.createElement('div');
|
||||
btnDiv.className = 'geCommentEditBtns';
|
||||
|
||||
function reset()
|
||||
{
|
||||
cdiv.removeChild(textArea);
|
||||
cdiv.removeChild(btnDiv);
|
||||
actionsDiv.style.display = 'block';
|
||||
commentTxt.style.display = 'block';
|
||||
};
|
||||
|
||||
var cancelBtn = mxUtils.button(mxResources.get('cancel'), function()
|
||||
{
|
||||
if (deleteOnCancel)
|
||||
{
|
||||
cdiv.parentNode.removeChild(cdiv);
|
||||
updateNoComments();
|
||||
}
|
||||
else
|
||||
{
|
||||
reset();
|
||||
}
|
||||
});
|
||||
|
||||
cancelBtn.className = 'geCommentEditBtn';
|
||||
btnDiv.appendChild(cancelBtn);
|
||||
|
||||
var saveBtn = mxUtils.button(mxResources.get('save'), function()
|
||||
{
|
||||
commentTxt.innerHTML = '';
|
||||
comment.content = textArea.value;
|
||||
mxUtils.write(commentTxt, comment.content);
|
||||
reset();
|
||||
saveCallback(comment);
|
||||
});
|
||||
|
||||
// Updates modified state and handles placeholder text
|
||||
mxEvent.addListener(textArea, 'keydown', mxUtils.bind(this, function(evt)
|
||||
{
|
||||
if (!mxEvent.isConsumed(evt))
|
||||
{
|
||||
if ((mxEvent.isControlDown(evt) || (mxClient.IS_MAC &&
|
||||
mxEvent.isMetaDown(evt))) && evt.keyCode == 13 /* Ctrl+Enter */)
|
||||
{
|
||||
saveBtn.click();
|
||||
mxEvent.consume(evt);
|
||||
}
|
||||
else if (evt.keyCode == 27 /* Escape */)
|
||||
{
|
||||
cancelBtn.click();
|
||||
mxEvent.consume(evt);
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
// Focused to include in viewport before focusin textbox
|
||||
saveBtn.focus();
|
||||
saveBtn.className = 'geCommentEditBtn gePrimaryBtn';
|
||||
btnDiv.appendChild(saveBtn);
|
||||
|
||||
cdiv.insertBefore(btnDiv, commentTxt);
|
||||
actionsDiv.style.display = 'none';
|
||||
commentTxt.style.display = 'none';
|
||||
textArea.focus();
|
||||
};
|
||||
|
||||
function writeCommentDate(comment, dateDiv)
|
||||
{
|
||||
dateDiv.innerHTML = '';
|
||||
var str = editorUi.timeSince(new Date(comment.modifiedDate));
|
||||
|
||||
if (str == null)
|
||||
{
|
||||
str = mxResources.get('lessThanAMinute');
|
||||
}
|
||||
|
||||
mxUtils.write(dateDiv, mxResources.get('timeAgo', [str], '{1} ago'));
|
||||
};
|
||||
|
||||
function showBusy(commentDiv)
|
||||
{
|
||||
var busyImg = document.createElement('img');
|
||||
busyImg.className = 'geCommentBusyImg';
|
||||
busyImg.src= '/images/spin.gif';
|
||||
commentDiv.appendChild(busyImg);
|
||||
commentDiv.busyImg = busyImg;
|
||||
};
|
||||
|
||||
function showError(commentDiv)
|
||||
{
|
||||
commentDiv.style.border = '1px solid red';
|
||||
commentDiv.removeChild(commentDiv.busyImg);
|
||||
};
|
||||
|
||||
function showDone(commentDiv)
|
||||
{
|
||||
commentDiv.style.border = '';
|
||||
commentDiv.removeChild(commentDiv.busyImg);
|
||||
};
|
||||
|
||||
function addComment(comment, parentArr, parent, level, showResolved)
|
||||
{
|
||||
//Skip resolved comments if showResolved is not set
|
||||
if (!showResolved && comment.isResolved)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
noComments.style.display = 'none';
|
||||
|
||||
var cdiv = document.createElement('div');
|
||||
cdiv.className = 'geCommentContainer';
|
||||
cdiv.setAttribute('data-commentId', comment.id);
|
||||
cdiv.style.marginLeft = (level * 20 + 5) + 'px';
|
||||
|
||||
if (comment.isResolved && uiTheme != 'dark')
|
||||
{
|
||||
cdiv.style.backgroundColor = 'ghostWhite';
|
||||
}
|
||||
|
||||
var headerDiv = document.createElement('div');
|
||||
headerDiv.className = 'geCommentHeader';
|
||||
|
||||
var userImg = document.createElement('img');
|
||||
userImg.className = 'geCommentUserImg';
|
||||
userImg.src = comment.user.pictureUrl || Editor.userImage;
|
||||
headerDiv.appendChild(userImg);
|
||||
|
||||
var headerTxt = document.createElement('div');
|
||||
headerTxt.className = 'geCommentHeaderTxt';
|
||||
headerDiv.appendChild(headerTxt);
|
||||
|
||||
var usernameDiv = document.createElement('div');
|
||||
usernameDiv.className = 'geCommentUsername';
|
||||
mxUtils.write(usernameDiv, comment.user.displayName || '');
|
||||
headerTxt.appendChild(usernameDiv);
|
||||
|
||||
var dateDiv = document.createElement('div');
|
||||
dateDiv.className = 'geCommentDate';
|
||||
dateDiv.setAttribute('data-commentId', comment.id);
|
||||
writeCommentDate(comment, dateDiv);
|
||||
headerTxt.appendChild(dateDiv);
|
||||
cdiv.appendChild(headerDiv);
|
||||
|
||||
var commentTxtDiv = document.createElement('div');
|
||||
commentTxtDiv.className = 'geCommentTxt';
|
||||
mxUtils.write(commentTxtDiv, comment.content || '');
|
||||
cdiv.appendChild(commentTxtDiv);
|
||||
|
||||
var actionsDiv = document.createElement('div');
|
||||
actionsDiv.className = 'geCommentActions';
|
||||
var actionsList = document.createElement('ul');
|
||||
actionsList.className = 'geCommentActionsList';
|
||||
actionsDiv.appendChild(actionsList);
|
||||
|
||||
function addAction(name, evtHandler, hide)
|
||||
{
|
||||
var action = document.createElement('li');
|
||||
action.className = 'geCommentAction';
|
||||
var actionLnk = document.createElement('a');
|
||||
actionLnk.className = 'geCommentActionLnk';
|
||||
mxUtils.write(actionLnk, name);
|
||||
action.appendChild(actionLnk);
|
||||
|
||||
mxEvent.addListener(actionLnk, 'click', function(evt)
|
||||
{
|
||||
evtHandler(evt, comment);
|
||||
evt.preventDefault();
|
||||
mxEvent.consume(evt);
|
||||
});
|
||||
|
||||
actionsList.appendChild(action);
|
||||
|
||||
if (hide) action.style.display = 'none';
|
||||
};
|
||||
|
||||
function collectReplies()
|
||||
{
|
||||
var replies = [];
|
||||
var pdiv = cdiv;
|
||||
|
||||
function collectReplies(comment)
|
||||
{
|
||||
replies.push(pdiv);
|
||||
|
||||
if (comment.replies != null)
|
||||
{
|
||||
for (var i = 0; i < comment.replies.length; i++)
|
||||
{
|
||||
pdiv = pdiv.nextSibling;
|
||||
collectReplies(comment.replies[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
collectReplies(comment);
|
||||
|
||||
return {pdiv: pdiv, replies: replies};
|
||||
};
|
||||
|
||||
function addReply(initContent, editIt, saveCallback, doResolve, doReopen)
|
||||
{
|
||||
var pdiv = collectReplies().pdiv;
|
||||
|
||||
var newReply = editorUi.newComment(initContent, editorUi.getCurrentUser());
|
||||
newReply.pCommentId = comment.id;
|
||||
|
||||
if (comment.replies == null) comment.replies = [];
|
||||
|
||||
var replyComment = addComment(newReply, comment.replies, pdiv, level + 1);
|
||||
|
||||
function doAddReply()
|
||||
{
|
||||
showBusy(replyComment);
|
||||
|
||||
comment.addReply(newReply, function(id)
|
||||
{
|
||||
newReply.id = id;
|
||||
comment.replies.push(newReply);
|
||||
showDone(replyComment);
|
||||
|
||||
if (saveCallback) saveCallback();
|
||||
|
||||
}, function(err)
|
||||
{
|
||||
doEdit();
|
||||
showError(replyComment);
|
||||
editorUi.handleError(err, null, null, null,
|
||||
mxUtils.htmlEntities(mxResources.get('objectNotFound')));
|
||||
}, doResolve, doReopen);
|
||||
};
|
||||
|
||||
function doEdit()
|
||||
{
|
||||
editComment(newReply, replyComment, function(newReply)
|
||||
{
|
||||
doAddReply();
|
||||
}, true);
|
||||
};
|
||||
|
||||
if (editIt)
|
||||
{
|
||||
doEdit();
|
||||
}
|
||||
else
|
||||
{
|
||||
doAddReply();
|
||||
}
|
||||
};
|
||||
|
||||
if (!readOnly && (level == 0 || canReplyToReplies))
|
||||
{
|
||||
addAction(mxResources.get('reply'), function()
|
||||
{
|
||||
addReply('', true);
|
||||
}, comment.isResolved);
|
||||
}
|
||||
|
||||
var user = editorUi.getCurrentUser();
|
||||
|
||||
if (user != null && user.id == comment.user.id && !readOnly)
|
||||
{
|
||||
addAction(mxResources.get('edit'), function()
|
||||
{
|
||||
function doEditComment()
|
||||
{
|
||||
editComment(comment, cdiv, function()
|
||||
{
|
||||
showBusy(cdiv);
|
||||
|
||||
comment.editComment(comment.content, function()
|
||||
{
|
||||
showDone(cdiv);
|
||||
}, function(err)
|
||||
{
|
||||
showError(cdiv);
|
||||
doEditComment();
|
||||
editorUi.handleError(err, null, null, null,
|
||||
mxUtils.htmlEntities(mxResources.get('objectNotFound')));
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
doEditComment();
|
||||
}, comment.isResolved);
|
||||
|
||||
addAction(mxResources.get('delete'), function()
|
||||
{
|
||||
editorUi.confirm(mxResources.get('areYouSure'), function()
|
||||
{
|
||||
showBusy(cdiv);
|
||||
|
||||
comment.deleteComment(function()
|
||||
{
|
||||
var replies = collectReplies(comment).replies;
|
||||
|
||||
for (var i = 0; i < replies.length; i++)
|
||||
{
|
||||
listDiv.removeChild(replies[i]);
|
||||
}
|
||||
|
||||
for (var i = 0; i < parentArr.length; i++)
|
||||
{
|
||||
if (parentArr[i] == comment)
|
||||
{
|
||||
parentArr.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
noComments.style.display = (listDiv.getElementsByTagName('div').length == 0) ? 'block' : 'none';
|
||||
}, function(err)
|
||||
{
|
||||
showError(cdiv);
|
||||
editorUi.handleError(err, null, null, null,
|
||||
mxUtils.htmlEntities(mxResources.get('objectNotFound')));
|
||||
});
|
||||
});
|
||||
}, comment.isResolved);
|
||||
}
|
||||
|
||||
if (!readOnly && level == 0) //Resolve is a top-level action only
|
||||
{
|
||||
function toggleResolve(evt)
|
||||
{
|
||||
function doToggle()
|
||||
{
|
||||
var resolveActionLnk = evt.target;
|
||||
resolveActionLnk.innerHTML = '';
|
||||
|
||||
comment.isResolved = !comment.isResolved;
|
||||
mxUtils.write(resolveActionLnk, comment.isResolved? mxResources.get('reopen') : mxResources.get('resolve'));
|
||||
var actionsDisplay = comment.isResolved? 'none' : '';
|
||||
var replies = collectReplies(comment).replies;
|
||||
|
||||
|
||||
var color = (uiTheme == 'dark') ? 'transparent' : (comment.isResolved? 'ghostWhite' : 'white');
|
||||
|
||||
for (var i = 0; i < replies.length; i++)
|
||||
{
|
||||
replies[i].style.backgroundColor = color;
|
||||
|
||||
var forOpenActions = replies[i].querySelectorAll('.geCommentAction');
|
||||
|
||||
for (var j = 0; j < forOpenActions.length; j ++)
|
||||
{
|
||||
if (forOpenActions[j] == resolveActionLnk.parentNode) continue;
|
||||
|
||||
forOpenActions[j].style.display = actionsDisplay;
|
||||
}
|
||||
|
||||
if (!resolvedChecked)
|
||||
{
|
||||
replies[i].style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
updateNoComments();
|
||||
};
|
||||
|
||||
if (comment.isResolved)
|
||||
{
|
||||
addReply(mxResources.get('reOpened') + ': ', true, doToggle, false, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
addReply(mxResources.get('markedAsResolved'), false, doToggle, true);
|
||||
}
|
||||
};
|
||||
|
||||
addAction(comment.isResolved? mxResources.get('reopen') : mxResources.get('resolve'), toggleResolve);
|
||||
}
|
||||
|
||||
cdiv.appendChild(actionsDiv);
|
||||
|
||||
if (parent != null)
|
||||
{
|
||||
listDiv.insertBefore(cdiv, parent.nextSibling);
|
||||
}
|
||||
else
|
||||
{
|
||||
listDiv.appendChild(cdiv);
|
||||
}
|
||||
|
||||
for (var i = 0; comment.replies != null && i < comment.replies.length; i++)
|
||||
{
|
||||
var reply = comment.replies[i];
|
||||
reply.isResolved = comment.isResolved; //copy isResolved to child comments (replies)
|
||||
addComment(reply, comment.replies, null, level + 1, showResolved);
|
||||
}
|
||||
|
||||
return cdiv;
|
||||
};
|
||||
|
||||
if (!readOnly)
|
||||
{
|
||||
var addLink = link.cloneNode();
|
||||
addLink.innerHTML = '<div class="geSprite geSprite-plus" style="display:inline-block;"></div>';
|
||||
addLink.setAttribute('title', mxResources.get('create') + '...');
|
||||
|
||||
mxEvent.addListener(addLink, 'click', function(evt)
|
||||
{
|
||||
var newComment = editorUi.newComment('', editorUi.getCurrentUser());
|
||||
var newCommentDiv = addComment(newComment, comments, null, 0);
|
||||
|
||||
function doAddComment()
|
||||
{
|
||||
editComment(newComment, newCommentDiv, function(newComment)
|
||||
{
|
||||
showBusy(newCommentDiv);
|
||||
|
||||
editorUi.addComment(newComment, function(id)
|
||||
{
|
||||
newComment.id = id;
|
||||
comments.push(newComment);
|
||||
showDone(newCommentDiv);
|
||||
}, function(err)
|
||||
{
|
||||
showError(newCommentDiv);
|
||||
doAddComment();
|
||||
editorUi.handleError(err, null, null, null,
|
||||
mxUtils.htmlEntities(mxResources.get('objectNotFound')));
|
||||
});
|
||||
}, true);
|
||||
}
|
||||
|
||||
doAddComment();
|
||||
evt.preventDefault();
|
||||
mxEvent.consume(evt);
|
||||
});
|
||||
|
||||
ldiv.appendChild(addLink);
|
||||
}
|
||||
|
||||
var resolvedLink = link.cloneNode();
|
||||
resolvedLink.innerHTML = '<img src="/images/check.png" style="width: 16px; padding: 2px;">';
|
||||
resolvedLink.setAttribute('title', mxResources.get('showResolved'));
|
||||
var resolvedChecked = false;
|
||||
|
||||
if (uiTheme == 'dark')
|
||||
{
|
||||
resolvedLink.style.filter = 'invert(100%)';
|
||||
}
|
||||
|
||||
mxEvent.addListener(resolvedLink, 'click', function(evt)
|
||||
{
|
||||
resolvedChecked = !resolvedChecked;
|
||||
|
||||
this.className = resolvedChecked? 'geButton geCheckedBtn' : 'geButton';
|
||||
refresh();
|
||||
|
||||
evt.preventDefault();
|
||||
mxEvent.consume(evt);
|
||||
});
|
||||
|
||||
ldiv.appendChild(resolvedLink);
|
||||
|
||||
if (editorUi.commentsRefreshNeeded())
|
||||
{
|
||||
var refreshLink = link.cloneNode();
|
||||
refreshLink.innerHTML = '<img src="/images/update16.png" style="width: 16px; padding: 2px;">';
|
||||
refreshLink.setAttribute('title', mxResources.get('refresh'));
|
||||
|
||||
if (uiTheme == 'dark')
|
||||
{
|
||||
refreshLink.style.filter = 'invert(100%)';
|
||||
}
|
||||
|
||||
mxEvent.addListener(refreshLink, 'click', function(evt)
|
||||
{
|
||||
refresh();
|
||||
|
||||
evt.preventDefault();
|
||||
mxEvent.consume(evt);
|
||||
});
|
||||
|
||||
ldiv.appendChild(refreshLink);
|
||||
}
|
||||
|
||||
if (editorUi.commentsSaveNeeded())
|
||||
{
|
||||
var saveLink = link.cloneNode();
|
||||
saveLink.innerHTML = '<img src="/images/save.png" style="width: 20px; padding: 2px;">';
|
||||
saveLink.setAttribute('title', mxResources.get('save'));
|
||||
|
||||
if (uiTheme == 'dark')
|
||||
{
|
||||
saveLink.style.filter = 'invert(100%)';
|
||||
}
|
||||
|
||||
mxEvent.addListener(saveLink, 'click', function(evt)
|
||||
{
|
||||
saveCallback();
|
||||
|
||||
evt.preventDefault();
|
||||
mxEvent.consume(evt);
|
||||
});
|
||||
|
||||
ldiv.appendChild(saveLink);
|
||||
}
|
||||
|
||||
div.appendChild(ldiv);
|
||||
|
||||
var comments = [];
|
||||
|
||||
var refresh = mxUtils.bind(this, function()
|
||||
{
|
||||
listDiv.innerHTML = '<div style="padding-top:10px;text-align:center;"><img src="/images/spin.gif" valign="middle"> ' +
|
||||
mxUtils.htmlEntities(mxResources.get('loading')) + '...</div>';
|
||||
|
||||
canReplyToReplies = editorUi.canReplyToReplies();
|
||||
|
||||
if (editorUi.commentsSupported())
|
||||
{
|
||||
editorUi.getComments(function(list)
|
||||
{
|
||||
function sortReplies(replies)
|
||||
{
|
||||
if (replies != null)
|
||||
{
|
||||
//Sort replies old to new
|
||||
replies.sort(function(r1, r2)
|
||||
{
|
||||
return new Date(r1.modifiedDate) - new Date(r2.modifiedDate);
|
||||
});
|
||||
|
||||
for (var i = 0; i < replies.length; i++)
|
||||
{
|
||||
sortReplies(replies[i].replies);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//Sort comments old to new
|
||||
list.sort(function(c1, c2)
|
||||
{
|
||||
return new Date(c1.modifiedDate) - new Date(c2.modifiedDate);
|
||||
});
|
||||
|
||||
listDiv.innerHTML = '';
|
||||
listDiv.appendChild(noComments);
|
||||
noComments.style.display = 'block';
|
||||
comments = list;
|
||||
|
||||
for (var i = 0; i < comments.length; i++)
|
||||
{
|
||||
sortReplies(comments[i].replies);
|
||||
addComment(comments[i], comments, null, 0, resolvedChecked);
|
||||
}
|
||||
}, function()
|
||||
{
|
||||
listDiv.innerHTML = mxUtils.htmlEntities(mxResources.get('error'));
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
//TODO if comments are not supported, close the dialog
|
||||
listDiv.innerHTML = mxUtils.htmlEntities(mxResources.get('error'));
|
||||
}
|
||||
});
|
||||
|
||||
refresh();
|
||||
|
||||
this.refreshComments = refresh;
|
||||
|
||||
//Refresh the modified date of each comment if the window is visible
|
||||
var refreshCommentsTime = mxUtils.bind(this, function()
|
||||
{
|
||||
if (!this.window.isVisible()) return; //only update if it is visible
|
||||
|
||||
var modDateDivs = listDiv.querySelectorAll('.geCommentDate');
|
||||
var modDateDivsMap = {};
|
||||
|
||||
for (var i = 0; i < modDateDivs.length; i++)
|
||||
{
|
||||
var div = modDateDivs[i];
|
||||
modDateDivsMap[div.getAttribute('data-commentId')] = div;
|
||||
}
|
||||
|
||||
function processComment(comment)
|
||||
{
|
||||
var div = modDateDivsMap[comment.id];
|
||||
|
||||
if (div == null) return; //resolved comments
|
||||
|
||||
writeCommentDate(comment, div);
|
||||
|
||||
for (var i = 0; comment.replies != null && i < comment.replies.length; i++)
|
||||
{
|
||||
processComment(comment.replies[i]);
|
||||
}
|
||||
};
|
||||
|
||||
for (var i = 0; i < comments.length; i++)
|
||||
{
|
||||
processComment(comments[i]);
|
||||
}
|
||||
});
|
||||
|
||||
//Periodically refresh time every one minute
|
||||
setInterval(refreshCommentsTime, 60000);
|
||||
this.refreshCommentsTime = refreshCommentsTime;
|
||||
|
||||
this.window = new mxWindow(mxResources.get('comments'), div, x, y, w, h, true, true);
|
||||
this.window.minimumSize = new mxRectangle(0, 0, 300, 200);
|
||||
this.window.destroyOnClose = false;
|
||||
this.window.setMaximizable(false);
|
||||
this.window.setResizable(true);
|
||||
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;
|
||||
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();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
var ConfirmDialog = function(editorUi, message, okFn, cancelFn, okLabel, cancelLabel, okImg, cancelImg, showRememberOption, imgSrc)
|
||||
{
|
||||
var div = document.createElement('div');
|
||||
div.style.textAlign = 'center';
|
||||
|
||||
var p2 = document.createElement('div');
|
||||
p2.style.padding = '6px';
|
||||
p2.style.overflow = 'auto';
|
||||
p2.style.maxHeight = '44px';
|
||||
p2.style.lineHeight = '1.2em';
|
||||
|
||||
if (mxClient.IS_QUIRKS)
|
||||
{
|
||||
p2.style.height = '60px';
|
||||
}
|
||||
|
||||
mxUtils.write(p2, message);
|
||||
div.appendChild(p2);
|
||||
|
||||
if (imgSrc != null)
|
||||
{
|
||||
var p3 = document.createElement('div');
|
||||
p3.style.padding = '6px 0 6px 0';
|
||||
var img = document.createElement('img');
|
||||
img.setAttribute('src', imgSrc);
|
||||
p3.appendChild(img);
|
||||
div.appendChild(p3);
|
||||
}
|
||||
|
||||
var btns = document.createElement('div');
|
||||
btns.style.textAlign = 'center';
|
||||
btns.style.whiteSpace = 'nowrap';
|
||||
|
||||
var cb = document.createElement('input');
|
||||
cb.setAttribute('type', 'checkbox');
|
||||
|
||||
var cancelBtn = mxUtils.button(cancelLabel || mxResources.get('cancel'), function()
|
||||
{
|
||||
editorUi.hideDialog();
|
||||
|
||||
if (cancelFn != null)
|
||||
{
|
||||
cancelFn(cb.checked);
|
||||
}
|
||||
});
|
||||
cancelBtn.className = 'geBtn';
|
||||
|
||||
if (cancelImg != null)
|
||||
{
|
||||
cancelBtn.innerHTML = cancelImg + '<br>' + cancelBtn.innerHTML;
|
||||
cancelBtn.style.paddingBottom = '8px';
|
||||
cancelBtn.style.paddingTop = '8px';
|
||||
cancelBtn.style.height = 'auto';
|
||||
cancelBtn.style.width = '40%';
|
||||
}
|
||||
|
||||
if (editorUi.editor.cancelFirst)
|
||||
{
|
||||
btns.appendChild(cancelBtn);
|
||||
}
|
||||
|
||||
var okBtn = mxUtils.button(okLabel || mxResources.get('ok'), function()
|
||||
{
|
||||
editorUi.hideDialog();
|
||||
|
||||
if (okFn != null)
|
||||
{
|
||||
okFn(cb.checked);
|
||||
}
|
||||
});
|
||||
btns.appendChild(okBtn);
|
||||
|
||||
if (okImg != null)
|
||||
{
|
||||
okBtn.innerHTML = okImg + '<br>' + okBtn.innerHTML + '<br>';
|
||||
okBtn.style.paddingBottom = '8px';
|
||||
okBtn.style.paddingTop = '8px';
|
||||
okBtn.style.height = 'auto';
|
||||
okBtn.className = 'geBtn';
|
||||
okBtn.style.width = '40%';
|
||||
}
|
||||
else
|
||||
{
|
||||
okBtn.className = 'geBtn gePrimaryBtn';
|
||||
}
|
||||
|
||||
if (!editorUi.editor.cancelFirst)
|
||||
{
|
||||
btns.appendChild(cancelBtn);
|
||||
}
|
||||
|
||||
div.appendChild(btns);
|
||||
|
||||
if (showRememberOption)
|
||||
{
|
||||
btns.style.marginTop = '10px';
|
||||
var p2 = document.createElement('p');
|
||||
p2.style.marginTop = '20px';
|
||||
p2.appendChild(cb);
|
||||
var span = document.createElement('span');
|
||||
mxUtils.write(span, ' ' + mxResources.get('rememberThisSetting'));
|
||||
p2.appendChild(span);
|
||||
div.appendChild(p2);
|
||||
|
||||
mxEvent.addListener(span, 'click', function(evt)
|
||||
{
|
||||
cb.checked = !cb.checked;
|
||||
mxEvent.consume(evt);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
btns.style.marginTop = '12px';
|
||||
}
|
||||
|
||||
this.init = function()
|
||||
{
|
||||
okBtn.focus();
|
||||
};
|
||||
|
||||
this.container = div;
|
||||
};
|
||||
|
|
1125
src/main/webapp/js/viewer.min.js
vendored
1125
src/main/webapp/js/viewer.min.js
vendored
File diff suppressed because one or more lines are too long
|
@ -286,7 +286,12 @@ Draw.loadPlugin(function(ui)
|
|||
{
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
ui.commentsRefreshNeeded = function()
|
||||
{
|
||||
return false;
|
||||
};
|
||||
|
||||
function confCommentToDrawio(cComment, pCommentId)
|
||||
{
|
||||
var comment = new DrawioComment(null, cComment.id, cComment.content,
|
||||
|
|
Loading…
Reference in a new issue