Merge "RCFilters: Display specific error if query times out"
[lhc/web/wiklou.git] / resources / src / mediawiki.rcfilters / mw.rcfilters.Controller.js
index b805b24..8d36cf5 100644 (file)
                                        separator: ';',
                                        fullCoverage: true,
                                        filters: items
+                               },
+                               {
+                                       name: 'invertGroup',
+                                       type: 'boolean',
+                                       hidden: true,
+                                       filters: [ {
+                                               name: 'invert',
+                                               'default': '0'
+                                       } ]
                                } ]
                        };
                }
         * Reset to default filters
         */
        mw.rcfilters.Controller.prototype.resetToDefaults = function () {
-               this.uriProcessor.updateModelBasedOnQuery( this._getDefaultParams() );
+               this.filtersModel.updateStateFromParams( this._getDefaultParams() );
 
                this.updateChangesList();
        };
         * @return {boolean} Defaults are all false
         */
        mw.rcfilters.Controller.prototype.areDefaultsEmpty = function () {
-               var defaultParams = this._getDefaultParams(),
-                       defaultFilters = this.filtersModel.getFiltersFromParameters( defaultParams );
-
-               this._deleteExcludedValuesFromFilterState( defaultFilters );
-
-               if ( Object.keys( defaultParams ).some( function ( paramName ) {
-                       return paramName.endsWith( '_color' ) && defaultParams[ paramName ] !== null;
-               } ) ) {
-                       // There are highlights in the defaults, they're definitely
-                       // not empty
-                       return false;
-               }
-
-               // Defaults can change in a session, so we need to do this every time
-               return Object.keys( defaultFilters ).every( function ( filterName ) {
-                       return !defaultFilters[ filterName ];
-               } );
+               return $.isEmptyObject( this._getDefaultParams( true ) );
        };
 
        /**
                        .getHighlightedItems()
                        .map( function ( filterItem ) { return { name: filterItem.getName() }; } );
 
-               this.filtersModel.emptyAllFilters();
-               this.filtersModel.clearAllHighlightColors();
-               // Check all filter interactions
-               this.filtersModel.reassessFilterInteractions();
+               this.filtersModel.updateStateFromParams( {} );
 
                this.updateChangesList();
 
         */
        mw.rcfilters.Controller.prototype.clearFilter = function ( filterName ) {
                var filterItem = this.filtersModel.getItemByName( filterName ),
-                       isHighlighted = filterItem.isHighlighted();
+                       isHighlighted = filterItem.isHighlighted(),
+                       isSelected = filterItem.isSelected();
 
-               if ( filterItem.isSelected() || isHighlighted ) {
+               if ( isSelected || isHighlighted ) {
                        this.filtersModel.clearHighlightColor( filterName );
                        this.filtersModel.toggleFilterSelected( filterName, false );
-                       this.updateChangesList();
+
+                       if ( isSelected ) {
+                               // Only update the changes list if the filter changed
+                               // its selection state. If it only changed its highlight
+                               // then don't reload
+                               this.updateChangesList();
+                       }
+
                        this.filtersModel.reassessFilterInteractions( filterItem );
 
                        // Log filter grouping
         */
        mw.rcfilters.Controller.prototype.toggleHighlight = function () {
                this.filtersModel.toggleHighlight();
-               this._updateURL();
+               this.uriProcessor.updateURL();
 
                if ( this.filtersModel.isHighlightEnabled() ) {
                        mw.hook( 'RcFilters.highlight.enable' ).fire();
         */
        mw.rcfilters.Controller.prototype.setHighlightColor = function ( filterName, color ) {
                this.filtersModel.setHighlightColor( filterName, color );
-               this._updateURL();
+               this.uriProcessor.updateURL();
                this._trackHighlight( 'set', { name: filterName, color: color } );
        };
 
         */
        mw.rcfilters.Controller.prototype.clearHighlightColor = function ( filterName ) {
                this.filtersModel.clearHighlightColor( filterName );
-               this._updateURL();
+               this.uriProcessor.updateURL();
                this._trackHighlight( 'clear', filterName );
        };
 
         * @param {boolean} [setAsDefault=false] This query should be set as the default
         */
        mw.rcfilters.Controller.prototype.saveCurrentQuery = function ( label, setAsDefault ) {
-               var highlightedItems = {},
-                       highlightEnabled = this.filtersModel.isHighlightEnabled(),
-                       selectedState = this.filtersModel.getSelectedState();
-
-               // Prepare highlights
-               this.filtersModel.getHighlightedItems().forEach( function ( item ) {
-                       highlightedItems[ item.getName() + '_color' ] = highlightEnabled ?
-                               item.getHighlightColor() : null;
-               } );
-
-               // Delete all excluded filters
-               this._deleteExcludedValuesFromFilterState( selectedState );
-
                // Add item
                this.savedQueriesModel.addNewQuery(
                        label || mw.msg( 'rcfilters-savedqueries-defaultlabel' ),
-                       {
-                               params: $.extend(
-                                       true,
-                                       {
-                                               invert: String( Number( this.filtersModel.areNamespacesInverted() ) ),
-                                               highlight: String( Number( this.filtersModel.isHighlightEnabled() ) )
-                                       },
-                                       this.filtersModel.getParametersFromFilters( selectedState )
-                               ),
-                               highlights: highlightedItems
-                       },
+                       this.filtersModel.getCurrentParameterState( true ),
                        setAsDefault
                );
 
         * @param {string} queryID Query id
         */
        mw.rcfilters.Controller.prototype.applySavedQuery = function ( queryID ) {
-               var highlights,
-                       queryItem = this.savedQueriesModel.getItemByID( queryID ),
-                       data = this.savedQueriesModel.getItemFullData( queryID ),
-                       currentMatchingQuery = this.findQueryMatchingCurrentState();
+               var currentMatchingQuery,
+                       params = this.savedQueriesModel.getItemParams( queryID );
+
+               currentMatchingQuery = this.findQueryMatchingCurrentState();
 
                if (
-                       queryItem &&
-                       (
-                               // If there's already a query, don't reload it
-                               // if it's the same as the one that already exists
-                               !currentMatchingQuery ||
-                               currentMatchingQuery.getID() !== queryItem.getID()
-                       )
+                       currentMatchingQuery &&
+                       currentMatchingQuery.getID() === queryID
                ) {
-                       highlights = data.highlights;
-
-                       // Update model state from filters
-                       this.filtersModel.toggleFiltersSelected(
-                               // Merge filters with excluded values
-                               $.extend(
-                                       true,
-                                       {},
-                                       this.filtersModel.getFiltersFromParameters( data.params ),
-                                       this.filtersModel.getExcludedFiltersState()
-                               )
-                       );
-
-                       // Update namespace inverted property
-                       this.filtersModel.toggleInvertedNamespaces( !!Number( data.params.invert ) );
-
-                       // Update highlight state
-                       this.filtersModel.toggleHighlight( !!Number( data.params.highlight ) );
-                       this.filtersModel.getItems().forEach( function ( filterItem ) {
-                               var color = highlights[ filterItem.getName() + '_color' ];
-                               if ( color ) {
-                                       filterItem.setHighlightColor( color );
-                               } else {
-                                       filterItem.clearHighlightColor();
-                               }
-                       } );
+                       // If the query we want to load is the one that is already
+                       // loaded, don't reload it
+                       return;
+               }
 
-                       // Check all filter interactions
-                       this.filtersModel.reassessFilterInteractions();
+               // Apply parameters to model
+               this.filtersModel.updateStateFromParams( params );
 
-                       this.updateChangesList();
+               this.updateChangesList();
 
-                       // Log filter grouping
-                       this.trackFilterGroupings( 'savedfilters' );
-               }
+               // Log filter grouping
+               this.trackFilterGroupings( 'savedfilters' );
        };
 
        /**
         * Check whether the current filter and highlight state exists
         * in the saved queries model.
         *
-        * @return {boolean} Query exists
+        * @return {mw.rcfilters.dm.SavedQueryItemModel} Matching item model
         */
        mw.rcfilters.Controller.prototype.findQueryMatchingCurrentState = function () {
-               var highlightedItems = {},
-                       selectedState = this.filtersModel.getSelectedState();
-
-               // Prepare highlights of the current query
-               this.filtersModel.getItemsSupportingHighlights().forEach( function ( item ) {
-                       highlightedItems[ item.getName() + '_color' ] = item.getHighlightColor();
-               } );
-
-               // Remove anything that should be excluded from the saved query
-               // this includes sticky filters and filters marked with 'excludedFromSavedQueries'
-               this._deleteExcludedValuesFromFilterState( selectedState );
-
                return this.savedQueriesModel.findMatchingQuery(
-                       {
-                               params: $.extend(
-                                       true,
-                                       {
-                                               highlight: String( Number( this.filtersModel.isHighlightEnabled() ) ),
-                                               invert: String( Number( this.filtersModel.areNamespacesInverted() ) )
-                                       },
-                                       this.filtersModel.getParametersFromFilters( selectedState )
-                               ),
-                               highlights: highlightedItems
-                       }
+                       this.filtersModel.getCurrentParameterState( true )
                );
        };
 
-       /**
-        * Delete sticky filters from given object
-        *
-        * @param {Object} filterState Filter state
-        */
-       mw.rcfilters.Controller.prototype._deleteExcludedValuesFromFilterState = function ( filterState ) {
-               // Remove excluded filters
-               $.each( this.filtersModel.getExcludedFiltersState(), function ( filterName ) {
-                       delete filterState[ filterName ];
-               } );
-       };
-
        /**
         * Save the current state of the saved queries model with all
         * query item representation in the user settings.
         * without adding an history entry.
         */
        mw.rcfilters.Controller.prototype.replaceUrl = function () {
-               mw.rcfilters.UriProcessor.static.replaceState( this._getUpdatedUri() );
+               this.uriProcessor.replaceUpdatedUri();
        };
 
        /**
                updateMode = updateMode === undefined ? this.FILTER_CHANGE : updateMode;
 
                if ( updateMode === this.FILTER_CHANGE ) {
-                       this._updateURL( params );
+                       this.uriProcessor.updateURL( params );
                }
                if ( updateMode === this.FILTER_CHANGE || updateMode === this.SHOW_NEW_CHANGES ) {
                        this.changesListModel.invalidate();
         * Get an object representing the default parameter state, whether
         * it is from the model defaults or from the saved queries.
         *
+        * @param {boolean} [excludeHiddenParams] Exclude hidden and sticky params
         * @return {Object} Default parameters
         */
-       mw.rcfilters.Controller.prototype._getDefaultParams = function () {
-               var savedFilters,
-                       data = ( !mw.user.isAnon() && this.savedQueriesModel.getItemFullData( this.savedQueriesModel.getDefault() ) ) || {};
-
-               if ( !$.isEmptyObject( data ) ) {
-                       // Merge saved filter state with sticky filter values
-                       savedFilters = $.extend(
-                               true, {},
-                               this.filtersModel.getFiltersFromParameters( data.params ),
-                               this.filtersModel.getStickyFiltersState()
-                       );
-
-                       // Return parameter representation
-                       return $.extend( true, {},
-                               this.filtersModel.getParametersFromFilters( savedFilters ),
-                               data.highlights,
-                               { highlight: data.params.highlight, invert: data.params.invert }
-                       );
-               }
-               return this.filtersModel.getDefaultParams();
-       };
-
-       /**
-        * 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.
-        *
-        * @param {Object} [params] Extra parameters to add to the API call
-        */
-       mw.rcfilters.Controller.prototype._updateURL = function ( params ) {
-               var currentUri = new mw.Uri(),
-                       updatedUri = this._getUpdatedUri();
-
-               updatedUri.extend( params || {} );
-
-               if (
-                       this.uriProcessor.getVersion( currentUri.query ) !== 2 ||
-                       this.uriProcessor.isNewState( currentUri.query, updatedUri.query )
-               ) {
-                       mw.rcfilters.UriProcessor.static.replaceState( updatedUri );
+       mw.rcfilters.Controller.prototype._getDefaultParams = function ( excludeHiddenParams ) {
+               if ( this.savedQueriesModel.getDefault() ) {
+                       return this.savedQueriesModel.getDefaultParams( excludeHiddenParams );
+               } else {
+                       return this.filtersModel.getDefaultParams( excludeHiddenParams );
                }
        };
 
-       /**
-        * Get an updated mw.Uri object based on the model state
-        *
-        * @return {mw.Uri} Updated Uri
-        */
-       mw.rcfilters.Controller.prototype._getUpdatedUri = function () {
-               var uri = new mw.Uri();
-
-               // Minimize url
-               uri.query = this.uriProcessor.minimizeQuery(
-                       $.extend(
-                               true,
-                               {},
-                               // We want to retain unrecognized params
-                               // The uri params from model will override
-                               // any recognized value in the current uri
-                               // query, retain unrecognized params, and
-                               // the result will then be minimized
-                               uri.query,
-                               this.uriProcessor.getUriParametersFromModel(),
-                               { urlversion: '2' }
-                       )
-               );
-
-               return uri;
-       };
-
        /**
         * Query the list of changes from the server for the current filters
         *
         * @return {jQuery.Promise} Promise object resolved with { content, status }
         */
        mw.rcfilters.Controller.prototype._queryChangesList = function ( counterId, params ) {
-               var uri = this._getUpdatedUri(),
-                       stickyParams = this.filtersModel.getStickyParams(),
+               var uri = this.uriProcessor.getUpdatedUri(),
+                       stickyParams = this.filtersModel.getStickyParamsValues(),
                        requestId,
                        latestRequest;