Add UserDelete Handler
authorjoshuaruesweg <ruesweg@woltlab.com>
Wed, 23 Jun 2021 13:06:38 +0000 (15:06 +0200)
committerjoshuaruesweg <ruesweg@woltlab.com>
Mon, 28 Jun 2021 15:28:46 +0000 (17:28 +0200)
ts/WoltLabSuite/Core/Acp/Ui/User/Action/DeleteAction.ts [new file with mode: 0644]
ts/WoltLabSuite/Core/Acp/Ui/User/Action/Handler/Delete.ts [new file with mode: 0644]
ts/WoltLabSuite/Core/Acp/Ui/User/Editor.ts
wcfsetup/install/files/acp/templates/userList.tpl
wcfsetup/install/files/js/WoltLabSuite/Core/Acp/Ui/User/Action/DeleteAction.js [new file with mode: 0644]
wcfsetup/install/files/js/WoltLabSuite/Core/Acp/Ui/User/Action/DisableAction.js
wcfsetup/install/files/js/WoltLabSuite/Core/Acp/Ui/User/Action/Handler/Delete.js [new file with mode: 0644]
wcfsetup/install/files/js/WoltLabSuite/Core/Acp/Ui/User/Action/ToggleConfirmEmailAction.js
wcfsetup/install/files/js/WoltLabSuite/Core/Acp/Ui/User/Editor.js

diff --git a/ts/WoltLabSuite/Core/Acp/Ui/User/Action/DeleteAction.ts b/ts/WoltLabSuite/Core/Acp/Ui/User/Action/DeleteAction.ts
new file mode 100644 (file)
index 0000000..559527d
--- /dev/null
@@ -0,0 +1,25 @@
+import AbstractUserAction from "./AbstractUserAction";
+import * as Language from "../../../../Language";
+import Delete from "./Handler/Delete";
+
+/**
+ * @author  Joshua Ruesweg
+ * @copyright  2001-2021 WoltLab GmbH
+ * @license  GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @module  WoltLabSuite/Core/Acp/Ui/User/Action
+ * @since       5.5
+ */
+export class DeleteAction extends AbstractUserAction {
+  protected init() {
+    this.button.addEventListener("click", (event) => {
+      event.preventDefault();
+
+      let deleteHandler = new Delete([this.userId], () => {
+        this.userData.remove();
+      }, this.button.dataset.confirmMessage);
+      deleteHandler.delete();
+    });
+  }
+}
+
+export default DeleteAction;
diff --git a/ts/WoltLabSuite/Core/Acp/Ui/User/Action/Handler/Delete.ts b/ts/WoltLabSuite/Core/Acp/Ui/User/Action/Handler/Delete.ts
new file mode 100644 (file)
index 0000000..3a6a58a
--- /dev/null
@@ -0,0 +1,53 @@
+import * as Language from "../../../../../Language";
+import * as UiConfirmation from "../../../../../Ui/Confirmation";
+import * as Ajax from "../../../../../Ajax";
+import { CallbackSuccess } from "../../../../../Ajax/Data";
+
+/**
+ * @author  Joshua Ruesweg
+ * @copyright  2001-2021 WoltLab GmbH
+ * @license  GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @module  WoltLabSuite/Core/Acp/Ui/User/Action/Handler
+ * @since       5.5
+ */
+export class Delete {
+  private userIDs: number[];
+  private successCallback: CallbackSuccess;
+  private deleteMessage: string;
+
+  public constructor(userIDs: number[], successCallback: CallbackSuccess, deleteMessage?: string) {
+    this.userIDs = userIDs;
+    this.successCallback = successCallback;
+    if (deleteMessage) {
+      this.deleteMessage = deleteMessage;
+    }
+    else {
+      this.deleteMessage = Language.get("wcf.button.delete.confirmMessage"); // @todo find better variable for a generic message
+    }
+  }
+
+  delete(): void {
+    UiConfirmation.show({
+      confirm: () => {
+        Ajax.api(
+          {
+            _ajaxSetup: () => {
+              return {
+                data: {
+                  actionName: "delete",
+                  className: "wcf\\data\\user\\UserAction",
+                  objectIDs: this.userIDs,
+                },
+              };
+            },
+            _ajaxSuccess: this.successCallback,
+          }
+        );
+      },
+      message: this.deleteMessage,
+      messageIsHtml: true,
+    });
+  }
+}
+
+export default Delete;
index 0bf7cd619468895fe0c12d293fd54a6e87ca8cf4..406d795eec933c523b3a7e43a8ba145ff9720152 100644 (file)
@@ -18,6 +18,7 @@ import SendNewPasswordAction from "./Action/SendNewPasswordAction";
 import ToggleConfirmEmailAction from "./Action/ToggleConfirmEmailAction";
 import DisableAction from "./Action/DisableAction";
 import BanAction from "./Action/BanAction";
+import DeleteAction from "./Action/DeleteAction";
 
 interface RefreshUsersData {
   userIds: number[];
@@ -89,6 +90,11 @@ class AcpUiUserEditor {
     if (banUser !== null) {
       new BanAction(banUser, userId, userRow);
     }
+
+    const deleteUser = dropdownMenu.querySelector(".jsDelete") as HTMLAnchorElement;
+    if (deleteUser !== null) {
+      new DeleteAction(deleteUser, userId, userRow);
+    }
   }
 
   /**
@@ -102,12 +108,6 @@ class AcpUiUserEditor {
     const items: HTMLLIElement[] = [];
     let deleteButton: HTMLAnchorElement | null = null;
     Array.from(legacyButtonContainer.children).forEach((button: HTMLAnchorElement) => {
-      if (button.classList.contains("jsObjectAction") && button.dataset.objectAction === "delete") {
-        deleteButton = button;
-
-        return;
-      }
-
       const item = document.createElement("li");
       item.className = "jsLegacyItem";
       item.innerHTML = '<a href="#"></a>';
@@ -132,15 +132,6 @@ class AcpUiUserEditor {
       dropdownMenu.insertAdjacentElement("afterbegin", item);
     });
 
-    if (deleteButton !== null) {
-      const dispatchDeleteButton = dropdownMenu.querySelector(".jsDispatchDelete") as HTMLAnchorElement;
-      dispatchDeleteButton.addEventListener("click", (event) => {
-        event.preventDefault();
-
-        deleteButton!.click();
-      });
-    }
-
     // check if there are visible items before each divider
     const listItems = Array.from(dropdownMenu.children) as HTMLElement[];
     listItems.forEach((element) => DomUtil.show(element));
index e0b314dc72d4fbf98a3cebde79be6adf7080b82f..fcb9179880cd7afeb6b276a16742a105b6c147b7 100644 (file)
 
                                                                        {if $user->deletable}
                                                                                <li class="dropdownDivider"></li>
-                                                                               <li><a href="#" class="jsDispatchDelete">{lang}wcf.global.button.delete{/lang}</a></li>
+                                                                               <li><a href="#" class="jsDelete" data-confirm-message="{lang __encode=true objectTitle=$user->username}wcf.button.delete.confirmMessage{/lang}">{lang}wcf.global.button.delete{/lang}</a></li>
                                                                                <li><a href="#" class="jsDeleteContent">{lang}wcf.acp.content.removeContent{/lang}</a></li>
                                                                        {/if}
 
                                                                   based insert calls. Clicks are forwarded to them anyway, thus there is no
                                                                   significant downside, other than "just" some more legacy code. *}
 
-                                                               {if $user->deletable}
-                                                                       {objectAction action="delete" objectTitle=$user->getTitle()}
-                                                               {/if}
-
                                                                {event name='rowButtons'}
                                                        </div>
                                                </td>
diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Acp/Ui/User/Action/DeleteAction.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Acp/Ui/User/Action/DeleteAction.js
new file mode 100644 (file)
index 0000000..f1b4ab1
--- /dev/null
@@ -0,0 +1,27 @@
+define(["require", "exports", "tslib", "./AbstractUserAction", "./Handler/Delete"], function (require, exports, tslib_1, AbstractUserAction_1, Delete_1) {
+    "use strict";
+    Object.defineProperty(exports, "__esModule", { value: true });
+    exports.DeleteAction = void 0;
+    AbstractUserAction_1 = tslib_1.__importDefault(AbstractUserAction_1);
+    Delete_1 = tslib_1.__importDefault(Delete_1);
+    /**
+     * @author  Joshua Ruesweg
+     * @copyright  2001-2021 WoltLab GmbH
+     * @license  GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+     * @module  WoltLabSuite/Core/Acp/Ui/User/Action
+     * @since       5.5
+     */
+    class DeleteAction extends AbstractUserAction_1.default {
+        init() {
+            this.button.addEventListener("click", (event) => {
+                event.preventDefault();
+                let deleteHandler = new Delete_1.default([this.userId], () => {
+                    this.userData.remove();
+                }, this.button.dataset.confirmMessage);
+                deleteHandler.delete();
+            });
+        }
+    }
+    exports.DeleteAction = DeleteAction;
+    exports.default = DeleteAction;
+});
index aa967c63f254b1e55e620d21dc513a1b50a103c9..efceca214d925d7c14fe113bd17a229b126cb4db 100644 (file)
@@ -29,25 +29,26 @@ define(["require", "exports", "tslib", "../../../../Ajax", "../../../../Core", "
                             },
                         };
                     },
-                }, undefined, (data) => {
-                    if (data.objectIDs.includes(this.userId)) {
-                        switch (data.actionName) {
-                            case "enable":
-                                this.userData.dataset.enabled = "true";
-                                this.button.textContent = this.button.dataset.disableMessage;
-                                break;
-                            case "disable":
-                                this.userData.dataset.enabled = "false";
-                                this.button.textContent = this.button.dataset.enableMessage;
-                                break;
-                            default:
-                                throw new Error("Unreachable");
+                    _ajaxSuccess: (data) => {
+                        if (data.objectIDs.includes(this.userId)) {
+                            switch (data.actionName) {
+                                case "enable":
+                                    this.userData.dataset.enabled = "true";
+                                    this.button.textContent = this.button.dataset.disableMessage;
+                                    break;
+                                case "disable":
+                                    this.userData.dataset.enabled = "false";
+                                    this.button.textContent = this.button.dataset.enableMessage;
+                                    break;
+                                default:
+                                    throw new Error("Unreachable");
+                            }
                         }
-                    }
-                    UiNotification.show();
-                    EventHandler.fire("com.woltlab.wcf.acp.user", "refresh", {
-                        userIds: [this.userId]
-                    });
+                        UiNotification.show();
+                        EventHandler.fire("com.woltlab.wcf.acp.user", "refresh", {
+                            userIds: [this.userId]
+                        });
+                    },
                 });
             });
         }
diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Acp/Ui/User/Action/Handler/Delete.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Acp/Ui/User/Action/Handler/Delete.js
new file mode 100644 (file)
index 0000000..f0ecfe2
--- /dev/null
@@ -0,0 +1,49 @@
+define(["require", "exports", "tslib", "../../../../../Language", "../../../../../Ui/Confirmation", "../../../../../Ajax"], function (require, exports, tslib_1, Language, UiConfirmation, Ajax) {
+    "use strict";
+    Object.defineProperty(exports, "__esModule", { value: true });
+    exports.Delete = void 0;
+    Language = tslib_1.__importStar(Language);
+    UiConfirmation = tslib_1.__importStar(UiConfirmation);
+    Ajax = tslib_1.__importStar(Ajax);
+    /**
+     * @author  Joshua Ruesweg
+     * @copyright  2001-2021 WoltLab GmbH
+     * @license  GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+     * @module  WoltLabSuite/Core/Acp/Ui/User/Action/Handler
+     * @since       5.5
+     */
+    class Delete {
+        constructor(userIDs, successCallback, deleteMessage) {
+            this.userIDs = userIDs;
+            this.successCallback = successCallback;
+            if (deleteMessage) {
+                this.deleteMessage = deleteMessage;
+            }
+            else {
+                this.deleteMessage = Language.get("wcf.button.delete.confirmMessage"); // @todo find better variable for a generic message
+            }
+        }
+        delete() {
+            UiConfirmation.show({
+                confirm: () => {
+                    Ajax.api({
+                        _ajaxSetup: () => {
+                            return {
+                                data: {
+                                    actionName: "delete",
+                                    className: "wcf\\data\\user\\UserAction",
+                                    objectIDs: this.userIDs,
+                                },
+                            };
+                        },
+                        _ajaxSuccess: this.successCallback,
+                    });
+                },
+                message: this.deleteMessage,
+                messageIsHtml: true,
+            });
+        }
+    }
+    exports.Delete = Delete;
+    exports.default = Delete;
+});
index 20bdb65974ff362ff979cea972587112264899e2..3243b6245bde5040e4aa0561ea19daff825867b9 100644 (file)
@@ -28,22 +28,23 @@ define(["require", "exports", "tslib", "./AbstractUserAction", "../../../../Ajax
                             },
                         };
                     },
-                }, undefined, (data) => {
-                    if (data.objectIDs.includes(this.userId)) {
-                        switch (data.actionName) {
-                            case "confirmEmail":
-                                this.userData.dataset.emailConfirmed = "true";
-                                this.button.textContent = this.button.dataset.unconfirmEmailMessage;
-                                break;
-                            case "unconfirmEmail":
-                                this.userData.dataset.emailConfirmed = "false";
-                                this.button.textContent = this.button.dataset.confirmEmailMessage;
-                                break;
-                            default:
-                                throw new Error("Unreachable");
+                    _ajaxSuccess: (data) => {
+                        if (data.objectIDs.includes(this.userId)) {
+                            switch (data.actionName) {
+                                case "confirmEmail":
+                                    this.userData.dataset.emailConfirmed = "true";
+                                    this.button.textContent = this.button.dataset.unconfirmEmailMessage;
+                                    break;
+                                case "unconfirmEmail":
+                                    this.userData.dataset.emailConfirmed = "false";
+                                    this.button.textContent = this.button.dataset.confirmEmailMessage;
+                                    break;
+                                default:
+                                    throw new Error("Unreachable");
+                            }
                         }
-                    }
-                    UiNotification.show();
+                        UiNotification.show();
+                    },
                 });
             });
         }
index 97b69e68704903f869ec74c5ae8a8e7a97b6a770..eda27b916d3c6f5f14f84f510c5c61da94bd2aec 100644 (file)
@@ -7,7 +7,7 @@
  * @module  WoltLabSuite/Core/Acp/Ui/User/Editor
  * @since       3.1
  */
-define(["require", "exports", "tslib", "./Content/Remove/Handler", "../../../Core", "../../../Event/Handler", "../../../Language", "../../../Ui/Dropdown/Simple", "../../../Dom/Util", "./Action/SendNewPasswordAction", "./Action/ToggleConfirmEmailAction", "./Action/DisableAction", "./Action/BanAction"], function (require, exports, tslib_1, Handler_1, Core, EventHandler, Language, Simple_1, Util_1, SendNewPasswordAction_1, ToggleConfirmEmailAction_1, DisableAction_1, BanAction_1) {
+define(["require", "exports", "tslib", "./Content/Remove/Handler", "../../../Core", "../../../Event/Handler", "../../../Language", "../../../Ui/Dropdown/Simple", "../../../Dom/Util", "./Action/SendNewPasswordAction", "./Action/ToggleConfirmEmailAction", "./Action/DisableAction", "./Action/BanAction", "./Action/DeleteAction"], function (require, exports, tslib_1, Handler_1, Core, EventHandler, Language, Simple_1, Util_1, SendNewPasswordAction_1, ToggleConfirmEmailAction_1, DisableAction_1, BanAction_1, DeleteAction_1) {
     "use strict";
     Handler_1 = tslib_1.__importDefault(Handler_1);
     Core = tslib_1.__importStar(Core);
@@ -19,6 +19,7 @@ define(["require", "exports", "tslib", "./Content/Remove/Handler", "../../../Cor
     ToggleConfirmEmailAction_1 = tslib_1.__importDefault(ToggleConfirmEmailAction_1);
     DisableAction_1 = tslib_1.__importDefault(DisableAction_1);
     BanAction_1 = tslib_1.__importDefault(BanAction_1);
+    DeleteAction_1 = tslib_1.__importDefault(DeleteAction_1);
     class AcpUiUserEditor {
         /**
          * Initializes the edit dropdown for each user.
@@ -73,6 +74,10 @@ define(["require", "exports", "tslib", "./Content/Remove/Handler", "../../../Cor
             if (banUser !== null) {
                 new BanAction_1.default(banUser, userId, userRow);
             }
+            const deleteUser = dropdownMenu.querySelector(".jsDelete");
+            if (deleteUser !== null) {
+                new DeleteAction_1.default(deleteUser, userId, userRow);
+            }
         }
         /**
          * Rebuilds the dropdown by adding wrapper links for legacy buttons,
@@ -84,10 +89,6 @@ define(["require", "exports", "tslib", "./Content/Remove/Handler", "../../../Cor
             const items = [];
             let deleteButton = null;
             Array.from(legacyButtonContainer.children).forEach((button) => {
-                if (button.classList.contains("jsObjectAction") && button.dataset.objectAction === "delete") {
-                    deleteButton = button;
-                    return;
-                }
                 const item = document.createElement("li");
                 item.className = "jsLegacyItem";
                 item.innerHTML = '<a href="#"></a>';
@@ -108,13 +109,6 @@ define(["require", "exports", "tslib", "./Content/Remove/Handler", "../../../Cor
             items.forEach((item) => {
                 dropdownMenu.insertAdjacentElement("afterbegin", item);
             });
-            if (deleteButton !== null) {
-                const dispatchDeleteButton = dropdownMenu.querySelector(".jsDispatchDelete");
-                dispatchDeleteButton.addEventListener("click", (event) => {
-                    event.preventDefault();
-                    deleteButton.click();
-                });
-            }
             // check if there are visible items before each divider
             const listItems = Array.from(dropdownMenu.children);
             listItems.forEach((element) => Util_1.default.show(element));