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