X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=resources%2Fsrc%2Fmediawiki.rcfilters%2Fui%2Fmw.rcfilters.ui.ChangesListWrapperWidget.js;h=955e01dd700768e05314ee06851f61d9fffa5a69;hb=51690a5c79cc2ad8ee35ef8f728ccb1b70298ce1;hp=0e9e843be1746d13a77cde8a8daf980d2c4165b3;hpb=4a5f646a7fea7cbe0421c5cf38b72bae5c1bcf65;p=lhc%2Fweb%2Fwiklou.git diff --git a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ChangesListWrapperWidget.js b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ChangesListWrapperWidget.js index 0e9e843be1..955e01dd70 100644 --- a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ChangesListWrapperWidget.js +++ b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ChangesListWrapperWidget.js @@ -3,17 +3,18 @@ * List of changes * * @extends OO.ui.Widget - * @mixins OO.ui.mixin.PendingElement * * @constructor * @param {mw.rcfilters.dm.FiltersViewModel} filtersViewModel View model * @param {mw.rcfilters.dm.ChangesListViewModel} changesListViewModel View model + * @param {mw.rcfilters.Controller} controller * @param {jQuery} $changesListRoot Root element of the changes list to attach to - * @param {Object} config Configuration object + * @param {Object} [config] Configuration object */ mw.rcfilters.ui.ChangesListWrapperWidget = function MwRcfiltersUiChangesListWrapperWidget( filtersViewModel, changesListViewModel, + controller, $changesListRoot, config ) { @@ -23,11 +24,10 @@ // Parent mw.rcfilters.ui.ChangesListWrapperWidget.parent.call( this, config ); - // Mixin constructors - OO.ui.mixin.PendingElement.call( this, config ); this.filtersViewModel = filtersViewModel; this.changesListViewModel = changesListViewModel; + this.controller = controller; // Events this.filtersViewModel.connect( this, { @@ -36,7 +36,8 @@ } ); this.changesListViewModel.connect( this, { invalidate: 'onModelInvalidate', - update: 'onModelUpdate' + update: 'onModelUpdate', + newChangesExist: 'onNewChangesExist' } ); this.$element @@ -46,12 +47,15 @@ // Set up highlight containers this.setupHighlightContainers( this.$element ); + + if ( mw.rcfilters.featureFlags.liveUpdate ) { + this.setupNewChangesButtonContainer( this.$element ); + } }; /* Initialization */ OO.inheritClass( mw.rcfilters.ui.ChangesListWrapperWidget, OO.ui.Widget ); - OO.mixinClass( mw.rcfilters.ui.ChangesListWrapperWidget, OO.ui.mixin.PendingElement ); /** * Respond to the highlight feature being toggled on and off @@ -80,7 +84,8 @@ * Respond to changes list model invalidate */ mw.rcfilters.ui.ChangesListWrapperWidget.prototype.onModelInvalidate = function () { - this.pushPending(); + $( '.rcfilters-spinner' ).removeClass( 'mw-rcfilters-ui-ready' ); + this.$element.removeClass( 'mw-rcfilters-ui-ready' ); }; /** @@ -89,16 +94,24 @@ * @param {jQuery|string} $changesListContent The content of the updated changes list * @param {jQuery} $fieldset The content of the updated fieldset * @param {boolean} isInitialDOM Whether $changesListContent is the existing (already attached) DOM + * @param {boolean} from Timestamp of the new changes */ - mw.rcfilters.ui.ChangesListWrapperWidget.prototype.onModelUpdate = function ( $changesListContent, $fieldset, isInitialDOM ) { + mw.rcfilters.ui.ChangesListWrapperWidget.prototype.onModelUpdate = function ( + $changesListContent, $fieldset, isInitialDOM, from + ) { var conflictItem, $message = $( '
' ) .addClass( 'mw-rcfilters-ui-changesListWrapperWidget-results' ), - isEmpty = $changesListContent === 'NO_RESULTS'; + isEmpty = $changesListContent === 'NO_RESULTS', + // For enhanced mode, we have to load these modules, which are + // not loaded for the 'regular' mode in the backend + loaderPromise = mw.user.options.get( 'usenewrc' ) ? + mw.loader.using( [ 'mediawiki.special.changeslist.enhanced', 'mediawiki.icon' ] ) : + $.Deferred().resolve(), + widget = this; this.$element.toggleClass( 'mw-changeslist', !isEmpty ); if ( isEmpty ) { - this.$changesListContent = null; this.$element.empty(); if ( this.filtersViewModel.hasConflict() ) { @@ -124,22 +137,109 @@ this.$element.append( $message ); } else { - this.$changesListContent = $changesListContent; if ( !isInitialDOM ) { - this.$element.empty().append( this.$changesListContent ); + this.$element.empty().append( $changesListContent ); + + if ( from ) { + this.emphasizeNewChanges( from ); + } } + // Set up highlight containers this.setupHighlightContainers( this.$element ); // Apply highlight this.applyHighlight(); - if ( !isInitialDOM ) { + } + + loaderPromise.done( function () { + if ( !isInitialDOM && !isEmpty ) { // Make sure enhanced RC re-initializes correctly - mw.hook( 'wikipage.content' ).fire( this.$element ); + mw.hook( 'wikipage.content' ).fire( widget.$element ); } + + $( '.rcfilters-spinner' ).addClass( 'mw-rcfilters-ui-ready' ); + widget.$element.addClass( 'mw-rcfilters-ui-ready' ); + } ); + }; + + /** + * Emphasize the elements (or groups) newer than the 'from' parameter + * @param {string} from Anything newer than this is considered 'new' + */ + mw.rcfilters.ui.ChangesListWrapperWidget.prototype.emphasizeNewChanges = function ( from ) { + var $firstNew, + $indicator, + $newChanges = $( [] ), + selector = this.inEnhancedMode() ? + 'table.mw-enhanced-rc[data-mw-ts]' : + 'li[data-mw-ts]', + set = this.$element.find( selector ), + length = set.length; + + set.each( function ( index ) { + var $this = $( this ), + ts = $this.data( 'mw-ts' ); + + if ( ts >= from ) { + $newChanges = $newChanges.add( $this ); + $firstNew = $this; + + // guards against putting the marker after the last element + if ( index === ( length - 1 ) ) { + $firstNew = null; + } + } + } ); + + if ( $firstNew ) { + $indicator = $( '
' ) + .addClass( 'mw-rcfilters-ui-changesListWrapperWidget-previousChangesIndicator' ); + + $firstNew.after( $indicator ); } - this.popPending(); + + $newChanges + .hide() + .fadeIn( 1000 ); + }; + + /** + * Respond to changes list model newChangesExist + * + * @param {boolean} newChangesExist Whether new changes exist + */ + mw.rcfilters.ui.ChangesListWrapperWidget.prototype.onNewChangesExist = function ( newChangesExist ) { + this.showNewChangesLink.toggle( newChangesExist ); + }; + + /** + * Respond to the user clicking the 'show new changes' button + */ + mw.rcfilters.ui.ChangesListWrapperWidget.prototype.onShowNewChangesClick = function () { + this.controller.showNewChanges(); + }; + + /** + * Setup the container for the 'new changes' button. + * + * @param {jQuery} $content + */ + mw.rcfilters.ui.ChangesListWrapperWidget.prototype.setupNewChangesButtonContainer = function ( $content ) { + this.showNewChangesLink = new OO.ui.ButtonWidget( { + framed: false, + label: mw.message( 'rcfilters-show-new-changes' ).text(), + flags: [ 'progressive' ] + } ); + this.showNewChangesLink.connect( this, { click: 'onShowNewChangesClick' } ); + this.showNewChangesLink.toggle( false ); + + $content.before( + $( '
' ) + .addClass( 'mw-rcfilters-ui-changesListWrapperWidget-newChanges' ) + .append( this.showNewChangesLink.$element ) + ); }; /** @@ -148,9 +248,9 @@ * @param {jQuery|string} $content The content of the updated changes list */ mw.rcfilters.ui.ChangesListWrapperWidget.prototype.setupHighlightContainers = function ( $content ) { - var uri = new mw.Uri(), + var highlightClass = 'mw-rcfilters-ui-changesListWrapperWidget-highlights', $highlights = $( '
' ) - .addClass( 'mw-rcfilters-ui-changesListWrapperWidget-highlights' ) + .addClass( highlightClass ) .append( $( '
' ) .addClass( 'mw-rcfilters-ui-changesListWrapperWidget-highlights-color-none' ) @@ -170,10 +270,7 @@ ); } ); - if ( - ( uri.query.enhanced !== undefined && Number( uri.query.enhanced ) ) || - ( uri.query.enhanced === undefined && Number( mw.user.options.get( 'usenewrc' ) ) ) - ) { + if ( this.inEnhancedMode() ) { // Enhanced RC $content.find( 'td.mw-enhanced-rc' ) .parent() @@ -188,6 +285,15 @@ } }; + /** + * @return {boolean} Whether the changes are grouped by page + */ + mw.rcfilters.ui.ChangesListWrapperWidget.prototype.inEnhancedMode = function () { + var uri = new mw.Uri(); + return ( uri.query.enhanced !== undefined && Number( uri.query.enhanced ) ) || + ( uri.query.enhanced === undefined && Number( mw.user.options.get( 'usenewrc' ) ) ); + }; + /** * Apply color classes based on filters highlight configuration */ @@ -197,10 +303,33 @@ } this.filtersViewModel.getHighlightedItems().forEach( function ( filterItem ) { + var $elements = this.$element.find( '.' + filterItem.getCssClass() ); + // Add highlight class to all highlighted list items - this.$element.find( '.' + filterItem.getCssClass() ) + $elements .addClass( 'mw-rcfilters-highlight-color-' + filterItem.getHighlightColor() ); + + $elements.each( function () { + var filterString = $( this ).attr( 'data-highlightedFilters' ) || '', + filters = filterString ? filterString.split( '|' ) : []; + + if ( filters.indexOf( filterItem.getLabel() ) === -1 ) { + filters.push( filterItem.getLabel() ); + } + + $( this ) + .attr( 'data-highlightedFilters', filters.join( '|' ) ); + } ); }.bind( this ) ); + // Apply a title for relevant filters + this.$element.find( '[data-highlightedFilters]' ).each( function () { + var filterString = $( this ).attr( 'data-highlightedFilters' ) || '', + filters = filterString ? filterString.split( '|' ) : []; + + if ( filterString ) { + $( this ).attr( 'title', mw.msg( 'rcfilters-highlighted-filters-list', filters.join( ', ' ) ) ); + } + } ); // Turn on highlights this.$element.addClass( 'mw-rcfilters-ui-changesListWrapperWidget-highlighted' ); @@ -215,6 +344,9 @@ this.$element.find( '.mw-rcfilters-highlight-color-' + color ).removeClass( 'mw-rcfilters-highlight-color-' + color ); }.bind( this ) ); + this.$element.find( '[data-highlightedFilters]' ) + .removeAttr( 'title' ) + .removeAttr( 'data-highlightedFilters' ); // Turn off highlights this.$element.removeClass( 'mw-rcfilters-ui-changesListWrapperWidget-highlighted' ); };