Added editor autosave controls
authorAlexander Ebert <ebert@woltlab.com>
Tue, 20 Sep 2016 09:23:29 +0000 (11:23 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Tue, 20 Sep 2016 09:23:29 +0000 (11:23 +0200)
com.woltlab.wcf/templates/wysiwyg.tpl
wcfsetup/install/files/acp/templates/wysiwyg.tpl
wcfsetup/install/files/js/3rdParty/redactor2/plugins/WoltLabAutosave.js
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Redactor/Autosave.js
wcfsetup/install/files/style/ui/redactor.scss
wcfsetup/install/lang/de.xml
wcfsetup/install/lang/en.xml

index 162b73b792781c030fcfa7f27e7eea022efee4b1..8d0a61da3e8a07f8f55eaa6869e11b1380870af9 100644 (file)
@@ -54,6 +54,8 @@
                                'wcf.attachment.dragAndDrop.dropHere': '{lang}wcf.attachment.dragAndDrop.dropHere{/lang}',
                                'wcf.attachment.dragAndDrop.dropNow': '{lang}wcf.attachment.dragAndDrop.dropNow{/lang}',
                                
+                               'wcf.editor.autosave.restored': '{lang}wcf.editor.autosave.restored{/lang}',
+                               
                                'wcf.editor.code.edit': '{lang}wcf.editor.code.edit{/lang}',
                                'wcf.editor.code.file': '{lang}wcf.editor.code.file{/lang}',
                                'wcf.editor.code.file.description': '{lang}wcf.editor.code.file.description{/lang}',
index 162b73b792781c030fcfa7f27e7eea022efee4b1..8d0a61da3e8a07f8f55eaa6869e11b1380870af9 100644 (file)
@@ -54,6 +54,8 @@
                                'wcf.attachment.dragAndDrop.dropHere': '{lang}wcf.attachment.dragAndDrop.dropHere{/lang}',
                                'wcf.attachment.dragAndDrop.dropNow': '{lang}wcf.attachment.dragAndDrop.dropNow{/lang}',
                                
+                               'wcf.editor.autosave.restored': '{lang}wcf.editor.autosave.restored{/lang}',
+                               
                                'wcf.editor.code.edit': '{lang}wcf.editor.code.edit{/lang}',
                                'wcf.editor.code.file': '{lang}wcf.editor.code.file{/lang}',
                                'wcf.editor.code.file.description': '{lang}wcf.editor.code.file.description{/lang}',
index 2c9762a26b3d5344e1835aa9f6e010aadb8eafc4..7b033d53998f05bcae49c13b2b8bb52734d36f16 100644 (file)
@@ -7,6 +7,8 @@ $.Redactor.prototype.WoltLabAutosave = function() {
                        if (this.opts.woltlab.autosave) {
                                //noinspection JSUnresolvedVariable
                                this.opts.woltlab.autosave.watch(this);
+                               //noinspection JSUnresolvedVariable
+                               this.opts.woltlab.autosave.createOverlay();
                                
                                WCF.System.Event.addListener('com.woltlab.wcf.redactor2', 'autosaveDestroy_' + this.$element[0].id, this.WoltLabAutosave.destroy.bind(this));
                                WCF.System.Event.addListener('com.woltlab.wcf.redactor2', 'autosaveReset_' + this.$element[0].id, this.WoltLabAutosave.reset.bind(this));
index d964565cefb119f96f54ba2aa310d029cacd184f..fd51448f62de7ebe16df08fe9683d805c0f69383 100644 (file)
@@ -7,7 +7,7 @@
  * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
  * @module     WoltLabSuite/Core/Ui/Redactor/Autosave
  */
-define(['Dom/Traverse'], function(DomTraverse) {
+define(['Language', 'Dom/Traverse'], function(Language, DomTraverse) {
        "use strict";
        
        // time between save requests in seconds
@@ -28,10 +28,14 @@ define(['Dom/Traverse'], function(DomTraverse) {
                 * @param       {Element}       element         textarea element
                 */
                init: function (element) {
+                       this._container = null;
                        this._editor = null;
                        this._element = element;
                        this._key = _prefix + elData(this._element, 'autosave');
                        this._lastMessage = '';
+                       this._originalMessage = '';
+                       this._overlay = null;
+                       this._restored = false;
                        this._timer = null;
                        
                        this._cleanup();
@@ -75,6 +79,10 @@ define(['Dom/Traverse'], function(DomTraverse) {
                                        return this._element.value;
                                }
                                
+                               //noinspection JSUnresolvedVariable
+                               this._originalMessage = this._element.value;
+                               this._restored = true;
+                               
                                return value.content;
                        }
                        
@@ -125,6 +133,71 @@ define(['Dom/Traverse'], function(DomTraverse) {
                        }
                },
                
+               /**
+                * Creates the autosave controls, used to keep or discard the restored draft.
+                */
+               createOverlay: function () {
+                       if (!this._restored) {
+                               return;
+                       }
+                       
+                       var container = elCreate('div');
+                       container.className = 'redactorAutosaveRestored active';
+                       
+                       var title = elCreate('span');
+                       title.textContent = Language.get('wcf.editor.autosave.restored');
+                       container.appendChild(title);
+                       
+                       var button = elCreate('a');
+                       button.href = '#';
+                       button.innerHTML = '<span class="icon icon16 fa-check green"></span>';
+                       button.addEventListener(WCF_CLICK_EVENT, (function (event) {
+                               event.preventDefault();
+                               
+                               this.hideOverlay();
+                       }).bind(this));
+                       container.appendChild(button);
+                       
+                       button = elCreate('a');
+                       button.href = '#';
+                       button.innerHTML = '<span class="icon icon16 fa-times red"></span>';
+                       button.addEventListener(WCF_CLICK_EVENT, (function (event) {
+                               event.preventDefault();
+                               
+                               // remove from storage
+                               this.clear();
+                               
+                               // set code
+                               this._editor.code.start(this._originalMessage);
+                               
+                               // set value
+                               this._editor.core.textarea().val(this._editor.clean.onSync(this._editor.$editor.html()));
+                               
+                               this.hideOverlay();
+                       }).bind(this));
+                       container.appendChild(button);
+                       
+                       this._editor.core.box()[0].appendChild(container);
+                       
+                       this._container = container;
+               },
+               
+               /**
+                * Hides the autosave controls.
+                */
+               hideOverlay: function () {
+                       if (this._container !== null) {
+                               this._container.classList.remove('active');
+                               
+                               window.setTimeout((function () {
+                                       elRemove(this._container);
+                                       
+                                       this._container = null;
+                                       this._originalMessage = '';
+                               }).bind(this), 1000);
+                       }
+               },
+               
                /**
                 * Saves the current message to storage unless there was no change.
                 * 
@@ -148,6 +221,8 @@ define(['Dom/Traverse'], function(DomTraverse) {
                                }));
                                
                                this._lastMessage = content;
+                               
+                               this.hideOverlay();
                        }
                        catch (e) {
                                window.console.warn("Unable to write to local storage: " + e.message);
index be3ca19efe67a84d2e739396e1de0abef102df43..89456b6b527aaa9b257709f166ace0feae0b9340 100644 (file)
                }
        }
 }
+
+.redactorAutosaveRestored {
+       background-color: $wcfContentBackground;
+       border-top: 1px solid $wcfContentBorderInner;
+       bottom: 1px;
+       display: flex;
+       opacity: 0;
+       position: absolute;
+       right: 1px;
+       transition: opacity .12s linear, visibility 0s linear .12s;
+       visibility: hidden;
+       
+       &.active {
+               opacity: 1;
+               transition-delay: 0s;
+               visibility: visible;
+       }
+       
+       > a {
+               border-left: 1px solid $wcfContentBorderInner;
+               flex: 0 0 auto;
+               padding: 10px;
+       }
+       
+       > span {
+               color: $wcfContentDimmedText;
+               flex: 1 1 auto;
+               padding: 10px;
+       }
+       
+       @include screen-sm-up {
+               border-left: 1px solid $wcfContentBorderInner;
+               border-top-left-radius: 2px;
+               
+               > span {
+                       padding: 10px 20px;
+               }
+       }
+       
+       @include screen-xs {
+               left: 1px;
+               
+               > span {
+                       text-align: center;
+               }
+       }
+}
index 5437a97a36a56d20054b61b2d4cb16a73cbcb760..ebf10f99de04fab5e3001388f7468cd464d64372 100644 (file)
@@ -2350,6 +2350,8 @@ Fehler sind beispielsweise:
                <item name="wcf.editor.alignment.left"><![CDATA[Linksbündig ausrichten]]></item>
                <item name="wcf.editor.alignment.right"><![CDATA[Rechtsbündig ausrichten]]></item>
                
+               <item name="wcf.editor.autosave.restored"><![CDATA[Entwurf wiederhergestellt]]></item>
+               
                <item name="wcf.editor.button.alignment"><![CDATA[Ausrichtung]]></item>
                <item name="wcf.editor.button.bold"><![CDATA[Fett]]></item>
                <item name="wcf.editor.button.code"><![CDATA[Code]]></item>
index fcbd6b9ea0a69a69a63778e06e9a5adea4412f55..6630e0800a741f7c23f975e35678694206f2339c 100644 (file)
@@ -2312,6 +2312,8 @@ Errors are:
                <item name="wcf.editor.alignment.left"><![CDATA[Align left]]></item>
                <item name="wcf.editor.alignment.right"><![CDATA[Align right]]></item>
                
+               <item name="wcf.editor.autosave.restored"><![CDATA[Draft restored]]></item>
+               
                <item name="wcf.editor.button.alignment"><![CDATA[Alignment]]></item>
                <item name="wcf.editor.button.bold"><![CDATA[Bold]]></item>
                <item name="wcf.editor.button.code"><![CDATA[Code]]></item>