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} ],
);
});
</script>
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;
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) {
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);
}
#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 + "'");
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) {
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;
*/
private array $files = [];
private bool $singleFileUpload = false;
+ private array $actionButtons = [];
#[\Override]
public function readValue()
#[\Override]
public function getHtmlVariables()
{
+ $this->addActionButton(
+ 'delete',
+ 'wcf.form.field.fileProcessor.action.delete',
+ FontAwesomeIcon::fromValues('trash')
+ );
return [
'fileProcessorHtmlElement' => FileProcessor::getInstance()->getHtmlElement(
$this->getFileProcessor(),
'imageOnly' => \array_diff(
$this->getFileProcessor()->getAllowedFileExtensions($this->context),
ImageUtil::IMAGE_EXTENSIONS
- ) === []
+ ) === [],
+ 'actionButtons' => $this->actionButtons,
];
}
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.