RCFilters: Make 'related links' collapsible
authorMoriel Schottlender <moriel@gmail.com>
Fri, 28 Jul 2017 07:53:57 +0000 (00:53 -0700)
committerMoriel Schottlender <moriel@gmail.com>
Sat, 29 Jul 2017 01:03:49 +0000 (18:03 -0700)
Bug: T166919
Change-Id: I89d69c6614f641ac92143f0b1a718145e9cd61bd

includes/specials/SpecialRecentchanges.php
languages/i18n/en.json
languages/i18n/qqq.json
resources/Resources.php
resources/src/mediawiki.rcfilters/mw.rcfilters.init.js
resources/src/mediawiki.rcfilters/styles/mw.rcfilters.less
resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterWrapperWidget.less
resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterWrapperWidget.js

index f0c2bc4..f9052ad 100644 (file)
@@ -718,17 +718,35 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
 
                $message = $this->msg( 'recentchangestext' )->inContentLanguage();
                if ( !$message->isDisabled() ) {
-                       $this->getOutput()->addWikiText(
-                               Html::rawElement( 'div',
-                                       [
-                                               'class' => 'mw-recentchanges-toplinks',
-                                               'lang' => $wgContLang->getHtmlCode(),
-                                               'dir' => $wgContLang->getDir()
-                                       ],
-                                       "\n" . $message->plain() . "\n"
-                               ),
-                               /* $lineStart */ true,
-                               /* $interface */ false
+                       $content = $message->parse();
+
+                       $langAttributes = [
+                               'lang' => $wgContLang->getHtmlCode(),
+                               'dir' => $wgContLang->getDir(),
+                       ];
+
+                       $topLinksAttributes = [ 'class' => 'mw-recentchanges-toplinks' ];
+
+                       if ( $this->getUser()->getOption( 'rcenhancedfilters' ) ) {
+                               $contentTitle = Html::rawElement( 'div',
+                                       [ 'class' => 'mw-recentchanges-toplinks-title' ],
+                                       $this->msg( 'rcfilters-other-review-tools' )->parse()
+                               );
+                               $contentWrapper = Html::rawElement( 'div',
+                                       array_merge( [ 'class' => 'mw-collapsible-content' ], $langAttributes ),
+                                       $content
+                               );
+                               $content = $contentTitle . $contentWrapper;
+                       } else {
+                               // Language direction should be on the top div only
+                               // if the title is not there. If it is there, it's
+                               // interface direction, and the language/dir attributes
+                               // should be on the content itself
+                               $topLinksAttributes = array_merge( $topLinksAttributes, $langAttributes );
+                       }
+
+                       $this->getOutput()->addHTML(
+                               Html::rawElement( 'div', $topLinksAttributes, $content )
                        );
                }
        }
index 2f09573..b51738e 100644 (file)
        "recentchanges-legend-plusminus": "(<em>±123</em>)",
        "recentchanges-submit": "Show",
        "rcfilters-legend-heading": "<strong>List of abbreviations:</strong>",
+       "rcfilters-other-review-tools": "<strong>Other review tools:</strong>",
        "rcfilters-activefilters": "Active filters",
        "rcfilters-advancedfilters": "Advanced filters",
        "rcfilters-limit-title": "Changes to show",
index c0d6ad5..66c3c4d 100644 (file)
        "recentchanges-legend-plusminus": "{{optional}}\nA plus/minus sign with a number for the legend.",
        "recentchanges-submit": "Label for submit button in [[Special:RecentChanges]]\n{{Identical|Show}}",
        "rcfilters-legend-heading": "Used as a heading for legend box on [[Special:RecentChanges]] and [[Special:Watchlist]] when RCFilters are enabled.",
+       "rcfilters-other-review-tools": "Used as a heading for the community collection of other links on [[Special:RecentChanges]] when RCFilters are enabled.",
        "rcfilters-activefilters": "Title for the filters selection showing the active filters.",
        "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.",
index 64ecc96..1db5172 100644 (file)
@@ -1880,6 +1880,7 @@ return [
                        'rcfilters-view-tags-tooltip',
                        'rcfilters-view-return-to-default-tooltip',
                        'rcfilters-liveupdates-button',
+                       'rcfilters-other-review-tools',
                        'blanknamespace',
                        'namespaces',
                        'invert',
@@ -1888,6 +1889,7 @@ return [
                ],
                'dependencies' => [
                        'oojs-ui',
+                       'jquery.makeCollapsible',
                        'mediawiki.language',
                        'mediawiki.user',
                        'mediawiki.rcfilters.filters.dm',
index 04a3fda..12a83cd 100644 (file)
@@ -8,7 +8,11 @@
                 * @private
                 */
                init: function () {
-                       var filtersModel = new mw.rcfilters.dm.FiltersViewModel(),
+                       var toplinksTitle,
+                               topLinksCookieName = 'rcfilters-toplinks-collapsed-state',
+                               topLinksCookie = mw.cookie.get( topLinksCookieName ),
+                               topLinksCookieValue = topLinksCookie || 'collapsed',
+                               filtersModel = new mw.rcfilters.dm.FiltersViewModel(),
                                changesListModel = new mw.rcfilters.dm.ChangesListViewModel(),
                                savedQueriesModel = new mw.rcfilters.dm.SavedQueriesModel(),
                                controller = new mw.rcfilters.Controller( filtersModel, changesListModel, savedQueriesModel ),
                        );
 
                        controller.replaceUrl();
+
+                       toplinksTitle = new OO.ui.ButtonWidget( {
+                               framed: false,
+                               indicator: topLinksCookieValue === 'collapsed' ? 'down' : 'up',
+                               flags: [ 'progressive' ],
+                               label: $( '<span>' ).append( mw.message( 'rcfilters-other-review-tools' ).parse() ).contents()
+                       } );
+                       $( '.mw-recentchanges-toplinks-title' ).replaceWith( toplinksTitle.$element );
+                       // Move the top links to a designated area so it's near the
+                       // 'saved filters' button and make it collapsible
+                       $( '.mw-recentchanges-toplinks' )
+                               .addClass( 'mw-rcfilters-ui-ready' )
+                               .makeCollapsible( {
+                                       collapsed: topLinksCookieValue === 'collapsed',
+                                       $customTogglers: toplinksTitle.$element
+                               } )
+                               .on( 'beforeExpand.mw-collapsible', function () {
+                                       mw.cookie.set( topLinksCookieName, 'expanded' );
+                                       toplinksTitle.setIndicator( 'up' );
+                               } )
+                               .on( 'beforeCollapse.mw-collapsible', function () {
+                                       mw.cookie.set( topLinksCookieName, 'collapsed' );
+                                       toplinksTitle.setIndicator( 'down' );
+                               } )
+                               .appendTo( '.mw-rcfilters-ui-filterWrapperWidget-top-placeholder' );
                }
        };
 
index 9f3b809..0d12b81 100644 (file)
@@ -9,8 +9,28 @@
                }
        }
 
+       .mw-recentchanges-toplinks {
+               padding: 0 0.5em;
+
+               &-title,
+               .mw-collapsible-text {
+                       // Same as the legend
+                       font-size: 0.85em;
+               }
+
+               &:not( .mw-collapsed ) {
+                       // Same as the legend
+                       border: 1px solid #ddd;
+               }
+
+               &:not( .mw-rcfilters-ui-ready ) {
+                       display: none;
+               }
+       }
+
        .rcfilters-head {
                min-height: 310px;
+               margin-top: 1em;
 
                &:not( .mw-rcfilters-ui-ready ) {
                        opacity: 0.5;
index df4592c..87d09e0 100644 (file)
@@ -8,6 +8,17 @@
                margin-top: 1em;
        }
 
+       &-top {
+               &-placeholder {
+                       width: 100%;
+               }
+
+               &-savedLinks {
+                       padding-left: 1em;
+                       vertical-align: bottom;
+               }
+       }
+
        &-bottom {
                margin-top: 1em;
 
index 9b4ce7f..a6b363d 100644 (file)
@@ -14,7 +14,7 @@
         * @cfg {jQuery} [$overlay] A jQuery object serving as overlay for popups
         */
        mw.rcfilters.ui.FilterWrapperWidget = function MwRcfiltersUiFilterWrapperWidget( controller, model, savedQueriesModel, config ) {
-               var $bottom;
+               var $top, $topRow, $bottom;
                config = config || {};
 
                // Parent
                );
 
                // Initialize
-               this.$element
-                       .addClass( 'mw-rcfilters-ui-filterWrapperWidget' );
+               $topRow = $( '<div>' )
+                       .addClass( 'mw-rcfilters-ui-row' )
+                       .append(
+                               $( '<div>' )
+                                       .addClass( 'mw-rcfilters-ui-cell' )
+                                       .addClass( 'mw-rcfilters-ui-filterWrapperWidget-top-placeholder' )
+                       );
+               $top = $( '<div>' )
+                       .addClass( 'mw-rcfilters-ui-filterWrapperWidget-top' )
+                       .addClass( 'mw-rcfilters-ui-table' )
+                       .append( $topRow );
+
+               $bottom = $( '<div>' )
+                       .addClass( 'mw-rcfilters-ui-filterWrapperWidget-bottom' )
+                       .append(
+                               this.numChangesWidget.$element,
+                               this.dateWidget.$element
+                       );
 
                if ( mw.config.get( 'wgStructuredChangeFiltersEnableSaving' ) ) {
                        this.savedLinksListWidget = new mw.rcfilters.ui.SavedLinksListWidget(
                                { $overlay: this.$overlay }
                        );
 
-                       this.$element.append(
-                               this.savedLinksListWidget.$element
+                       $topRow.append(
+                               $( '<div>' )
+                                       .addClass( 'mw-rcfilters-ui-cell' )
+                                       .addClass( 'mw-rcfilters-ui-filterWrapperWidget-top-savedLinks' )
+                                       .append( this.savedLinksListWidget.$element )
                        );
                }
 
-               $bottom = $( '<div>' )
-                       .addClass( 'mw-rcfilters-ui-filterWrapperWidget-bottom' )
-                       .append(
-                               this.numChangesWidget.$element,
-                               this.dateWidget.$element
-                       );
-
                if (
                        mw.config.get( 'wgStructuredChangeFiltersEnableLiveUpdate' ) ||
                        // Allow users to enable live update with ?liveupdate=1
                        $bottom.append( this.liveUpdateButton.$element );
                }
 
-               this.$element.append(
-                       this.filterTagWidget.$element,
-                       $bottom
-               );
+               this.$element
+                       .addClass( 'mw-rcfilters-ui-filterWrapperWidget' )
+                       .append(
+                               $top,
+                               this.filterTagWidget.$element,
+                               $bottom
+                       );
        };
 
        /* Initialization */