Make message_sidebar_user_options sortable
authorMatthias Schmidt <gravatronics@live.com>
Tue, 9 Feb 2016 19:09:44 +0000 (20:09 +0100)
committerMatthias Schmidt <gravatronics@live.com>
Tue, 9 Feb 2016 19:09:44 +0000 (20:09 +0100)
CHANGELOG.md
com.woltlab.wcf/option.xml
wcfsetup/install/files/acp/templates/useroptionsOptionType.tpl
wcfsetup/install/files/js/WoltLab/WCF/Ui/TabMenu/Simple.js
wcfsetup/install/files/lib/system/option/UseroptionsOptionType.class.php

index 2046f3c4fdf8666836a80afd1fb711259c773254..de8656e303c2938f06a6debdf148e7b3bb144309 100644 (file)
@@ -22,6 +22,8 @@
        * Ported the PHP-BBCode parser, massively improves accuracy and ensures validity
 * Show error message if poll options are given but not question instead of discarding poll options.
 * `parentObjectID` column added to `modification_log` and `wcf\system\log\modification\AbstractModificationLogHandler` introduced as a replacement for `wcf\system\log\modification\ModificationLogHandler`.
+* Add sort support for `useroptions` option type.
+* Make user options shown in sidebar sortable.
 
 #### New Traits
 
index 053be465ce0a86f7f6116a2150d1dcc40c9251f4..5e535db096f2532d5982731551769301754a632e 100644 (file)
@@ -1429,6 +1429,7 @@ DESC:wcf.global.sortOrder.descending]]></selectoptions>
                                <categoryname>message.sidebar</categoryname>
                                <optiontype>useroptions</optiontype>
                                <defaultvalue></defaultvalue>
+                               <issortable>1</issortable>
                        </option>
                        
                        <!-- message.general -->
index 9b500ceacc1cc1307c5430e775dce636edcb7901..2bf3f5d84312b77e2656580ecc9fc02c39fbcc6f 100644 (file)
@@ -1,3 +1,36 @@
-{foreach from=$availableOptions item=availableOption}
-       <label><input type="checkbox" name="values[{$option->optionName}][]" value="{$availableOption}" {if $availableOption|in_array:$value}checked="checked" {/if}/> {lang}wcf.user.option.{$availableOption}{/lang}</label>
-{/foreach}
+{if $option->issortable}
+       <script data-relocate="true">
+               document.addEventListener('DOMContentLoaded', function() {
+                       require(['Dom/Traverse', 'Dom/Util', 'Ui/TabMenu'], function (DomTraverse, DomUtil, UiTabMenu) {
+                               var sortableList = elById('{$option->optionName}SortableList');
+                               var tabMenu = UiTabMenu.getTabMenu(DomUtil.identify(DomTraverse.parentByClass(sortableList, 'tabMenuContainer')));
+                               var activeTab = tabMenu.getActiveTab();
+                               
+                               // select the tab the sortable list is in as jQuery's sortable requires
+                               // the sortable list to be visible
+                               tabMenu.select(null, DomTraverse.parentByClass(sortableList, 'tabMenuContent'));
+                               
+                               new WCF.Sortable.List('{$option->optionName}SortableList', null, 0, { }, true);
+                               
+                               // re-select the previously selected tab
+                               tabMenu.select(null, activeTab);
+                       });
+               });
+       </script>
+       
+       <div id="{$option->optionName}SortableList" class="sortableListContainer">
+               <ol class="sortableList">
+                       {foreach from=$availableOptions item=availableOption}
+                               <li class="sortableNode">
+                                       <span class="sortableNodeLabel">
+                                               <label><input type="checkbox" name="values[{$option->optionName}][]" value="{$availableOption}" {if $availableOption|in_array:$value}checked="checked" {/if}/> {lang}wcf.user.option.{$availableOption}{/lang}</label>
+                                       </span>
+                               </li>
+                       {/foreach}
+               </ol>
+       </div>
+{else}
+       {foreach from=$availableOptions item=availableOption}
+               <label><input type="checkbox" name="values[{$option->optionName}][]" value="{$availableOption}" {if $availableOption|in_array:$value}checked="checked" {/if}/> {lang}wcf.user.option.{$availableOption}{/lang}</label>
+       {/foreach}
+{/if}
\ No newline at end of file
index 50d39526862902295213834bf1af5ea818076844..e35b09a547179ca3ce4cc464b206765abb1f3184 100644 (file)
@@ -199,7 +199,7 @@ define(['Dictionary', 'Dom/Traverse', 'Dom/Util', 'EventHandler'], function(Dict
                        name = name || elAttr(tab, 'data-name');
                        
                        // unmark active tab
-                       var oldTab = elBySel('#' + this._container.id + ' > nav > ul > li.active');
+                       var oldTab = this.getActiveTab();
                        var oldContent = null;
                        if (oldTab) {
                                oldTab.classList.remove('active');
@@ -305,6 +305,15 @@ define(['Dictionary', 'Dom/Traverse', 'Dom/Util', 'EventHandler'], function(Dict
                        return name;
                },
                
+               /**
+                * Returns the currently active tab.
+                *
+                * @return      {Element}       active tab
+                */
+               getActiveTab: function() {
+                       return elBySel('#' + this._container.id + ' > nav > ul > li.active');
+               },
+               
                /**
                 * Returns the list of registered content containers.
                 * 
index 0ccaa1ab949d35e1f90752d1cddaa6cb24f93ff3..6e4a0b1ceaf936b7fc384335cd78bd52bb14f0f4 100644 (file)
@@ -8,7 +8,7 @@ use wcf\system\WCF;
  * Option type implementation for user option selection.
  * 
  * @author     Marcel Werk
- * @copyright  2001-2015 WoltLab GmbH
+ * @copyright  2001-2016 WoltLab GmbH
  * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
  * @package    com.woltlab.wcf
  * @subpackage system.option
@@ -17,16 +17,16 @@ use wcf\system\WCF;
 class UseroptionsOptionType extends AbstractOptionType {
        /**
         * list of available user options
-        * @var array<string>
+        * @var string[]
         */
        protected static $userOptions = null;
        
        /**
-        * @see \wcf\system\option\IOptionType::validate()
+        * @inheritDoc
         */
        public function validate(Option $option, $newValue) {
                if (!is_array($newValue)) {
-                       $newValue = array();
+                       $newValue = [];
                }
                
                foreach ($newValue as $optionName) {
@@ -37,7 +37,7 @@ class UseroptionsOptionType extends AbstractOptionType {
        }
        
        /**
-        * @see \wcf\system\option\IOptionType::getData()
+        * @inheritDoc
         */
        public function getData(Option $option, $newValue) {
                if (!is_array($newValue)) return '';
@@ -45,38 +45,47 @@ class UseroptionsOptionType extends AbstractOptionType {
        }
        
        /**
-        * @see \wcf\system\option\IOptionType::getFormElement()
+        * @inheritDoc
         */
        public function getFormElement(Option $option, $value) {
-               WCF::getTPL()->assign(array(
+               $userOptions = self::getUserOptions();
+               if ($option->issortable && $value) {
+                       $sortedOptions = explode(',', $value);
+                       
+                       // remove old options
+                       $sortedOptions = array_intersect($sortedOptions, $userOptions);
+                       
+                       // append the non-checked options after the checked and sorted options
+                       $userOptions = array_merge($sortedOptions, array_diff($userOptions, $sortedOptions));
+               }
+               
+               WCF::getTPL()->assign([
                        'option' => $option,
                        'value' => explode(',', $value),
-                       'availableOptions' => self::getUserOptions()
-               ));
+                       'availableOptions' => $userOptions
+               ]);
                return WCF::getTPL()->fetch('useroptionsOptionType');
        }
        
        /**
         * Returns the list of available user options.
         * 
-        * @return      string
+        * @return      string[]
         */
        protected static function getUserOptions() {
                if (self::$userOptions === null) {
-                       self::$userOptions = array();
+                       self::$userOptions = [];
                        $sql = "SELECT  optionName
                                FROM    wcf".WCF_N."_user_option
                                WHERE   categoryName IN (
                                                SELECT  categoryName
                                                FROM    wcf".WCF_N."_user_option_category
-                                               WHERE   parentCategoryName = 'profile'  
+                                               WHERE   parentCategoryName = 'profile'
                                        )
                                        AND optionType <> 'boolean'";
                        $statement = WCF::getDB()->prepareStatement($sql);
                        $statement->execute();
-                       while ($row = $statement->fetchArray()) {
-                               self::$userOptions[] = $row['optionName'];
-                       }
+                       self::$userOptions = $statement->fetchAll(\PDO::FETCH_COLUMN);
                }
                
                return self::$userOptions;