Comments prototype
This commit is contained in:
parent
e6af3476d9
commit
3be884d702
|
@ -11,8 +11,6 @@ CKEDITOR.editorConfig = function( config ) {
|
||||||
config.removePlugins= 'resize,elementspath';
|
config.removePlugins= 'resize,elementspath';
|
||||||
config.resize_enabled= false; //bottom-bar
|
config.resize_enabled= false; //bottom-bar
|
||||||
config.extraPlugins= 'autolink,colorbutton,colordialog,font,indentblock,justify,mediatag,print,blockbase64,mathjax,wordcount,comments';
|
config.extraPlugins= 'autolink,colorbutton,colordialog,font,indentblock,justify,mediatag,print,blockbase64,mathjax,wordcount,comments';
|
||||||
// FIXME translation for default? updating to a newer CKEditor seems like it will add 'default' by default
|
|
||||||
config.fontSize_sizes = '(Default)/unset;8/8px;9/9px;10/10px;11/11px;12/12px;14/14px;16/16px;18/18px;20/20px;22/22px;24/24px;26/26px;28/28px;36/36px;48/48px;72/72px';
|
|
||||||
config.toolbarGroups= [
|
config.toolbarGroups= [
|
||||||
// {"name":"clipboard","groups":["clipboard","undo"]},
|
// {"name":"clipboard","groups":["clipboard","undo"]},
|
||||||
//{"name":"editing","groups":["find","selection"]},
|
//{"name":"editing","groups":["find","selection"]},
|
||||||
|
|
|
@ -24,6 +24,9 @@ body.cp-app-pad {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
}
|
}
|
||||||
|
.cke_button__comment_label {
|
||||||
|
display: inline !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.cke_wysiwyg_frame {
|
.cke_wysiwyg_frame {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
|
@ -15,13 +15,8 @@
|
||||||
//icons: 'image',
|
//icons: 'image',
|
||||||
//hidpi: true,
|
//hidpi: true,
|
||||||
onLoad: function () {
|
onLoad: function () {
|
||||||
|
CKEDITOR.addCss('comment { background-color: rgba(252, 165, 3, 0.8); }' +
|
||||||
/*
|
'comment * { background-color: transparent !important; }');
|
||||||
CKEDITOR.addCss(
|
|
||||||
'media-tag *{' +
|
|
||||||
'width:100%; height:100%;' +
|
|
||||||
'}');
|
|
||||||
*/
|
|
||||||
},
|
},
|
||||||
init: function (editor) {
|
init: function (editor) {
|
||||||
var pluginName = 'comment';
|
var pluginName = 'comment';
|
||||||
|
@ -41,31 +36,62 @@
|
||||||
childRule: isUnstylable
|
childRule: isUnstylable
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// XXX define default style
|
||||||
|
// XXX we can't uncomment if nothing has been added yet
|
||||||
|
// XXX "styles" is useless because not rebuilt on reload
|
||||||
|
// XXX and one style can remove all the other ones so no need to store all of them?
|
||||||
|
|
||||||
// Register the command.
|
// Register the command.
|
||||||
var removeStyle = new CKEDITOR.style(styleDef, { 'uid': '' });
|
var removeStyle = new CKEDITOR.style(styleDef, { 'uid': '' });
|
||||||
editor.addCommand(pluginName, {
|
editor.addCommand(pluginName, {
|
||||||
exec: function (editor, data) {
|
exec: function (editor, data) {
|
||||||
if (editor.readOnly) { return; }
|
if (editor.readOnly) { return; }
|
||||||
editor.focus();
|
editor.focus();
|
||||||
editor.fire('saveSnapshot');
|
|
||||||
// XXX call cryptpad code here
|
|
||||||
Object.keys(styles).forEach(function (id) {
|
|
||||||
editor.removeStyle(styles[id]);
|
|
||||||
});
|
|
||||||
var uid = CKEDITOR.tools.getUniqueId();
|
|
||||||
styles[uid] = new CKEDITOR.style(styleDef, { 'uid': uid });
|
|
||||||
editor.applyStyle(styles[uid]);
|
|
||||||
|
|
||||||
//editor.removeStyle(removeStyle); // XXX to remove comment on the selection
|
// If we're inside another comment, abort
|
||||||
//editor.plugins.comments.addComment();
|
var isComment = removeStyle.checkActive(editor.elementPath(), editor);
|
||||||
// Save the undo snapshot after all changes are affected.
|
if (isComment) { return; }
|
||||||
|
|
||||||
|
// We can't comment on empty text!
|
||||||
|
if (!editor.getSelection().getSelectedText()) { return; }
|
||||||
|
|
||||||
|
var uid = CKEDITOR.tools.getUniqueId();
|
||||||
|
editor.plugins.comments.addComment(uid, function () {
|
||||||
|
// XXX call cryptpad code here
|
||||||
|
editor.fire('saveSnapshot');
|
||||||
|
editor.removeStyle(removeStyle);
|
||||||
|
/*
|
||||||
|
Object.keys(styles).forEach(function (id) {
|
||||||
|
editor.removeStyle(styles[id]);
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
styles[uid] = new CKEDITOR.style(styleDef, { 'uid': uid });
|
||||||
|
editor.applyStyle(styles[uid]);
|
||||||
|
|
||||||
|
//editor.removeStyle(removeStyle); // XXX to remove comment on the selection
|
||||||
|
//editor.plugins.comments.addComment();
|
||||||
|
// Save the undo snapshot after all changes are affected.
|
||||||
|
setTimeout( function() {
|
||||||
|
editor.fire('saveSnapshot');
|
||||||
|
}, 0 );
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// XXX Uncomment selection, remove on prod, only used for dev
|
||||||
|
editor.addCommand('uncomment', {
|
||||||
|
exec: function (editor, data) {
|
||||||
|
if (editor.readOnly) { return; }
|
||||||
|
editor.focus();
|
||||||
|
editor.fire('saveSnapshot');
|
||||||
|
editor.removeStyle(removeStyle);
|
||||||
setTimeout( function() {
|
setTimeout( function() {
|
||||||
editor.fire('saveSnapshot');
|
editor.fire('saveSnapshot');
|
||||||
}, 0 );
|
}, 0 );
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// Register the toolbar button.
|
// Register the toolbar button.
|
||||||
editor.ui.addButton && editor.ui.addButton('UnComment', {
|
editor.ui.addButton && editor.ui.addButton('UnComment', {
|
||||||
label: 'UNCOMMENT',
|
label: 'UNCOMMENT',
|
||||||
|
|
|
@ -0,0 +1,105 @@
|
||||||
|
define([
|
||||||
|
'json.sortify',
|
||||||
|
'/common/common-util.js',
|
||||||
|
'/common/common-interface.js',
|
||||||
|
'/customize/messages.js'
|
||||||
|
], function (Sortify, Util, UI, Messages) {
|
||||||
|
var Comments = {};
|
||||||
|
|
||||||
|
var COMMENTS = {
|
||||||
|
authors: {},
|
||||||
|
messages: {}
|
||||||
|
};
|
||||||
|
|
||||||
|
// XXX function duplicated from www/code/markers.js
|
||||||
|
var authorUid = function (existing) {
|
||||||
|
if (!Array.isArray(existing)) { existing = []; }
|
||||||
|
var n;
|
||||||
|
var i = 0;
|
||||||
|
while (!n || existing.indexOf(n) !== -1 && i++ < 1000) {
|
||||||
|
n = Math.floor(Math.random() * 1000000);
|
||||||
|
}
|
||||||
|
// If we can't find a valid number in 1000 iterations, use 0...
|
||||||
|
if (existing.indexOf(n) !== -1) { n = 0; }
|
||||||
|
return n;
|
||||||
|
};
|
||||||
|
var getAuthorId = function (Env, curve) {
|
||||||
|
var existing = Object.keys(Env.comments.authors || {}).map(Number);
|
||||||
|
if (!Env.common.isLoggedIn()) { return authorUid(existing); }
|
||||||
|
|
||||||
|
var uid;
|
||||||
|
existing.some(function (id) {
|
||||||
|
var author = Env.comments.authors[id] || {};
|
||||||
|
if (author.curvePublic !== curvePublic) { return; }
|
||||||
|
uid = Number(id);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
return uid || authorUid(existing);
|
||||||
|
};
|
||||||
|
|
||||||
|
var updateAuthorData = function (Env) {
|
||||||
|
var userData = Env.metadataMgr.getUserData();
|
||||||
|
var myAuthorId = getAuthorId(Env, userData.curvePublic);
|
||||||
|
var data = Env.comments.authors[myAuthorId] = Env.comments.authors[myAuthorId] || {};
|
||||||
|
data.name = userData.name;
|
||||||
|
data.avatar = userData.avatar;
|
||||||
|
data.profile = userData.profile;
|
||||||
|
data.curvePublic = userData.curvePublic;
|
||||||
|
console.log(data);
|
||||||
|
return myAuthorId;
|
||||||
|
};
|
||||||
|
|
||||||
|
var onChange = function (Env) {
|
||||||
|
var md = Util.clone(Env.metadataMgr.getMetadata());
|
||||||
|
Env.comments = md.comments;
|
||||||
|
if (!Env.comments) { Env.comments = Util.clone(COMMENTS); }
|
||||||
|
};
|
||||||
|
|
||||||
|
Comments.create = function (cfg) {
|
||||||
|
var Env = cfg;
|
||||||
|
Env.comments = Util.clone(COMMENTS);
|
||||||
|
|
||||||
|
Env.editor.plugins.comments.addComment = function (uid, addMark) {
|
||||||
|
if (!Env.comments) { Env.comments = Util.clone(COMMENTS); }
|
||||||
|
|
||||||
|
UI.prompt("Message", "", function (val) { // XXX
|
||||||
|
if (!val) { return; }
|
||||||
|
if (!editor.getSelection().getSelectedText()) {
|
||||||
|
// text has been deleted by another user while we were typing our comment?
|
||||||
|
return void UI.warn(Messages.error);
|
||||||
|
}
|
||||||
|
var myId = updateAuthorData(Env);
|
||||||
|
Env.comments.messages[uid] = {
|
||||||
|
user: myId,
|
||||||
|
time: +new Date(),
|
||||||
|
message: val
|
||||||
|
};
|
||||||
|
var md = Util.clone(Env.metadataMgr.getMetadata());
|
||||||
|
md.comments = Util.clone(Env.comments);
|
||||||
|
metadataMgr.updateMetadata(md);
|
||||||
|
|
||||||
|
addMark();
|
||||||
|
|
||||||
|
Env.framework.localChange();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var call = function (f) {
|
||||||
|
return function () {
|
||||||
|
try {
|
||||||
|
[].unshift.call(arguments, Env);
|
||||||
|
return f.apply(null, arguments);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
Env.metadataMgr.onChange(call(onChange));
|
||||||
|
|
||||||
|
return {
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
return Comments;
|
||||||
|
});
|
|
@ -25,6 +25,7 @@ define([
|
||||||
'/common/TypingTests.js',
|
'/common/TypingTests.js',
|
||||||
'/customize/messages.js',
|
'/customize/messages.js',
|
||||||
'/pad/links.js',
|
'/pad/links.js',
|
||||||
|
'/pad/comments.js',
|
||||||
'/pad/export.js',
|
'/pad/export.js',
|
||||||
'/pad/cursor.js',
|
'/pad/cursor.js',
|
||||||
'/bower_components/nthen/index.js',
|
'/bower_components/nthen/index.js',
|
||||||
|
@ -51,6 +52,7 @@ define([
|
||||||
TypingTest,
|
TypingTest,
|
||||||
Messages,
|
Messages,
|
||||||
Links,
|
Links,
|
||||||
|
Comments,
|
||||||
Exporter,
|
Exporter,
|
||||||
Cursors,
|
Cursors,
|
||||||
nThen,
|
nThen,
|
||||||
|
@ -461,9 +463,9 @@ define([
|
||||||
|
|
||||||
framework._.sfCommon.addShortcuts(ifrWindow);
|
framework._.sfCommon.addShortcuts(ifrWindow);
|
||||||
|
|
||||||
var privateData = framework._.sfCommon.getMetadataMgr().getPrivateData();
|
|
||||||
|
|
||||||
var documentBody = ifrWindow.document.body;
|
var documentBody = ifrWindow.document.body;
|
||||||
|
var inner = window.inner = documentBody;
|
||||||
|
var $inner = $(inner);
|
||||||
|
|
||||||
var observer = new MutationObserver(function (muts) {
|
var observer = new MutationObserver(function (muts) {
|
||||||
muts.forEach(function (mut) {
|
muts.forEach(function (mut) {
|
||||||
|
@ -483,8 +485,38 @@ define([
|
||||||
childList: true
|
childList: true
|
||||||
});
|
});
|
||||||
|
|
||||||
var inner = window.inner = documentBody;
|
var metadataMgr = framework._.sfCommon.getMetadataMgr();
|
||||||
var $inner = $(inner);
|
var privateData = metadataMgr.getPrivateData();
|
||||||
|
var userData = metadataMgr.getUserData();
|
||||||
|
var common = framework._.sfCommon;
|
||||||
|
|
||||||
|
var comments = Comments.create({
|
||||||
|
framework: framework,
|
||||||
|
metadataMgr: metadataMgr,
|
||||||
|
common: common,
|
||||||
|
editor: editor
|
||||||
|
});
|
||||||
|
|
||||||
|
editor.plugins.comments.addComment = function (uid, cb) {
|
||||||
|
if (!comments) {
|
||||||
|
comments = Util.clone(COMMENTS);
|
||||||
|
}
|
||||||
|
// XXX display input
|
||||||
|
UI.prompt("Message", "", function (val) {
|
||||||
|
if (!val) { return; }
|
||||||
|
if (!editor.getSelection().getSelectedText()) {
|
||||||
|
// text has been deleted by another user while we were typing our comment?
|
||||||
|
return void UI.warn(Messages.error);
|
||||||
|
}
|
||||||
|
var myId = updateAuthorData();
|
||||||
|
comments.messages[uid] = {
|
||||||
|
user: myId,
|
||||||
|
time: +new Date(),
|
||||||
|
message: val
|
||||||
|
};
|
||||||
|
cb();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
var onLinkClicked = function (e) {
|
var onLinkClicked = function (e) {
|
||||||
var $target = $(e.target);
|
var $target = $(e.target);
|
||||||
|
@ -650,6 +682,12 @@ define([
|
||||||
// off so that we don't end up with multiple identical handlers
|
// off so that we don't end up with multiple identical handlers
|
||||||
$links.off('click', openLink).on('click', openLink);
|
$links.off('click', openLink).on('click', openLink);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXX check comments
|
||||||
|
// new comments
|
||||||
|
// deleted comments
|
||||||
|
// check comment authors too
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
framework.setTextContentGetter(function () {
|
framework.setTextContentGetter(function () {
|
||||||
|
@ -997,9 +1035,6 @@ define([
|
||||||
}).nThen(function () {
|
}).nThen(function () {
|
||||||
editor.plugins.mediatag.import = function ($mt) {
|
editor.plugins.mediatag.import = function ($mt) {
|
||||||
framework._.sfCommon.importMediaTag($mt);
|
framework._.sfCommon.importMediaTag($mt);
|
||||||
};
|
|
||||||
editor.plugins.comments.addComment = function (uid, cb) {
|
|
||||||
|
|
||||||
};
|
};
|
||||||
Links.addSupportForOpeningLinksInNewTab(Ckeditor)({editor: editor});
|
Links.addSupportForOpeningLinksInNewTab(Ckeditor)({editor: editor});
|
||||||
}).nThen(function () {
|
}).nThen(function () {
|
||||||
|
|
Loading…
Reference in New Issue