Add a preview feature when restoring a draft
authorAlexander Ebert <ebert@woltlab.com>
Wed, 5 Jul 2023 11:22:34 +0000 (13:22 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Wed, 5 Jul 2023 11:22:34 +0000 (13:22 +0200)
See https://www.woltlab.com/community/thread/300352-dialog-entwurf-wiederherstellen-verbessern/

com.woltlab.wcf/templates/wysiwyg.tpl
ts/WoltLabSuite/Core/Component/Ckeditor/Autosave.ts
wcfsetup/install/files/acp/templates/wysiwyg.tpl
wcfsetup/install/files/js/WoltLabSuite/Core/Component/Ckeditor/Autosave.js
wcfsetup/install/files/style/ui/ckeditor.scss
wcfsetup/install/lang/de.xml
wcfsetup/install/lang/en.xml

index 92cccf7f41bd227b3bde01423328c26e2b82dc5d..b365d2f985383704c51a62f721d78f3add383920 100644 (file)
@@ -25,6 +25,8 @@
                {jsphrase name='wcf.editor.button.group.list'}
                {jsphrase name='wcf.editor.button.spoiler'}
                {jsphrase name='wcf.editor.restoreDraft'}
+               {jsphrase name='wcf.editor.restoreDraft.preview'}
+               {jsphrase name='wcf.editor.restoreDraft.restoreOrDiscard'}
 
                {include file='mediaJavaScript'}
 
index a4e4e0d7f79af0a6b694c8b20321f0ae82d8a679..86ff69cc0e54de34c42e411f3276242345e10853 100644 (file)
@@ -41,12 +41,28 @@ function getRestoreDialog(): HTMLElement {
       <button type="button" class="button small" data-type="cancel">
         ${escapeHTML(getPhrase("wcf.dialog.button.cancel"))}
       </button>
+      <button type="button" class="button small" data-type="preview">
+        ${escapeHTML(getPhrase("wcf.editor.restoreDraft.preview"))}
+      </button>
     </div>
   `;
 
   return dialog;
 }
 
+function getReturnToRestoreDialogOverlay(): HTMLElement {
+  const overlay = document.createElement("div");
+  overlay.classList.add("ck", "ck-toolbar__items");
+
+  overlay.innerHTML = `
+    <button type="button" class="ck ck-button">
+      ${escapeHTML(getPhrase("wcf.editor.restoreDraft.restoreOrDiscard"))}
+    </button>
+  `;
+
+  return overlay;
+}
+
 export function deleteDraft(identifier: string): void {
   try {
     window.localStorage.removeItem(getLocalStorageKey(identifier));
@@ -147,6 +163,30 @@ export function setupRestoreDraft(editor: ClassicEditor, identifier: string): vo
 
     revertEditor();
   });
+
+  const lockId = Symbol("autosave");
+  dialog.querySelector('button[data-type="preview"]')!.addEventListener("click", () => {
+    editor.enableReadOnlyMode(lockId);
+
+    const overlay = getReturnToRestoreDialogOverlay();
+
+    const toolbar = editor.ui.view.toolbar.element!;
+    const existingItems = Array.from(toolbar.children) as HTMLElement[];
+    existingItems.forEach((items) => (items.hidden = true));
+
+    toolbar.append(overlay);
+    dialogWrapper.hidden = true;
+
+    const closeOverlayButton = overlay.querySelector("button")!;
+    closeOverlayButton.addEventListener("click", () => {
+      editor.disableReadOnlyMode(lockId);
+
+      dialogWrapper.hidden = false;
+      overlay.remove();
+      existingItems.forEach((items) => (items.hidden = false));
+    });
+    closeOverlayButton.focus();
+  });
 }
 
 function removeExpiredDrafts(): void {
index 92cccf7f41bd227b3bde01423328c26e2b82dc5d..b365d2f985383704c51a62f721d78f3add383920 100644 (file)
@@ -25,6 +25,8 @@
                {jsphrase name='wcf.editor.button.group.list'}
                {jsphrase name='wcf.editor.button.spoiler'}
                {jsphrase name='wcf.editor.restoreDraft'}
+               {jsphrase name='wcf.editor.restoreDraft.preview'}
+               {jsphrase name='wcf.editor.restoreDraft.restoreOrDiscard'}
 
                {include file='mediaJavaScript'}
 
index f459c21579c5d5822fd3d38c1f59971cf1f95229..80dffdd5a9818a03542e3e129a68906b4eb7abd0 100644 (file)
@@ -30,10 +30,23 @@ define(["require", "exports", "../../Core", "../../Language", "../../StringUtil"
       <button type="button" class="button small" data-type="cancel">
         ${(0, StringUtil_1.escapeHTML)((0, Language_1.getPhrase)("wcf.dialog.button.cancel"))}
       </button>
+      <button type="button" class="button small" data-type="preview">
+        ${(0, StringUtil_1.escapeHTML)((0, Language_1.getPhrase)("wcf.editor.restoreDraft.preview"))}
+      </button>
     </div>
   `;
         return dialog;
     }
+    function getReturnToRestoreDialogOverlay() {
+        const overlay = document.createElement("div");
+        overlay.classList.add("ck", "ck-toolbar__items");
+        overlay.innerHTML = `
+    <button type="button" class="ck ck-button">
+      ${(0, StringUtil_1.escapeHTML)((0, Language_1.getPhrase)("wcf.editor.restoreDraft.restoreOrDiscard"))}
+    </button>
+  `;
+        return overlay;
+    }
     function deleteDraft(identifier) {
         try {
             window.localStorage.removeItem(getLocalStorageKey(identifier));
@@ -115,6 +128,24 @@ define(["require", "exports", "../../Core", "../../Language", "../../StringUtil"
             }
             revertEditor();
         });
+        const lockId = Symbol("autosave");
+        dialog.querySelector('button[data-type="preview"]').addEventListener("click", () => {
+            editor.enableReadOnlyMode(lockId);
+            const overlay = getReturnToRestoreDialogOverlay();
+            const toolbar = editor.ui.view.toolbar.element;
+            const existingItems = Array.from(toolbar.children);
+            existingItems.forEach((items) => (items.hidden = true));
+            toolbar.append(overlay);
+            dialogWrapper.hidden = true;
+            const closeOverlayButton = overlay.querySelector("button");
+            closeOverlayButton.addEventListener("click", () => {
+                editor.disableReadOnlyMode(lockId);
+                dialogWrapper.hidden = false;
+                overlay.remove();
+                existingItems.forEach((items) => (items.hidden = false));
+            });
+            closeOverlayButton.focus();
+        });
     }
     exports.setupRestoreDraft = setupRestoreDraft;
     function removeExpiredDrafts() {
index 08bdc09aff4400b924c87dad2b998d0a129834b0..f905d25b68b968905253afaa7e4017ffd68cca50 100644 (file)
@@ -312,6 +312,10 @@ html[data-color-scheme="dark"] {
        margin-top: 20px;
 }
 
+.ckeditor5__restoreDraft__buttons button[data-type="preview"] {
+       margin-right: auto;
+}
+
 html[data-color-scheme="dark"] {
        .ckeditor5__restoreDraft__dialog {
                border-color: var(--wcfContentBorderInner);
index ddad1405ad1da2f35fb2ec53f578aa7a6ed5f6b1..1a7f982349584574ea135af4dc55157cae5ffb76 100644 (file)
@@ -3910,6 +3910,8 @@ Dateianhänge:
                <item name="wcf.editor.button.media"><![CDATA[Media]]></item>
                <item name="wcf.editor.button.page"><![CDATA[CMS-Seite]]></item>
                <item name="wcf.editor.restoreDraft"><![CDATA[Möchten Sie den zwischengespeicherten Entwurf wiederherstellen?]]></item>
+               <item name="wcf.editor.restoreDraft.preview"><![CDATA[Vorschau]]></item>
+               <item name="wcf.editor.restoreDraft.restoreOrDiscard"><![CDATA[Entwurf wiederherstellen oder verwerfen]]></item>
        </category>
        <category name="wcf.global">
                <item name="wcf.global.button.add"><![CDATA[Hinzufügen]]></item>
index 78f93e5c52669c150c2564a75a472c61fc0766a1..896da4e0a815bbe7bddb00a1685fc59b78abd2f0 100644 (file)
@@ -3856,6 +3856,8 @@ Attachments:
                <item name="wcf.editor.button.media"><![CDATA[Media]]></item>
                <item name="wcf.editor.button.page"><![CDATA[CMS Page]]></item>
                <item name="wcf.editor.restoreDraft"><![CDATA[Do you want to restore the saved draft?]]></item>
+               <item name="wcf.editor.restoreDraft.preview"><![CDATA[Preview]]></item>
+               <item name="wcf.editor.restoreDraft.restoreOrDiscard"><![CDATA[Discard or Restore Draft]]></item>
        </category>
        <category name="wcf.global">
                <item name="wcf.global.button.add"><![CDATA[Add]]></item>