Improved rebuild data UI/UX
authorAlexander Ebert <ebert@woltlab.com>
Tue, 21 Nov 2017 11:48:43 +0000 (12:48 +0100)
committerAlexander Ebert <ebert@woltlab.com>
Tue, 21 Nov 2017 11:48:43 +0000 (12:48 +0100)
Actions no longer force a page reload with the exception to the database
encoding conversion after an import.

Successfully completed actions will now display a notice adjacent to the
button, making it easier to tell already executed actions apart.

wcfsetup/install/files/acp/js/WCF.ACP.js
wcfsetup/install/files/acp/templates/rebuildData.tpl
wcfsetup/install/files/js/WoltLabSuite/Core/Acp/Ui/Worker.js [new file with mode: 0644]
wcfsetup/install/lang/de.xml
wcfsetup/install/lang/en.xml

index a5760d3ff647ad98d437b8c7ec2e3a324db51180..7cca145c9a2f7b0da1de28a035aa97f619110e9f 100644 (file)
@@ -1567,44 +1567,10 @@ WCF.ACP.PluginStore.PurchasedItems.Search = Class.extend({
  * @param      string          title
  * @param      object          parameters
  * @param      object          callback
+ * 
+ * @deprecated  3.1 - please use `WoltLabSuite/Core/Acp/Ui/Worker` instead
  */
 WCF.ACP.Worker = Class.extend({
-       /**
-        * worker aborted
-        * @var boolean
-        */
-       _aborted: false,
-       
-       /**
-        * callback invoked after worker completed
-        * @var object
-        */
-       _callback: null,
-       
-       /**
-        * dialog id
-        * @var string
-        */
-       _dialogID: null,
-       
-       /**
-        * dialog object
-        * @var jQuery
-        */
-       _dialog: null,
-       
-       /**
-        * action proxy
-        * @var WCF.Action.Proxy
-        */
-       _proxy: null,
-       
-       /**
-        * dialog title
-        * @var string
-        */
-       _title: '',
-       
        /**
         * Initializes a new worker instance.
         * 
@@ -1613,81 +1579,23 @@ WCF.ACP.Worker = Class.extend({
         * @param       string          title
         * @param       object          parameters
         * @param       object          callback
-        * @param       object          confirmMessage
         */
        init: function(dialogID, className, title, parameters, callback) {
-               this._aborted = false;
-               this._callback = callback || null;
-               this._dialogID = dialogID + 'Worker';
-               this._dialog = null;
-               this._proxy = new WCF.Action.Proxy({
-                       autoSend: true,
-                       data: {
-                               className: className,
-                               parameters: parameters || { }
-                       },
-                       showLoadingOverlay: false,
-                       success: $.proxy(this._success, this),
-                       url: 'index.php?worker-proxy/&t=' + SECURITY_TOKEN
-               });
-               this._title = title;
-       },
-       
-       /**
-        * Handles response from server.
-        * 
-        * @param       object          data
-        */
-       _success: function(data) {
-               // init binding
-               if (this._dialog === null) {
-                       this._dialog = $('<div id="' + this._dialogID + '" />').hide().appendTo(document.body);
-                       this._dialog.wcfDialog({
-                               closeConfirmMessage: WCF.Language.get('wcf.acp.worker.abort.confirmMessage'),
-                               closeViaModal: false,
-                               onClose: $.proxy(function() {
-                                       this._aborted = true;
-                                       this._proxy.abortPrevious();
-                                       
-                                       window.location.reload();
-                               }, this),
-                               title: this._title
-                       });
-               }
-               
-               if (this._aborted) {
-                       return;
+               if (typeof callback === 'function') {
+                       throw new Error("The callback parameter is no longer supported, please migrate to 'WoltLabSuite/Core/Acp/Ui/Worker'.");
                }
                
-               if (data.template) {
-                       this._dialog.html(data.template);
-               }
-               
-               // update progress
-               this._dialog.find('progress').attr('value', data.progress).text(data.progress + '%').next('span').text(data.progress + '%');
-               
-               // worker is still busy with its business, carry on
-               if (data.progress < 100) {
-                       // send request for next loop
-                       this._proxy.setOption('data', {
-                               className: data.className,
-                               loopCount: data.loopCount,
-                               parameters: data.parameters
+               require(['WoltLabSuite/Core/Acp/Ui/Worker'], function(AcpUiWorker) {
+                       new AcpUiWorker({
+                               // dialog
+                               dialogId: dialogID,
+                               dialogTitle: title,
+                               
+                               // ajax
+                               className: className,
+                               parameters: parameters
                        });
-                       this._proxy.sendRequest();
-               }
-               else if (this._callback !== null) {
-                       this._callback(this, data);
-               }
-               else {
-                       this._dialog.find('.fa-spinner').removeClass('fa-spinner').addClass('fa-check');
-                       
-                       // display continue button
-                       var $formSubmit = $('<div class="formSubmit" />').appendTo(this._dialog);
-                       $('<button class="buttonPrimary">' + WCF.Language.get('wcf.global.button.next') + '</button>').appendTo($formSubmit).focus().click(function() { window.location = data.proceedURL; });
-                       
-                       this._dialog.wcfDialog('render');
-               }
+               });
        }
 });
 
index fc50f88e75eab9e1ba83995fdb996e42c58f03fb..61a92ee3caee1a34ea1805020832fb26acb8fec3 100644 (file)
@@ -1,9 +1,45 @@
 {include file='header' pageTitle='wcf.acp.rebuildData'}
 
 <script data-relocate="true">
-               $(function() {
-                       WCF.Language.add('wcf.acp.worker.abort.confirmMessage', '{lang}wcf.acp.worker.abort.confirmMessage{/lang}');
+       require(['Language', 'WoltLabSuite/Core/Acp/Ui/Worker'], function (Language, AcpUiWorker) {
+               Language.add('wcf.acp.worker.abort.confirmMessage', '{lang}wcf.acp.worker.abort.confirmMessage{/lang}');
+               
+               elBySelAll('.jsRebuildDataWorker', undefined, function (button) {
+                       if (button.classList.contains('disabled')) return;
+                       
+                       button.addEventListener(WCF_CLICK_EVENT, function (event) {
+                               event.preventDefault();
+                               
+                               new AcpUiWorker({
+                                       // dialog
+                                       dialogId: 'cache',
+                                       dialogTitle: button.textContent,
+                                       
+                                       // ajax
+                                       className: elData(button, 'class-name'),
+                                       loopCount: -1,
+                                       parameters: { },
+                                       
+                                       // callbacks
+                                       callbackAbort: null,
+                                       callbackFailure: null,
+                                       callbackSuccess: function() {
+                                               {if $convertEncoding}
+                                                       var span = button.nextElementSibling;
+                                                       if (span && span.nodeName === 'SPAN') elRemove(span);
+                                                               
+                                                       span = elCreate('span');
+                                                       span.innerHTML = ' <span class="icon icon16 fa-check green"></span> {lang}wcf.acp.worker.success{/lang}';
+                                                       button.parentNode.insertBefore(span, button.nextElementSibling);
+                                               {else}
+                                                       // force reload after converting the database encoding
+                                                       window.location.reload();
+                                               {/if}
+                                       }
+                               });
+                       });
                });
+       });
 </script>
 
 <header class="contentHeader">
                
                <dl class="wide">
                        <dd>
-                               <a class="button small{if !$_allowRebuild} disabled{/if}" id="rebuildData{@$objectType->objectTypeID}">{lang}wcf.acp.rebuildData.{@$objectType->objectType}{/lang}</a>
+                               <a href="#"
+                                  class="button small jsRebuildDataWorker{if !$_allowRebuild} disabled{/if}"
+                                  data-class-name="{$objectType->className}" data-object-type="{$objectType->objectType}"
+                               >{lang}wcf.acp.rebuildData.{@$objectType->objectType}{/lang}</a>
                                <small>{lang}wcf.acp.rebuildData.{@$objectType->objectType}.description{/lang}</small>
-                               
-                               {if $_allowRebuild}
-                                       <script data-relocate="true">
-                                               $(function() {
-                                                       $('#rebuildData{@$objectType->objectTypeID}').click(function () {
-                                                               new WCF.ACP.Worker('cache', '{@$objectType->className|encodeJS}', '{lang}wcf.acp.rebuildData.{@$objectType->objectType}{/lang}');
-                                                       });
-                                               });
-                                       </script>
-                               {/if}
                        </dd>
                </dl>
        {/foreach}
diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Acp/Ui/Worker.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Acp/Ui/Worker.js
new file mode 100644 (file)
index 0000000..1a54ba2
--- /dev/null
@@ -0,0 +1,143 @@
+/**
+ * Worker manager with support for custom callbacks and loop counts.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2017 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @module     WoltLabSuite/Core/Acp/Ui/Worker
+ */
+define(['Ajax', 'Core', 'Language', 'Ui/Dialog'], function(Ajax, Core, Language, UiDialog) {
+       "use strict";
+       
+       /**
+        * Creates a new worker instance.
+        * 
+        * @param       {Object}        options         configuration options
+        * @constructor
+        */
+       function AcpUiWorker(options) { this.init(options); }
+       AcpUiWorker.prototype = {
+               /**
+                * Creates a new worker instance.
+                * 
+                * @param       {Object}        options         configuration options
+                */
+               init: function (options) {
+                       this._aborted = false;
+                       this._options = Core.extend({
+                               // dialog
+                               dialogId: '',
+                               dialogTitle: '',
+                               
+                               // ajax
+                               className: '',
+                               loopCount: -1,
+                               parameters: {},
+                               
+                               // callbacks
+                               callbackAbort: null,
+                               callbackFailure: null,
+                               callbackSuccess: null
+                       }, options);
+                       this._options.dialogId += 'Worker';
+                       
+                       this._request = Ajax.api(this);
+               },
+               
+               _ajaxSuccess: function (data) {
+                       if (this._aborted) return;
+                       
+                       if (typeof data.template === 'string') {
+                               UiDialog.open(this, data.template);
+                       }
+                       
+                       var content = UiDialog.getDialog(this).content;
+                       
+                       // update progress
+                       var progress = elBySel('progress', content);
+                       progress.value = data.progress;
+                       progress.nextElementSibling.textContent = data.progress + '%';
+                       
+                       // worker is still busy
+                       if (data.progress < 100) {
+                               Ajax.api(this, {
+                                       loopCount: data.loopCount,
+                                       parameters: data.parameters
+                               });
+                       }
+                       else {
+                               var spinner = elBySel('.fa-spinner', content);
+                               spinner.classList.remove('fa-spinner');
+                               spinner.classList.add('fa-check');
+                               spinner.classList.add('green');
+                               
+                               var formSubmit = elCreate('div');
+                               formSubmit.className = 'formSubmit';
+                               formSubmit.innerHTML = '<button class="buttonPrimary">' + Language.get('wcf.global.button.next') + '</button>';
+                               
+                               content.appendChild(formSubmit);
+                               UiDialog.rebuild(this);
+                               
+                               var button = formSubmit.children[0];
+                               button.addEventListener(WCF_CLICK_EVENT, (function(event) {
+                                       event.preventDefault();
+                                       
+                                       if (typeof this._options.callbackSuccess === 'function') {
+                                               this._options.callbackSuccess(data);
+                                               
+                                               UiDialog.close(this);
+                                       }
+                                       else {
+                                               window.location = data.proceedURL;
+                                       }
+                               }).bind(this));
+                       }
+               },
+               
+               _ajaxFailure: function () {
+                       var dialog = UiDialog.getDialog(this);
+                       if (dialog !== null) {
+                               var spinner = elBySel('.fa-spinner', dialog.content);
+                               spinner.classList.remove('fa-spinner');
+                               spinner.classList.add('fa-times');
+                               spinner.classList.add('red');
+                       }
+               },
+               
+               _ajaxSetup: function () {
+                       return {
+                               data: {
+                                       className: this._options.className,
+                                       loopCount: this._options.loopCount,
+                                       parameters: this._options.parameters
+                               },
+                               silent: true,
+                               url: 'index.php?worker-proxy/&t=' + SECURITY_TOKEN
+                       };
+               },
+               
+               _dialogSetup: function () {
+                       return {
+                               id: this._options.dialogId,
+                               onClose: (function () {
+                                       this._aborted = true;
+                                       this._request.abortPrevious();
+                                       
+                                       if (typeof this._options.callbackAbort === 'function') {
+                                               this._options.callbackAbort();
+                                       }
+                                       else {
+                                               window.location.reload();
+                                       }
+                               }).bind(this),
+                               options: {
+                                       backdropCloseOnClick: false,
+                                       title: this._options.dialogTitle
+                               },
+                               source: null
+                       }
+               }
+       };
+       
+       return AcpUiWorker;
+});
index e81a1b5150b5227016194df31706b060f90f5c70..60493870b2bcf4d994674936745804880e6eb00f 100644 (file)
@@ -2268,6 +2268,7 @@ Benutzerkontos nun in vollem Umfang nutzen.]]></item>
        
        <category name="wcf.acp.worker">
                <item name="wcf.acp.worker.abort.confirmMessage"><![CDATA[{if LANGUAGE_USE_INFORMAL_VARIANT}Willst du{else}Wollen Sie{/if} die Ausführung wirklich abbrechen?]]></item>
+               <item name="wcf.acp.worker.success"><![CDATA[Aufgabe abgeschlossen]]></item>
        </category>
        
        <category name="wcf.ajax">
index d8aa4407130e294b765d310c109286caa244ef8e..11c926ee44180155799323485e6111a264112a10 100644 (file)
@@ -2204,6 +2204,7 @@ full extend.]]></item>
        
        <category name="wcf.acp.worker">
                <item name="wcf.acp.worker.abort.confirmMessage"><![CDATA[Do you really want to terminate the execution?]]></item>
+               <item name="wcf.acp.worker.success"><![CDATA[Task completed]]></item>
        </category>
        
        <category name="wcf.ajax">