Convert `Acp/Ui/Page/BoxOrder` to TypeScript
authorAlexander Ebert <ebert@woltlab.com>
Mon, 30 Nov 2020 00:18:26 +0000 (01:18 +0100)
committerAlexander Ebert <ebert@woltlab.com>
Mon, 30 Nov 2020 00:18:26 +0000 (01:18 +0100)
global.d.ts
wcfsetup/install/files/acp/templates/pageBoxOrder.tpl
wcfsetup/install/files/js/WoltLabSuite/Core/Acp/Ui/Page/BoxOrder.js
wcfsetup/install/files/ts/WoltLabSuite/Core/Acp/Ui/Page/BoxOrder.js [deleted file]
wcfsetup/install/files/ts/WoltLabSuite/Core/Acp/Ui/Page/BoxOrder.ts [new file with mode: 0644]

index 73b8a0c5abdcd3c70c2e177585a1b5c1a487f949..45b8cc974343fadb8fbae6ec1724ecd77a2cfeb4 100644 (file)
@@ -34,6 +34,8 @@ declare global {
   }
 
   interface JQuery {
+    sortable(...args: any[]): unknown;
+
     redactor(...args: any[]): unknown;
   }
 
index 39e74ffd6e85d9f118fdbbd1b07ea3afea48a409..c4e0c2f95b6992c3aaa92ee491b61273840d444d 100644 (file)
                        'wcf.acp.page.boxOrder.discard.confirmMessage': '{jslang}wcf.acp.page.boxOrder.discard.confirmMessage{/jslang}'
                });
                
-               var boxes = new Dictionary();
+               const boxes = new Map();
                {foreach from=$boxes key=position item=boxData}
                        {if $position != 'mainMenu'}
-                               boxes.set('{$position}', [{implode from=$boxData item=box}{ boxID: {@$box->boxID}, name: '{$box->name|encodeJS}', isDisabled: {if $box->isDisabled}true{else}false{/if} }{/implode}]);
+                               boxes.set('{$position}', [{implode from=$boxData item=box}{ boxId: {@$box->boxID}, name: '{$box->name|encodeJS}', isDisabled: {if $box->isDisabled}true{else}false{/if} }{/implode}]);
                        {/if}
                {/foreach}
                
index ef082080f37df0460ed88bc533804045e3137638..235cc55574e05da8cd7d156c7afc825e323bc76e 100644 (file)
  * Provides helper functions to sort boxes per page.
  *
  * @author      Alexander Ebert
- * @copyright  2001-2019 WoltLab GmbH
+ * @copyright  2001-2019 WoltLab GmbH
  * @license     GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
  * @module      WoltLabSuite/Core/Acp/Ui/Page/BoxOrder
  */
-define(['Ajax', 'Language', 'Dom/ChangeListener', 'Ui/Confirmation', 'Ui/Notification'], function (Ajax, Language, DomChangeListener, UiConfirmation, UiNotification) {
+define(["require", "exports", "tslib", "../../../Ajax", "../../../Dom/Change/Listener", "../../../Language", "../../../Ui/Confirmation", "../../../Ui/Notification"], function (require, exports, tslib_1, Ajax, Listener_1, Language, UiConfirmation, UiNotification) {
     "use strict";
-    var _pageId = 0;
-    var _pbo = elById('pbo');
-    /**
-     * @exports     WoltLabSuite/Core/Acp/Ui/Page/BoxOrder
-     */
-    return {
+    Object.defineProperty(exports, "__esModule", { value: true });
+    exports.init = void 0;
+    Ajax = tslib_1.__importStar(Ajax);
+    Listener_1 = tslib_1.__importDefault(Listener_1);
+    Language = tslib_1.__importStar(Language);
+    UiConfirmation = tslib_1.__importStar(UiConfirmation);
+    UiNotification = tslib_1.__importStar(UiNotification);
+    class AcpUiPageBoxOrder {
         /**
          * Initializes the sorting capabilities.
-         *
-         * @param       {int}           pageId          page id
-         * @param       {Dictionary}    boxes           list of boxes per position
          */
-        init: function (pageId, boxes) {
-            _pageId = pageId;
-            boxes.forEach(function (boxData, position) {
-                var container = elCreate('ul');
-                boxData.forEach(function (box) {
-                    var item = elCreate('li');
-                    elData(item, 'box-id', box.boxID);
-                    var icon = '';
+        constructor(pageId, boxes) {
+            this.pageId = pageId;
+            this.pbo = document.getElementById("pbo");
+            boxes.forEach((boxData, position) => {
+                const container = document.createElement("ul");
+                boxData.forEach((box) => {
+                    const item = document.createElement("li");
+                    item.dataset.boxId = box.boxId.toString();
+                    let icon = "";
                     if (box.isDisabled) {
-                        icon = ' <span class="icon icon16 fa-exclamation-triangle red jsTooltip" title="' + Language.get('wcf.acp.box.isDisabled') + '"></span>';
+                        icon = ` <span class="icon icon16 fa-exclamation-triangle red jsTooltip" title="${Language.get("wcf.acp.box.isDisabled")}"></span>`;
                     }
                     item.innerHTML = box.name + icon;
                     container.appendChild(item);
                 });
                 if (boxData.length > 1) {
                     window.jQuery(container).sortable({
-                        opacity: .6,
-                        placeholder: 'sortablePlaceholder'
+                        opacity: 0.6,
+                        placeholder: "sortablePlaceholder",
                     });
                 }
-                elBySel('[data-placeholder="' + position + '"]', _pbo).appendChild(container);
+                const wrapper = this.pbo.querySelector(`[data-placeholder="${position}"]`);
+                wrapper.appendChild(container);
             });
-            elBySel('button[data-type="submit"]').addEventListener('click', this._save.bind(this));
-            var buttonDiscard = elBySel('.jsButtonCustomShowOrder');
+            const submitButton = document.querySelector('button[data-type="submit"]');
+            submitButton.addEventListener("click", (ev) => this.save(ev));
+            const buttonDiscard = document.querySelector(".jsButtonCustomShowOrder");
             if (buttonDiscard)
-                buttonDiscard.addEventListener('click', this._discard.bind(this));
-            DomChangeListener.trigger();
-        },
+                buttonDiscard.addEventListener("click", (ev) => this.discard(ev));
+            Listener_1.default.trigger();
+        }
         /**
          * Saves the order of all boxes per position.
-         *
-         * @param       {Event}         event           event object
-         * @protected
          */
-        _save: function (event) {
+        save(event) {
             event.preventDefault();
-            var data = {};
+            const data = {};
             // collect data
-            elBySelAll('[data-placeholder]', _pbo, function (position) {
-                var boxes = [];
-                elBySelAll('li', position, function (li) {
-                    var id = ~~elData(li, 'box-id');
-                    if (id)
-                        boxes.push(id);
-                });
-                data[elData(position, 'placeholder')] = boxes;
+            this.pbo.querySelectorAll("[data-placeholder]").forEach((position) => {
+                const boxIds = Array.from(position.querySelectorAll("li"))
+                    .map((element) => ~~element.dataset.boxId)
+                    .filter((id) => id > 0);
+                const placeholder = position.dataset.placeholder;
+                data[placeholder] = boxIds;
             });
             Ajax.api(this, {
                 parameters: {
-                    position: data
-                }
+                    position: data,
+                },
             });
-        },
+        }
         /**
          * Shows an dialog to discard the individual box show order for this page.
-         *
-         * @param       {Event}         event           event object
-         * @protected
          */
-        _discard: function (event) {
+        discard(event) {
             event.preventDefault();
             UiConfirmation.show({
-                confirm: (function () {
+                confirm: () => {
                     Ajax.api(this, {
-                        actionName: 'resetPosition'
+                        actionName: "resetPosition",
                     });
-                }).bind(this),
-                message: Language.get('wcf.acp.page.boxOrder.discard.confirmMessage')
+                },
+                message: Language.get("wcf.acp.page.boxOrder.discard.confirmMessage"),
             });
-        },
-        _ajaxSuccess: function (data) {
+        }
+        _ajaxSuccess(data) {
             switch (data.actionName) {
-                case 'updatePosition':
+                case "updatePosition":
                     UiNotification.show();
                     break;
-                case 'resetPosition':
-                    UiNotification.show(undefined, function () {
+                case "resetPosition":
+                    UiNotification.show(undefined, () => {
                         window.location.reload();
                     });
                     break;
             }
-        },
-        _ajaxSetup: function () {
+        }
+        _ajaxSetup() {
             return {
                 data: {
-                    actionName: 'updatePosition',
-                    className: 'wcf\\data\\page\\PageAction',
-                    interfaceName: 'wcf\\data\\ISortableAction',
-                    objectIDs: [_pageId]
-                }
+                    actionName: "updatePosition",
+                    className: "wcf\\data\\page\\PageAction",
+                    interfaceName: "wcf\\data\\ISortableAction",
+                    objectIDs: [this.pageId],
+                },
             };
         }
-    };
+    }
+    let acpUiPageBoxOrder;
+    /**
+     * Initializes the sorting capabilities.
+     */
+    function init(pageId, boxes) {
+        if (!acpUiPageBoxOrder) {
+            acpUiPageBoxOrder = new AcpUiPageBoxOrder(pageId, boxes);
+        }
+    }
+    exports.init = init;
 });
diff --git a/wcfsetup/install/files/ts/WoltLabSuite/Core/Acp/Ui/Page/BoxOrder.js b/wcfsetup/install/files/ts/WoltLabSuite/Core/Acp/Ui/Page/BoxOrder.js
deleted file mode 100644 (file)
index cad31e2..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-/**
- * Provides helper functions to sort boxes per page.
- *
- * @author      Alexander Ebert
- * @copyright  2001-2019 WoltLab GmbH
- * @license     GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @module      WoltLabSuite/Core/Acp/Ui/Page/BoxOrder
- */
-define(['Ajax', 'Language', 'Dom/ChangeListener', 'Ui/Confirmation', 'Ui/Notification'], function (Ajax, Language, DomChangeListener, UiConfirmation, UiNotification) {
-       "use strict";
-       
-       var _pageId = 0;
-       var _pbo = elById('pbo');
-       
-       /**
-        * @exports     WoltLabSuite/Core/Acp/Ui/Page/BoxOrder
-        */
-       return {
-               /**
-                * Initializes the sorting capabilities.
-                * 
-                * @param       {int}           pageId          page id
-                * @param       {Dictionary}    boxes           list of boxes per position
-                */
-               init: function (pageId, boxes) {
-                       _pageId = pageId;
-                       
-                       boxes.forEach(function(boxData, position) {
-                               var container = elCreate('ul');
-                               boxData.forEach(function(box) {
-                                       var item = elCreate('li');
-                                       elData(item, 'box-id', box.boxID);
-                                       
-                                       var icon = '';
-                                       if (box.isDisabled) {
-                                               icon = ' <span class="icon icon16 fa-exclamation-triangle red jsTooltip" title="' + Language.get('wcf.acp.box.isDisabled') + '"></span>';
-                                       }
-                                       
-                                       item.innerHTML = box.name + icon;
-                                       
-                                       container.appendChild(item);
-                               });
-                               
-                               if (boxData.length > 1) {
-                                       window.jQuery(container).sortable({
-                                               opacity: .6,
-                                               placeholder: 'sortablePlaceholder'
-                                       });
-                               }
-                               
-                               elBySel('[data-placeholder="' + position + '"]', _pbo).appendChild(container);
-                       });
-                       
-                       elBySel('button[data-type="submit"]').addEventListener('click', this._save.bind(this));
-                       
-                       var buttonDiscard = elBySel('.jsButtonCustomShowOrder');
-                       if (buttonDiscard) buttonDiscard.addEventListener('click', this._discard.bind(this));
-                       
-                       DomChangeListener.trigger();
-               },
-               
-               /**
-                * Saves the order of all boxes per position.
-                * 
-                * @param       {Event}         event           event object
-                * @protected
-                */
-               _save: function (event) {
-                       event.preventDefault();
-                       
-                       var data = {};
-                       
-                       // collect data
-                       elBySelAll('[data-placeholder]', _pbo, function (position) {
-                               var boxes = [];
-                               elBySelAll('li', position, function (li) {
-                                       var id = ~~elData(li, 'box-id');
-                                       if (id) boxes.push(id);
-                               });
-                               
-                               data[elData(position, 'placeholder')] = boxes;
-                       });
-                       
-                       Ajax.api(this, {
-                               parameters: {
-                                       position: data
-                               }
-                       });
-               },
-               
-               /**
-                * Shows an dialog to discard the individual box show order for this page.
-                * 
-                * @param       {Event}         event           event object
-                * @protected
-                */
-               _discard: function (event) {
-                       event.preventDefault();
-                       
-                       UiConfirmation.show({
-                               confirm: (function () {
-                                       Ajax.api(this, {
-                                               actionName: 'resetPosition'
-                                       });
-                               }).bind(this),
-                               message: Language.get('wcf.acp.page.boxOrder.discard.confirmMessage')
-                       })
-               },
-               
-               _ajaxSuccess: function (data) {
-                       switch (data.actionName) {
-                               case 'updatePosition':
-                                       UiNotification.show();
-                                       break;
-                                       
-                               case 'resetPosition':
-                                       UiNotification.show(undefined, function () {
-                                               window.location.reload();
-                                       });
-                                       break;
-                       }
-               },
-               
-               _ajaxSetup: function () {
-                       return {
-                               data: {
-                                       actionName: 'updatePosition',
-                                       className: 'wcf\\data\\page\\PageAction',
-                                       interfaceName: 'wcf\\data\\ISortableAction',
-                                       objectIDs: [_pageId]
-                               }
-                       };
-               }
-       };
-});
diff --git a/wcfsetup/install/files/ts/WoltLabSuite/Core/Acp/Ui/Page/BoxOrder.ts b/wcfsetup/install/files/ts/WoltLabSuite/Core/Acp/Ui/Page/BoxOrder.ts
new file mode 100644 (file)
index 0000000..b2378c3
--- /dev/null
@@ -0,0 +1,152 @@
+/**
+ * Provides helper functions to sort boxes per page.
+ *
+ * @author      Alexander Ebert
+ * @copyright  2001-2019 WoltLab GmbH
+ * @license     GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @module      WoltLabSuite/Core/Acp/Ui/Page/BoxOrder
+ */
+
+import * as Ajax from "../../../Ajax";
+import DomChangeListener from "../../../Dom/Change/Listener";
+import * as Language from "../../../Language";
+import * as UiConfirmation from "../../../Ui/Confirmation";
+import * as UiNotification from "../../../Ui/Notification";
+import { AjaxCallbackSetup } from "../../../Ajax/Data";
+
+interface AjaxResponse {
+  actionName: string;
+}
+
+interface BoxData {
+  boxId: number;
+  isDisabled: boolean;
+  name: string;
+}
+
+class AcpUiPageBoxOrder {
+  private readonly pageId: number;
+  private readonly pbo: HTMLElement;
+
+  /**
+   * Initializes the sorting capabilities.
+   */
+  constructor(pageId: number, boxes: Map<string, BoxData[]>) {
+    this.pageId = pageId;
+    this.pbo = document.getElementById("pbo")!;
+
+    boxes.forEach((boxData, position) => {
+      const container = document.createElement("ul");
+      boxData.forEach((box) => {
+        const item = document.createElement("li");
+        item.dataset.boxId = box.boxId.toString();
+
+        let icon = "";
+        if (box.isDisabled) {
+          icon = ` <span class="icon icon16 fa-exclamation-triangle red jsTooltip" title="${Language.get(
+            "wcf.acp.box.isDisabled",
+          )}"></span>`;
+        }
+
+        item.innerHTML = box.name + icon;
+
+        container.appendChild(item);
+      });
+
+      if (boxData.length > 1) {
+        window.jQuery(container).sortable({
+          opacity: 0.6,
+          placeholder: "sortablePlaceholder",
+        });
+      }
+
+      const wrapper = this.pbo.querySelector(`[data-placeholder="${position}"]`) as HTMLElement;
+      wrapper.appendChild(container);
+    });
+
+    const submitButton = document.querySelector('button[data-type="submit"]') as HTMLButtonElement;
+    submitButton.addEventListener("click", (ev) => this.save(ev));
+
+    const buttonDiscard = document.querySelector(".jsButtonCustomShowOrder") as HTMLAnchorElement;
+    if (buttonDiscard) buttonDiscard.addEventListener("click", (ev) => this.discard(ev));
+
+    DomChangeListener.trigger();
+  }
+
+  /**
+   * Saves the order of all boxes per position.
+   */
+  private save(event: MouseEvent): void {
+    event.preventDefault();
+
+    const data = {};
+
+    // collect data
+    this.pbo.querySelectorAll("[data-placeholder]").forEach((position: HTMLElement) => {
+      const boxIds = Array.from(position.querySelectorAll("li"))
+        .map((element) => ~~element.dataset.boxId!)
+        .filter((id) => id > 0);
+
+      const placeholder = position.dataset.placeholder!;
+      data[placeholder] = boxIds;
+    });
+
+    Ajax.api(this, {
+      parameters: {
+        position: data,
+      },
+    });
+  }
+
+  /**
+   * Shows an dialog to discard the individual box show order for this page.
+   */
+  private discard(event: MouseEvent): void {
+    event.preventDefault();
+
+    UiConfirmation.show({
+      confirm: () => {
+        Ajax.api(this, {
+          actionName: "resetPosition",
+        });
+      },
+      message: Language.get("wcf.acp.page.boxOrder.discard.confirmMessage"),
+    });
+  }
+
+  _ajaxSuccess(data: AjaxResponse): void {
+    switch (data.actionName) {
+      case "updatePosition":
+        UiNotification.show();
+        break;
+
+      case "resetPosition":
+        UiNotification.show(undefined, () => {
+          window.location.reload();
+        });
+        break;
+    }
+  }
+
+  _ajaxSetup(): ReturnType<AjaxCallbackSetup> {
+    return {
+      data: {
+        actionName: "updatePosition",
+        className: "wcf\\data\\page\\PageAction",
+        interfaceName: "wcf\\data\\ISortableAction",
+        objectIDs: [this.pageId],
+      },
+    };
+  }
+}
+
+let acpUiPageBoxOrder: AcpUiPageBoxOrder;
+
+/**
+ * Initializes the sorting capabilities.
+ */
+export function init(pageId: number, boxes: Map<string, BoxData[]>): void {
+  if (!acpUiPageBoxOrder) {
+    acpUiPageBoxOrder = new AcpUiPageBoxOrder(pageId, boxes);
+  }
+}