* @param {mw.rcfilters.dm.FiltersViewModel} filtersModel Filters view model
* @param {mw.rcfilters.dm.ChangesListViewModel} changesListModel Changes list view model
* @param {mw.rcfilters.dm.SavedQueriesModel} savedQueriesModel Saved queries model
+ * @param {Object} config Additional configuration
+ * @cfg {string} savedQueriesPreferenceName Where to save the saved queries
*/
- mw.rcfilters.Controller = function MwRcfiltersController( filtersModel, changesListModel, savedQueriesModel ) {
+ mw.rcfilters.Controller = function MwRcfiltersController( filtersModel, changesListModel, savedQueriesModel, config ) {
this.filtersModel = filtersModel;
this.changesListModel = changesListModel;
this.savedQueriesModel = savedQueriesModel;
+ this.savedQueriesPreferenceName = config.savedQueriesPreferenceName;
+
this.requestCounter = {};
this.baseFilterState = {};
this.uriProcessor = null;
this.initializing = false;
this.prevLoggedItems = [];
+
+ this.FILTER_CHANGE = 'filterChange';
+ this.SHOW_NEW_CHANGES = 'showNewChanges';
+ this.LIVE_UPDATE = 'liveUpdate';
};
/* Initialization */
allowArbitrary: true,
validate: $.isNumeric,
range: {
- min: 1,
+ min: 0, // The server normalizes negative numbers to 0 results
max: 1000
},
sortFunc: function ( a, b ) { return Number( a.name ) - Number( b.name ); },
// we should remove all sticky behavior methods completely
// See T172156
// isSticky: true,
- filters: displayConfig.arrayLimit.map( function ( num ) {
+ excludedFromSavedQueries: true,
+ filters: displayConfig.limitArray.map( function ( num ) {
return controller._createFilterDataFromNumber( num, num );
} )
},
validate: $.isNumeric,
range: {
min: 0,
- max: displayConfig.maxLimit
+ max: displayConfig.maxDays
},
sortFunc: function ( a, b ) { return Number( a.name ) - Number( b.name ); },
numToLabelFunc: function ( i ) {
'default': mw.user.options.get( 'rcdays', '30' ),
// Temporarily making this not sticky while limit is not sticky, see above
// isSticky: true,
+ excludedFromSavedQueries: true,
filters: [
// Hours (1, 2, 6, 12)
0.04166, 0.0833, 0.25, 0.5
// Days
- ].concat( displayConfig.arrayDays )
+ ].concat( displayConfig.daysArray )
.map( function ( num ) {
return controller._createFilterDataFromNumber(
num,
);
try {
- parsedSavedQueries = JSON.parse( mw.user.options.get( 'rcfilters-saved-queries' ) || '{}' );
+ parsedSavedQueries = JSON.parse( mw.user.options.get( this.savedQueriesPreferenceName ) || '{}' );
} catch ( err ) {
parsedSavedQueries = {};
}
this.savedQueriesModel.initialize(
parsedSavedQueries,
this._getBaseFilterState(),
- // This is for backwards compatibility - delete all sticky filter states
- Object.keys( this.filtersModel.getStickyFiltersState() )
+ // This is for backwards compatibility - delete all excluded filter states
+ Object.keys( this.filtersModel.getExcludedFiltersState() )
);
// Check whether we need to load defaults.
// so it gets processed
this.changesListModel.update(
$changesList.length ? $changesList : 'NO_RESULTS',
- $( 'fieldset.rcoptions' ).first(),
+ $( 'fieldset.cloptions' ).first(),
true // We're using existing DOM elements
);
}
this.filtersModel.toggleInvertedNamespaces();
if (
- this.filtersModel.getFiltersByView( 'namespaces' )
- .filter( function ( filterItem ) {
- return filterItem.isSelected();
- } )
- .length
+ this.filtersModel.getFiltersByView( 'namespaces' ).filter(
+ function ( filterItem ) { return filterItem.isSelected(); }
+ ).length
) {
// Only re-fetch results if there are namespace items that are actually selected
this.updateChangesList();
mw.rcfilters.Controller.prototype.toggleLiveUpdate = function ( enable ) {
this.changesListModel.toggleLiveUpdate( enable );
if ( this.changesListModel.getLiveUpdate() && this.changesListModel.getNewChangesExist() ) {
- this.showNewChanges();
+ this.updateChangesList( null, this.LIVE_UPDATE );
}
};
if ( data.changes !== 'NO_RESULTS' ) {
if ( this.changesListModel.getLiveUpdate() ) {
- return this.updateChangesList( false, null, true, false );
+ return this.updateChangesList( null, this.LIVE_UPDATE );
} else {
this.changesListModel.setNewChangesExist( true );
}
* @private
*/
mw.rcfilters.Controller.prototype._shouldCheckForNewChanges = function () {
- var liveUpdateFeatureFlag = mw.config.get( 'wgStructuredChangeFiltersEnableLiveUpdate' ) ||
- new mw.Uri().query.liveupdate;
-
return !document.hidden &&
+ !this.filtersModel.hasConflict() &&
!this.changesListModel.getNewChangesExist() &&
!this.updatingChangesList &&
- liveUpdateFeatureFlag;
+ mw.rcfilters.featureFlags.liveUpdate;
};
/**
* fetching and showing the new changes
*/
mw.rcfilters.Controller.prototype.showNewChanges = function () {
- return this.updateChangesList( false, null, true, true );
+ return this.updateChangesList( null, this.SHOW_NEW_CHANGES );
};
/**
// These are filter states; highlight is stored as boolean
highlightedItems.highlight = this.filtersModel.isHighlightEnabled();
- // Delete all sticky filters
- this._deleteStickyValuesFromFilterState( selectedState );
+ // Delete all excluded filters
+ this._deleteExcludedValuesFromFilterState( selectedState );
// Add item
queryID = this.savedQueriesModel.addNewQuery(
// Update model state from filters
this.filtersModel.toggleFiltersSelected(
- // Merge filters with sticky values
- $.extend( true, {}, data.filters, this.filtersModel.getStickyFiltersState() )
+ // Merge filters with excluded values
+ $.extend( true, {}, data.filters, this.filtersModel.getExcludedFiltersState() )
);
// Update namespace inverted property
} );
highlightedItems.highlight = this.filtersModel.isHighlightEnabled();
- // Remove sticky filters
- this._deleteStickyValuesFromFilterState( selectedState );
+ // 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(
{
*
* @param {Object} filterState Filter state
*/
- mw.rcfilters.Controller.prototype._deleteStickyValuesFromFilterState = function ( filterState ) {
- // Remove sticky filters
- $.each( this.filtersModel.getStickyFiltersState(), function ( filterName ) {
+ mw.rcfilters.Controller.prototype._deleteExcludedValuesFromFilterState = function ( filterState ) {
+ // Remove excluded filters
+ $.each( this.filtersModel.getExcludedFiltersState(), function ( filterName ) {
delete filterState[ filterName ];
} );
};
* @return {Object} Minimal filters and highlights list
*/
mw.rcfilters.Controller.prototype._getMinimalFilterList = function ( valuesObject ) {
- var result = { filters: {}, highlights: {} },
+ var result = { filters: {}, highlights: {}, invert: valuesObject.invert },
baseState = this._getBaseFilterState();
// XOR results
}
// Save the preference
- new mw.Api().saveOption( 'rcfilters-saved-queries', stringified );
+ new mw.Api().saveOption( this.savedQueriesPreferenceName, stringified );
// Update the preference for this session
- mw.user.options.set( 'rcfilters-saved-queries', stringified );
+ mw.user.options.set( this.savedQueriesPreferenceName, stringified );
};
/**
/**
* Update the list of changes and notify the model
*
- * @param {boolean} [updateUrl=true] Whether the URL should be updated with the current state of the filters
* @param {Object} [params] Extra parameters to add to the API call
- * @param {boolean} [isLiveUpdate=false] The purpose of this update is to show new results for the same filters
- * @param {boolean} [invalidateCurrentChanges=true] Invalidate current changes by default (show spinner)
+ * @param {string} [updateMode='filterChange'] One of 'filterChange', 'liveUpdate', 'showNewChanges', 'markSeen'
* @return {jQuery.Promise} Promise that is resolved when the update is complete
*/
- mw.rcfilters.Controller.prototype.updateChangesList = function ( updateUrl, params, isLiveUpdate, invalidateCurrentChanges ) {
- updateUrl = updateUrl === undefined ? true : updateUrl;
- invalidateCurrentChanges = invalidateCurrentChanges === undefined ? true : invalidateCurrentChanges;
- if ( updateUrl ) {
+ mw.rcfilters.Controller.prototype.updateChangesList = function ( params, updateMode ) {
+ updateMode = updateMode === undefined ? this.FILTER_CHANGE : updateMode;
+
+ if ( updateMode === this.FILTER_CHANGE ) {
this._updateURL( params );
}
- if ( invalidateCurrentChanges ) {
+ if ( updateMode === this.FILTER_CHANGE || updateMode === this.SHOW_NEW_CHANGES ) {
this.changesListModel.invalidate();
}
this.changesListModel.setNewChangesExist( false );
function ( pieces ) {
var $changesListContent = pieces.changes,
$fieldset = pieces.fieldset;
- this.changesListModel.update( $changesListContent, $fieldset, false, isLiveUpdate );
+ this.changesListModel.update(
+ $changesListContent,
+ $fieldset,
+ false,
+ // separator between old and new changes
+ updateMode === this.SHOW_NEW_CHANGES || updateMode === this.LIVE_UPDATE
+ );
}.bind( this )
// Do nothing for failure
)
return $.ajax( uri.toString(), { contentType: 'html' } )
.then(
- // Success
function ( html ) {
- var $parsed;
+ var $parsed,
+ pieces;
+
if ( !latestRequest() ) {
return $.Deferred().reject();
}
$parsed = $( $.parseHTML( html ) );
- return {
+ pieces = {
// Changes list
changes: $parsed.find( '.mw-changeslist' ).first().contents(),
// Fieldset
- fieldset: $parsed.find( 'fieldset.rcoptions' ).first()
+ fieldset: $parsed.find( 'fieldset.cloptions' ).first()
};
+
+ // Watchlist returns 200 when there is no results
+ if ( pieces.changes.length === 0 ) {
+ pieces.changes = 'NO_RESULTS';
+ }
+
+ return pieces;
},
- // Failure
+ // RC returns 404 when there is no results
function ( responseObj ) {
var $parsed;
// Force a resolve state to this promise
return $.Deferred().resolve( {
changes: 'NO_RESULTS',
- fieldset: $parsed.find( 'fieldset.rcoptions' ).first()
+ fieldset: $parsed.find( 'fieldset.cloptions' ).first()
} ).promise();
}
);
this.prevLoggedItems = filters;
}
};
+
+ /**
+ * Mark all changes as seen on Watchlist
+ */
+ mw.rcfilters.Controller.prototype.markAllChangesAsSeen = function () {
+ var api = new mw.Api();
+ api.postWithToken( 'csrf', {
+ formatversion: 2,
+ action: 'setnotificationtimestamp',
+ entirewatchlist: true
+ } ).then( function () {
+ this.updateChangesList( null, 'markSeen' );
+ }.bind( this ) );
+ };
}( mediaWiki, jQuery ) );