Sbisson has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/372187 )
Change subject: [WIP] Enable RCFilters app on Watchlist ...................................................................... [WIP] Enable RCFilters app on Watchlist Bug: T171132 Change-Id: If7c63284224df24fa02022b4ea74bef116f28ca6 --- M includes/DefaultSettings.php M includes/Preferences.php M includes/specialpage/ChangesListSpecialPage.php M includes/specials/SpecialRecentchanges.php M includes/specials/SpecialWatchlist.php M resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.ChangesListViewModel.js M resources/src/mediawiki.rcfilters/mw.rcfilters.Controller.js M resources/src/mediawiki.rcfilters/mw.rcfilters.init.js M resources/src/mediawiki.rcfilters/mw.rcfilters.js M resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FormWrapperWidget.js 10 files changed, 288 insertions(+), 172 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core refs/changes/87/372187/1 diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index 4e162f6..b65d016 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -6847,6 +6847,11 @@ $wgStructuredChangeFiltersEnableLiveUpdate = false; /** + * Whether to enable RCFilters app on Special:Watchlist + */ +$wgRcfiltersOnWatchlist = false; + +/** * Use new page patrolling to check new pages on Special:Newpages */ $wgUseNPPatrol = true; diff --git a/includes/Preferences.php b/includes/Preferences.php index c74d6e1..25f0dbd 100644 --- a/includes/Preferences.php +++ b/includes/Preferences.php @@ -920,6 +920,9 @@ $defaultPreferences['rcfilters-saved-queries'] = [ 'type' => 'api', ]; + $defaultPreferences['rcfilters-wl-saved-queries'] = [ + 'type' => 'api', + ]; $defaultPreferences['rcfilters-rclimit'] = [ 'type' => 'api', ]; diff --git a/includes/specialpage/ChangesListSpecialPage.php b/includes/specialpage/ChangesListSpecialPage.php index 645fbb2..e98e1af 100644 --- a/includes/specialpage/ChangesListSpecialPage.php +++ b/includes/specialpage/ChangesListSpecialPage.php @@ -553,6 +553,57 @@ LoggerFactory::getInstance( 'objectcache' ) ) ); } + + $this->includeRcFiltersApp(); + } + + /** + * Include the modules and configuration for the RCFilters app. + * Conditional on the user having the feature enabled. + */ + protected function includeRcFiltersApp() { + if ( $this->isStructuredFilterUiEnabled() ) { + $out = $this->getOutput(); + $jsData = $this->getStructuredFilterJsData(); + + $messages = []; + foreach ( $jsData['messageKeys'] as $key ) { + $messages[$key] = $this->msg( $key )->plain(); + } + + $out->addHTML( + ResourceLoader::makeInlineScript( + ResourceLoader::makeMessageSetScript( $messages ) + ) + ); + + $experimentalStructuredChangeFilters = + $this->getConfig()->get( 'StructuredChangeFiltersEnableExperimentalViews' ); + + $out->addJsConfigVars( 'wgStructuredChangeFilters', $jsData['groups'] ); + $out->addJsConfigVars( + 'wgStructuredChangeFiltersEnableExperimentalViews', + $experimentalStructuredChangeFilters + ); + $out->addJsConfigVars( + 'wgStructuredChangeFiltersEnableLiveUpdate', + $this->getConfig()->get( 'StructuredChangeFiltersEnableLiveUpdate' ) + ); + if ( $experimentalStructuredChangeFilters ) { + $out->addJsConfigVars( + 'wgRCFiltersChangeTags', + $this->buildChangeTagList() + ); + } + $out->addJsConfigVars( + 'StructuredChangeFiltersDisplayConfig', + [ + 'maxDays' => (int)$this->getConfig()->get( 'RCMaxAge' ) / ( 24 * 3600 ), // Translate to days + 'limitArray' => $this->getConfig()->get( 'RCLinkLimits' ), + 'daysArray' => $this->getConfig()->get( 'RCLinkDays' ), + ] + ); + } } /** @@ -779,19 +830,20 @@ * @return FormOptions */ public function getDefaultOptions() { - $config = $this->getConfig(); $opts = new FormOptions(); - $structuredUI = $this->getUser()->getOption( 'rcenhancedfilters' ); + $structuredUI = $this->isStructuredFilterUiEnabled(); // If urlversion=2 is set, ignore the filter defaults and set them all to false/empty $useDefaults = $this->getRequest()->getInt( 'urlversion' ) !== 2; // Add all filters + /** @var ChangesListFilterGroup $filterGroup */ foreach ( $this->filterGroups as $filterGroup ) { // URL parameters can be per-group, like 'userExpLevel', // or per-filter, like 'hideminor'. if ( $filterGroup->isPerGroupRequestParameter() ) { $opts->add( $filterGroup->getName(), $useDefaults ? $filterGroup->getDefault() : '' ); } else { + /** @var ChangesListBooleanFilter $filter */ foreach ( $filterGroup->getFilters() as $filter ) { $opts->add( $filter->getName(), $useDefaults ? $filter->getDefault( $structuredUI ) : false ); } @@ -856,8 +908,6 @@ 'groups' => [], 'messageKeys' => [], ]; - - $context = $this->getContext(); usort( $this->filterGroups, function ( $a, $b ) { return $b->getPriority() - $a->getPriority(); @@ -1055,9 +1105,7 @@ &$join_conds, FormOptions $opts ) { $dbr = $this->getDB(); - $user = $this->getUser(); - $context = $this->getContext(); foreach ( $this->filterGroups as $filterGroup ) { // URL parameters can be per-group, like 'userExpLevel', // or per-filter, like 'hideminor'. @@ -1279,12 +1327,11 @@ ) . "\n"; $legend .= Html::closeElement( 'dl' ) . "\n"; - # Collapsibility - $legendHeading = $this->getUser()->getOption( - 'rcenhancedfilters' - ) ? + $legendHeading = $this->isStructuredFilterUiEnabled() ? $context->msg( 'rcfilters-legend-heading' )->parse() : $context->msg( 'recentchanges-legend-heading' )->parse(); + + # Collapsible $legend = '<div class="mw-changeslist-legend">' . $legendHeading . @@ -1305,6 +1352,11 @@ 'mediawiki.special.changeslist', ] ); $out->addModules( 'mediawiki.special.changeslist.legend.js' ); + + if ( $this->isStructuredFilterUiEnabled() ) { + $out->addModules( 'mediawiki.rcfilters.filters.ui' ); + $out->addModuleStyles( 'mediawiki.rcfilters.filters.base.styles' ); + } } protected function getGroupName() { @@ -1426,4 +1478,13 @@ $conds[] = reset( $conditions ); } } + + /** + * Check whether the structured filter UI is enabled + * + * @return bool + */ + protected function isStructuredFilterUiEnabled() { + return $this->getUser()->getOption( 'rcenhancedfilters' ); + } } diff --git a/includes/specials/SpecialRecentchanges.php b/includes/specials/SpecialRecentchanges.php index 0b48d40..3136d32 100644 --- a/includes/specials/SpecialRecentchanges.php +++ b/includes/specials/SpecialRecentchanges.php @@ -164,43 +164,9 @@ parent::execute( $subpage ); if ( $this->isStructuredFilterUiEnabled() ) { - $jsData = $this->getStructuredFilterJsData(); - - $messages = []; - foreach ( $jsData['messageKeys'] as $key ) { - $messages[$key] = $this->msg( $key )->plain(); - } - - $out->addHTML( - ResourceLoader::makeInlineScript( - ResourceLoader::makeMessageSetScript( $messages ) - ) - ); - - $experimentalStructuredChangeFilters = - $this->getConfig()->get( 'StructuredChangeFiltersEnableExperimentalViews' ); - - $out->addJsConfigVars( 'wgStructuredChangeFilters', $jsData['groups'] ); - $out->addJsConfigVars( - 'wgStructuredChangeFiltersEnableExperimentalViews', - $experimentalStructuredChangeFilters - ); - $out->addJsConfigVars( - 'wgStructuredChangeFiltersEnableLiveUpdate', - $this->getConfig()->get( 'StructuredChangeFiltersEnableLiveUpdate' ) - ); - $out->addJsConfigVars( - 'wgRCFiltersChangeTags', - $this->buildChangeTagList() - ); - $out->addJsConfigVars( - 'StructuredChangeFiltersDisplayConfig', - [ - 'maxDays' => (int)$this->getConfig()->get( 'RCMaxAge' ) / ( 24 * 3600 ), // Translate to days - 'limitArray' => $this->getConfig()->get( 'RCLinkLimits' ), - 'daysArray' => $this->getConfig()->get( 'RCLinkDays' ), - ] - ); + $out->addJsConfigVars( 'wgStructuredChangeFiltersLiveUpdateSupported', true ); + $out->addJsConfigVars( 'wgSavedQueriesPreferenceName', 'rcfilters-saved-queries' ); + $out->addJsConfigVars( 'wgEnableLimit', true ); } } @@ -540,8 +506,6 @@ && $this->getUser()->getOption( 'shownumberswatching' ); $watcherCache = []; - $dbr = $this->getDB(); - $counter = 1; $list = ChangesList::newFromContext( $this->getContext(), $this->filterGroups ); $list->initChangesListRows( $rows ); @@ -636,7 +600,7 @@ ++$count; $addSubmit = ( $count === $extraOptsCount ) ? $submit : ''; - $out .= Xml::openElement( 'tr' ); + $out .= Xml::openElement( 'tr', [ 'class' => $name . 'Form' ] ); if ( is_array( $optionRow ) ) { $out .= Xml::tags( 'td', @@ -673,11 +637,11 @@ $rcoptions = Xml::fieldset( $this->msg( 'recentchanges-legend' )->text(), $panelString, - [ 'class' => 'rcoptions' ] + [ 'class' => 'rcoptions cloptions' ] ); // Insert a placeholder for RCFilters - if ( $this->getUser()->getOption( 'rcenhancedfilters' ) ) { + if ( $this->isStructuredFilterUiEnabled() ) { $rcfilterContainer = Html::element( 'div', [ 'class' => 'rcfilters-container' ] @@ -729,7 +693,7 @@ $topLinksAttributes = [ 'class' => 'mw-recentchanges-toplinks' ]; - if ( $this->getUser()->getOption( 'rcenhancedfilters' ) ) { + if ( $this->isStructuredFilterUiEnabled() ) { $contentTitle = Html::rawElement( 'div', [ 'class' => 'mw-recentchanges-toplinks-title' ], $this->msg( 'rcfilters-other-review-tools' )->parse() @@ -786,27 +750,12 @@ } /** - * Check whether the structured filter UI is enabled - * - * @return bool - */ - protected function isStructuredFilterUiEnabled() { - return $this->getUser()->getOption( - 'rcenhancedfilters' - ); - } - - /** * Add page-specific modules. */ protected function addModules() { parent::addModules(); $out = $this->getOutput(); $out->addModules( 'mediawiki.special.recentchanges' ); - if ( $this->isStructuredFilterUiEnabled() ) { - $out->addModules( 'mediawiki.rcfilters.filters.ui' ); - $out->addModuleStyles( 'mediawiki.rcfilters.filters.base.styles' ); - } } /** @@ -1030,7 +979,6 @@ $filterGroups = $this->getFilterGroups(); - $context = $this->getContext(); foreach ( $filterGroups as $groupName => $group ) { if ( !$group->isPerGroupRequestParameter() ) { foreach ( $group->getFilters() as $key => $filter ) { @@ -1047,7 +995,7 @@ [ $key => 1 - $options[$key] ], $nondefaults ); $attribs = [ - 'class' => "$msg rcshowhideoption", + 'class' => "$msg rcshowhideoption clshowhideoption", 'data-filter-name' => $filter->getName(), ]; diff --git a/includes/specials/SpecialWatchlist.php b/includes/specials/SpecialWatchlist.php index 1d76e36..4a8e53c 100644 --- a/includes/specials/SpecialWatchlist.php +++ b/includes/specials/SpecialWatchlist.php @@ -32,6 +32,8 @@ * @ingroup SpecialPage */ class SpecialWatchlist extends ChangesListSpecialPage { + private $maxDays; + public function __construct( $page = 'Watchlist', $restriction = 'viewmywatchlist' ) { parent::__construct( $page, $restriction ); @@ -93,6 +95,18 @@ } parent::execute( $subpage ); + + if ( $this->isStructuredFilterUiEnabled() ) { + $output->addJsConfigVars( 'wgStructuredChangeFiltersLiveUpdateSupported', false ); + $output->addJsConfigVars( 'wgSavedQueriesPreferenceName', 'rcfilters-wl-saved-queries' ); + $output->addJsConfigVars( 'wgEnableLimit', !$opts['extended'] ); + } + } + + protected function isStructuredFilterUiEnabled() { + return parent::isStructuredFilterUiEnabled() + && ( $this->getConfig()->get( 'RcfiltersOnWatchlist' ) + || $this->getRequest()->getBool( 'rcfilters' ) ); } /** @@ -172,6 +186,7 @@ $opts->add( 'days', $user->getOption( 'watchlistdays' ), FormOptions::FLOAT ); $opts->add( 'extended', $user->getBoolOption( 'extendwatchlist' ) ); + $opts->add( 'limit', $user->getIntOption( 'wllimit' ), FormOptions::INT ); return $opts; } @@ -300,7 +315,7 @@ $query_options = array_merge( [ 'ORDER BY' => 'rc_timestamp DESC', - 'LIMIT' => $user->getIntOption( 'wllimit' ) + 'LIMIT' => $opts['limit'] ], $query_options ); $join_conds = array_merge( [ @@ -458,6 +473,11 @@ } $s = $list->beginRecentChangesList(); + + if ( $this->isStructuredFilterUiEnabled() ) { + $s .= $this->makeLegend(); + } + $userShowHiddenCats = $this->getUser()->getBoolOption( 'showhiddencats' ); $counter = 1; foreach ( $rows as $obj ) { @@ -516,7 +536,7 @@ ) ) ); - $this->setTopText( $opts ); + $form = $this->setTopText( $opts ); $lang = $this->getLanguage(); if ( $opts['days'] > 0 ) { @@ -530,11 +550,14 @@ )->parse() . "<br />\n"; $nondefaults = $opts->getChangedValues(); - $cutofflinks = $this->msg( 'wlshowtime' ) . ' ' . $this->cutoffselector( $opts ); + $cutofflinks = Html::rawElement( + 'span', + [ 'class' => 'cldays cloption' ], + $this->msg( 'wlshowtime' ) . ' ' . $this->cutoffselector( $opts ) + ); # Spit out some control panel links $links = []; - $context = $this->getContext(); $namesOfDisplayedFilters = []; foreach ( $this->getFilterGroups() as $groupName => $group ) { if ( !$group->isPerGroupRequestParameter() ) { @@ -545,7 +568,8 @@ $nondefaults, $filter->getShowHide(), $filterName, - $opts[$filterName] + $opts[$filterName], + $filter->isFeatureAvailableOnStructuredUi( $this ) ); } } @@ -562,17 +586,19 @@ unset( $hiddenFields[$filterName] ); } - # Create output - $form = ''; - # Namespace filter and put the whole form together. $form .= $wlInfo; $form .= $cutofflinks; - $form .= $this->msg( 'watchlist-hide' ) . + $form .= Html::rawElement( + 'span', + [ 'class' => 'clshowhide' ], + $this->msg( 'watchlist-hide' ) . $this->msg( 'colon-separator' )->escaped() . - implode( ' ', $links ); + implode( ' ', $links ) + ); $form .= "\n<br />\n"; - $form .= Html::namespaceSelector( + + $namespaceForm = Html::namespaceSelector( [ 'selected' => $opts['namespace'], 'all' => '', @@ -583,27 +609,66 @@ 'class' => 'namespaceselector', ] ) . "\n"; - $form .= '<span class="mw-input-with-label">' . Xml::checkLabel( + $namespaceForm .= '<span class="mw-input-with-label">' . Xml::checkLabel( $this->msg( 'invert' )->text(), 'invert', 'nsinvert', $opts['invert'], [ 'title' => $this->msg( 'tooltip-invert' )->text() ] ) . "</span>\n"; - $form .= '<span class="mw-input-with-label">' . Xml::checkLabel( + $namespaceForm .= '<span class="mw-input-with-label">' . Xml::checkLabel( $this->msg( 'namespace_association' )->text(), 'associated', 'nsassociated', $opts['associated'], [ 'title' => $this->msg( 'tooltip-namespace_association' )->text() ] ) . "</span>\n"; - $form .= Xml::submitButton( $this->msg( 'watchlist-submit' )->text() ) . "\n"; + $form .= Html::rawElement( + 'span', + [ 'class' => 'namespaceForm cloption' ], + $namespaceForm + ); + + $form .= Xml::submitButton( + $this->msg( 'watchlist-submit' )->text(), + [ 'class' => 'cloption-submit' ] + ) . "\n"; foreach ( $hiddenFields as $key => $value ) { $form .= Html::hidden( $key, $value ) . "\n"; } $form .= Xml::closeElement( 'fieldset' ) . "\n"; $form .= Xml::closeElement( 'form' ) . "\n"; - $this->getOutput()->addHTML( $form ); + + // Insert a placeholder for RCFilters + if ( $this->isStructuredFilterUiEnabled() ) { + $rcfilterContainer = Html::element( + 'div', + [ 'class' => 'rcfilters-container' ] + ); + + $loadingContainer = Html::rawElement( + 'div', + [ 'class' => 'rcfilters-spinner' ], + Html::element( + 'div', + [ 'class' => 'rcfilters-spinner-bounce' ] + ) + ); + + // Wrap both with rcfilters-head + $this->getOutput()->addHTML( + Html::rawElement( + 'div', + [ 'class' => 'rcfilters-head' ], + $rcfilterContainer . $form + ) + ); + + // Add spinner + $this->getOutput()->addHTML( $loadingContainer ); + } else { + $this->getOutput()->addHTML( $form ); + } $this->setBottomText( $opts ); } @@ -701,23 +766,34 @@ $form .= Xml::fieldset( $this->msg( 'watchlist-options' )->text(), false, - [ 'id' => 'mw-watchlist-options' ] + [ 'id' => 'mw-watchlist-options', 'class' => 'cloptions' ] ); - $form .= $this->makeLegend(); + if ( !$this->isStructuredFilterUiEnabled() ) { + $form .= $this->makeLegend(); + } - $this->getOutput()->addHTML( $form ); + return $form; } - protected function showHideCheck( $options, $message, $name, $value ) { + protected function showHideCheck( $options, $message, $name, $value, $inStructuredUi ) { $options[$name] = 1 - (int)$value; - return '<span class="mw-input-with-label">' . Xml::checkLabel( - $this->msg( $message, '' )->text(), - $name, - $name, - (int)$value - ) . '</span>'; + $attribs = [ 'class' => 'clshowhideoption cloption' ]; + if ( $inStructuredUi ) { + $attribs[ 'data-feature-in-structured-ui' ] = true; + } + + return Html::rawElement( + 'span', + $attribs, + Xml::checkLabel( + $this->msg( $message, '' )->text(), + $name, + $name, + (int)$value + ) + ); } /** diff --git a/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.ChangesListViewModel.js b/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.ChangesListViewModel.js index f221b2b..e343f6d 100644 --- a/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.ChangesListViewModel.js +++ b/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.ChangesListViewModel.js @@ -78,7 +78,9 @@ mw.rcfilters.dm.ChangesListViewModel.prototype.update = function ( changesListContent, $fieldset, isInitialDOM, separateOldAndNew ) { var from = this.nextFrom; this.valid = true; - this.extractNextFrom( $fieldset ); + if ( mw.rcfilters.featureFlags.liveUpdate ) { + this.extractNextFrom( $fieldset ); + } this.emit( 'update', changesListContent, $fieldset, isInitialDOM, separateOldAndNew ? from : null ); }; @@ -109,6 +111,7 @@ */ mw.rcfilters.dm.ChangesListViewModel.prototype.extractNextFrom = function ( $fieldset ) { this.nextFrom = $fieldset.find( '.rclistfrom > a' ).data( 'params' ).from; + }; /** diff --git a/resources/src/mediawiki.rcfilters/mw.rcfilters.Controller.js b/resources/src/mediawiki.rcfilters/mw.rcfilters.Controller.js index 0085bd6..a233856 100644 --- a/resources/src/mediawiki.rcfilters/mw.rcfilters.Controller.js +++ b/resources/src/mediawiki.rcfilters/mw.rcfilters.Controller.js @@ -8,11 +8,17 @@ * @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 + * @cfg {boolean} enableLimit Whether to enable the limit parameter */ - 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.enableLimit = config.enableLimit; + this.requestCounter = {}; this.baseFilterState = {}; this.uriProcessor = null; @@ -99,67 +105,68 @@ limitDefault = Number( mw.user.options.get( 'rclimit', '50' ) ); // Add parameter range operations - views.range = { - groups: [ - { - name: 'limit', - type: 'single_option', - title: '', // Because it's a hidden group, this title actually appears nowhere - hidden: true, - allowArbitrary: true, - validate: $.isNumeric, - range: { - min: 0, // The server normalizes negative numbers to 0 results - max: 1000 - }, - sortFunc: function ( a, b ) { return Number( a.name ) - Number( b.name ); }, - 'default': String( limitDefault ), - // 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, - excludedFromSavedQueries: true, - filters: displayConfig.limitArray.map( function ( num ) { - return controller._createFilterDataFromNumber( num, num ); - } ) + views.range = { groups: [] }; + + if ( this.enableLimit ) { + views.range.groups.push( { + name: 'limit', + type: 'single_option', + title: '', // Because it's a hidden group, this title actually appears nowhere + hidden: true, + allowArbitrary: true, + validate: $.isNumeric, + range: { + min: 0, // The server normalizes negative numbers to 0 results + max: 1000 }, - { - name: 'days', - type: 'single_option', - title: '', // Because it's a hidden group, this title actually appears nowhere - hidden: true, - allowArbitrary: true, - validate: $.isNumeric, - range: { - min: 0, - max: displayConfig.maxDays - }, - sortFunc: function ( a, b ) { return Number( a.name ) - Number( b.name ); }, - numToLabelFunc: function ( i ) { - return Number( i ) < 1 ? - ( Number( i ) * 24 ).toFixed( 2 ) : - Number( 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.daysArray ) - .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 - ); - } ) - } - ] - }; + sortFunc: function ( a, b ) { return Number( a.name ) - Number( b.name ); }, + 'default': String( limitDefault ), + // 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, + excludedFromSavedQueries: true, + filters: displayConfig.limitArray.map( function ( num ) { + return controller._createFilterDataFromNumber( num, num ); + } ) + } ); + } + + views.range.groups.push( { + name: 'days', + type: 'single_option', + title: '', // Because it's a hidden group, this title actually appears nowhere + hidden: true, + allowArbitrary: true, + validate: $.isNumeric, + range: { + min: 0, + max: displayConfig.maxDays + }, + sortFunc: function ( a, b ) { return Number( a.name ) - Number( b.name ); }, + numToLabelFunc: function ( i ) { + return Number( i ) < 1 ? + ( Number( i ) * 24 ).toFixed( 2 ) : + Number( 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.daysArray ) + .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: [ @@ -209,7 +216,7 @@ ); try { - parsedSavedQueries = JSON.parse( mw.user.options.get( 'rcfilters-saved-queries' ) || '{}' ); + parsedSavedQueries = JSON.parse( mw.user.options.get( this.savedQueriesPreferenceName ) || '{}' ); } catch ( err ) { parsedSavedQueries = {}; } @@ -254,7 +261,7 @@ // 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 ); } @@ -868,9 +875,9 @@ } // 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 ); }; /** @@ -880,7 +887,9 @@ // Update default sticky values with selected, whether they came from // 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() ); + if ( this.filtersModel.getGroup( 'limit' ) ) { + 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 @@ -1163,7 +1172,7 @@ // Changes list changes: $parsed.find( '.mw-changeslist' ).first().contents(), // Fieldset - fieldset: $parsed.find( 'fieldset.rcoptions' ).first() + fieldset: $parsed.find( 'fieldset.cloptions' ).first() }; }, // Failure @@ -1179,7 +1188,7 @@ // 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(); } ); diff --git a/resources/src/mediawiki.rcfilters/mw.rcfilters.init.js b/resources/src/mediawiki.rcfilters/mw.rcfilters.init.js index 701e61d..323d07a 100644 --- a/resources/src/mediawiki.rcfilters/mw.rcfilters.init.js +++ b/resources/src/mediawiki.rcfilters/mw.rcfilters.init.js @@ -12,10 +12,18 @@ topLinksCookieName = 'rcfilters-toplinks-collapsed-state', topLinksCookie = mw.cookie.get( topLinksCookieName ), topLinksCookieValue = topLinksCookie || 'collapsed', + savedQueriesPreferenceName = mw.config.get( 'wgSavedQueriesPreferenceName' ), + enableLimit = mw.config.get( 'wgEnableLimit' ), filtersModel = new mw.rcfilters.dm.FiltersViewModel(), changesListModel = new mw.rcfilters.dm.ChangesListViewModel(), savedQueriesModel = new mw.rcfilters.dm.SavedQueriesModel(), - controller = new mw.rcfilters.Controller( filtersModel, changesListModel, savedQueriesModel ), + controller = new mw.rcfilters.Controller( + filtersModel, changesListModel, savedQueriesModel, + { + savedQueriesPreferenceName: savedQueriesPreferenceName, + enableLimit: enableLimit + } + ), $overlay = $( '<div>' ) .addClass( 'mw-rcfilters-ui-overlay' ), filtersWidget = new mw.rcfilters.ui.FilterWrapperWidget( @@ -35,7 +43,7 @@ // eslint-disable-next-line no-new new mw.rcfilters.ui.FormWrapperWidget( - filtersModel, changesListModel, controller, $( 'fieldset.rcoptions' ) ); + filtersModel, changesListModel, controller, $( 'fieldset.cloptions' ) ); $( '.rcfilters-container' ).append( filtersWidget.$element ); $( 'body' ).append( $overlay ); diff --git a/resources/src/mediawiki.rcfilters/mw.rcfilters.js b/resources/src/mediawiki.rcfilters/mw.rcfilters.js index 7bdc2a2..7ff6819 100644 --- a/resources/src/mediawiki.rcfilters/mw.rcfilters.js +++ b/resources/src/mediawiki.rcfilters/mw.rcfilters.js @@ -46,7 +46,8 @@ } }, featureFlags: { - liveUpdate: mw.config.get( 'wgStructuredChangeFiltersEnableLiveUpdate' ) || new mw.Uri().query.liveupdate + liveUpdate: mw.config.get( 'wgStructuredChangeFiltersLiveUpdateSupported' ) + && ( mw.config.get( 'wgStructuredChangeFiltersEnableLiveUpdate' ) || new mw.Uri().query.liveupdate ) } }; }( mediaWiki ) ); diff --git a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FormWrapperWidget.js b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FormWrapperWidget.js index 82992fb..7183bb5 100644 --- a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FormWrapperWidget.js +++ b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FormWrapperWidget.js @@ -117,9 +117,7 @@ * Clean up the old-style show/hide that we have implemented in the filter list */ mw.rcfilters.ui.FormWrapperWidget.prototype.cleanUpFieldset = function () { - var $namespaceSelect = this.$element.find( '#namespace' ); - - this.$element.find( '.rcshowhideoption[data-feature-in-structured-ui=1]' ).each( function () { + this.$element.find( '.clshowhideoption[data-feature-in-structured-ui=1]' ).each( function () { // HACK: Remove the text node after the span. // If there isn't one, we're at the end, so remove the text node before the span. // This would be unnecessary if we added separators with CSS. @@ -133,11 +131,11 @@ } ); // Hide namespaces and tags - $namespaceSelect.closest( 'tr' ).detach(); + this.$element.find( '.namespaceForm' ).detach(); this.$element.find( '.mw-tagfilter-label' ).closest( 'tr' ).detach(); // Hide limit and days - this.$element.find( '.rclinks' ).detach(); + this.$element.find( '.rclinks, .cldays' ).detach(); if ( !this.$element.find( '.mw-recentchanges-table tr' ).length ) { this.$element.find( '.mw-recentchanges-table' ).detach(); @@ -151,6 +149,10 @@ this.$element.find( 'br' ).detach(); } + if ( this.$element.find( '.cloption' ).text().trim() === '' ) { + this.$element.find( '.cloption-submit' ).detach(); + } + if ( mw.rcfilters.featureFlags.liveUpdate ) { this.$element.find( 'legend, .rclistfrom, .rcnotefrom, .rcoptions-listfromreset' -- To view, visit https://gerrit.wikimedia.org/r/372187 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: If7c63284224df24fa02022b4ea74bef116f28ca6 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/core Gerrit-Branch: master Gerrit-Owner: Sbisson <sbis...@wikimedia.org> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits