Add button to run all rebuildData workers
authorTim Düsterhus <duesterhus@woltlab.com>
Tue, 23 Feb 2021 11:15:09 +0000 (12:15 +0100)
committerTim Düsterhus <duesterhus@woltlab.com>
Tue, 23 Feb 2021 11:15:09 +0000 (12:15 +0100)
Resolves #3974

ts/WoltLabSuite/Core/Acp/Ui/Maintenance/RebuildData.ts [new file with mode: 0644]
wcfsetup/install/files/acp/templates/rebuildData.tpl
wcfsetup/install/files/js/WoltLabSuite/Core/Acp/Ui/Maintenance/RebuildData.js [new file with mode: 0644]
wcfsetup/install/lang/de.xml
wcfsetup/install/lang/en.xml

diff --git a/ts/WoltLabSuite/Core/Acp/Ui/Maintenance/RebuildData.ts b/ts/WoltLabSuite/Core/Acp/Ui/Maintenance/RebuildData.ts
new file mode 100644 (file)
index 0000000..4deae5b
--- /dev/null
@@ -0,0 +1,55 @@
+import Worker from "../Worker";
+import * as Language from "../../../Language";
+
+const workers = new Map<HTMLElement, number>();
+
+export function register(button: HTMLElement): void {
+  if (!button.dataset.className) {
+    throw new Error(`Missing 'data-class-name' attribute.`);
+  }
+
+  workers.set(button, parseInt(button.dataset.nicevalue!, 10));
+
+  button.addEventListener("click", function (event) {
+    event.preventDefault();
+
+    void runWorker(button);
+  });
+}
+
+export async function runAllWorkers(): Promise<void> {
+  const sorted = Array.from(workers)
+    .sort(([, a], [, b]) => {
+      return a - b;
+    })
+    .map(([el]) => el);
+
+  let i = 1;
+  for (const worker of sorted) {
+    await runWorker(worker, `${worker.textContent!} (${i++} / ${sorted.length})`);
+  }
+}
+
+async function runWorker(button: HTMLElement, dialogTitle: string = button.textContent!): Promise<void> {
+  return new Promise<void>((resolve, reject) => {
+    new Worker({
+      dialogId: "cache",
+      dialogTitle,
+      className: button.dataset.className,
+      callbackAbort() {
+        reject();
+      },
+      callbackSuccess() {
+        let span = button.nextElementSibling;
+        if (span && span.nodeName === "SPAN") {
+          span.remove();
+        }
+
+        span = document.createElement("span");
+        span.innerHTML = `<span class="icon icon16 fa-check green"></span> ${Language.get("wcf.acp.worker.success")}`;
+        button.parentNode!.insertBefore(span, button.nextElementSibling);
+        resolve();
+      },
+    });
+  });
+}
index 4b7370de114bfeea7e739ef0a670894d52073b06..77b5e67394682529478c82a52b403899b0384b5b 100644 (file)
@@ -1,34 +1,19 @@
 {include file='header' pageTitle='wcf.acp.rebuildData'}
 
 <script data-relocate="true">
-       require(['Language', 'WoltLabSuite/Core/Acp/Ui/Worker'], function (Language, AcpUiWorker) {
-               Language.add('wcf.acp.worker.abort.confirmMessage', '{jslang}wcf.acp.worker.abort.confirmMessage{/jslang}');
+       require(['Language', 'WoltLabSuite/Core/Acp/Ui/Maintenance/RebuildData'], (Language, RebuildData) => {
+               Language.addObject({
+                       'wcf.acp.worker.abort.confirmMessage': '{jslang}wcf.acp.worker.abort.confirmMessage{/jslang}',
+                       'wcf.acp.worker.success': '{jslang}wcf.acp.worker.success{/jslang}',
+               });
                
-               elBySelAll('.jsRebuildDataWorker', undefined, function (button) {
-                       if (button.classList.contains('disabled')) return;
-                       
-                       button.addEventListener('click', function (event) {
-                               event.preventDefault();
-                               
-                               new AcpUiWorker({
-                                       // dialog
-                                       dialogId: 'cache',
-                                       dialogTitle: button.textContent,
-                                       
-                                       // ajax
-                                       className: elData(button, 'class-name'),
-                                       
-                                       // callbacks
-                                       callbackAbort: null,
-                                       callbackSuccess: () => {
-                                               var span = button.nextElementSibling;
-                                               if (span && span.nodeName === 'SPAN') elRemove(span);
-                                                       
-                                               span = elCreate('span');
-                                               span.innerHTML = ' <span class="icon icon16 fa-check green"></span> {lang}wcf.acp.worker.success{/lang}';
-                                               button.parentNode.insertBefore(span, button.nextElementSibling);
-                                       }
-                               });
+               document.querySelectorAll('.jsRebuildDataWorker').forEach((button) => {
+                       RebuildData.register(button);
+               });
+               document.querySelectorAll('.jsRebuildAll').forEach((button) => {
+                       button.addEventListener('click', (ev) => {
+                               ev.preventDefault();
+                               void RebuildData.runAllWorkers();
                        });
                });
        });
                <h1 class="contentTitle">{lang}wcf.acp.rebuildData{/lang}</h1>
        </div>
        
-       {hascontent}
-               <nav class="contentHeaderNavigation">
-                       <ul>
-                               {content}{event name='contentHeaderNavigation'}{/content}
-                       </ul>
-               </nav>
-       {/hascontent}
+       <nav class="contentHeaderNavigation">
+               <ul>
+                       <li><a href="#" class="button jsRebuildAll"><span class="icon icon16 fa-long-arrow-down"></span> <span>{lang}wcf.acp.rebuildData.rebuildAll{/lang}</span></a></li>
+                       {event name='contentHeaderNavigation'}
+               </ul>
+       </nav>
 </header>
 
 {event name='afterContentHeader'}
@@ -61,7 +45,9 @@
                        <dd>
                                <a href="#"
                                   class="button small jsRebuildDataWorker"
-                                  data-class-name="{$objectType->className}" data-object-type="{$objectType->objectType}"
+                                  data-class-name="{$objectType->className}"
+                                  data-object-type="{$objectType->objectType}"
+                                  data-nicevalue="{if $objectType->nicevalue}{$objectType->nicevalue}{else}0{/if}"
                                >{lang}wcf.acp.rebuildData.{@$objectType->objectType}{/lang}</a>
                                <small>{lang}wcf.acp.rebuildData.{@$objectType->objectType}.description{/lang}</small>
                        </dd>
diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Acp/Ui/Maintenance/RebuildData.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Acp/Ui/Maintenance/RebuildData.js
new file mode 100644 (file)
index 0000000..77bb0db
--- /dev/null
@@ -0,0 +1,53 @@
+define(["require", "exports", "tslib", "../Worker", "../../../Language"], function (require, exports, tslib_1, Worker_1, Language) {
+    "use strict";
+    Object.defineProperty(exports, "__esModule", { value: true });
+    exports.runAllWorkers = exports.register = void 0;
+    Worker_1 = tslib_1.__importDefault(Worker_1);
+    Language = tslib_1.__importStar(Language);
+    const workers = new Map();
+    function register(button) {
+        if (!button.dataset.className) {
+            throw new Error(`Missing 'data-class-name' attribute.`);
+        }
+        workers.set(button, parseInt(button.dataset.nicevalue, 10));
+        button.addEventListener("click", function (event) {
+            event.preventDefault();
+            void runWorker(button);
+        });
+    }
+    exports.register = register;
+    async function runAllWorkers() {
+        const sorted = Array.from(workers)
+            .sort(([, a], [, b]) => {
+            return a - b;
+        })
+            .map(([el]) => el);
+        let i = 1;
+        for (const worker of sorted) {
+            await runWorker(worker, `${worker.textContent} (${i++} / ${sorted.length})`);
+        }
+    }
+    exports.runAllWorkers = runAllWorkers;
+    async function runWorker(button, dialogTitle = button.textContent) {
+        return new Promise((resolve, reject) => {
+            new Worker_1.default({
+                dialogId: "cache",
+                dialogTitle,
+                className: button.dataset.className,
+                callbackAbort() {
+                    reject();
+                },
+                callbackSuccess() {
+                    let span = button.nextElementSibling;
+                    if (span && span.nodeName === "SPAN") {
+                        span.remove();
+                    }
+                    span = document.createElement("span");
+                    span.innerHTML = `<span class="icon icon16 fa-check green"></span> ${Language.get("wcf.acp.worker.success")}`;
+                    button.parentNode.insertBefore(span, button.nextElementSibling);
+                    resolve();
+                },
+            });
+        });
+    }
+});
index ec7c8e2c17c86cd025ffaa3e9dab46267ca50297..29d5e64681a3e1e8d639cf67c7143ec58df7171d 100644 (file)
@@ -2670,6 +2670,7 @@ Kein Abschnitt darf leer sein und alle Abschnitten dürfen nur folgende Zeichen
                <item name="wcf.acp.rebuildData.com.woltlab.wcf.activityPointItems.description"><![CDATA[Berechnet Anzahl an Aktivitäten neu, für die Benutzer Punkte erhalten; aktualisiert Benutzerränge]]></item>
                <item name="wcf.acp.rebuildData.com.woltlab.wcf.searchEngineConvertInnoDb.description"><![CDATA[Stellt die Tabellen des Suchindex auf die InnoDB-Engine um.]]></item>
                <item name="wcf.acp.rebuildData.com.woltlab.wcf.searchEngineConvertInnoDb"><![CDATA[Suchindex auf InnoDB umstellen]]></item>
+               <item name="wcf.acp.rebuildData.rebuildAll"><![CDATA[Alle aktualisieren]]></item>
        </category>
        <category name="wcf.acp.rescueMode">
                <item name="wcf.acp.rescueMode"><![CDATA[Systemwiederherstellung]]></item>
index f6bc07eae01e7e8c4fe38589134747a27c9a14b7..5f5e01a74820e485767c8d1b65459f324c305bfe 100644 (file)
@@ -2598,6 +2598,7 @@ If you have <strong>already bought the licenses for the listed apps</strong>, th
                <item name="wcf.acp.rebuildData.com.woltlab.wcf.activityPointItems.description"><![CDATA[Recalculates the number of activities for which users get points and rebuilds user ranks.]]></item>
                <item name="wcf.acp.rebuildData.com.woltlab.wcf.searchEngineConvertInnoDb.description"><![CDATA[Migrates the search engine tables to the InnoDB storage engine.]]></item>
                <item name="wcf.acp.rebuildData.com.woltlab.wcf.searchEngineConvertInnoDb"><![CDATA[Migrate Search Index to InnoDB]]></item>
+               <item name="wcf.acp.rebuildData.rebuildAll"><![CDATA[Rebuild All]]></item>
        </category>
        <category name="wcf.acp.rescueMode">
                <item name="wcf.acp.rescueMode"><![CDATA[Rescue Mode]]></item>