"recentchanges-submit": "Show",
"rcfilters-legend-heading": "<strong>List of abbreviations:</strong>",
"rcfilters-other-review-tools": "<strong>Other review tools:</strong>",
+ "rcfilters-group-results-by-page": "Group results by page",
+ "rcfilters-grouping-title": "Grouping",
"rcfilters-activefilters": "Active filters",
"rcfilters-advancedfilters": "Advanced filters",
"rcfilters-limit-title": "Changes to show",
- "rcfilters-limit-shownum": "Show last $1 changes",
+ "rcfilters-limit-shownum": "Show last {{PLURAL:$1|change|$1 changes}}",
"rcfilters-days-title": "Recent days",
"rcfilters-hours-title": "Recent hours",
"rcfilters-days-show-days": "$1 {{PLURAL:$1|day|days}}",
"rcfilters-tag-prefix-tags": "#$1",
"rcfilters-exclude-button-off": "Exclude selected",
"rcfilters-exclude-button-on": "Excluding selected",
+ "rcfilters-view-advanced-filters-label": "Advanced filters",
"rcfilters-view-tags": "Tagged edits",
"rcfilters-view-namespaces-tooltip": "Filter results by namespace",
"rcfilters-view-tags-tooltip": "Filter results using edit tags",
"recentchanges-submit": "Label for submit button in [[Special:RecentChanges]]\n{{Identical|Show}}",
"rcfilters-legend-heading": "Used as a heading for legend box on [[Special:RecentChanges]] and [[Special:Watchlist]] when RCFilters are enabled.",
"rcfilters-other-review-tools": "Used as a heading for the community collection of other links on [[Special:RecentChanges]] when RCFilters are enabled.",
+ "rcfilters-group-results-by-page": "A label for the checkbox describing whether the results in [[Special:RecentChanges]] are grouped by page when RCFilters are enabled.",
+ "rcfilters-grouping-title": "Title for the section showing display options for grouping results in [[Special:RecentChanges]] when RCFilters are enabled.",
"rcfilters-activefilters": "Title for the filters selection showing the active filters.",
"rcfilters-advancedfilters": "Title for the buttons allowing the user to switch to the various advanced filters views.",
"rcfilters-limit-title": "Title for the options to change the number of results shown.",
"rcfilters-tag-prefix-tags": "Prefix for the edit tags in [[Special:RecentChanges]]. Edit tags use a hash (#) as prefix. Please keep this format.\n\nParameters:\n* $1 - Tag display name.",
"rcfilters-exclude-button-off": "Title for the button that excludes selected namespaces, when it is not yet active.",
"rcfilters-exclude-button-on": "Title for the button that excludes selected namespaces, when it is not yet active.",
+ "rcfilters-view-advanced-filters-label": "Label for the view switch that changes between advanced filters in [[Special:RecentChanges]]",
"rcfilters-view-tags": "Title for the tags view in [[Special:RecentChanges]]\n{{Identical|Tag}}",
"rcfilters-view-namespaces-tooltip": "Tooltip for the button that loads the namespace view in [[Special:RecentChanges]]",
"rcfilters-view-tags-tooltip": "Tooltip for the button that loads the tags view in [[Special:RecentChanges]]",
'styles' => 'resources/src/mediawiki.action/mediawiki.action.edit.css',
'dependencies' => [
'mediawiki.action.edit.styles',
- 'jquery.accessKeyLabel',
'jquery.textSelection',
'jquery.byteLimit',
'mediawiki.widgets.visibleByteLimit',
'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.MenuSelectWidget.less',
'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ViewSwitchWidget.less',
'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ValuePickerWidget.less',
+ 'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ChangesLimitPopupWidget.less',
'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.DatePopupWidget.less',
'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterWrapperWidget.less',
'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ChangesListWrapperWidget.less',
'messages' => [
'rcfilters-activefilters',
'rcfilters-advancedfilters',
+ 'rcfilters-group-results-by-page',
+ 'rcfilters-grouping-title',
'rcfilters-limit-title',
'rcfilters-limit-shownum',
'rcfilters-days-title',
'rcfilters-tag-prefix-tags',
'rcfilters-exclude-button-off',
'rcfilters-exclude-button-on',
+ 'rcfilters-view-advanced-filters-label',
'rcfilters-view-tags',
'rcfilters-view-namespaces-tooltip',
'rcfilters-view-tags-tooltip',
* @cfg {boolean} [hidden] This group is hidden from the regular menu views
* @cfg {boolean} [allowArbitrary] Allows for an arbitrary value to be added to the
* group from the URL, even if it wasn't initially set up.
+ * @cfg {number} [range] An object defining minimum and maximum values for numeric
+ * groups. { min: x, max: y }
+ * @cfg {number} [minValue] Minimum value for numeric groups
* @cfg {string} [separator='|'] Value separator for 'string_options' groups
* @cfg {boolean} [active] Group is active
* @cfg {boolean} [fullCoverage] This filters in this group collectively cover all results
this.title = config.title || name;
this.hidden = !!config.hidden;
this.allowArbitrary = !!config.allowArbitrary;
+ this.numericRange = config.range;
this.separator = config.separator || '|';
this.labelPrefixKey = config.labelPrefixKey;
// Store the default parameter state
// For this group type, parameter values are direct
// We need to convert from a boolean to a string ('1' and '0')
- model.defaultParams[ filter.name ] = String( Number( !!filter.default ) );
+ model.defaultParams[ filter.name ] = String( Number( filter.default || 0 ) );
}
} );
return this.allowArbitrary;
};
+ /**
+ * Get group maximum value for numeric groups
+ *
+ * @return {number|null} Group max value
+ */
+ mw.rcfilters.dm.FilterGroup.prototype.getMaxValue = function () {
+ return this.numericRange && this.numericRange.max !== undefined ?
+ this.numericRange.max : null;
+ };
+
+ /**
+ * Get group minimum value for numeric groups
+ *
+ * @return {number|null} Group max value
+ */
+ mw.rcfilters.dm.FilterGroup.prototype.getMinValue = function () {
+ return this.numericRange && this.numericRange.min !== undefined ?
+ this.numericRange.min : null;
+ };
+
/**
* Get group name
*
*/
mw.rcfilters.Controller.prototype.initialize = function ( filterStructure, namespaceStructure, tagList ) {
var parsedSavedQueries, limitDefault,
+ displayConfig = mw.config.get( 'StructuredChangeFiltersDisplayConfig' ),
controller = this,
views = {},
items = [],
hidden: true,
allowArbitrary: true,
validate: $.isNumeric,
+ range: {
+ min: 1,
+ max: 1000
+ },
sortFunc: function ( a, b ) { return Number( a.name ) - Number( b.name ); },
'default': String( limitDefault ),
- isSticky: true,
- filters: [ 50, 100, 250, 500 ].map( function ( num ) {
+ // Temporarily making this not sticky until we resolve the problem
+ // with the misleading preference. Note that if this is to be permanent
+ // we should remove all sticky behavior methods completely
+ // See T172156
+ // isSticky: true,
+ filters: displayConfig.arrayLimit.map( function ( num ) {
return controller._createFilterDataFromNumber( num, num );
} )
},
hidden: true,
allowArbitrary: true,
validate: $.isNumeric,
+ range: {
+ min: 0,
+ max: displayConfig.maxLimit
+ },
sortFunc: function ( a, b ) { return Number( a.name ) - Number( b.name ); },
numToLabelFunc: function ( i ) {
return Number( i ) < 1 ?
Number( i );
},
'default': mw.user.options.get( 'rcdays', '30' ),
- isSticky: true,
+ // Temporarily making this not sticky while limit is not sticky, see above
+ // isSticky: true,
filters: [
// Hours (1, 2, 6, 12)
- 0.04166, 0.0833, 0.25, 0.5,
- // Days
- 1, 3, 7, 14, 30
- ].map( function ( num ) {
- return controller._createFilterDataFromNumber(
- num,
- // Convert fractions of days to number of hours for the labels
- num < 1 ? Math.round( num * 24 ) : num
- );
- } )
+ 0.04166, 0.0833, 0.25, 0.5
+ // Days
+ ].concat( displayConfig.arrayDays )
+ .map( function ( num ) {
+ return controller._createFilterDataFromNumber(
+ num,
+ // Convert fractions of days to number of hours for the labels
+ num < 1 ? Math.round( num * 24 ) : num
+ );
+ } )
}
]
};
+ views.display = {
+ groups: [
+ {
+ name: 'display',
+ type: 'boolean',
+ title: '', // Because it's a hidden group, this title actually appears nowhere
+ hidden: true,
+ isSticky: true,
+ filters: [
+ {
+ name: 'enhanced',
+ 'default': String( mw.user.options.get( 'usenewrc', 0 ) )
+ }
+ ]
+ }
+ ]
+ };
+
// Before we do anything, we need to see if we require additional items in the
// groups that have 'AllowArbitrary'. For the moment, those are only single_option
// groups; if we ever expand it, this might need further generalization:
arbitraryValues = Array.isArray( arbitraryValues ) ? arbitraryValues : [ arbitraryValues ];
+ // Normalize the arbitrary values
+ if ( groupData.range ) {
+ arbitraryValues = arbitraryValues.map( function ( val ) {
+ if ( val < 0 ) {
+ return groupData.range.min; // Min
+ } else if ( val >= groupData.range.max ) {
+ return groupData.range.max; // Max
+ }
+ return val;
+ } );
+ }
+
// This is only true for single_option group
// We assume these are the only groups that will allow for
// arbitrary, since it doesn't make any sense for the other
// but if that value isn't already in the definition
groupData.filters
.map( function ( filterData ) {
- return filterData.name;
+ return String( filterData.name );
} )
- .indexOf( val ) === -1
+ .indexOf( String( val ) ) === -1
) {
// Add the filter information
groupData.filters.push( controller._createFilterDataFromNumber(
*/
mw.rcfilters.Controller.prototype.toggleInvertedNamespaces = function () {
this.filtersModel.toggleInvertedNamespaces();
- this.updateChangesList();
+
+ if (
+ 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.applySavedQuery = function ( queryID ) {
var data, highlights,
- queryItem = this.savedQueriesModel.getItemByID( queryID );
+ queryItem = this.savedQueriesModel.getItemByID( queryID ),
+ currentMatchingQuery = this.findQueryMatchingCurrentState();
- if ( queryItem ) {
+ 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()
+ )
+ ) {
data = queryItem.getData();
highlights = data.highlights;
// the initial defaults or from the URL value that is being normalized
this.updateDaysDefault( this.filtersModel.getGroup( 'days' ).getSelectedItems()[ 0 ].getParamName() );
this.updateLimitDefault( this.filtersModel.getGroup( 'limit' ).getSelectedItems()[ 0 ].getParamName() );
+
+ // TODO: Make these automatic by having the model go over sticky
+ // items and update their default values automatically
};
/**
* Update the limit default value
*
- * @param {number} newValue New value
+ * param {number} newValue New value
*/
- mw.rcfilters.Controller.prototype.updateLimitDefault = function ( newValue ) {
+ mw.rcfilters.Controller.prototype.updateLimitDefault = function ( /* newValue */ ) {
+ // HACK: Temporarily remove this from being sticky
+ // See T172156
+
+ /*
if ( !$.isNumeric( newValue ) ) {
return;
}
// Update the preference for this session
mw.user.options.set( 'rcfilters-rclimit', newValue );
}
+ */
+ return;
};
/**
* Update the days default value
*
- * @param {number} newValue New value
+ * param {number} newValue New value
*/
- mw.rcfilters.Controller.prototype.updateDaysDefault = function ( newValue ) {
+ mw.rcfilters.Controller.prototype.updateDaysDefault = function ( /* newValue */ ) {
+ // HACK: Temporarily remove this from being sticky
+ // See T172156
+
+ /*
if ( !$.isNumeric( newValue ) ) {
return;
}
// Update the preference for this session
mw.user.options.set( 'rcdays', newValue );
}
+ */
+ return;
};
+ /**
+ * Update the group by page default value
+ *
+ * @param {number} newValue New value
+ */
+ mw.rcfilters.Controller.prototype.updateGroupByPageDefault = function ( newValue ) {
+ if ( !$.isNumeric( newValue ) ) {
+ return;
+ }
+
+ newValue = Number( newValue );
+
+ if ( mw.user.options.get( 'usenewrc' ) !== newValue ) {
+ // Save the preference
+ new mw.Api().saveOption( 'usenewrc', newValue );
+ // Update the preference for this session
+ mw.user.options.set( 'usenewrc', newValue );
+ }
+ };
+
/**
* Synchronize the URL with the current state of the filters
* without adding an history entry.