From 97ea5ff90995aee7fb23d3841c71570f6ff29703 Mon Sep 17 00:00:00 2001 From: Cyperghost Date: Fri, 21 Jun 2024 10:47:51 +0200 Subject: [PATCH] Add extra buttons to FileProcessorFormField --- .../shared_fileProcessorFormField.tpl | 8 +++- .../Builder/Field/Controller/FileProcessor.ts | 37 ++++++++++++++++++- .../Builder/Field/Controller/FileProcessor.js | 23 +++++++++++- .../field/FileProcessorFormField.class.php | 25 ++++++++++++- 4 files changed, 88 insertions(+), 5 deletions(-) diff --git a/com.woltlab.wcf/templates/shared_fileProcessorFormField.tpl b/com.woltlab.wcf/templates/shared_fileProcessorFormField.tpl index 4de1018743..4c603cc03d 100644 --- a/com.woltlab.wcf/templates/shared_fileProcessorFormField.tpl +++ b/com.woltlab.wcf/templates/shared_fileProcessorFormField.tpl @@ -25,7 +25,13 @@ new FileProcessor( '{@$field->getPrefixedId()|encodeJS}', {if $field->isSingleFileUpload()}true{else}false{/if}, - {if $imageOnly}true{else}false{/if} + {if $imageOnly}true{else}false{/if}, + [{implode from=$actionButtons item=actionButton}{ + title: '{@$actionButton['title']|encodeJS}', + icon: {if $actionButton['icon'] === null}undefined + {else}'{@$actionButton['icon']->toHtml()|encodeJS}'{/if}, + actionName: '{@$actionButton['actionName']|encodeJS}', + }{/implode} ], ); }); diff --git a/ts/WoltLabSuite/Core/Form/Builder/Field/Controller/FileProcessor.ts b/ts/WoltLabSuite/Core/Form/Builder/Field/Controller/FileProcessor.ts index 1d4901371f..2236967643 100644 --- a/ts/WoltLabSuite/Core/Form/Builder/Field/Controller/FileProcessor.ts +++ b/ts/WoltLabSuite/Core/Form/Builder/Field/Controller/FileProcessor.ts @@ -11,6 +11,12 @@ import { deleteFile } from "WoltLabSuite/Core/Api/Files/DeleteFile"; import { formatFilesize } from "WoltLabSuite/Core/FileUtil"; import DomChangeListener from "WoltLabSuite/Core/Dom/Change/Listener"; +export interface ExtraButton { + title: string; + icon?: string; + actionName: string; +} + export class FileProcessor { readonly #container: HTMLElement; readonly #uploadButton: WoltlabCoreFileUploadElement; @@ -19,11 +25,18 @@ export class FileProcessor { readonly #fileInput: HTMLInputElement; readonly #imageOnly: boolean; readonly #singleFileUpload: boolean; - - constructor(fieldId: string, singleFileUpload: boolean = false, imageOnly: boolean = false) { + readonly #extraButtons: ExtraButton[]; + + constructor( + fieldId: string, + singleFileUpload: boolean = false, + imageOnly: boolean = false, + extraButtons: ExtraButton[] = [], + ) { this.#fieldId = fieldId; this.#imageOnly = imageOnly; this.#singleFileUpload = singleFileUpload; + this.#extraButtons = extraButtons; this.#container = document.getElementById(fieldId + "Container")!; if (this.#container === null) { @@ -60,6 +73,26 @@ export class FileProcessor { this.addReplaceButton(element, buttons); } + this.#extraButtons.forEach((button) => { + const extraButton = document.createElement("button"); + extraButton.type = "button"; + extraButton.classList.add("button", "small"); + if (button.icon === undefined) { + extraButton.textContent = button.title; + } else { + extraButton.classList.add("jsTooltip"); + extraButton.title = button.title; + extraButton.innerHTML = button.icon; + } + extraButton.addEventListener("click", () => { + element.dispatchEvent(new CustomEvent("fileProcessorCustomAction", { detail: button.actionName })); + }); + + const listItem = document.createElement("li"); + listItem.append(extraButton); + buttons.append(listItem); + }); + container.append(buttons); } diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Field/Controller/FileProcessor.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Field/Controller/FileProcessor.js index 4abc8d785e..a8949c2751 100644 --- a/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Field/Controller/FileProcessor.js +++ b/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Field/Controller/FileProcessor.js @@ -17,10 +17,12 @@ define(["require", "exports", "tslib", "WoltLabSuite/Core/Language", "WoltLabSui #fileInput; #imageOnly; #singleFileUpload; - constructor(fieldId, singleFileUpload = false, imageOnly = false) { + #extraButtons; + constructor(fieldId, singleFileUpload = false, imageOnly = false, extraButtons = []) { this.#fieldId = fieldId; this.#imageOnly = imageOnly; this.#singleFileUpload = singleFileUpload; + this.#extraButtons = extraButtons; this.#container = document.getElementById(fieldId + "Container"); if (this.#container === null) { throw new Error("Unknown field with id '" + fieldId + "'"); @@ -48,6 +50,25 @@ define(["require", "exports", "tslib", "WoltLabSuite/Core/Language", "WoltLabSui if (this.#singleFileUpload) { this.addReplaceButton(element, buttons); } + this.#extraButtons.forEach((button) => { + const extraButton = document.createElement("button"); + extraButton.type = "button"; + extraButton.classList.add("button", "small"); + if (button.icon === undefined) { + extraButton.textContent = button.title; + } + else { + extraButton.classList.add("jsTooltip"); + extraButton.title = button.title; + extraButton.innerHTML = button.icon; + } + extraButton.addEventListener("click", () => { + element.dispatchEvent(new CustomEvent("fileProcessorCustomAction", { detail: button.actionName })); + }); + const listItem = document.createElement("li"); + listItem.append(extraButton); + buttons.append(listItem); + }); container.append(buttons); } #markElementUploadHasFailed(container, element, reason) { diff --git a/wcfsetup/install/files/lib/system/form/builder/field/FileProcessorFormField.class.php b/wcfsetup/install/files/lib/system/form/builder/field/FileProcessorFormField.class.php index ca4f9428b1..a35bf4fa20 100644 --- a/wcfsetup/install/files/lib/system/form/builder/field/FileProcessorFormField.class.php +++ b/wcfsetup/install/files/lib/system/form/builder/field/FileProcessorFormField.class.php @@ -9,6 +9,8 @@ use wcf\system\file\processor\FileProcessor; use wcf\system\file\processor\IFileProcessor; use wcf\system\form\builder\field\validation\FormFieldValidationError; use wcf\system\form\builder\TObjectTypeFormNode; +use wcf\system\style\FontAwesomeIcon; +use wcf\system\style\IFontAwesomeIcon; use wcf\util\ArrayUtil; use wcf\util\ImageUtil; @@ -35,6 +37,7 @@ final class FileProcessorFormField extends AbstractFormField */ private array $files = []; private bool $singleFileUpload = false; + private array $actionButtons = []; #[\Override] public function readValue() @@ -61,6 +64,11 @@ final class FileProcessorFormField extends AbstractFormField #[\Override] public function getHtmlVariables() { + $this->addActionButton( + 'delete', + 'wcf.form.field.fileProcessor.action.delete', + FontAwesomeIcon::fromValues('trash') + ); return [ 'fileProcessorHtmlElement' => FileProcessor::getInstance()->getHtmlElement( $this->getFileProcessor(), @@ -70,7 +78,8 @@ final class FileProcessorFormField extends AbstractFormField 'imageOnly' => \array_diff( $this->getFileProcessor()->getAllowedFileExtensions($this->context), ImageUtil::IMAGE_EXTENSIONS - ) === [] + ) === [], + 'actionButtons' => $this->actionButtons, ]; } @@ -170,6 +179,20 @@ final class FileProcessorFormField extends AbstractFormField parent::validate(); } + /** + * Adds an action button to the file processor. + * If the button is clicked, the event `fileProcessorCustomAction` will be triggered. + */ + public function addActionButton(string $actionName, string $title, ?IFontAwesomeIcon $icon = null): self + { + $this->actionButtons[] = [ + 'actionName' => $actionName, + 'title' => $title, + 'icon' => $icon + ]; + + return $this; + } /** * Returns the context for the file processor. -- 2.20.1