diff --git a/src/wp-admin/css/list-tables.css b/src/wp-admin/css/list-tables.css index 81ec41a0c4..c8e0eece06 100644 --- a/src/wp-admin/css/list-tables.css +++ b/src/wp-admin/css/list-tables.css @@ -1578,6 +1578,21 @@ div.action-links, display: inline; } +.plugin-card-update-failed .update-now { + font-weight: 600; +} + +.plugin-card-update-failed .notice-error { + margin: 0; + padding-left: 16px; + -webkit-box-shadow: 0 -1px 0 #dedede; + box-shadow: 0 -1px 0 #dedede; +} + +.plugin-card-update-failed .plugin-card-bottom { + display: none; +} + .plugin-card .column-rating { line-height: 23px; } diff --git a/src/wp-admin/js/common.js b/src/wp-admin/js/common.js index 8484f8bcb3..796e1400f4 100644 --- a/src/wp-admin/js/common.js +++ b/src/wp-admin/js/common.js @@ -400,24 +400,29 @@ $document.ready( function() { $( 'div.updated, div.error, div.notice' ).not( '.inline, .below-h2' ).insertAfter( $( '.wrap' ).children( ':header' ).first() ); // Make notices dismissible - $( '.notice.is-dismissible' ).each( function() { - var $this = $( this ), - $button = $( '' ), - btnText = commonL10n.dismiss || ''; + function makeNoticesDismissible() { + $( '.notice.is-dismissible' ).each( function() { + var $el = $( this ), + $button = $( '' ), + btnText = commonL10n.dismiss || ''; - // Ensure plain text - $button.find( '.screen-reader-text' ).text( btnText ); - - $this.append( $button ); - - $button.on( 'click.wp-dismiss-notice', function( event ) { - event.preventDefault(); - $this.fadeTo( 100 , 0, function() { - $(this).slideUp( 100, function() { - $(this).remove(); + // Ensure plain text + $button.find( '.screen-reader-text' ).text( btnText ); + $button.on( 'click.wp-dismiss-notice', function( event ) { + event.preventDefault(); + $el.fadeTo( 100, 0, function() { + $el.slideUp( 100, function() { + $el.remove(); + }); }); }); + + $el.append( $button ); }); + } + + $document.on( 'wp-plugin-update-error', function() { + makeNoticesDismissible(); }); // Init screen meta @@ -895,6 +900,7 @@ $document.ready( function() { window.wpResponsive.init(); setPinMenu(); currentMenuItemHasPopup(); + makeNoticesDismissible(); $document.on( 'wp-pin-menu wp-window-resized.pin-menu postboxes-columnchange.pin-menu postbox-toggled.pin-menu wp-collapse-menu.pin-menu wp-scroll-start.pin-menu', setPinMenu ); }); diff --git a/src/wp-admin/js/updates.js b/src/wp-admin/js/updates.js index d967e3ec91..3f1dba71e3 100644 --- a/src/wp-admin/js/updates.js +++ b/src/wp-admin/js/updates.js @@ -146,13 +146,17 @@ window.wp = window.wp || {}; * @param {string} slug */ wp.updates.updatePlugin = function( plugin, slug ) { - var $message, name; + var $message, name, + $card = $( '.plugin-card-' + slug ); + if ( 'plugins' === pagenow || 'plugins-network' === pagenow ) { $message = $( '[data-slug="' + slug + '"]' ).next().find( '.update-message' ); } else if ( 'plugin-install' === pagenow ) { - $message = $( '.plugin-card-' + slug ).find( '.update-now' ); + $message = $card.find( '.update-now' ); name = $message.data( 'name' ); $message.attr( 'aria-label', wp.updates.l10n.updatingLabel.replace( '%s', name ) ); + // Remove previous error messages, if any. + $card.removeClass( 'plugin-card-update-failed' ).find( '.notice.notice-error' ).remove(); } $message.addClass( 'updating-message' ); @@ -248,23 +252,47 @@ window.wp = window.wp || {}; * @param {object} response */ wp.updates.updateError = function( response ) { - var $message, name; + var $card = $( '.plugin-card-' + response.slug ), + $message, + $button, + name, + error_message; + wp.updates.updateDoneSuccessfully = false; + if ( response.errorCode && response.errorCode == 'unable_to_connect_to_filesystem' && wp.updates.shouldRequestFilesystemCredentials ) { wp.updates.credentialError( response, 'update-plugin' ); return; } + + error_message = wp.updates.l10n.updateFailed.replace( '%s', response.error ); + if ( 'plugins' === pagenow || 'plugins-network' === pagenow ) { $message = $( '[data-slug="' + response.slug + '"]' ).next().find( '.update-message' ); + $message.html( error_message ).removeClass( 'updating-message' ); } else if ( 'plugin-install' === pagenow ) { - $message = $( '.plugin-card-' + response.slug ).find( '.update-now' ); + $button = $card.find( '.update-now' ); + name = $button.data( 'name' ); - name = $message.data( 'name' ); - $message.attr( 'aria-label', wp.updates.l10n.updateFailedLabel.replace( '%s', name ) ); + $card + .addClass( 'plugin-card-update-failed' ) + .append( '

' + error_message + '

' ); + + $button + .attr( 'aria-label', wp.updates.l10n.updateFailedLabel.replace( '%s', name ) ) + .html( wp.updates.l10n.updateFailedShort ).removeClass( 'updating-message' ); + + $card.on( 'click', '.notice.is-dismissible .notice-dismiss', function() { + // Use same delay as the total duration of the notice fadeTo + slideUp animation. + setTimeout( function() { + $card + .removeClass( 'plugin-card-update-failed' ) + .find( '.column-name a' ).focus(); + }, 200 ); + }); } - $message.removeClass( 'updating-message' ); - $message.html( wp.updates.l10n.updateFailed.replace( '%s', response.error ) ); - wp.a11y.speak( wp.updates.l10n.updateFailed ); + + wp.a11y.speak( error_message, 'assertive' ); /* * The lock can be released since this failure was diff --git a/src/wp-includes/script-loader.php b/src/wp-includes/script-loader.php index 5288896a3b..88962cdfab 100644 --- a/src/wp-includes/script-loader.php +++ b/src/wp-includes/script-loader.php @@ -583,6 +583,7 @@ function wp_default_scripts( &$scripts ) { 'l10n' => array( 'updating' => __( 'Updating...' ), // no ellipsis 'updated' => __( 'Updated!' ), + 'updateFailedShort' => __( 'Update Failed!' ), /* translators: Error string for a failed update */ 'updateFailed' => __( 'Update Failed: %s' ), /* translators: Plugin name and version */