Initialize existing attachments
authorAlexander Ebert <ebert@woltlab.com>
Fri, 26 Apr 2024 13:28:32 +0000 (15:28 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Sat, 8 Jun 2024 10:19:38 +0000 (12:19 +0200)
com.woltlab.wcf/templates/shared_messageFormAttachments.tpl
ts/WoltLabSuite/Core/Component/Attachment/List.ts
ts/WoltLabSuite/Core/Component/File/woltlab-core-file.ts
wcfsetup/install/files/js/WoltLabSuite/Core/Component/Attachment/List.js
wcfsetup/install/files/js/WoltLabSuite/Core/Component/File/woltlab-core-file.js
wcfsetup/install/files/lib/data/attachment/Attachment.class.php
wcfsetup/install/files/lib/data/file/File.class.php

index 958dd19742ee99a9fcc659fe2117fca1873dc307..ac9e314d3aa3466acca64900ba1fe3df15e35412 100644 (file)
@@ -1,5 +1,12 @@
 <div class="messageTabMenuContent" id="attachments_{if $wysiwygSelector|isset}{$wysiwygSelector}{else}text{/if}">
        {unsafe:$attachmentHandler->getHtmlElement()}
+
+       <div class="attachment__list__existingFiles">
+               {foreach from=$attachmentHandler->getAttachmentList() item=attachment}
+                       {unsafe:$attachment->toHtmlElement()}
+               {/foreach}
+       </div>
+
        <dl class="wide">
                <dt></dt>
                <dd>
@@ -8,10 +15,6 @@
                </dd>
        </dl>
 
-       {foreach from=$attachmentHandler->getAttachmentList() item=attachment}
-               {unsafe:$attachment->toHtmlElement()}
-       {/foreach}
-
        <script data-relocate="true">
                require(["WoltLabSuite/Core/Component/Attachment/List"], ({ setup }) => {
                        setup("{if $wysiwygSelector|isset}{$wysiwygSelector}{else}text{/if}");
index bedf2d13a3d79696375c6f5753c17e523baf8d27..acd7101dbf79517e61d574916115d82f34cc25af 100644 (file)
@@ -2,6 +2,8 @@ import { deleteFile } from "WoltLabSuite/Core/Api/Files/DeleteFile";
 import { dispatchToCkeditor } from "../Ckeditor/Event";
 import WoltlabCoreFileElement from "../File/woltlab-core-file";
 
+import "../File/woltlab-core-file";
+
 type FileProcessorData = {
   attachmentID: number;
 };
@@ -150,4 +152,13 @@ export function setup(editorId: string): void {
   uploadButton.addEventListener("uploadStart", (event: CustomEvent<WoltlabCoreFileElement>) => {
     upload(fileList!, event.detail, editorId);
   });
+
+  const existingFiles = container.querySelector<HTMLElement>(".attachment__list__existingFiles");
+  if (existingFiles !== null) {
+    existingFiles.querySelectorAll("woltlab-core-file").forEach((file) => {
+      upload(fileList, file, editorId);
+    });
+
+    existingFiles.remove();
+  }
 }
index 1148cd1c89c15e449664aff6618f16629b1f34dc..998c1c2fd8366736addb0998edbafd475c3fd0a3 100644 (file)
@@ -52,14 +52,19 @@ export class WoltlabCoreFileElement extends HTMLElement {
   }
 
   connectedCallback() {
+    let wasAlreadyReady = false;
     if (this.#state === State.Initial) {
-      this.#initializeState();
+      wasAlreadyReady = this.#initializeState();
     }
 
     this.#rebuildElement();
+
+    if (wasAlreadyReady) {
+      this.#readyResolve();
+    }
   }
 
-  #initializeState(): void {
+  #initializeState(): boolean {
     // Files that exist at page load have a valid file id, otherwise a new
     // file element can only be the result of an upload attempt.
     if (this.#fileId === undefined) {
@@ -75,7 +80,7 @@ export class WoltlabCoreFileElement extends HTMLElement {
       } else {
         this.#state = State.Uploading;
 
-        return;
+        return false;
       }
     }
 
@@ -87,7 +92,13 @@ export class WoltlabCoreFileElement extends HTMLElement {
       }
     }
 
+    if (this.dataset.metaData) {
+      this.#data = JSON.parse(this.dataset.metaData);
+    }
+
     this.#state = State.Ready;
+
+    return true;
   }
 
   #rebuildElement(): void {
index d84d83ad825a9631b38fdca71ac23e428e3d7531..54e633c75cb5cc51eec797c3c0326f9263a599c2 100644 (file)
@@ -1,4 +1,4 @@
-define(["require", "exports", "WoltLabSuite/Core/Api/Files/DeleteFile", "../Ckeditor/Event"], function (require, exports, DeleteFile_1, Event_1) {
+define(["require", "exports", "WoltLabSuite/Core/Api/Files/DeleteFile", "../Ckeditor/Event", "../File/woltlab-core-file"], function (require, exports, DeleteFile_1, Event_1) {
     "use strict";
     Object.defineProperty(exports, "__esModule", { value: true });
     exports.setup = void 0;
@@ -111,6 +111,13 @@ define(["require", "exports", "WoltLabSuite/Core/Api/Files/DeleteFile", "../Cked
         uploadButton.addEventListener("uploadStart", (event) => {
             upload(fileList, event.detail, editorId);
         });
+        const existingFiles = container.querySelector(".attachment__list__existingFiles");
+        if (existingFiles !== null) {
+            existingFiles.querySelectorAll("woltlab-core-file").forEach((file) => {
+                upload(fileList, file, editorId);
+            });
+            existingFiles.remove();
+        }
     }
     exports.setup = setup;
 });
index dc7ef5b8096b1bf2d49babef437acadb7fa0cadd..942dc5aca4d6aec12b258ea1ab5977399ff92f09 100644 (file)
@@ -36,10 +36,14 @@ define(["require", "exports"], function (require, exports) {
             });
         }
         connectedCallback() {
+            let wasAlreadyReady = false;
             if (this.#state === 0 /* State.Initial */) {
-                this.#initializeState();
+                wasAlreadyReady = this.#initializeState();
             }
             this.#rebuildElement();
+            if (wasAlreadyReady) {
+                this.#readyResolve();
+            }
         }
         #initializeState() {
             // Files that exist at page load have a valid file id, otherwise a new
@@ -55,7 +59,7 @@ define(["require", "exports"], function (require, exports) {
                 }
                 else {
                     this.#state = 1 /* State.Uploading */;
-                    return;
+                    return false;
                 }
             }
             // Initialize the list of thumbnails from the data attribute.
@@ -65,7 +69,11 @@ define(["require", "exports"], function (require, exports) {
                     this.#thumbnails.push(new Thumbnail(thumbnail.identifier, thumbnail.link));
                 }
             }
+            if (this.dataset.metaData) {
+                this.#data = JSON.parse(this.dataset.metaData);
+            }
             this.#state = 3 /* State.Ready */;
+            return true;
         }
         #rebuildElement() {
             switch (this.#state) {
index 0275687f58ef352eff4d06fad935f028ca1f9d7c..de414d1b7f511e0e74ab44475bbb61334cd4ef0d 100644 (file)
@@ -408,7 +408,9 @@ class Attachment extends DatabaseObject implements ILinkableObject, IRouteContro
 
     public function toHtmlElement(): ?string
     {
-        return $this->getFile()?->toHtmlElement();
+        return $this->getFile()?->toHtmlElement([
+            'attachmentID' => $this->attachmentID,
+        ]);
     }
 
     public static function findByFileID(int $fileID): ?Attachment
index 2d837eadf1cbc80bb6a15a546da6f4138492acbf..147449269a84041a73d82a42ff6b43096f13c01c 100644 (file)
@@ -132,7 +132,7 @@ class File extends DatabaseObject
         return $this->thumbnails[$identifier] ?? null;
     }
 
-    public function toHtmlElement(): string
+    public function toHtmlElement(array $metaData): string
     {
         $thumbnails = [];
         foreach ($this->thumbnails as $thumbnail) {
@@ -150,12 +150,14 @@ class File extends DatabaseObject
                     data-filename="%s"
                     data-mime-type="%s"
                     data-thumbnails="%s"
+                    data-meta-data="%s"
                 ></woltlab-core-file>
                 EOT,
             $this->fileID,
             StringUtil::encodeHTML($this->filename),
             StringUtil::encodeHTML($this->mimeType),
             StringUtil::encodeHTML(\json_encode($thumbnails)),
+            StringUtil::encodeHTML(\json_encode($metaData)),
         );
     }