Add clipboard action to delete user content
authorjoshuaruesweg <ruesweg@woltlab.com>
Wed, 16 Dec 2020 15:26:54 +0000 (16:26 +0100)
committerjoshuaruesweg <ruesweg@woltlab.com>
Wed, 6 Jan 2021 14:41:41 +0000 (15:41 +0100)
com.woltlab.wcf/clipboardAction.xml
wcfsetup/install/files/acp/templates/userList.tpl
wcfsetup/install/files/js/WoltLabSuite/Core/Acp/Ui/User/Content/Remove/Clipboard.js [new file with mode: 0644]
wcfsetup/install/files/lib/system/clipboard/action/UserClipboardAction.class.php
wcfsetup/install/files/lib/system/worker/UserContentRemoveWorker.class.php
wcfsetup/install/files/ts/WoltLabSuite/Core/Acp/Ui/User/Content/Remove/Clipboard.ts [new file with mode: 0644]
wcfsetup/install/lang/de.xml
wcfsetup/install/lang/en.xml

index e4b159bd48b49a0d07a7cf6972ce7b35623b122e..3f48d7992503e9b84e506db96b41ea8b1b4fae19 100644 (file)
                                <page>wcf\acp\page\UserListPage</page>
                        </pages>
                </action>
-               <action name="ban">
+               <action name="deleteUserContent">
                        <actionclassname>wcf\system\clipboard\action\UserClipboardAction</actionclassname>
                        <showorder>3</showorder>
                        <pages>
                                <page>wcf\acp\page\UserListPage</page>
                        </pages>
                </action>
-               <action name="merge">
+               <action name="ban">
                        <actionclassname>wcf\system\clipboard\action\UserClipboardAction</actionclassname>
                        <showorder>4</showorder>
                        <pages>
                                <page>wcf\acp\page\UserListPage</page>
                        </pages>
                </action>
-               <action name="enable">
+               <action name="merge">
                        <actionclassname>wcf\system\clipboard\action\UserClipboardAction</actionclassname>
                        <showorder>5</showorder>
                        <pages>
                                <page>wcf\acp\page\UserListPage</page>
                        </pages>
                </action>
-               <action name="confirmEmail">
+               <action name="enable">
                        <actionclassname>wcf\system\clipboard\action\UserClipboardAction</actionclassname>
                        <showorder>6</showorder>
                        <pages>
                                <page>wcf\acp\page\UserListPage</page>
                        </pages>
                </action>
-               <action name="unconfirmEmail">
+               <action name="confirmEmail">
                        <actionclassname>wcf\system\clipboard\action\UserClipboardAction</actionclassname>
                        <showorder>7</showorder>
                        <pages>
                                <page>wcf\acp\page\UserListPage</page>
                        </pages>
                </action>
-               <action name="resendActivationMail">
+               <action name="unconfirmEmail">
                        <actionclassname>wcf\system\clipboard\action\UserClipboardAction</actionclassname>
                        <showorder>8</showorder>
                        <pages>
                                <page>wcf\acp\page\UserListPage</page>
                        </pages>
                </action>
-               <action name="sendMail">
+               <action name="resendActivationMail">
                        <actionclassname>wcf\system\clipboard\action\UserClipboardAction</actionclassname>
                        <showorder>9</showorder>
                        <pages>
                                <page>wcf\acp\page\UserListPage</page>
                        </pages>
                </action>
-               <action name="exportMailAddress">
+               <action name="sendMail">
                        <actionclassname>wcf\system\clipboard\action\UserClipboardAction</actionclassname>
                        <showorder>10</showorder>
                        <pages>
                                <page>wcf\acp\page\UserListPage</page>
                        </pages>
                </action>
-               <action name="sendNewPassword">
+               <action name="exportMailAddress">
                        <actionclassname>wcf\system\clipboard\action\UserClipboardAction</actionclassname>
                        <showorder>11</showorder>
                        <pages>
                                <page>wcf\acp\page\UserListPage</page>
                        </pages>
                </action>
+               <action name="sendNewPassword">
+                       <actionclassname>wcf\system\clipboard\action\UserClipboardAction</actionclassname>
+                       <showorder>12</showorder>
+                       <pages>
+                               <page>wcf\acp\page\UserListPage</page>
+                       </pages>
+               </action>
                <action name="revertContentChanges">
                        <actionclassname>wcf\system\clipboard\action\UserContentClipboardAction</actionclassname>
-                       <showorder>12</showorder>
+                       <showorder>13</showorder>
                        <pages>
                                <page>wcf\acp\page\UserListPage</page>
                        </pages>
index 1984ced19a21548ea5a238eec4b1b96962a90c5a..53323e7dd6bfbe84643998a76c1a04371f498fce 100644 (file)
                        WCF.ACP.User.SendNewPasswordHandler.init();
                {/if}
                
-               require(['Language', 'WoltLabSuite/Core/Acp/Ui/User/Editor'], function (Language, AcpUiUserList) {
+               require(['Language', 'WoltLabSuite/Core/Acp/Ui/User/Editor', 'WoltLabSuite/Core/Acp/Ui/User/Content/Remove/Clipboard'], function (Language, AcpUiUserList, AcpUserContentRemoveClipboard) {
                        Language.addObject({
                                'wcf.acp.user.action.sendNewPassword.confirmMessage': '{jslang}wcf.acp.user.action.sendNewPassword.confirmMessage{/jslang}'
                        });
                        
                        new AcpUiUserList();
+                       
+                       new AcpUserContentRemoveClipboard();
                });
                
                {event name='javascriptInit'}
diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Acp/Ui/User/Content/Remove/Clipboard.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Acp/Ui/User/Content/Remove/Clipboard.js
new file mode 100644 (file)
index 0000000..a14b0bc
--- /dev/null
@@ -0,0 +1,93 @@
+/**
+ * Handles the user content remove clipboard action.
+ *
+ * @author  Joshua Ruesweg
+ * @copyright  2001-2020 WoltLab GmbH
+ * @license  GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @module  WoltLabSuite/Core/Acp/Ui/User/Content/Remove/Clipboard
+ * @since       5.4
+ */
+define(["require", "exports", "tslib", "../../../Worker", "../../../../../Ajax", "../../../../../Language", "../../../../../Ui/Dialog", "../../../../../Event/Handler"], function (require, exports, tslib_1, Worker_1, Ajax, Language, Dialog_1, EventHandler) {
+    "use strict";
+    Object.defineProperty(exports, "__esModule", { value: true });
+    exports.AcpUserContentRemoveClipboard = void 0;
+    Worker_1 = tslib_1.__importDefault(Worker_1);
+    Ajax = tslib_1.__importStar(Ajax);
+    Language = tslib_1.__importStar(Language);
+    Dialog_1 = tslib_1.__importDefault(Dialog_1);
+    EventHandler = tslib_1.__importStar(EventHandler);
+    class AcpUserContentRemoveClipboard {
+        /**
+         * Initializes the content remove handler.
+         */
+        constructor() {
+            this.dialogId = "userContentRemoveClipboardPrepareDialog";
+            EventHandler.add("com.woltlab.wcf.clipboard", "com.woltlab.wcf.user", (data) => {
+                if (data.data.actionName === "com.woltlab.wcf.user.deleteUserContent") {
+                    this.userIds = data.data.parameters.objectIDs;
+                    Ajax.api(this);
+                }
+            });
+        }
+        /**
+         * Executes the remove content worker.
+         */
+        executeWorker(objectTypes) {
+            new Worker_1.default({
+                // dialog
+                dialogId: "removeContentWorker",
+                dialogTitle: Language.get("wcf.acp.content.removeContent"),
+                // ajax
+                className: "wcf\\system\\worker\\UserContentRemoveWorker",
+                parameters: {
+                    userIDs: this.userIds,
+                    contentProvider: objectTypes,
+                },
+            });
+        }
+        /**
+         * Handles a click on the submit button in the overlay.
+         */
+        submit() {
+            const objectTypes = Array.from(this.dialogContent.querySelectorAll("input.contentProviderObjectType"))
+                .filter((element) => element.checked)
+                .map((element) => element.name);
+            Dialog_1.default.close(this.dialogId);
+            if (objectTypes.length > 0) {
+                window.setTimeout(() => {
+                    this.executeWorker(objectTypes);
+                }, 200);
+            }
+        }
+        get dialogContent() {
+            return Dialog_1.default.getDialog(this.dialogId).content;
+        }
+        _ajaxSuccess(data) {
+            Dialog_1.default.open(this, data.returnValues.template);
+            const submitButton = this.dialogContent.querySelector('input[type="submit"]');
+            submitButton.addEventListener("click", () => this.submit());
+        }
+        _ajaxSetup() {
+            return {
+                data: {
+                    actionName: "prepareRemoveContent",
+                    className: "wcf\\data\\user\\UserAction",
+                    parameters: {
+                        userIDs: this.userIds,
+                    },
+                },
+            };
+        }
+        _dialogSetup() {
+            return {
+                id: this.dialogId,
+                options: {
+                    title: Language.get("wcf.acp.content.removeContent"),
+                },
+                source: null,
+            };
+        }
+    }
+    exports.AcpUserContentRemoveClipboard = AcpUserContentRemoveClipboard;
+    exports.default = AcpUserContentRemoveClipboard;
+});
index f8bfc47628756ab275c6fda726d6416c1fcae0e6..b2e459d56c3d93f4cc8edaf6668d7208e21549e5 100644 (file)
@@ -25,7 +25,7 @@ class UserClipboardAction extends AbstractClipboardAction {
        /**
         * @inheritDoc
         */
-       protected $supportedActions = ['assignToGroup', 'ban', 'confirmEmail', 'delete', 'enable', 'exportMailAddress', 'merge', 'sendMail', 'sendNewPassword', 'resendActivationMail', 'unconfirmEmail'];
+       protected $supportedActions = ['assignToGroup', 'ban', 'confirmEmail', 'delete', 'deleteUserContent', 'enable', 'exportMailAddress', 'merge', 'sendMail', 'sendNewPassword', 'resendActivationMail', 'unconfirmEmail'];
        
        /**
         * @inheritDoc
@@ -282,4 +282,14 @@ class UserClipboardAction extends AbstractClipboardAction {
                
                return $userIDs;
        }
+       
+       /**
+        * Returns the ids of the users whose contents can be deleted.
+        * 
+        * @return      integer[]
+        * @since       5.4
+        */
+       protected function validateDeleteUserContent() {
+               return $this->__validateAccessibleGroups(array_keys($this->objects));
+       }
 }
index cccb8e8e0dc2b4d75197a5bdeb6634a5cd56541b..61488b02d8975043c88c9d9309c869ab40494a36 100644 (file)
@@ -240,6 +240,10 @@ class UserContentRemoveWorker extends AbstractWorker {
                $dataArray[$this->generateKey()] = $this->data;
                
                WCF::getSession()->register(self::USER_CONTENT_REMOVE_WORKER_SESSION_NAME, $dataArray);
+               
+               ClipboardHandler::getInstance()->unmark(array_map(function (User $user) {
+                       return $user->userID;
+               }, $this->user), ClipboardHandler::getInstance()->getObjectTypeID('com.woltlab.wcf.user'));
        }
        
        /**
diff --git a/wcfsetup/install/files/ts/WoltLabSuite/Core/Acp/Ui/User/Content/Remove/Clipboard.ts b/wcfsetup/install/files/ts/WoltLabSuite/Core/Acp/Ui/User/Content/Remove/Clipboard.ts
new file mode 100644 (file)
index 0000000..b0b596d
--- /dev/null
@@ -0,0 +1,126 @@
+/**
+ * Handles the user content remove clipboard action.
+ *
+ * @author  Joshua Ruesweg
+ * @copyright  2001-2020 WoltLab GmbH
+ * @license  GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @module  WoltLabSuite/Core/Acp/Ui/User/Content/Remove/Clipboard
+ * @since       5.4
+ */
+
+import AcpUiWorker from "../../../Worker";
+import * as Ajax from "../../../../../Ajax";
+import * as Language from "../../../../../Language";
+import UiDialog from "../../../../../Ui/Dialog";
+import { AjaxCallbackSetup } from "../../../../../Ajax/Data";
+import { DialogCallbackSetup } from "../../../../../Ui/Dialog/Data";
+import * as EventHandler from "../../../../../Event/Handler";
+
+interface AjaxResponse {
+  returnValues: {
+    template: string;
+  };
+}
+
+interface EventData {
+  data: {
+    actionName: string;
+    internalData: any[];
+    label: string;
+    parameters: {
+      objectIDs: number[];
+      url: string;
+    };
+  };
+  listItem: HTMLElement;
+}
+
+export class AcpUserContentRemoveClipboard {
+  public userIds: number[];
+  private readonly dialogId = "userContentRemoveClipboardPrepareDialog";
+
+  /**
+   * Initializes the content remove handler.
+   */
+  constructor() {
+    EventHandler.add("com.woltlab.wcf.clipboard", "com.woltlab.wcf.user", (data: EventData) => {
+      if (data.data.actionName === "com.woltlab.wcf.user.deleteUserContent") {
+        this.userIds = data.data.parameters.objectIDs;
+
+        Ajax.api(this);
+      }
+    });
+  }
+
+  /**
+   * Executes the remove content worker.
+   */
+  private executeWorker(objectTypes: string[]): void {
+    new AcpUiWorker({
+      // dialog
+      dialogId: "removeContentWorker",
+      dialogTitle: Language.get("wcf.acp.content.removeContent"),
+
+      // ajax
+      className: "wcf\\system\\worker\\UserContentRemoveWorker",
+      parameters: {
+        userIDs: this.userIds,
+        contentProvider: objectTypes,
+      },
+    });
+  }
+
+  /**
+   * Handles a click on the submit button in the overlay.
+   */
+  private submit(): void {
+    const objectTypes = Array.from<HTMLInputElement>(
+      this.dialogContent.querySelectorAll("input.contentProviderObjectType"),
+    )
+      .filter((element) => element.checked)
+      .map((element) => element.name);
+
+    UiDialog.close(this.dialogId);
+
+    if (objectTypes.length > 0) {
+      window.setTimeout(() => {
+        this.executeWorker(objectTypes);
+      }, 200);
+    }
+  }
+
+  get dialogContent(): HTMLElement {
+    return UiDialog.getDialog(this.dialogId)!.content;
+  }
+
+  _ajaxSuccess(data: AjaxResponse): void {
+    UiDialog.open(this, data.returnValues.template);
+
+    const submitButton = this.dialogContent.querySelector('input[type="submit"]') as HTMLElement;
+    submitButton.addEventListener("click", () => this.submit());
+  }
+
+  _ajaxSetup(): ReturnType<AjaxCallbackSetup> {
+    return {
+      data: {
+        actionName: "prepareRemoveContent",
+        className: "wcf\\data\\user\\UserAction",
+        parameters: {
+          userIDs: this.userIds,
+        },
+      },
+    };
+  }
+
+  _dialogSetup(): ReturnType<DialogCallbackSetup> {
+    return {
+      id: this.dialogId,
+      options: {
+        title: Language.get("wcf.acp.content.removeContent"),
+      },
+      source: null,
+    };
+  }
+}
+
+export default AcpUserContentRemoveClipboard;
index 5b95ebf0930b19a87cba5edce6d7eb61099ff00e..a220ab02bc2c817fcaa66080c2abeaaeb40d7d08 100644 (file)
@@ -3429,6 +3429,7 @@ Fehler sind beispielsweise:
                <item name="wcf.clipboard.item.com.woltlab.wcf.user.sendNewPassword.confirmMessage"><![CDATA[{if LANGUAGE_USE_INFORMAL_VARIANT}Willst du{else}Wollen Sie{/if} wirklich {if $count == 1}einem Benutzer{else}{#$count} Benutzern{/if} ein neues Kennwort zusenden?]]></item>
                <item name="wcf.clipboard.item.com.woltlab.wcf.user.confirmEmail"><![CDATA[E-Mail-Adresse bestätigen ({#$count})]]></item>
                <item name="wcf.clipboard.item.com.woltlab.wcf.user.unconfirmEmail"><![CDATA[Bestätigung der E-Mail-Adresse widerrufen ({#$count})]]></item>
+               <item name="wcf.clipboard.item.com.woltlab.wcf.user.deleteUserContent"><![CDATA[Inhalte der Benutzer löschen ({#$count})]]></item>
                <item name="wcf.clipboard.label.com.woltlab.wcf.article.marked"><![CDATA[{if $count == 1}Ein{else}{#$count}{/if} Artikel]]></item>
                <item name="wcf.clipboard.label.com.woltlab.wcf.media.marked"><![CDATA[{if $count == 1}Eine Datei{else}{#$count} Dateien{/if}]]></item>
                <item name="wcf.clipboard.label.com.woltlab.wcf.tag.marked"><![CDATA[{if $count == 1}Ein Tag{else}{#$count} Tags{/if}]]></item>
index 5016fae1259b63b66de8fc655bd059b3917df4a9..ac810dfb59cb92030dbda64668126cbd7fb3df8e 100644 (file)
@@ -3353,6 +3353,7 @@ Errors are:
                <item name="wcf.clipboard.item.com.woltlab.wcf.user.sendNewPassword.confirmMessage"><![CDATA[Do you really want to send a new password to {#$count} user{if $count != 1}s{/if}?]]></item>
                <item name="wcf.clipboard.item.com.woltlab.wcf.user.confirmEmail"><![CDATA[Confirm Email Address ({#$count})]]></item>
                <item name="wcf.clipboard.item.com.woltlab.wcf.user.unconfirmEmail"><![CDATA[Unconfirm Email Address ({#$count})]]></item>
+               <item name="wcf.clipboard.item.com.woltlab.wcf.user.deleteUserContent"><![CDATA[Delete User Contents ({#$count})]]></item>
                <item name="wcf.clipboard.label.com.woltlab.wcf.article.marked"><![CDATA[{if $count == 1}One Article{else}{#$count} Articles{/if}]]></item>
                <item name="wcf.clipboard.label.com.woltlab.wcf.media.marked"><![CDATA[{if $count == 1}One File{else}{#$count} Files{/if}]]></item>
                <item name="wcf.clipboard.label.com.woltlab.wcf.tag.marked"><![CDATA[{if $count == 1}One Tag{else}{#$count} Tags{/if}]]></item>