Mooeypoo has uploaded a new change for review. ( 
https://gerrit.wikimedia.org/r/353925 )

Change subject: [wip] Minimize url query
......................................................................

[wip] Minimize url query

In order to minimize the URL query, we use a base representation of the
parameters as if they were all '0' or '' empty and internally expand
on it.

- Only display parameters with a value that is not empty or '0' in the
  URI. Any parameter that is missing from the URI is presumed to have
  an empty value.
- Stop pushing defaultParameters everywhere. Default parameters should
  only be considered either on load (when/if needed) or when the user
  actively requests for them.
- Minimize parameters to the URL, and expand when reading into the model.

Similar to using base filters, we can use a representation of base
parameters to make the URL small but the representation all-encompassing.

Change-Id: I1d21c38137fde51fcd561e2de24592722bf532c6
---
M resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FiltersViewModel.js
M resources/src/mediawiki.rcfilters/mw.rcfilters.Controller.js
M tests/qunit/suites/resources/mediawiki.rcfilters/dm.FiltersViewModel.test.js
3 files changed, 116 insertions(+), 33 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core 
refs/changes/25/353925/1

diff --git 
a/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FiltersViewModel.js 
b/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FiltersViewModel.js
index 88ce33c..739556485 100644
--- a/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FiltersViewModel.js
+++ b/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FiltersViewModel.js
@@ -505,10 +505,10 @@
         *                  are the selected highlight colors.
         */
        mw.rcfilters.dm.FiltersViewModel.prototype.getHighlightParameters = 
function () {
-               var result = { highlight: Number( this.isHighlightEnabled() ) };
+               var result = {};
 
                this.getItems().forEach( function ( filterItem ) {
-                       result[ filterItem.getName() + '_color' ] = 
filterItem.getHighlightColor();
+                       result[ filterItem.getName() + '_color' ] = 
filterItem.getHighlightColor() || null;
                } );
                return result;
        };
diff --git a/resources/src/mediawiki.rcfilters/mw.rcfilters.Controller.js 
b/resources/src/mediawiki.rcfilters/mw.rcfilters.Controller.js
index e9274f5..8c294f0 100644
--- a/resources/src/mediawiki.rcfilters/mw.rcfilters.Controller.js
+++ b/resources/src/mediawiki.rcfilters/mw.rcfilters.Controller.js
@@ -12,7 +12,8 @@
                this.changesListModel = changesListModel;
                this.savedQueriesModel = savedQueriesModel;
                this.requestCounter = 0;
-               this.baseState = {};
+               this.baseFilterState = {};
+               this.emptyParameterState = {};
        };
 
        /* Initialization */
@@ -24,12 +25,16 @@
         * @param {Array} filterStructure Filter definition and structure for 
the model
         */
        mw.rcfilters.Controller.prototype.initialize = function ( 
filterStructure ) {
-               var parsedSavedQueries,
+               var parsedSavedQueries, validParameterNames,
+                       uri = new mw.Uri(),
                        $changesList = $( '.mw-changeslist' 
).first().contents();
+
                // Initialize the model
                this.filtersModel.initializeFilters( filterStructure );
 
                this._buildBaseFilterState();
+               this._buildEmptyParameterState();
+               validParameterNames = Object.keys( 
this._getEmptyParameterState() );
 
                try {
                        parsedSavedQueries = JSON.parse( mw.user.options.get( 
'rcfilters-saved-queries' ) || '{}' );
@@ -42,10 +47,27 @@
                // can normalize them per each query item
                this.savedQueriesModel.initialize(
                        parsedSavedQueries,
-                       this._getBaseState()
+                       this._getBaseFilterState()
                );
 
-               this.updateStateBasedOnUrl();
+               // Check whether we need to load defaults.
+               // We do this by checking whether the current URI query
+               // is a subset of the base state. If it is, we don't load
+               // defaults. If it isn't, we have no values at all, and
+               // we need to load defaults.
+               // Defaults should only be applied on load (if necessary)
+               // or on request
+               if (
+                       Object.keys( uri.query ).some( function ( parameter, 
value ) {
+                               return validParameterNames.indexOf( parameter ) 
> -1;
+                       } )
+               ) {
+                       // There are parameters in the url, update model state
+                       this.updateStateBasedOnUrl();
+               } else {
+                       // No valid parameters are given, load defaults
+                       this._updateModelState( this._getDefaultParams() );
+               }
 
                // Update the changes list with the existing data
                // so it gets processed
@@ -59,7 +81,7 @@
         * Reset to default filters
         */
        mw.rcfilters.Controller.prototype.resetToDefaults = function () {
-               this._updateModelState( this._getDefaultParams() );
+               this._updateModelState( $.extend( true, { highlight: '0' }, 
this._getDefaultParams() ) );
                this.updateChangesList();
        };
 
@@ -335,15 +357,35 @@
                } );
                highlightedItems.highlight = false;
 
-               this.baseState = {
+               this.baseFilterState = {
                        filters: this.filtersModel.getFiltersFromParameters( 
defaultParams ),
                        highlights: highlightedItems
                };
        };
 
        /**
-        * Get an object representing the base state of parameters
-        * and highlights. The structure is similar to what we use
+        * Build an empty representation of the parameters, where all parameters
+        * are either set to '0' or '' depending on their type.
+        * This must run during initialization, before highlights are set.
+        *
+        * @return {Object} Empty parameter state
+        */
+       mw.rcfilters.Controller.prototype._buildEmptyParameterState = function 
() {
+               var emptyParams = this.filtersModel.getParametersFromFilters( 
{} ),
+                       emptyHighlights = 
this.filtersModel.getHighlightParameters();
+
+               this.emptyParameterState = $.extend(
+                       true,
+                       {},
+                       emptyParams,
+                       emptyHighlights,
+                       { highlight: '0' }
+               );
+       };
+
+       /**
+        * Get an object representing the base filter state of both
+        * filters and highlights. The structure is similar to what we use
         * to store each query in the saved queries object:
         * {
         *    filters: {
@@ -357,8 +399,24 @@
         * @return {Object} Object representing the base state of
         *  parameters and highlights
         */
-       mw.rcfilters.Controller.prototype._getBaseState = function () {
-               return this.baseState;
+       mw.rcfilters.Controller.prototype._getBaseFilterState = function () {
+               return this.baseFilterState;
+       };
+
+       /**
+        * Get an object representing the base state of parameters
+        * and highlights. The structure is similar to what we use
+        * to store each query in the saved queries object:
+        * {
+        *    param1: "value",
+        *    param2: "value1|value2"
+        * }
+        *
+        * @return {Object} Object representing the base state of
+        *  parameters and highlights
+        */
+       mw.rcfilters.Controller.prototype._getEmptyParameterState = function () 
{
+               return this.emptyParameterState;
        };
 
        /**
@@ -374,7 +432,7 @@
         */
        mw.rcfilters.Controller.prototype._getMinimalFilterList = function ( 
valuesObject ) {
                var result = { filters: {}, highlights: {} },
-                       baseState = this._getBaseState();
+                       baseState = this._getBaseFilterState();
 
                // XOR results
                $.each( valuesObject.filters, function ( name, value ) {
@@ -434,13 +492,12 @@
 
        /**
         * Update filter state (selection and highlighting) based
-        * on current URL and default values.
+        * on current URL values.
         */
        mw.rcfilters.Controller.prototype.updateStateBasedOnUrl = function () {
-               var uri = new mw.Uri(),
-                       defaultParams = this._getDefaultParams();
+               var uri = new mw.Uri();
 
-               this._updateModelState( $.extend( {}, defaultParams, uri.query 
) );
+               this._updateModelState( uri.query );
                this.updateChangesList();
        };
 
@@ -566,26 +623,35 @@
         */
        mw.rcfilters.Controller.prototype._getUpdatedUri = function () {
                var uri = new mw.Uri(),
-                       highlightParams = 
this.filtersModel.getHighlightParameters();
+                       highlightParams = 
this.filtersModel.getHighlightParameters(),
+                       modelParameters = 
this.filtersModel.getParametersFromFilters(),
+                       baseParams = this._getEmptyParameterState();
 
-               // Add to existing queries in URL
-               // TODO: Clean up the list of filters; perhaps 'falsy' filters
-               // shouldn't appear at all? Or compare to existing query string
-               // and see if current state of a specific filter is needed?
-               uri.extend( this.filtersModel.getParametersFromFilters() );
+               // Minimize values of the model parameters; show only the 
values that
+               // are non-zero. We assume that all parameters that are not 
literally
+               // showing in the URL are set to zero or empty
+               $.each( modelParameters, function ( paramName, value ) {
+                       if ( baseParams[ paramName ] !== value ) {
+                               uri.query[ paramName ] = value;
+                       } else {
+                               // We need to remove this value from the url
+                               delete uri.query[ paramName ];
+                       }
+               } );
 
                // highlight params
-               uri.query.highlight = Number( 
this.filtersModel.isHighlightEnabled() );
+               if ( this.filtersModel.isHighlightEnabled() ) {
+                       uri.query.highlight = Number( 
this.filtersModel.isHighlightEnabled() );
+               } else {
+                       delete uri.query.highlight;
+               }
                Object.keys( highlightParams ).forEach( function ( paramName ) {
-                       // Always have some value (either the color or null) so 
that
-                       // if we have something in the URL that doesn't have 
the highlight
-                       // intentionally, it can override default with 
highlight.
-                       // Otherwise, the $.extend will always add the 
highlight that
-                       // exists in the default even if the URL query that is 
being
-                       // refreshed has different highlights, or has 
highlights enabled
-                       // but no active highlights anywhere
-                       uri.query[ paramName ] = highlightParams[ paramName ] ?
-                               highlightParams[ paramName ] : null;
+                       // Only output if it is different than the base 
parameters
+                       if ( highlightParams[ paramName ] !== baseParams[ 
paramName ] ) {
+                               uri.query[ paramName ] = highlightParams[ 
paramName ];
+                       } else {
+                               delete uri.query[ paramName ];
+                       }
                } );
 
                return uri;
diff --git 
a/tests/qunit/suites/resources/mediawiki.rcfilters/dm.FiltersViewModel.test.js 
b/tests/qunit/suites/resources/mediawiki.rcfilters/dm.FiltersViewModel.test.js
index 618afb2..c38c2c1 100644
--- 
a/tests/qunit/suites/resources/mediawiki.rcfilters/dm.FiltersViewModel.test.js
+++ 
b/tests/qunit/suites/resources/mediawiki.rcfilters/dm.FiltersViewModel.test.js
@@ -603,6 +603,23 @@
                                                group3: ''
                                        },
                                        msg: 'Given an explicit (incomplete) 
filter state object, the result is the same as if the object give represented 
the model state.'
+                               },
+                               {
+                                       // This is mocking case above
+                                       // - 'One filters in one 
"send_unselected_if_any" group returns the other parameters truthy.'
+                                       input: {},
+                                       expected: {
+                                               // Group 1 (one selected, the 
others are true)
+                                               hidefilter1: '0',
+                                               hidefilter2: '0',
+                                               hidefilter3: '0',
+                                               // Group 2 (nothing is 
selected, all false)
+                                               hidefilter4: '0',
+                                               hidefilter5: '0',
+                                               hidefilter6: '0',
+                                               group3: ''
+                                       },
+                                       msg: 'Given an explicit empty object, 
the result is all filters set to their falsey unselected value.'
                                }
                        ];
 

-- 
To view, visit https://gerrit.wikimedia.org/r/353925
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I1d21c38137fde51fcd561e2de24592722bf532c6
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: Mooeypoo <mor...@gmail.com>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to