RCFilters: Preserve collapsed state and adjust display
authorMoriel Schottlender <moriel@gmail.com>
Mon, 18 Jun 2018 22:04:47 +0000 (15:04 -0700)
committerMoriel Schottlender <moriel@gmail.com>
Wed, 20 Jun 2018 18:12:00 +0000 (11:12 -0700)
When collapsed, make sure we are adjusting the 'min-height' on the
'rcfilters-head' div so that it actually takes the space it should.

Make sure the preference of whether the area is collapsed or not is
preserved for the user, per RC or WL pages, and that it is loaded
properly with the correct minimum height dimensions depending on
which state is in the preferences, so to prevent "jump" of the
result list after load.

Bug: T177206
Change-Id: I82c3042cd1bb85dedcd6b5458b157fed94def808

14 files changed:
includes/preferences/DefaultPreferencesFactory.php
includes/specialpage/ChangesListSpecialPage.php
includes/specials/SpecialRecentchanges.php
includes/specials/SpecialWatchlist.php
languages/i18n/en.json
languages/i18n/qqq.json
resources/Resources.php
resources/src/mediawiki.rcfilters/mw.rcfilters.Controller.js
resources/src/mediawiki.rcfilters/mw.rcfilters.init.js
resources/src/mediawiki.rcfilters/styles/mw.rcfilters.less
resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterTagMultiselectWidget.less
resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterTagMultiselectWidget.js
resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterWrapperWidget.js
resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.MainWrapperWidget.js

index bf6ab4a..03e4bdb 100644 (file)
@@ -1022,6 +1022,12 @@ class DefaultPreferencesFactory implements PreferencesFactory {
                        'label-message' => 'tog-hideminor',
                        'section' => 'rc/advancedrc',
                ];
+               $defaultPreferences['rcfilters-rc-collapsed'] = [
+                       'type' => 'api',
+               ];
+               $defaultPreferences['rcfilters-wl-collapsed'] = [
+                       'type' => 'api',
+               ];
                $defaultPreferences['rcfilters-saved-queries'] = [
                        'type' => 'api',
                ];
index 831644e..58944b4 100644 (file)
@@ -57,6 +57,12 @@ abstract class ChangesListSpecialPage extends SpecialPage {
         */
        protected static $limitPreferenceName;
 
+       /**
+        * Preference name for collapsing the active filter display. Subclasses should override this.
+        * @var string
+        */
+       protected static $collapsedPreferenceName;
+
        /** @var string */
        protected $rcSubpage;
 
@@ -779,9 +785,13 @@ abstract class ChangesListSpecialPage extends SpecialPage {
                        foreach ( $jsData['messageKeys'] as $key ) {
                                $messages[$key] = $this->msg( $key )->plain();
                        }
-
                        $out->addBodyClasses( 'mw-rcfilters-enabled' );
 
+                       $collapsed = $this->getUser()->getBoolOption( static::$collapsedPreferenceName );
+                       if ( $collapsed ) {
+                               $out->addBodyClasses( 'mw-rcfilters-collapsed' );
+                       }
+
                        $out->addHTML(
                                ResourceLoader::makeInlineScript(
                                        ResourceLoader::makeMessageSetScript( $messages ),
@@ -790,6 +800,7 @@ abstract class ChangesListSpecialPage extends SpecialPage {
                        );
 
                        $out->addJsConfigVars( 'wgStructuredChangeFilters', $jsData['groups'] );
+                       $out->addJsConfigVars( 'wgStructuredChangeFiltersCollapsedState', $collapsed );
 
                        $out->addJsConfigVars(
                                'wgRCFiltersChangeTags',
@@ -818,6 +829,10 @@ abstract class ChangesListSpecialPage extends SpecialPage {
                                'wgStructuredChangeFiltersDaysPreferenceName',
                                static::$daysPreferenceName
                        );
+                       $out->addJsConfigVars(
+                               'wgStructuredChangeFiltersCollapsedPreferenceName',
+                               static::$collapsedPreferenceName
+                       );
 
                        $out->addJsConfigVars(
                                'StructuredChangeFiltersLiveUpdatePollingRate',
index bfef5e0..2496192 100644 (file)
@@ -35,6 +35,7 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
        protected static $savedQueriesPreferenceName = 'rcfilters-saved-queries';
        protected static $daysPreferenceName = 'rcdays'; // Use general RecentChanges preference
        protected static $limitPreferenceName = 'rcfilters-limit'; // Use RCFilters-specific preference
+       protected static $collapsedPreferenceName = 'rcfilters-rc-collapsed';
 
        private $watchlistFilterGroupDefinition;
 
index ce7fea9..b9543d9 100644 (file)
@@ -35,6 +35,7 @@ class SpecialWatchlist extends ChangesListSpecialPage {
        protected static $savedQueriesPreferenceName = 'rcfilters-wl-saved-queries';
        protected static $daysPreferenceName = 'watchlistdays';
        protected static $limitPreferenceName = 'wllimit';
+       protected static $collapsedPreferenceName = 'rcfilters-wl-collapsed';
 
        private $maxDays;
 
index 86a05f0..139140f 100644 (file)
        "rcfilters-activefilters": "Active filters",
        "rcfilters-activefilters-hide": "Hide",
        "rcfilters-activefilters-show": "Show",
+       "rcfilters-activefilters-hide-tooltip": "Hide Active Filters area",
+       "rcfilters-activefilters-show-tooltip": "Show Active Filters area",
        "rcfilters-advancedfilters": "Advanced filters",
        "rcfilters-limit-title": "Results to show",
        "rcfilters-limit-and-date-label": "$1 {{PLURAL:$1|change|changes}}, $2",
index 0b92009..ee09e97 100644 (file)
        "rcfilters-activefilters": "{{doc-important|Translations of this message should not more than 3 cm long, otherwise it will make bad user experiences for potential mobile users.}}\nTitle for the filters selection showing the active filters.",
        "rcfilters-activefilters-hide": "Label for the button that hides the active filters list and dropdown in [[Special:RecentChanges]].\n{{Identical|Hide}}",
        "rcfilters-activefilters-show": "Label for the button that shows the active filters list and dropdown in [[Special:RecentChanges]].\n{{Identical|Show}}",
+       "rcfilters-activefilters-hide-tooltip": "Tooltip for the button that hides the active filters list and dropdown in [[Special:RecentChanges]].",
+       "rcfilters-activefilters-show-tooltip": "Tooltip for the button that shows the active filters list and dropdown in [[Special:RecentChanges]].",
        "rcfilters-advancedfilters": "Title for the buttons allowing the user to switch to the various advanced filters views.",
        "rcfilters-limit-title": "Title for the options to change the number of results shown.",
        "rcfilters-limit-and-date-label": "Title for the button that opens the operation to control how many results to show and in which time period to search. \n\nParameters: $1 - Number of results shown\n\n$2 - Time period to search. One of {{msg-mw|rcfilters-days-title}} or {{msg-mw|rcfilters-hours-title}} is used as $2\n{{Identical|Change}}",
index 69e9a2b..b7ecd10 100644 (file)
@@ -1889,6 +1889,8 @@ return [
                        'rcfilters-activefilters',
                        'rcfilters-activefilters-hide',
                        'rcfilters-activefilters-show',
+                       'rcfilters-activefilters-hide-tooltip',
+                       'rcfilters-activefilters-show-tooltip',
                        'rcfilters-advancedfilters',
                        'rcfilters-group-results-by-page',
                        'rcfilters-limit-title',
index cd3f684..3e900f0 100644 (file)
@@ -15,6 +15,8 @@
         * @cfg {string} savedQueriesPreferenceName Where to save the saved queries
         * @cfg {string} daysPreferenceName Preference name for the days filter
         * @cfg {string} limitPreferenceName Preference name for the limit filter
+        * @cfg {string} collapsedPreferenceName Preference name for collapsing and showing
+        *  the active filters area
         * @cfg {boolean} [normalizeTarget] Dictates whether or not to go through the
         *  title normalization to separate title subpage/parts into the target= url
         *  parameter
@@ -26,6 +28,7 @@
                this.savedQueriesPreferenceName = config.savedQueriesPreferenceName;
                this.daysPreferenceName = config.daysPreferenceName;
                this.limitPreferenceName = config.limitPreferenceName;
+               this.collapsedPreferenceName = config.collapsedPreferenceName;
                this.normalizeTarget = !!config.normalizeTarget;
 
                this.requestCounter = {};
                this.updateNumericPreference( 'usenewrc', Number( newValue ) );
        };
 
+       /**
+        * Update the collapsed state value
+        *
+        * @param {boolean} isCollapsed Filter area is collapsed
+        */
+       mw.rcfilters.Controller.prototype.updateCollapsedState = function ( isCollapsed ) {
+               this.updateNumericPreference( this.collapsedPreferenceName, Number( isCollapsed ) );
+       };
+
        /**
         * Update a numeric preference with a new value
         *
index d181532..c918df8 100644 (file)
@@ -15,6 +15,8 @@
                                savedQueriesPreferenceName = mw.config.get( 'wgStructuredChangeFiltersSavedQueriesPreferenceName' ),
                                daysPreferenceName = mw.config.get( 'wgStructuredChangeFiltersDaysPreferenceName' ),
                                limitPreferenceName = mw.config.get( 'wgStructuredChangeFiltersLimitPreferenceName' ),
+                               activeFiltersCollapsedName = mw.config.get( 'wgStructuredChangeFiltersCollapsedPreferenceName' ),
+                               initialCollapsedState = mw.config.get( 'wgStructuredChangeFiltersCollapsedState' ),
                                filtersModel = new mw.rcfilters.dm.FiltersViewModel(),
                                changesListModel = new mw.rcfilters.dm.ChangesListViewModel( $initialFieldset ),
                                savedQueriesModel = new mw.rcfilters.dm.SavedQueriesModel( filtersModel ),
@@ -25,6 +27,7 @@
                                                savedQueriesPreferenceName: savedQueriesPreferenceName,
                                                daysPreferenceName: daysPreferenceName,
                                                limitPreferenceName: limitPreferenceName,
+                                               collapsedPreferenceName: activeFiltersCollapsedName,
                                                normalizeTarget: specialPage === 'Recentchangeslinked'
                                        }
                                );
                                savedQueriesModel,
                                changesListModel,
                                {
+                                       $wrapper: $( 'body' ),
                                        $topSection: $topSection,
                                        $filtersContainer: $( '.rcfilters-container' ),
                                        $changesListContainer: $( '.mw-changeslist, .mw-changeslist-empty' ),
-                                       $formContainer: $initialFieldset
+                                       $formContainer: $initialFieldset,
+                                       collapsed: initialCollapsedState
                                }
                        );
 
index 11972de..c6d8d17 100644 (file)
@@ -6,6 +6,8 @@
 @rcfilters-head-min-height: 210px;
 @rcfilters-head-margin-bottom: 20px;
 @rcfilters-wl-head-min-height: 270px;
+@rcfilters-head-min-height-collapsed: 130px;
+@rcfilters-wl-head-min-height-collapsed: 200px;
 
 // Corrections for the standard special page
 .client-js {
                min-height: @rcfilters-wl-head-min-height;
        }
 
+       .mw-rcfilters-collapsed {
+               .rcfilters-head {
+                       min-height: @rcfilters-head-min-height-collapsed;
+               }
+
+               // On the watchlist, reserve a bit more
+               &.mw-special-Watchlist .rcfilters-head {
+                       min-height: @rcfilters-wl-head-min-height-collapsed;
+               }
+       }
+
        .mw-recentchanges-toplinks {
                padding-left: 0.5em;
 
index 83ca2bd..a2b3eb7 100644 (file)
@@ -22,7 +22,7 @@
                line-height: normal;
        }
 
-       &-collapsed {
+       .mw-rcfilters-collapsed & {
                // Taking from the handle, since border-bottom is set on the
                // filters view which is hidden when collapsed
                border-bottom: 1px solid @colorGray10;
index 5df7032..96f2f0b 100644 (file)
@@ -12,6 +12,9 @@
         * @param {mw.rcfilters.dm.SavedQueriesModel} savedQueriesModel Saved queries model
         * @param {Object} config Configuration object
         * @cfg {jQuery} [$overlay] A jQuery object serving as overlay for popups
+        * @cfg {jQuery} [$wrapper] A jQuery object for the wrapper of the general
+        *  system. If not given, falls back to this widget's $element
+        * @cfg {boolean} [collapsed] Filter area is collapsed
         */
        mw.rcfilters.ui.FilterTagMultiselectWidget = function MwRcfiltersUiFilterTagMultiselectWidget( controller, model, savedQueriesModel, config ) {
                var rcFiltersRow,
                this.model = model;
                this.queriesModel = savedQueriesModel;
                this.$overlay = config.$overlay || this.$element;
+               this.$wrapper = config.$wrapper || this.$element;
                this.matchingQuery = null;
                this.currentView = this.model.getCurrentView();
+               this.collapsed = false;
 
                // Parent
                mw.rcfilters.ui.FilterTagMultiselectWidget.parent.call( this, $.extend( true, {
                this.hideShowButton = new OO.ui.ButtonWidget( {
                        framed: false,
                        flags: [ 'progressive' ],
-                       label: mw.msg( 'rcfilters-activefilters-hide' ),
                        classes: [ 'mw-rcfilters-ui-filterTagMultiselectWidget-hideshowButton' ]
                } );
-               this.collapsed = false;
+               this.toggleCollapsed( !!config.collapsed );
 
                if ( !mw.user.isAnon() ) {
                        this.saveQueryButton = new mw.rcfilters.ui.SaveFiltersPopupButtonWidget(
        mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.toggleCollapsed = function ( isCollapsed ) {
                isCollapsed = isCollapsed === undefined ? !this.collapsed : !!isCollapsed;
 
-               if ( this.collapsed !== isCollapsed ) {
-                       this.collapsed = isCollapsed;
-
-                       if ( isCollapsed ) {
-                               // If we are collapsing, close the menu, in case it was open
-                               // We should make sure the menu closes before the rest of the elements
-                               // are hidden, otherwise there is an unknown error in jQuery as ooui
-                               // sets and unsets properties on the input (which is hidden at that point)
-                               this.menu.toggle( false );
-                       }
-                       this.input.setDisabled( isCollapsed );
-                       this.hideShowButton.setLabel( mw.msg(
-                               isCollapsed ? 'rcfilters-activefilters-show' : 'rcfilters-activefilters-hide'
-                       ) );
+               this.collapsed = isCollapsed;
 
-                       this.$element.toggleClass( 'mw-rcfilters-ui-filterTagMultiselectWidget-collapsed', isCollapsed );
+               if ( isCollapsed ) {
+                       // If we are collapsing, close the menu, in case it was open
+                       // We should make sure the menu closes before the rest of the elements
+                       // are hidden, otherwise there is an unknown error in jQuery as ooui
+                       // sets and unsets properties on the input (which is hidden at that point)
+                       this.menu.toggle( false );
                }
+               this.input.setDisabled( isCollapsed );
+               this.hideShowButton.setLabel( mw.msg(
+                       isCollapsed ? 'rcfilters-activefilters-show' : 'rcfilters-activefilters-hide'
+               ) );
+               this.hideShowButton.setTitle( mw.msg(
+                       isCollapsed ? 'rcfilters-activefilters-show-tooltip' : 'rcfilters-activefilters-hide-tooltip'
+               ) );
+
+               // Toggle the wrapper class, so we have min height values correctly throughout
+               this.$wrapper.toggleClass( 'mw-rcfilters-collapsed', isCollapsed );
+
+               // Save the state
+               this.controller.updateCollapsedState( isCollapsed );
        };
 
        /**
index dba24fc..a5a8187 100644 (file)
@@ -13,6 +13,9 @@
         * @param {Object} [config] Configuration object
         * @cfg {Object} [filters] A definition of the filter groups in this list
         * @cfg {jQuery} [$overlay] A jQuery object serving as overlay for popups
+        * @cfg {jQuery} [$wrapper] A jQuery object for the wrapper of the general
+        *  system. If not given, falls back to this widget's $element
+        * @cfg {boolean} [collapsed] Filter area is collapsed
         */
        mw.rcfilters.ui.FilterWrapperWidget = function MwRcfiltersUiFilterWrapperWidget(
                controller, model, savedQueriesModel, changesListModel, config
                this.queriesModel = savedQueriesModel;
                this.changesListModel = changesListModel;
                this.$overlay = config.$overlay || this.$element;
+               this.$wrapper = config.$wrapper || this.$element;
 
                this.filterTagWidget = new mw.rcfilters.ui.FilterTagMultiselectWidget(
                        this.controller,
                        this.model,
                        this.queriesModel,
-                       { $overlay: this.$overlay }
+                       {
+                               $overlay: this.$overlay,
+                               collapsed: config.collapsed,
+                               $wrapper: this.$wrapper
+                       }
                );
 
                this.liveUpdateButton = new mw.rcfilters.ui.LiveUpdateButtonWidget(
index 8002045..eab8499 100644 (file)
@@ -14,6 +14,9 @@
         * @cfg {jQuery} $filtersContainer
         * @cfg {jQuery} $changesListContainer
         * @cfg {jQuery} $formContainer
+        * @cfg {boolean} [collapsed] Filter area is collapsed
+        * @cfg {jQuery} [$wrapper] A jQuery object for the wrapper of the general
+        *  system. If not given, falls back to this widget's $element
         */
        mw.rcfilters.ui.MainWrapperWidget = function MwRcfiltersUiMainWrapperWidget(
                controller, model, savedQueriesModel, changesListModel, config
@@ -31,6 +34,7 @@
                this.$changesListContainer = config.$changesListContainer;
                this.$formContainer = config.$formContainer;
                this.$overlay = $( '<div>' ).addClass( 'mw-rcfilters-ui-overlay' );
+               this.$wrapper = config.$wrapper || this.$element;
 
                this.savedLinksListWidget = new mw.rcfilters.ui.SavedLinksListWidget(
                        controller, savedQueriesModel, { $overlay: this.$overlay }
@@ -42,7 +46,9 @@
                        savedQueriesModel,
                        changesListModel,
                        {
-                               $overlay: this.$overlay
+                               $overlay: this.$overlay,
+                               $wrapper: this.$wrapper,
+                               collapsed: config.collapsed
                        }
                );