Merge "RCFilters UI: Select filter when searching and add it on 'enter'"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Fri, 3 Mar 2017 19:52:42 +0000 (19:52 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Fri, 3 Mar 2017 19:52:42 +0000 (19:52 +0000)
1  2 
resources/src/mediawiki.rcfilters/mw.rcfilters.Controller.js
resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.CapsuleItemWidget.js
resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterWrapperWidget.js

@@@ -62,6 -62,7 +62,6 @@@
                // Check all filter interactions
                this.filtersModel.reassessFilterInteractions();
  
 -              this.updateURL();
                this.updateChangesList();
        };
  
                // Check all filter interactions
                this.filtersModel.reassessFilterInteractions();
  
 -              this.updateURL();
                this.updateChangesList();
        };
  
        /**
-        * Update the state of a filter
+        * Update the selected state of a filter
         *
         * @param {string} filterName Filter name
-        * @param {boolean} isSelected Filter selected state
+        * @param {boolean} [isSelected] Filter selected state
         */
-       mw.rcfilters.Controller.prototype.updateFilter = function ( filterName, isSelected ) {
+       mw.rcfilters.Controller.prototype.toggleFilterSelect = function ( filterName, isSelected ) {
                var obj = {},
                        filterItem = this.filtersModel.getItemByName( filterName );
  
+               isSelected = isSelected === undefined ? !filterItem.isSelected() : isSelected;
                if ( filterItem.isSelected() !== isSelected ) {
                        obj[ filterName ] = isSelected;
                        this.filtersModel.updateFilters( obj );
  
 -                      this.updateURL();
                        this.updateChangesList();
  
                        // Check filter interactions
  
        /**
         * Update the URL of the page to reflect current filters
 +       *
 +       * This should not be called directly from outside the controller.
 +       * If an action requires changing the URL, it should either use the
 +       * highlighting actions below, or call #updateChangesList which does
 +       * the uri corrections already.
 +       *
 +       * @private
 +       * @param {Object} [params] Extra parameters to add to the API call
         */
 -      mw.rcfilters.Controller.prototype.updateURL = function () {
 -              var uri = this.getUpdatedUri();
 +      mw.rcfilters.Controller.prototype.updateURL = function ( params ) {
 +              var uri;
 +
 +              params = params || {};
 +
 +              uri = this.getUpdatedUri();
 +              uri.extend( params );
 +
                window.history.pushState( { tag: 'rcfilters' }, document.title, uri.toString() );
        };
  
         * Fetch the list of changes from the server for the current filters
         *
         * @return {jQuery.Promise} Promise object that will resolve with the changes list
 +       *  or with a string denoting no results.
         */
        mw.rcfilters.Controller.prototype.fetchChangesList = function () {
                var uri = this.getUpdatedUri(),
                        latestRequest = function () {
                                return requestId === this.requestCounter;
                        }.bind( this );
 -              uri.extend( this.filtersModel.getParametersFromFilters() );
 +
                return $.ajax( uri.toString(), { contentType: 'html' } )
 -                      .then( function ( html ) {
 -                              return latestRequest() ?
 -                                      $( $.parseHTML( html ) ).find( '.mw-changeslist' ).first().contents() :
 -                                      null;
 -                      } ).then( null, function () {
 -                              return latestRequest() ? 'NO_RESULTS' : null;
 -                      } );
 +                      .then(
 +                              // Success
 +                              function ( html ) {
 +                                      var $parsed;
 +                                      if ( !latestRequest() ) {
 +                                              return $.Deferred().reject();
 +                                      }
 +
 +                                      $parsed = $( $.parseHTML( html ) );
 +
 +                                      return {
 +                                              // Changes list
 +                                              changes: $parsed.find( '.mw-changeslist' ).first().contents(),
 +                                              // Fieldset
 +                                              fieldset: $parsed.find( 'fieldset.rcoptions' ).first()
 +                                      };
 +                              },
 +                              // Failure
 +                              function ( responseObj ) {
 +                                      var $parsed;
 +
 +                                      if ( !latestRequest() ) {
 +                                              return $.Deferred().reject();
 +                                      }
 +
 +                                      $parsed = $( $.parseHTML( responseObj.responseText ) );
 +
 +                                      // Force a resolve state to this promise
 +                                      return $.Deferred().resolve( {
 +                                              changes: 'NO_RESULTS',
 +                                              fieldset: $parsed.find( 'fieldset.rcoptions' ).first()
 +                                      } ).promise();
 +                              }
 +                      );
        };
  
        /**
         * Update the list of changes and notify the model
 +       *
 +       * @param {Object} [params] Extra parameters to add to the API call
         */
 -      mw.rcfilters.Controller.prototype.updateChangesList = function () {
 +      mw.rcfilters.Controller.prototype.updateChangesList = function ( params ) {
 +              this.updateURL( params );
                this.changesListModel.invalidate();
                this.fetchChangesList()
 -                      .always( function ( changesListContent ) {
 -                              if ( changesListContent ) {
 -                                      this.changesListModel.update( changesListContent );
 -                              }
 -                      }.bind( this ) );
 +                      .then(
 +                              // Success
 +                              function ( pieces ) {
 +                                      var $changesListContent = pieces.changes,
 +                                              $fieldset = pieces.fieldset;
 +
 +                                      this.changesListModel.update( $changesListContent, $fieldset );
 +                              }.bind( this )
 +                              // Do nothing for failure
 +                      );
        };
  
        /**
                }
  
                // Respond to user removing the filter
-               this.controller.updateFilter( this.model.getName(), false );
+               this.controller.toggleFilterSelect( this.model.getName(), false );
                this.controller.clearHighlightColor( this.model.getName() );
        };
  
                                'mw-rcfilters-ui-capsuleItemWidget-muted',
                                !this.model.isSelected() ||
                                this.model.isIncluded() ||
 -                              this.model.isConflicted() ||
                                this.model.isFullyCovered()
 +                      )
 +                      .toggleClass(
 +                              'mw-rcfilters-ui-capsuleItemWidget-conflicted',
 +                              this.model.isConflicted()
                        );
        };
  
@@@ -40,7 -40,7 +40,7 @@@
                                icon: 'feedback',
                                flags: [ 'progressive' ],
                                label: mw.msg( 'rcfilters-filterlist-feedbacklink' ),
 -                              href: 'https://www.mediawiki.org/wiki/Help_talk:Edit_Review_Improvements/RC_filters'
 +                              href: 'https://www.mediawiki.org/wiki/Help_talk:New_filters_for_edit_review'
                        } ).$element
                );
  
@@@ -66,7 -66,8 +66,8 @@@
                        itemUpdate: 'onModelItemUpdate'
                } );
                this.textInput.connect( this, {
-                       change: 'onTextInputChange'
+                       change: 'onTextInputChange',
+                       enter: 'onTextInputEnter'
                } );
                this.capsule.connect( this, { capsuleItemClick: 'onCapsuleItemClick' } );
                this.capsule.popup.connect( this, { toggle: 'onCapsulePopupToggle' } );
@@@ -74,7 -75,6 +75,7 @@@
                // Initialize
                this.$element
                        .addClass( 'mw-rcfilters-ui-filterWrapperWidget' )
 +                      .addClass( 'mw-rcfilters-ui-ready' )
                        .append( this.capsule.$element, this.textInput.$element );
        };
  
         */
        mw.rcfilters.ui.FilterWrapperWidget.prototype.onCapsulePopupToggle = function ( isVisible ) {
                if ( !isVisible ) {
-                       this.filterPopup.resetSelection();
-                       this.capsule.resetSelection();
+                       if ( !this.textInput.getValue() ) {
+                               // Only reset selection if we are not filtering
+                               this.filterPopup.resetSelection();
+                               this.capsule.resetSelection();
+                       }
                } else {
                        this.scrollToTop( this.capsule.$element, 10 );
                }
         * @param {string} newValue Current value
         */
        mw.rcfilters.ui.FilterWrapperWidget.prototype.onTextInputChange = function ( newValue ) {
-               this.filterPopup.resetSelection();
                // Filter the results
                this.filterPopup.filter( this.model.findMatches( newValue ) );
+               if ( !newValue ) {
+                       // If the value is empty, we didn't actually
+                       // filter anything. the filter method will run
+                       // and show all, but then will select the
+                       // top item - but in this case, no selection
+                       // should be made.
+                       this.filterPopup.resetSelection();
+               }
                this.capsule.popup.clip();
        };
  
+       /**
+        * Respond to text input enter event
+        */
+       mw.rcfilters.ui.FilterWrapperWidget.prototype.onTextInputEnter = function () {
+               var filter = this.filterPopup.getSelectedFilter();
+               // Toggle the filter
+               this.controller.toggleFilterSelect( filter );
+       };
        /**
         * Respond to model update event and set up the available filters to choose
         * from.
         * any actual interaction with the system resets the selection state of any item.
         */
        mw.rcfilters.ui.FilterWrapperWidget.prototype.onModelItemUpdate = function () {
-               this.filterPopup.resetSelection();
+               if ( !this.textInput.getValue() ) {
+                       this.filterPopup.resetSelection();
+               }
        };
  
        /**