Replace the legacy category binding of label groups
authorAlexander Ebert <ebert@woltlab.com>
Sat, 23 Sep 2023 17:49:35 +0000 (19:49 +0200)
committerTim Düsterhus <duesterhus@woltlab.com>
Thu, 5 Oct 2023 15:22:51 +0000 (17:22 +0200)
com.woltlab.wcf/templates/articleAdd.tpl
ts/WoltLabSuite/Core/Component/Article/LabelPicker.ts [new file with mode: 0644]
wcfsetup/install/files/acp/templates/articleAdd.tpl
wcfsetup/install/files/js/WCF.Label.js
wcfsetup/install/files/js/WoltLabSuite/Core/Component/Article/LabelPicker.js [new file with mode: 0644]
wcfsetup/install/files/lib/acp/form/ArticleAddForm.class.php

index 5450ad8a7ca1df7c7e2ee742731a90f265682ca8..25396a07896de2713b8e64789a30663540b19fc5 100644 (file)
@@ -87,7 +87,7 @@
 {/if}
 
 <script data-relocate="true">
-       require(['Language', 'WoltLabSuite/Core/Ui/User/Search/Input', 'WoltLabSuite/Core/Acp/Ui/Article/InlineEditor'], function(Language, UiUserSearchInput, AcpUiArticleInlineEditor) {
+       require(['Language', 'WoltLabSuite/Core/Ui/User/Search/Input', 'WoltLabSuite/Core/Acp/Ui/Article/InlineEditor', "WoltLabSuite/Core/Component/Article/LabelPicker"], function(Language, UiUserSearchInput, AcpUiArticleInlineEditor, { setup: setupLabelPicker }) {
                Language.addObject({
                        'wcf.article.convertFromI18n.question': '{jslang}wcf.article.convertFromI18n.question{/jslang}',
                        'wcf.article.convertFromI18n.description': '{jslang}wcf.article.convertFromI18n.description{/jslang}',
                                redirectUrl: '{link controller='ArticleList'}{/link}'
                        });
                {/if}
+
+               setupLabelPicker(new Map([
+                       {implode from=$labelGroupsToCategories key=__labelCategoryID item=labelGroupIDs}
+                               [ {$__labelCategoryID}, [ {implode from=$labelGroupIDs item=labelGroupID}{$labelGroupID}{/implode} ] ],
+                       {/implode}
+               ]));
        });
 </script>
 
 <script data-relocate="true">
        $(function() {
                WCF.Language.addObject({
-                       'wcf.label.none': '{jslang}wcf.label.none{/jslang}',
                        'wcf.global.preview': '{jslang}wcf.global.preview{/jslang}',
                });
                
-               {if !$labelGroups|empty}
-                       //new WCF.Label.ArticleLabelChooser({ {implode from=$labelGroupsToCategories key=__labelCategoryID item=labelGroupIDs}{@$__labelCategoryID}: [ {implode from=$labelGroupIDs item=labelGroupID}{@$labelGroupID}{/implode} ] {/implode} }, { {implode from=$labelIDs key=groupID item=labelID}{@$groupID}: {@$labelID}{/implode} }, '.articleAddForm');
-               {/if}
-               
                new WCF.Message.I18nPreview({
                        messageFields: [
                                {if !$isMultilingual}
diff --git a/ts/WoltLabSuite/Core/Component/Article/LabelPicker.ts b/ts/WoltLabSuite/Core/Component/Article/LabelPicker.ts
new file mode 100644 (file)
index 0000000..46e8ea3
--- /dev/null
@@ -0,0 +1,38 @@
+type CategoryId = number;
+type LabelGroupId = number;
+
+function toggleVisibility(showLabelGroupIds: LabelGroupId[] | undefined): void {
+  if (showLabelGroupIds === undefined) {
+    showLabelGroupIds = [];
+  }
+
+  // TODO: Missing typings for `<woltlab-core-label-picker>`
+  document.querySelectorAll<HTMLElement>("woltlab-core-label-picker").forEach((labelPicker) => {
+    const groupId = parseInt(labelPicker.dataset.groupId!);
+    if (showLabelGroupIds!.includes(groupId)) {
+      (labelPicker as any).disabled = false;
+      labelPicker.closest("dl")!.hidden = false;
+    } else {
+      (labelPicker as any).disabled = true;
+      labelPicker.closest("dl")!.hidden = true;
+    }
+  });
+}
+
+export function setup(categoryMapping: Map<CategoryId, LabelGroupId[]>): void {
+  if (categoryMapping.size === 0) {
+    return;
+  }
+
+  const categoryId = document.getElementById("categoryID") as HTMLSelectElement;
+  function updateVisibility() {
+    const value = parseInt(categoryId.value);
+    toggleVisibility(categoryMapping.get(value));
+  }
+
+  categoryId.addEventListener("change", () => {
+    updateVisibility();
+  });
+
+  updateVisibility();
+}
index a718b08174638221e57d07094f22962131e2b6aa..08422a37372fc27b35f794accab894f51543957c 100644 (file)
@@ -88,7 +88,7 @@
 {/if}
 
 <script data-relocate="true">
-       require(['Language', 'WoltLabSuite/Core/Ui/User/Search/Input', 'WoltLabSuite/Core/Acp/Ui/Article/InlineEditor'], function(Language, UiUserSearchInput, AcpUiArticleInlineEditor) {
+       require(['Language', 'WoltLabSuite/Core/Ui/User/Search/Input', 'WoltLabSuite/Core/Acp/Ui/Article/InlineEditor', "WoltLabSuite/Core/Component/Article/LabelPicker"], function(Language, UiUserSearchInput, AcpUiArticleInlineEditor, { setup: setupLabelPicker }) {
                Language.addObject({
                        'wcf.article.convertFromI18n.question': '{jslang}wcf.article.convertFromI18n.question{/jslang}',
                        'wcf.article.convertFromI18n.description': '{jslang}wcf.article.convertFromI18n.description{/jslang}',
                                redirectUrl: '{link controller='ArticleList'}{/link}'
                        });
                {/if}
+
+               setupLabelPicker(new Map([
+                       {implode from=$labelGroupsToCategories key=__labelCategoryID item=labelGroupIDs}
+                               [ {$__labelCategoryID}, [ {implode from=$labelGroupIDs item=labelGroupID}{$labelGroupID}{/implode} ] ],
+                       {/implode}
+               ]));
        });
 </script>
 
                
                {event name='categoryFields'}
                
-               {if $labelGroups|count}
-                       {foreach from=$labelGroups item=labelGroup}
-                               {if $labelGroup|count}
-                                       <dl{if $errorField == 'label' && $errorType[$labelGroup->groupID]|isset} class="formError"{/if}>
-                                               <dt><label>{$labelGroup->getTitle()}</label></dt>
-                                               <dd>
-                                                       <ul class="labelList jsOnly" data-object-id="{@$labelGroup->groupID}">
-                                                               <li class="dropdown labelChooser" id="labelGroup{@$labelGroup->groupID}" data-group-id="{@$labelGroup->groupID}" data-force-selection="{if $labelGroup->forceSelection}true{else}false{/if}">
-                                                                       <div class="dropdownToggle" data-toggle="labelGroup{@$labelGroup->groupID}"><span class="badge label">{lang}wcf.label.none{/lang}</span></div>
-                                                                       <div class="dropdownMenu">
-                                                                               <ul class="scrollableDropdownMenu">
-                                                                                       {foreach from=$labelGroup item=label}
-                                                                                               <li data-label-id="{@$label->labelID}"><span>{@$label->render()}</span></li>
-                                                                                       {/foreach}
-                                                                               </ul>
-                                                                       </div>
-                                                               </li>
-                                                       </ul>
-                                                       <noscript>
-                                                               <select name="labelIDs[{@$labelGroup->groupID}]">
-                                                                       {foreach from=$labelGroup item=label}
-                                                                               <option value="{$label->labelID}">{$label->getTitle()}</option>
-                                                                       {/foreach}
-                                                               </select>
-                                                       </noscript>
-                                                       {if $errorField == 'label' && $errorType[$labelGroup->groupID]|isset}
-                                                               <small class="innerError">
-                                                                       {if $errorType[$labelGroup->groupID] == 'missing'}
-                                                                               {lang}wcf.label.error.missing{/lang}
-                                                                       {else}
-                                                                               {lang}wcf.label.error.invalid{/lang}
-                                                                       {/if}
-                                                               </small>
+               {foreach from=$labelPickers item=labelPicker}
+                       <dl>
+                               <dt><label for="{$labelPicker->getId()}">{$labelPicker->labelGroup->getTitle()}</label></dt>
+                               <dd>
+                                       {@$labelPicker->toHtml()}
+                                       {if $errorField == 'label' && $errorType[$labelPicker->labelGroup->groupID]|isset}
+                                               <small class="innerError">
+                                                       {if $errorType[$labelPicker->labelGroup->groupID] == 'missing'}
+                                                               {lang}wcf.label.error.missing{/lang}
+                                                       {else}
+                                                               {lang}wcf.label.error.invalid{/lang}
                                                        {/if}
-                                               </dd>
-                                       </dl>
-                               {/if}
-                       {/foreach}
-               {/if}
+                                               </small>
+                                       {/if}
+                               </dd>
+                       </dl>
+               {/foreach}
                
                <dl{if $errorField == 'username'} class="formError"{/if}>
                        <dt><label for="username">{lang}wcf.acp.article.author{/lang}</label></dt>
 <script data-relocate="true">
        $(function() {
                WCF.Language.addObject({
-                       'wcf.label.none': '{jslang}wcf.label.none{/jslang}',
                        'wcf.global.preview': '{jslang}wcf.global.preview{/jslang}',
                });
                
-               {if !$labelGroups|empty}
-                       new WCF.Label.ArticleLabelChooser({ {implode from=$labelGroupsToCategories key=__labelCategoryID item=labelGroupIDs}{@$__labelCategoryID}: [ {implode from=$labelGroupIDs item=labelGroupID}{@$labelGroupID}{/implode} ] {/implode} }, { {implode from=$labelIDs key=groupID item=labelID}{@$groupID}: {@$labelID}{/implode} }, '.articleAddForm');
-               {/if}
-               
                new WCF.Message.I18nPreview({
                        messageFields: [
                                {if !$isMultilingual}
index 191ae832b48e6c035d0f054cecced9d62c613c82..d62a2ad5940d6fb84d638e263ea68a3d0ee81295 100644 (file)
@@ -213,74 +213,3 @@ WCF.Label.Chooser = Class.extend({
        }
 });
 
-if (COMPILER_TARGET_DEFAULT) {
-       /**
-        * Handles displaying label groups based on the selected categories.
-        */
-       WCF.Label.ArticleLabelChooser = WCF.Label.Chooser.extend({
-               /**
-                * maps the available label group ids to the categories
-                * @var        object
-                */
-               _labelGroupsToCategories: null,
-               
-               /**
-                * Initializes a new WCF.Label.ArticleLabelChooser object.
-                *
-                * @param        object                labelGroupsToCategories
-                * @param        object                selectedLabelIDs
-                * @param        string                containerSelector
-                * @param        string                submitButtonSelector
-                * @param        boolean                showWithoutSelection
-                */
-               init: function (labelGroupsToCategories, selectedLabelIDs, containerSelector, submitButtonSelector, showWithoutSelection) {
-                       this._super(selectedLabelIDs, containerSelector, submitButtonSelector, showWithoutSelection);
-                       this._labelGroupsToCategories = labelGroupsToCategories;
-                       
-                       this._updateLabelGroups();
-                       
-                       $('#categoryID').change($.proxy(this._updateLabelGroups, this));
-               },
-               
-               /**
-                * Updates the visible label groups based on the selected categories.
-                */
-               _updateLabelGroups: function () {
-                       // hide all label choosers first
-                       $('.labelChooser').each(function (index, element) {
-                               $(element).parents('dl:eq(0)').hide();
-                       });
-                       
-                       var visibleGroupIDs = [];
-                       var categoryID = parseInt($('#categoryID').val());
-                       
-                       if (this._labelGroupsToCategories[categoryID]) {
-                               for (var i = 0, length = this._labelGroupsToCategories[categoryID].length; i < length; i++) {
-                                       $('#labelGroup' + this._labelGroupsToCategories[categoryID][i]).parents('dl:eq(0)').show();
-                               }
-                       }
-               },
-               
-               /**
-                * @see        WCF.Label.Chooser._submit()
-                */
-               _submit: function () {
-                       // delete non-selected groups to avoid submitting these labels
-                       for (var groupID in this._groups) {
-                               if (!this._groups[groupID].is(':visible')) {
-                                       delete this._groups[groupID];
-                               }
-                       }
-                       
-                       this._super();
-               }
-       });
-}
-else {
-       WCF.Label.ArticleLabelChooser = WCF.Label.Chooser.extend({
-               _labelGroupsToCategories: {},
-               init: function() {},
-               _updateLabelGroups: function () {},
-               _submit: function() {}
-       });
-}
diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Component/Article/LabelPicker.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Component/Article/LabelPicker.js
new file mode 100644 (file)
index 0000000..7715724
--- /dev/null
@@ -0,0 +1,37 @@
+define(["require", "exports"], function (require, exports) {
+    "use strict";
+    Object.defineProperty(exports, "__esModule", { value: true });
+    exports.setup = void 0;
+    function toggleVisibility(showLabelGroupIds) {
+        if (showLabelGroupIds === undefined) {
+            showLabelGroupIds = [];
+        }
+        // TODO: Missing typings for `<woltlab-core-label-picker>`
+        document.querySelectorAll("woltlab-core-label-picker").forEach((labelPicker) => {
+            const groupId = parseInt(labelPicker.dataset.groupId);
+            if (showLabelGroupIds.includes(groupId)) {
+                labelPicker.disabled = false;
+                labelPicker.closest("dl").hidden = false;
+            }
+            else {
+                labelPicker.disabled = true;
+                labelPicker.closest("dl").hidden = true;
+            }
+        });
+    }
+    function setup(categoryMapping) {
+        if (categoryMapping.size === 0) {
+            return;
+        }
+        const categoryId = document.getElementById("categoryID");
+        function updateVisibility() {
+            const value = parseInt(categoryId.value);
+            toggleVisibility(categoryMapping.get(value));
+        }
+        categoryId.addEventListener("change", () => {
+            updateVisibility();
+        });
+        updateVisibility();
+    }
+    exports.setup = setup;
+});
index 787d375892817f57c87cd62005778ac3366a57f7..5587f21e779283337219f62c23326ab3f7b1fb64 100644 (file)
@@ -6,7 +6,6 @@ use wcf\data\article\Article;
 use wcf\data\article\ArticleAction;
 use wcf\data\article\category\ArticleCategory;
 use wcf\data\category\CategoryNodeTree;
-use wcf\data\label\group\ViewableLabelGroup;
 use wcf\data\language\Language;
 use wcf\data\media\Media;
 use wcf\data\media\ViewableMediaList;
@@ -187,12 +186,6 @@ class ArticleAddForm extends AbstractForm
      */
     public $availableLanguages = [];
 
-    /**
-     * label group list
-     * @var ViewableLabelGroup[]
-     */
-    public $labelGroups;
-
     /**
      * @var LabelPicker[]
      * @since 6.1
@@ -607,7 +600,6 @@ class ArticleAddForm extends AbstractForm
         parent::readData();
 
         $this->labelGroupsToCategories = ArticleCategoryLabelCacheBuilder::getInstance()->getData();
-        $this->labelGroups = ArticleCategory::getAccessibleLabelGroups();
 
         if (empty($_POST)) {
             $this->setDefaultValues();
@@ -677,7 +669,6 @@ class ArticleAddForm extends AbstractForm
             'categoryNodeList' => (new CategoryNodeTree('com.woltlab.wcf.article.category'))->getIterator(),
             'accessibleCategoryIDs' => ArticleCategory::getAccessibleCategoryIDs(),
             'labelIDs' => $this->labelIDs,
-            'labelGroups' => $this->labelGroups,
             'labelGroupsToCategories' => $this->labelGroupsToCategories,
             'labelPickers' => $this->labelPickers,
             'attachmentHandler' => $this->attachmentHandler,