From 9c9e5db72d05a81053aeac40441dbc523125981f Mon Sep 17 00:00:00 2001 From: John McLear Date: Thu, 29 Mar 2012 19:40:55 +0100 Subject: [PATCH 1/3] Add ability to export specific pad revisions Conflicts: node/utils/Minify.js node/utils/Settings.js static/css/timeslider.css static/js/pad_impexp.js static/timeslider.html --- node/utils/Minify.js | 4 + static/css/timeslider.css | 5 +- static/timeslider.html | 159 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 167 insertions(+), 1 deletion(-) diff --git a/node/utils/Minify.js b/node/utils/Minify.js index 859ee07ae..3c3eb12fe 100644 --- a/node/utils/Minify.js +++ b/node/utils/Minify.js @@ -40,6 +40,10 @@ var CACHE_DIR = ROOT_DIR + '../var/'; var TAR_PATH = path.join(__dirname, 'tar.json'); var tar = JSON.parse(fs.readFileSync(TAR_PATH, 'utf8')); +var padJS = ["jquery.min.js", "pad_utils.js", "plugins.js", "undo-xpopup.js", "json2.js", "pad_cookie.js", "pad_editor.js", "pad_editbar.js", "pad_docbar.js", "pad_modals.js", "ace.js", "collab_client.js", "pad_userlist.js", "pad_impexp.js", "pad_savedrevs.js", "pad_connectionstatus.js", "pad2.js", "jquery-ui.js", "chat.js", "excanvas.js", "farbtastic.js"]; + +var timesliderJS = ["jquery.min.js", "plugins.js", "undo-xpopup.js", "json2.js", "colorutils.js", "draggable.js", "pad_utils.js", "pad_cookie.js", "pad_editor.js", "pad_editbar.js", "pad_docbar.js", "pad_modals.js", "pad_impexp.js", "easysync2_client.js", "domline_client.js", "linestylefilter_client.js", "cssmanager_client.js", "broadcast.js", "broadcast_slider.js", "broadcast_revisions.js"]; + /** * creates the minifed javascript for the given minified name * @param req the Express request diff --git a/static/css/timeslider.css b/static/css/timeslider.css index 6022e2d7c..1413e407d 100644 --- a/static/css/timeslider.css +++ b/static/css/timeslider.css @@ -195,8 +195,11 @@ float:right; color: #222; } -#importexport { top: 118px; } #importexport .popup { width: 185px; } +#importexport{ + top:118px; + width:185px; +} ul { margin-left: 1.5em; } ul ul { margin-left: 0 !important; } diff --git a/static/timeslider.html b/static/timeslider.html index 579e26ef6..e4588d356 100644 --- a/static/timeslider.html +++ b/static/timeslider.html @@ -9,6 +9,165 @@ + + + + + + + + From f631e1e8ab4c78c54cebf6a1d9dc116d05eaec27 Mon Sep 17 00:00:00 2001 From: Peter 'Pita' Martischka Date: Wed, 29 Feb 2012 14:40:14 -0500 Subject: [PATCH 2/3] Added saved revisions support --- node/db/Pad.js | 28 +- node/handler/PadMessageHandler.js | 22 + node/handler/TimesliderMessageHandler.js | 7 + static/css/pad.css | 3 + static/img/etherpad_lite_icons.png | Bin 5541 -> 8318 bytes static/img/star.png | Bin 0 -> 3241 bytes static/js/pad.js | 4 +- static/js/pad_docbar.js | 6 - static/js/pad_editbar.js | 4 +- static/js/pad_savedrevs.js | 518 +---------------------- static/pad.html | 5 + 11 files changed, 77 insertions(+), 520 deletions(-) create mode 100644 static/img/star.png diff --git a/node/db/Pad.js b/node/db/Pad.js index 632eebe8c..e1f7e6af6 100644 --- a/node/db/Pad.js +++ b/node/db/Pad.js @@ -13,6 +13,7 @@ var padManager = require("./PadManager"); var padMessageHandler = require("../handler/PadMessageHandler"); var readOnlyManager = require("./ReadOnlyManager"); var crypto = require("crypto"); +var randomString = require("../utils/randomstring"); /** * Copied from the Etherpad source code. It converts Windows line breaks to Unix line breaks and convert Tabs to spaces @@ -32,7 +33,7 @@ var Pad = function Pad(id) { this.publicStatus = false; this.passwordHash = null; this.id = id; - + this.savedRevisions = []; }; exports.Pad = Pad; @@ -466,6 +467,31 @@ Pad.prototype.isPasswordProtected = function isPasswordProtected() { return this.passwordHash != null; }; +Pad.prototype.addSavedRevision = function addSavedRevision(revNum, savedById, label) { + //if this revision is already saved, return silently + for(var i in this.savedRevisions){ + if(this.savedRevisions.revNum === revNum){ + return; + } + } + + //build the saved revision object + var savedRevision = {}; + savedRevision.revNum = revNum; + savedRevision.savedById = savedById; + savedRevision.label = label || "Revision " + revNum; + savedRevision.timestamp = new Date().getTime(); + savedRevision.id = randomString(10); + + //save this new saved revision + this.savedRevisions.push(savedRevision); + this.saveToDatabase(); +}; + +Pad.prototype.getSavedRevisions = function getSavedRevisions() { + return this.savedRevisions; +}; + /* Crypto helper methods */ function hash(password, salt) diff --git a/node/handler/PadMessageHandler.js b/node/handler/PadMessageHandler.js index 4a078542c..e931da4ec 100644 --- a/node/handler/PadMessageHandler.js +++ b/node/handler/PadMessageHandler.js @@ -184,6 +184,11 @@ exports.handleMessage = function(client, message) { handleChatMessage(client, message); } + else if(message.type == "COLLABROOM" && + message.data.type == "SAVE_REVISION") + { + handleSaveRevisionMessage(client, message); + } else if(message.type == "COLLABROOM" && message.data.type == "CLIENT_MESSAGE" && message.data.payload.type == "suggestUserName") @@ -197,6 +202,23 @@ exports.handleMessage = function(client, message) } } +/** + * Handles a save revision message + * @param client the client that send this message + * @param message the message from the client + */ +function handleSaveRevisionMessage(client, message){ + var padId = session2pad[client.id]; + var userId = sessioninfos[client.id].author; + + padManager.getPad(padId, function(err, pad) + { + if(ERR(err)) return; + + pad.addSavedRevision(pad.head, userId); + }); +} + /** * Handles a Chat Message * @param client the client that send this message diff --git a/node/handler/TimesliderMessageHandler.js b/node/handler/TimesliderMessageHandler.js index b30a9fc9d..bbee1f985 100644 --- a/node/handler/TimesliderMessageHandler.js +++ b/node/handler/TimesliderMessageHandler.js @@ -165,6 +165,7 @@ function createTimesliderClientVars (padId, callback) hooks: [], initialStyledContents: {} }; + var pad; var initialChangesets = []; @@ -179,6 +180,12 @@ function createTimesliderClientVars (padId, callback) callback(); }); }, + //get all saved revisions and add them + function(callback) + { + clientVars.savedRevisions = pad.getSavedRevisions(); + callback(); + }, //get all authors and add them to function(callback) { diff --git a/static/css/pad.css b/static/css/pad.css index e407b3a4f..db7aec309 100644 --- a/static/css/pad.css +++ b/static/css/pad.css @@ -1065,6 +1065,9 @@ margin-top: 1px; background-position: 0px -183px; display: inline-block; } +.buttonicon-savedRevision { + background-position: 0px -493px +} #usericon { diff --git a/static/img/etherpad_lite_icons.png b/static/img/etherpad_lite_icons.png index cadf5ed2b3717939e2f23dc0c24a5360f8e822d8..27867d428d6dcdb62a1271f691094f59333c02bc 100644 GIT binary patch literal 8318 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 literal 5541 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 diff --git a/static/img/star.png b/static/img/star.png new file mode 100644 index 0000000000000000000000000000000000000000..e0c7099e55887d32d2ed377e86a4c20bbbffda32 GIT binary patch literal 3241 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' + '
' + '' + '' + '
' + '
' + '' + '
'); - setBoxLabel(box, revisionInfo.label); - setBoxTimestamp(box, revisionInfo.timestamp); - box.find(".srauthor").html("by " + padutils.escapeHtml(revisionInfo.savedBy)); - var viewLink = '/ep/pad/view/' + pad.getPadId() + '/' + revisionInfo.id; - box.find(".srview").attr('href', viewLink); - var restoreLink = 'javascript:void(require('+JSON.stringify(module.id)+').padsavedrevs.restoreRevision(' + JSON.stringify(rnum) + ');'; - box.find(".srrestore").attr('href', restoreLink); - box.find(".srname").click(function(evt) - { - editRevisionLabel(rnum, box); - }); - return box; - } - - function setBoxLabel(box, label) - { - box.find(".srname").html(padutils.escapeHtml(label)).attr('title', label); - } - - function setBoxTimestamp(box, timestamp) - { - box.find(".srtime").html(padutils.escapeHtml( - padutils.timediff(new Date(timestamp)))); - } - - function getNthBox(n) - { - return $("#savedrevisions .srouterbox").eq(n); - } - - function editRevisionLabel(rnum, box) - { - var input = $(''); - box.find(".srnameedit").remove(); // just in case - var label = box.find(".srname"); - input.width(label.width()); - input.height(label.height()); - input.css('top', label.position().top); - input.css('left', label.position().left); - label.after(input); - label.css('opacity', 0); - - function endEdit() - { - input.remove(); - label.css('opacity', 1); - } - var rev = currentRevisionList[rnum]; - var oldLabel = rev.label; - input.blur(function() - { - var newLabel = input.val(); - if (newLabel && newLabel != oldLabel) - { - relabelRevision(rnum, newLabel); - } - endEdit(); - }); - input.val(rev.label).focus().select(); - padutils.bindEnterAndEscape(input, function onEnter() - { - input.blur(); - }, function onEscape() - { - input.val('').blur(); - }); - } - - function relabelRevision(rnum, newLabel) - { - var rev = currentRevisionList[rnum]; - $.ajax( - { - type: 'post', - url: '/ep/pad/saverevisionlabel', - data: { - userId: pad.getUserId(), - padId: pad.getPadId(), - revId: rev.id, - newLabel: newLabel - }, - success: success, - error: error - }); - - function success(text) - { - var newRevisionList = JSON.parse(text); - self.newRevisionList(newRevisionList); - pad.sendClientMessage( - { - type: 'revisionLabel', - revisionList: reversedCopy(currentRevisionList), - savedBy: pad.getUserName(), - newLabel: newLabel - }); - } - - function error(e) - { - alert("Oops! There was an error saving that revision label. Please try again later."); - } - } - - var currentRevisionList = []; - - function setRevisionList(newRevisionList, noAnimation) - { - // deals with changed labels and new added revisions - for (var i = 0; i < currentRevisionList.length; i++) - { - var a = currentRevisionList[i]; - var b = newRevisionList[i]; - if (b.label != a.label) - { - setBoxLabel(getNthBox(i), b.label); - } - } - for (var j = currentRevisionList.length; j < newRevisionList.length; j++) - { - var newBox = makeRevisionBox(newRevisionList[j], j); - $("#savedrevs-scrollinner").append(newBox); - newBox.css('left', j * REVISION_BOX_WIDTH); - } - var newOnes = (newRevisionList.length > currentRevisionList.length); - currentRevisionList = newRevisionList; - if (newOnes) - { - setDesiredScroll(getMaxScroll()); - if (noAnimation) - { - setScroll(desiredScroll); - } - - if (!noAnimation) - { - var nameOfLast = currentRevisionList[currentRevisionList.length - 1].label; - displaySavedTip(nameOfLast); - } - } - } - - function refreshRevisionList() - { - for (var i = 0; i < currentRevisionList.length; i++) - { - var r = currentRevisionList[i]; - var box = getNthBox(i); - setBoxTimestamp(box, r.timestamp); - } - } - - var savedTipAnimator = padutils.makeShowHideAnimator(function(state) - { - if (state == -1) - { - $("#revision-notifier").css('opacity', 0).css('display', 'block'); - } - else if (state == 0) - { - $("#revision-notifier").css('opacity', 1); - } - else if (state == 1) - { - $("#revision-notifier").css('opacity', 0).css('display', 'none'); - } - else if (state < 0) - { - $("#revision-notifier").css('opacity', 1); - } - else if (state > 0) - { - $("#revision-notifier").css('opacity', 1 - state); - } - }, false, 25, 300); - - function displaySavedTip(text) - { - $("#revision-notifier .name").html(padutils.escapeHtml(text)); - savedTipAnimator.show(); - padutils.cancelActions("hide-revision-notifier"); - var hideLater = padutils.getCancellableAction("hide-revision-notifier", function() - { - savedTipAnimator.hide(); - }); - window.setTimeout(hideLater, 3000); - } - - var REVISION_BOX_WIDTH = 120; - var curScroll = 0; // distance between left of revisions and right of view - var desiredScroll = 0; - - function getScrollWidth() - { - return REVISION_BOX_WIDTH * currentRevisionList.length; - } - - function getViewportWidth() - { - return $("#savedrevs-scrollouter").width(); - } - - function getMinScroll() - { - return Math.min(getViewportWidth(), getScrollWidth()); - } - - function getMaxScroll() - { - return getScrollWidth(); - } - - function setScroll(newScroll) - { - curScroll = newScroll; - $("#savedrevs-scrollinner").css('right', newScroll); - updateScrollArrows(); - } - - function setDesiredScroll(newDesiredScroll, dontUpdate) - { - desiredScroll = Math.min(getMaxScroll(), Math.max(getMinScroll(), newDesiredScroll)); - if (!dontUpdate) - { - updateScroll(); - } - } - - function updateScroll() - { - updateScrollArrows(); - scrollAnimator.scheduleAnimation(); - } - - function updateScrollArrows() - { - $("#savedrevs-scrollleft").toggleClass("disabledscrollleft", desiredScroll <= getMinScroll()); - $("#savedrevs-scrollright").toggleClass("disabledscrollright", desiredScroll >= getMaxScroll()); - } - var scrollAnimator = padutils.makeAnimationScheduler(function() - { - setDesiredScroll(desiredScroll, true); // re-clamp - if (Math.abs(desiredScroll - curScroll) < 1) - { - setScroll(desiredScroll); - return false; - } - else - { - setScroll(curScroll + (desiredScroll - curScroll) * 0.5); - return true; - } - }, 50, 2); - - var isSaving = false; - - function setIsSaving(v) - { - isSaving = v; - rerenderButton(); - } - - function haveReachedRevLimit() - { - var mv = pad.getPrivilege('maxRevisions'); - return (!(mv < 0 || mv > currentRevisionList.length)); - } - - function rerenderButton() - { - if (isSaving || (!pad.isFullyConnected()) || haveReachedRevLimit()) - { - $("#savedrevs-savenow").css('opacity', 0.75); - } - else - { - $("#savedrevs-savenow").css('opacity', 1); - } - } - - var scrollRepeatTimer = null; - var scrollStartTime = 0; - - function setScrollRepeatTimer(dir) - { - clearScrollRepeatTimer(); - scrollStartTime = +new Date; - scrollRepeatTimer = window.setTimeout(function f() - { - if (!scrollRepeatTimer) - { - return; - } - self.scroll(dir); - var scrollTime = (+new Date) - scrollStartTime; - var delay = (scrollTime > 2000 ? 50 : 300); - scrollRepeatTimer = window.setTimeout(f, delay); - }, 300); - $(document).bind('mouseup', clearScrollRepeatTimer); - } - - function clearScrollRepeatTimer() - { - if (scrollRepeatTimer) - { - window.clearTimeout(scrollRepeatTimer); - scrollRepeatTimer = null; - } - $(document).unbind('mouseup', clearScrollRepeatTimer); - } - - var pad = undefined; - var self = { - init: function(initialRevisions, _pad) - { - pad = _pad; - self.newRevisionList(initialRevisions, true); - - $("#savedrevs-savenow").click(function() - { - self.saveNow(); - }); - $("#savedrevs-scrollleft").mousedown(function() - { - self.scroll('left'); - setScrollRepeatTimer('left'); - }); - $("#savedrevs-scrollright").mousedown(function() - { - self.scroll('right'); - setScrollRepeatTimer('right'); - }); - $("#savedrevs-close").click(function() - { - paddocbar.setShownPanel(null); - }); - - // update "saved n minutes ago" times - window.setInterval(function() - { - refreshRevisionList(); - }, 60 * 1000); - }, - restoreRevision: function(rnum) - { - var rev = currentRevisionList[rnum]; - var warning = ("Restoring this revision will overwrite the current" + " text of the pad. " + "Are you sure you want to continue?"); - var hidePanel = paddocbar.hideLaterIfNoOtherInteraction(); - var box = getNthBox(rnum); - if (confirm(warning)) - { - box.find(".srtwirly").show(); - $.ajax( - { - type: 'get', - url: '/ep/pad/getrevisionatext', - data: { - padId: pad.getPadId(), - revId: rev.id - }, - success: success, - error: error - }); - } - - function success(resultJson) - { - untwirl(); - var result = JSON.parse(resultJson); - padeditor.restoreRevisionText(result); - window.setTimeout(function() - { - hidePanel(); - }, 0); - } - - function error(e) - { - untwirl(); - alert("Oops! There was an error retreiving the text (revNum= " + rev.revNum + "; padId=" + pad.getPadId()); - } - - function untwirl() - { - box.find(".srtwirly").hide(); - } - }, - showReachedLimit: function() - { - alert("Sorry, you do not have privileges to save more than " + pad.getPrivilege('maxRevisions') + " revisions."); - }, - newRevisionList: function(lst, noAnimation) - { - // server gives us list with newest first; - // we want chronological order - var L = reversedCopy(lst); - setRevisionList(L, noAnimation); - rerenderButton(); - }, - saveNow: function() - { - if (isSaving) - { - return; - } - if (!pad.isFullyConnected()) - { - return; - } - if (haveReachedRevLimit()) - { - self.showReachedLimit(); - return; - } - setIsSaving(true); - var savedBy = pad.getUserName() || "unnamed"; - pad.callWhenNotCommitting(submitSave); - - function submitSave() - { - $.ajax( - { - type: 'post', - url: '/ep/pad/saverevision', - data: { - padId: pad.getPadId(), - savedBy: savedBy, - savedById: pad.getUserId(), - revNum: pad.getCollabRevisionNumber() - }, - success: success, - error: error - }); - } - - function success(text) - { - setIsSaving(false); - var newRevisionList = JSON.parse(text); - self.newRevisionList(newRevisionList); - pad.sendClientMessage( - { - type: 'newRevisionList', - revisionList: newRevisionList, - savedBy: savedBy - }); - } - - function error(e) - { - setIsSaving(false); - alert("Oops! The server failed to save the revision. Please try again later."); - } - }, - handleResizePage: function() - { - updateScrollArrows(); - }, - handleIsFullyConnected: function(isConnected) - { - rerenderButton(); - }, - scroll: function(dir) - { - var minScroll = getMinScroll(); - var maxScroll = getMaxScroll(); - if (dir == 'left') - { - if (desiredScroll > minScroll) - { - var n = Math.floor((desiredScroll - 1 - minScroll) / REVISION_BOX_WIDTH); - setDesiredScroll(Math.max(0, n) * REVISION_BOX_WIDTH + minScroll); - } - } - else if (dir == 'right') - { - if (desiredScroll < maxScroll) - { - var n = Math.floor((maxScroll - desiredScroll - 1) / REVISION_BOX_WIDTH); - setDesiredScroll(maxScroll - Math.max(0, n) * REVISION_BOX_WIDTH); - } - } - } - }; - return self; -}()); - -exports.padsavedrevs = padsavedrevs; +exports.init = function(_pad){ + pad = _pad; +} diff --git a/static/pad.html b/static/pad.html index 0345d65b0..c326a116b 100644 --- a/static/pad.html +++ b/static/pad.html @@ -73,6 +73,11 @@