Add a custom form field for searching for a pageObjectID
authorCyperghost <olaf_schmitz_1@t-online.de>
Thu, 21 Nov 2024 08:16:59 +0000 (09:16 +0100)
committerCyperghost <olaf_schmitz_1@t-online.de>
Thu, 21 Nov 2024 08:16:59 +0000 (09:16 +0100)
ts/WoltLabSuite/Core/Acp/Ui/Menu/Item/Handler.ts
wcfsetup/install/files/acp/templates/__pageObjectIDFormField.tpl [new file with mode: 0644]
wcfsetup/install/files/js/WoltLabSuite/Core/Acp/Ui/Menu/Item/Handler.js
wcfsetup/install/files/lib/acp/form/MenuItemAddForm.class.php

index b5a0284d4fdc9c7e12db51998d79d1bcef3ae019..75f5920801b85cd1e219f1c95673b8674330d0df 100644 (file)
  * @license  GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
  */
 
-import Dictionary from "../../../../Dictionary";
-import DomUtil from "../../../../Dom/Util";
-import * as Language from "../../../../Language";
 import * as UiPageSearchHandler from "../../../../Ui/Page/Search/Handler";
+import { getPhrase } from "WoltLabSuite/Core/Language";
 
-class AcpUiMenuItemHandler {
-  private activePageId = 0;
-  private readonly cache = new Map<number, number>();
-  private readonly containerExternalLink: HTMLElement;
-  private readonly containerInternalLink: HTMLElement;
-  private readonly containerPageObjectId: HTMLElement;
-  private readonly handlers: Map<number, string>;
+export class AcpUiMenuItemHandler {
+  private readonly handlers: Map<number, boolean>;
   private readonly pageId: HTMLSelectElement;
   private readonly pageObjectId: HTMLInputElement;
 
   /**
    * Initializes the interface logic.
    */
-  constructor(handlers: Map<number, string>) {
+  constructor(fieldPrefix: string, handlers: Map<number, boolean>) {
     this.handlers = handlers;
 
-    this.containerInternalLink = document.getElementById("pageIDContainer")!;
-    this.containerExternalLink = document.getElementById("externalURLContainer")!;
-    this.containerPageObjectId = document.getElementById("pageObjectIDContainer")!;
-
     if (this.handlers.size) {
       this.pageId = document.getElementById("pageID") as HTMLSelectElement;
-      this.pageId.addEventListener("change", this.togglePageId.bind(this));
-
-      this.pageObjectId = document.getElementById("pageObjectID") as HTMLInputElement;
-
-      this.activePageId = ~~this.pageId.value;
-      if (this.activePageId && this.handlers.has(this.activePageId)) {
-        this.cache.set(this.activePageId, ~~this.pageObjectId.value);
-      }
-
-      const searchButton = document.getElementById("searchPageObjectID")!;
-      searchButton.addEventListener("click", (ev) => this.openSearch(ev));
-
-      // toggle page object id container on init
-      if (this.handlers.has(~~this.pageId.value)) {
-        DomUtil.show(this.containerPageObjectId);
-      }
-    }
-
-    document.querySelectorAll('input[name="isInternalLink"]').forEach((input: HTMLInputElement) => {
-      input.addEventListener("change", () => this.toggleIsInternalLink(input.value));
-
-      if (input.checked) {
-        this.toggleIsInternalLink(input.value);
-      }
-    });
-  }
+      this.pageObjectId = document.getElementById(fieldPrefix) as HTMLInputElement;
 
-  /**
-   * Toggles between the interface for internal and external links.
-   */
-  private toggleIsInternalLink(value: string): void {
-    if (~~value) {
-      DomUtil.show(this.containerInternalLink);
-      DomUtil.hide(this.containerExternalLink);
-      if (this.handlers.size) {
-        this.togglePageId();
-      }
-    } else {
-      DomUtil.hide(this.containerInternalLink);
-      DomUtil.hide(this.containerPageObjectId);
-      DomUtil.show(this.containerExternalLink);
+      const searchButton = document.getElementById(fieldPrefix + "Search")!;
+      searchButton.addEventListener("click", () => this.openSearch());
     }
   }
 
-  /**
-   * Handles the changed page selection.
-   */
-  private togglePageId(): void {
-    if (this.handlers.has(this.activePageId)) {
-      this.cache.set(this.activePageId, ~~this.pageObjectId.value);
-    }
-
-    this.activePageId = ~~this.pageId.value;
-
-    // page w/o pageObjectID support, discard value
-    if (!this.handlers.has(this.activePageId)) {
-      this.pageObjectId.value = "";
-
-      DomUtil.hide(this.containerPageObjectId);
-
-      return;
-    }
-
-    const newValue = this.cache.get(this.activePageId);
-    this.pageObjectId.value = newValue ? newValue.toString() : "";
-
-    const selectedOption = this.pageId.options[this.pageId.selectedIndex];
-    const pageIdentifier = selectedOption.dataset.identifier!;
-    let languageItem = `wcf.page.pageObjectID.${pageIdentifier}`;
-    if (Language.get(languageItem) === languageItem) {
-      languageItem = "wcf.page.pageObjectID";
-    }
-
-    this.containerPageObjectId.querySelector("label")!.textContent = Language.get(languageItem);
-
-    DomUtil.show(this.containerPageObjectId);
-  }
-
   /**
    * Opens the handler lookup dialog.
    */
-  private openSearch(event: MouseEvent): void {
-    event.preventDefault();
-
+  private openSearch(): void {
     const selectedOption = this.pageId.options[this.pageId.selectedIndex];
     const pageIdentifier = selectedOption.dataset.identifier!;
     const languageItem = `wcf.page.pageObjectID.search.${pageIdentifier}`;
 
     let labelLanguageItem;
-    if (Language.get(languageItem) !== languageItem) {
+    if (getPhrase(languageItem) !== languageItem) {
       labelLanguageItem = languageItem;
     }
 
     UiPageSearchHandler.open(
-      this.activePageId,
+      parseInt(selectedOption.value),
       selectedOption.textContent!.trim(),
       (objectId) => {
         this.pageObjectId.value = objectId.toString();
-        this.cache.set(this.activePageId, objectId);
       },
       labelLanguageItem,
     );
   }
 }
-
-let acpUiMenuItemHandler: AcpUiMenuItemHandler;
-
-export function init(handlers: Dictionary<string> | Map<number, string>): void {
-  if (!acpUiMenuItemHandler) {
-    let map: Map<number, string>;
-    if (!(handlers instanceof Map)) {
-      map = new Map();
-      handlers.forEach((value, key) => {
-        map.set(~~key, value);
-      });
-    } else {
-      map = handlers;
-    }
-
-    acpUiMenuItemHandler = new AcpUiMenuItemHandler(map);
-  }
-}
diff --git a/wcfsetup/install/files/acp/templates/__pageObjectIDFormField.tpl b/wcfsetup/install/files/acp/templates/__pageObjectIDFormField.tpl
new file mode 100644 (file)
index 0000000..0384e67
--- /dev/null
@@ -0,0 +1,35 @@
+<div class="inputAddon">
+       <input type="number" {*
+               *}step="{@$field->getStep()}" {*
+               *}id="{$field->getPrefixedId()}" {*
+               *}name="{$field->getPrefixedId()}" {*
+               *}value="{$field->getValue()}"{*
+               *}{if !$field->getFieldClasses()|empty} class="{implode from=$field->getFieldClasses() item='class' glue=' '}{$class}{/implode}"{/if}{*
+               *}{if $field->getAutoComplete() !== null} autocomplete="{$field->getAutoComplete()}"{/if}{*
+               *}{if $field->isAutofocused()} autofocus{/if}{*
+               *}{if $field->isRequired()} required{/if}{*
+               *}{if $field->isImmutable()} disabled{/if}{*
+               *}{if $field->getMinimum() !== null} min="{$field->getMinimum()}"{/if}{*
+               *}{if $field->getMaximum() !== null} max="{$field->getMaximum()}"{/if}{*
+               *}{if $field->getInputMode() !== null} inputmode="{$field->getInputMode()}"{/if}{*
+               *}{if $field->getPlaceholder() !== null} placeholder="{$field->getPlaceholder()}"{/if}{*
+               *}{if $field->getDocument()->isAjax()} data-dialog-submit-on-enter="true"{/if}{*
+               *}{foreach from=$field->getFieldAttributes() key='attributeName' item='attributeValue'} {$attributeName}="{$attributeValue}"{/foreach}{*
+       *}>
+       <button type="button" id="{$field->getPrefixedId()}Search" class="inputSuffix button jsTooltip" title="{lang}wcf.page.pageObjectID.search{/lang}">
+               {icon name='magnifying-glass'}
+       </button>
+</div>
+
+<script data-relocate="true">
+       {jsphrase name='wcf.page.pageObjectID'}
+       {jsphrase name='wcf.page.pageObjectID.search.noResults'}
+       {jsphrase name='wcf.page.pageObjectID.search.results'}
+       {jsphrase name='wcf.page.pageObjectID.search.terms'}
+
+       require(['WoltLabSuite/Core/Acp/Ui/Menu/Item/Handler'], ({ AcpUiMenuItemHandler }) => {
+               new AcpUiMenuItemHandler('{unsafe:$field->getPrefixedId()|encodeJS}', new Map([
+                       {implode from=$pageHandlers key=handlerPageID item=requireObjectID glue=', '}[{$handlerPageID}, {if $requireObjectID}true{else}false{/if}]{/implode}
+               ]));
+       });
+</script>
index e01bf33055c36dbe1dc27ef0aa42ab24a36027d8..97bd108daeaeaa44e7bbe084ba99f2c1cebde64a 100644 (file)
  * @copyright  2001-2019 WoltLab GmbH
  * @license  GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
  */
-define(["require", "exports", "tslib", "../../../../Dom/Util", "../../../../Language", "../../../../Ui/Page/Search/Handler"], function (require, exports, tslib_1, Util_1, Language, UiPageSearchHandler) {
+define(["require", "exports", "tslib", "../../../../Ui/Page/Search/Handler", "WoltLabSuite/Core/Language"], function (require, exports, tslib_1, UiPageSearchHandler, Language_1) {
     "use strict";
     Object.defineProperty(exports, "__esModule", { value: true });
-    exports.init = init;
-    Util_1 = tslib_1.__importDefault(Util_1);
-    Language = tslib_1.__importStar(Language);
+    exports.AcpUiMenuItemHandler = void 0;
     UiPageSearchHandler = tslib_1.__importStar(UiPageSearchHandler);
     class AcpUiMenuItemHandler {
-        activePageId = 0;
-        cache = new Map();
-        containerExternalLink;
-        containerInternalLink;
-        containerPageObjectId;
         handlers;
         pageId;
         pageObjectId;
         /**
          * Initializes the interface logic.
          */
-        constructor(handlers) {
+        constructor(fieldPrefix, handlers) {
             this.handlers = handlers;
-            this.containerInternalLink = document.getElementById("pageIDContainer");
-            this.containerExternalLink = document.getElementById("externalURLContainer");
-            this.containerPageObjectId = document.getElementById("pageObjectIDContainer");
             if (this.handlers.size) {
                 this.pageId = document.getElementById("pageID");
-                this.pageId.addEventListener("change", this.togglePageId.bind(this));
-                this.pageObjectId = document.getElementById("pageObjectID");
-                this.activePageId = ~~this.pageId.value;
-                if (this.activePageId && this.handlers.has(this.activePageId)) {
-                    this.cache.set(this.activePageId, ~~this.pageObjectId.value);
-                }
-                const searchButton = document.getElementById("searchPageObjectID");
-                searchButton.addEventListener("click", (ev) => this.openSearch(ev));
-                // toggle page object id container on init
-                if (this.handlers.has(~~this.pageId.value)) {
-                    Util_1.default.show(this.containerPageObjectId);
-                }
+                this.pageObjectId = document.getElementById(fieldPrefix);
+                const searchButton = document.getElementById(fieldPrefix + "Search");
+                searchButton.addEventListener("click", () => this.openSearch());
             }
-            document.querySelectorAll('input[name="isInternalLink"]').forEach((input) => {
-                input.addEventListener("change", () => this.toggleIsInternalLink(input.value));
-                if (input.checked) {
-                    this.toggleIsInternalLink(input.value);
-                }
-            });
-        }
-        /**
-         * Toggles between the interface for internal and external links.
-         */
-        toggleIsInternalLink(value) {
-            if (~~value) {
-                Util_1.default.show(this.containerInternalLink);
-                Util_1.default.hide(this.containerExternalLink);
-                if (this.handlers.size) {
-                    this.togglePageId();
-                }
-            }
-            else {
-                Util_1.default.hide(this.containerInternalLink);
-                Util_1.default.hide(this.containerPageObjectId);
-                Util_1.default.show(this.containerExternalLink);
-            }
-        }
-        /**
-         * Handles the changed page selection.
-         */
-        togglePageId() {
-            if (this.handlers.has(this.activePageId)) {
-                this.cache.set(this.activePageId, ~~this.pageObjectId.value);
-            }
-            this.activePageId = ~~this.pageId.value;
-            // page w/o pageObjectID support, discard value
-            if (!this.handlers.has(this.activePageId)) {
-                this.pageObjectId.value = "";
-                Util_1.default.hide(this.containerPageObjectId);
-                return;
-            }
-            const newValue = this.cache.get(this.activePageId);
-            this.pageObjectId.value = newValue ? newValue.toString() : "";
-            const selectedOption = this.pageId.options[this.pageId.selectedIndex];
-            const pageIdentifier = selectedOption.dataset.identifier;
-            let languageItem = `wcf.page.pageObjectID.${pageIdentifier}`;
-            if (Language.get(languageItem) === languageItem) {
-                languageItem = "wcf.page.pageObjectID";
-            }
-            this.containerPageObjectId.querySelector("label").textContent = Language.get(languageItem);
-            Util_1.default.show(this.containerPageObjectId);
         }
         /**
          * Opens the handler lookup dialog.
          */
-        openSearch(event) {
-            event.preventDefault();
+        openSearch() {
             const selectedOption = this.pageId.options[this.pageId.selectedIndex];
             const pageIdentifier = selectedOption.dataset.identifier;
             const languageItem = `wcf.page.pageObjectID.search.${pageIdentifier}`;
             let labelLanguageItem;
-            if (Language.get(languageItem) !== languageItem) {
+            if ((0, Language_1.getPhrase)(languageItem) !== languageItem) {
                 labelLanguageItem = languageItem;
             }
-            UiPageSearchHandler.open(this.activePageId, selectedOption.textContent.trim(), (objectId) => {
+            UiPageSearchHandler.open(parseInt(selectedOption.value), selectedOption.textContent.trim(), (objectId) => {
                 this.pageObjectId.value = objectId.toString();
-                this.cache.set(this.activePageId, objectId);
             }, labelLanguageItem);
         }
     }
-    let acpUiMenuItemHandler;
-    function init(handlers) {
-        if (!acpUiMenuItemHandler) {
-            let map;
-            if (!(handlers instanceof Map)) {
-                map = new Map();
-                handlers.forEach((value, key) => {
-                    map.set(~~key, value);
-                });
-            }
-            else {
-                map = handlers;
-            }
-            acpUiMenuItemHandler = new AcpUiMenuItemHandler(map);
-        }
-    }
+    exports.AcpUiMenuItemHandler = AcpUiMenuItemHandler;
 });
index 4770d79fc97611a15fe0ee028ed20fd63a68ba03..2824e7fae4fbe7188d7a020057d350fa2d559575 100644 (file)
@@ -7,6 +7,7 @@ use wcf\data\menu\item\MenuItemAction;
 use wcf\data\menu\item\MenuItemNodeTree;
 use wcf\data\menu\Menu;
 use wcf\data\page\Page;
+use wcf\data\page\PageNode;
 use wcf\data\page\PageNodeTree;
 use wcf\form\AbstractFormBuilderForm;
 use wcf\system\exception\IllegalLinkException;
@@ -91,6 +92,15 @@ class MenuItemAddForm extends AbstractFormBuilderForm
         parent::createForm();
 
         $this->menuItemNodeList = (new MenuItemNodeTree($this->menuID, null, false))->getNodeList();
+        $pageNodeList = (new PageNodeTree())->getNodeList();
+
+        $pageHandlers = [];
+        foreach ($pageNodeList as $page) {
+            \assert($page instanceof PageNode);
+            if ($page->getHandler() instanceof ILookupPageHandler) {
+                $pageHandlers[$page->pageID] = $page->requireObjectID;
+            }
+        }
 
         $this->form->appendChildren([
             FormContainer::create('generalContainer')
@@ -121,15 +131,15 @@ class MenuItemAddForm extends AbstractFormBuilderForm
                         ->value(1),
                     SingleSelectionFormField::create('pageID')
                         ->label('wcf.acp.page.page')
-                        ->options((new PageNodeTree())->getNodeList(), true)
+                        ->options($pageNodeList, true)
                         ->required()
                         ->addDependency(
                             ValueFormFieldDependency::create('isInternalLinkDependency')
                                 ->fieldId('isInternalLink')
                                 ->values([1])
                         ),
-                    // TODO change this to an new FormField
-                    IntegerFormField::create('pageObjectID')
+                    $this->getPageObjectIDFormField($pageHandlers)
+                        ->id('pageObjectID')
                         ->label('wcf.page.pageObjectID')
                         ->addFieldClass('short')
                         ->addValidator(
@@ -176,6 +186,11 @@ class MenuItemAddForm extends AbstractFormBuilderForm
                             ValueFormFieldDependency::create('isInternalLinkDependency')
                                 ->fieldId('isInternalLink')
                                 ->values([1])
+                        )
+                        ->addDependency(
+                            ValueFormFieldDependency::create('pageIDDependency')
+                                ->fieldId('pageID')
+                                ->values(\array_keys($pageHandlers))
                         ),
                     UrlFormField::create('externalURL')
                         ->label('wcf.acp.menu.item.externalURL')
@@ -255,4 +270,26 @@ class MenuItemAddForm extends AbstractFormBuilderForm
             )
         );
     }
+
+    protected function getPageObjectIDFormField(array $pageHandlers): IntegerFormField
+    {
+        return new class($pageHandlers) extends IntegerFormField {
+            protected $templateName = '__pageObjectIDFormField';
+            protected array $pageHandlers;
+
+            public function __construct(array $pageHandlers)
+            {
+                parent::__construct();
+                $this->pageHandlers = $pageHandlers;
+            }
+
+            #[\Override]
+            public function getHtmlVariables()
+            {
+                return array_merge(parent::getHtmlVariables(), [
+                    'pageHandlers' => $this->pageHandlers
+                ]);
+            }
+        };
+    }
 }