More specific warning when RC page fails to load
authorpetarpetkovic <ppetkovic@wikimedia.org>
Tue, 31 Oct 2017 15:36:14 +0000 (16:36 +0100)
committerpetarpetkovic <ppetkovic@wikimedia.org>
Wed, 1 Nov 2017 21:14:40 +0000 (22:14 +0100)
- Provide more specific message when the page fails to load
(when the connection drops for any reason), replacing the current message,
which says misleadingly that no results could be found.
- Center warning messages horizontally.

Bug: T177413
Change-Id: Ie2bc4fe4bd19103b513e4753e59f4adb295fbafa

languages/i18n/en.json
languages/i18n/qqq.json
resources/Resources.php
resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.ChangesListViewModel.js
resources/src/mediawiki.rcfilters/mw.rcfilters.Controller.js
resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ChangesListWrapperWidget.less
resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ChangesListWrapperWidget.js
resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FormWrapperWidget.js

index e4aa867..27bc813 100644 (file)
        "recentchangestext": "-",
        "recentchanges-noresult": "No changes during the given period match these criteria.",
        "recentchanges-timeout": "This search has timed out. You may wish to try different search parameters.",
+       "recentchanges-network": "Due to a technical error, no results could be loaded. Please try refreshing the page.",
        "recentchanges-feed-description": "Track the most recent changes to the wiki in this feed.",
        "recentchanges-label-newpage": "This edit created a new page",
        "recentchanges-label-minor": "This is a minor edit",
index 9e7bfca..d2666c4 100644 (file)
        "recentchangestext": "Text in [[Special:RecentChanges]]",
        "recentchanges-noresult": "Used in [[Special:RecentChanges]], [[Special:RecentChangesLinked]], and [[Special:Watchlist]] when there are no changes to be shown.",
        "recentchanges-timeout": "Used in [[Special:RecentChanges]], [[Special:RecentChangesLinked]], and [[Special:Watchlist]] when a query times out.",
+       "recentchanges-network": "Used in [[Special:RecentChanges]], [[Special:RecentChangesLinked]] and [[Special:Watchlist]] when network error occurs.",
        "recentchanges-feed-description": "Used in feed of RecentChanges. See example [{{canonicalurl:Special:RecentChanges|feed=atom}} feed].",
        "recentchanges-label-newpage": "# Used as tooltip for {{msg-mw|Newpageletter}}.\n# Also used as legend. Preceded by {{msg-mw|Newpageletter}} and followed by {{msg-mw|Recentchanges-legend-newpage}}.",
        "recentchanges-label-minor": "# Used as tooltip for {{msg-mw|Minoreditletter}}\n# Also used as legend. Preceded by {{msg-mw|Minoreditletter}}",
index df0c249..7d606e7 100644 (file)
@@ -1891,6 +1891,7 @@ return [
                        'invert',
                        'recentchanges-noresult',
                        'recentchanges-timeout',
+                       'recentchanges-network',
                        'quotation-marks',
                ],
                'dependencies' => [
index 3c03c70..15fe334 100644 (file)
@@ -33,7 +33,7 @@
         * @event update
         * @param {jQuery|string} $changesListContent List of changes
         * @param {jQuery} $fieldset Server-generated form
-        * @param {boolean} isDatabaseTimeout Whether this is an error state due to a database query
+        * @param {string} noResultsDetails Type of no result error
         * @param {boolean} isInitialDOM Whether the previous dom variables are from the initial page load
         * @param {boolean} fromLiveUpdate These are new changes fetched via Live Update
         *
         *
         * @param {jQuery|string} changesListContent
         * @param {jQuery} $fieldset
-        * @param {boolean} isDatabaseTimeout Whether this is an error state due to a database query
+        * @param {string} noResultsDetails Type of no result error
         *   timeout.
         * @param {boolean} [isInitialDOM] Using the initial (already attached) DOM elements
         * @param {boolean} [separateOldAndNew] Whether a logical separation between old and new changes is needed
         * @fires update
         */
-       mw.rcfilters.dm.ChangesListViewModel.prototype.update = function ( changesListContent, $fieldset, isDatabaseTimeout, isInitialDOM, separateOldAndNew ) {
+       mw.rcfilters.dm.ChangesListViewModel.prototype.update = function ( changesListContent, $fieldset, noResultsDetails, isInitialDOM, separateOldAndNew ) {
                var from = this.nextFrom;
                this.valid = true;
                this.extractNextFrom( $fieldset );
                this.checkForUnseenWatchedChanges( changesListContent );
-               this.emit( 'update', changesListContent, $fieldset, isDatabaseTimeout, isInitialDOM, separateOldAndNew ? from : null );
+               this.emit( 'update', changesListContent, $fieldset, noResultsDetails, isInitialDOM, separateOldAndNew ? from : null );
        };
 
        /**
index 8d36cf5..d1092a1 100644 (file)
                                        this.changesListModel.update(
                                                $changesListContent,
                                                $fieldset,
-                                               pieces.noResultsDetails === 'NO_RESULTS_TIMEOUT',
+                                               pieces.noResultsDetails,
                                                false,
                                                // separator between old and new changes
                                                updateMode === this.SHOW_NEW_CHANGES || updateMode === this.LIVE_UPDATE
                return this._queryChangesList( 'updateChangesList' )
                        .then(
                                function ( data ) {
-                                       var $parsed = $( '<div>' ).append( $( $.parseHTML( data.content ) ) );
+                                       var $parsed;
+
+                                       // Status code 0 is not HTTP status code,
+                                       // but is valid value of XMLHttpRequest status.
+                                       // It is used for variety of network errors, for example
+                                       // when an AJAX call was cancelled before getting the response
+                                       if ( data && data.status === 0 ) {
+                                               return {
+                                                       changes: 'NO_RESULTS',
+                                                       // We need empty result set, to avoid exceptions because of undefined value
+                                                       fieldset: $( [] ),
+                                                       noResultsDetails: 'NO_RESULTS_NETWORK_ERROR'
+                                               };
+                                       }
+
+                                       $parsed = $( '<div>' ).append( $( $.parseHTML( data.content ) ) );
 
                                        return this._extractChangesListInfo( $parsed );
 
index 0fa3137..b923efb 100644 (file)
@@ -31,8 +31,9 @@
 
                &-noresult,
                &-conflict {
-                       font-weight: bold;
                        margin-bottom: 0.5em;
+                       font-weight: bold;
+                       text-align: center;
                }
        }
 
index d4faf83..b6a0a4f 100644 (file)
         *
         * @param {jQuery|string} $changesListContent The content of the updated changes list
         * @param {jQuery} $fieldset The content of the updated fieldset
-        * @param {boolean} isDatabaseTimeout Whether this is an error state due to a database query
+        * @param {string} noResultsDetails Type of no result error
         * @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, isDatabaseTimeout, isInitialDOM, from
+               $changesListContent, $fieldset, noResultsDetails, isInitialDOM, from
        ) {
                var conflictItem, noResultsKey,
                        $message = $( '<div>' )
                                                        .text( mw.message( conflictItem.getCurrentConflictResultMessage() ).text() )
                                        );
                        } else {
-                               noResultsKey = isDatabaseTimeout ?
-                                       'recentchanges-timeout' :
-                                       'recentchanges-noresult';
+                               noResultsKey =
+                                       ( noResultsDetails === 'NO_RESULTS_TIMEOUT' ) ?
+                                               'recentchanges-timeout' :
+                                               ( noResultsDetails === 'NO_RESULTS_NETWORK_ERROR' ) ?
+                                                       'recentchanges-network' :
+                                                       'recentchanges-noresult';
 
                                $message
                                        .append(
index 4edc272..6aa335a 100644 (file)
         *
         * @param {jQuery|string} $changesList Updated changes list
         * @param {jQuery} $fieldset Updated fieldset
-        * @param {boolean} isDatabaseTimeout Whether this is an error state due to a database query
+        * @param {string} noResultsDetails Type of no result error
         * @param {boolean} isInitialDOM Whether $changesListContent is the existing (already attached) DOM
         */
-       mw.rcfilters.ui.FormWrapperWidget.prototype.onChangesModelUpdate = function ( $changesList, $fieldset, isDatabaseTimeout, isInitialDOM ) {
+       mw.rcfilters.ui.FormWrapperWidget.prototype.onChangesModelUpdate = function ( $changesList, $fieldset, noResultsDetails, isInitialDOM ) {
                this.$submitButton.prop( 'disabled', false );
 
                // Replace the entire fieldset