Customize: Add changeset locking in Customizer to prevent users from overriding each other's changes.

* Customization locking is checked when changesets are saved and when heartbeat ticks.
* Lock is lifted immediately upon a user closing the Customizer.
* Heartbeat is introduced into Customizer.
* Changes made to user after it was locked by another user are stored as an autosave revision for restoration.
* Lock notification displays link to preview the other user's changes on the frontend.
* A user loading a locked Customizer changeset will be presented with an option to take over.
* Autosave revisions attached to a published changeset are converted into auto-drafts so that they will be presented to users for restoration.
* Focus constraining is improved in overlay notifications.
* Escape key is stopped from propagating in overlay notifications, and it dismisses dismissible overlay notifications.
* Introduces `changesetLocked` state which is used to disable the Save button and suppress the AYS dialog when leaving the Customizer.
* Fixes bug where users could be presented with each other's autosave revisions.

Props sayedwp, westonruter, melchoyce.
See #31436, #31897, #39896.
Fixes #42024.

Built from https://develop.svn.wordpress.org/trunk@41839


git-svn-id: http://core.svn.wordpress.org/trunk@41673 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
Weston Ruter
2017-10-12 04:01:46 +00:00
parent f44ed386c1
commit 434e3aba82
12 changed files with 676 additions and 68 deletions

View File

@@ -547,7 +547,7 @@ function wp_default_scripts( &$scripts ) {
$scripts->add( 'customize-preview', "/wp-includes/js/customize-preview$suffix.js", array( 'wp-a11y', 'customize-base' ), false, 1 );
$scripts->add( 'customize-models', "/wp-includes/js/customize-models.js", array( 'underscore', 'backbone' ), false, 1 );
$scripts->add( 'customize-views', "/wp-includes/js/customize-views.js", array( 'jquery', 'underscore', 'imgareaselect', 'customize-models', 'media-editor', 'media-views' ), false, 1 );
$scripts->add( 'customize-controls', "/wp-admin/js/customize-controls$suffix.js", array( 'customize-base', 'wp-a11y', 'wp-util' ), false, 1 );
$scripts->add( 'customize-controls', "/wp-admin/js/customize-controls$suffix.js", array( 'customize-base', 'wp-a11y', 'wp-util', 'jquery-ui-core' ), false, 1 );
did_action( 'init' ) && $scripts->localize( 'customize-controls', '_wpCustomizeControlsL10n', array(
'activate' => __( 'Activate & Publish' ),
'save' => __( 'Save & Publish' ), // @todo Remove as not required.
@@ -574,11 +574,13 @@ function wp_default_scripts( &$scripts ) {
'collapseSidebar' => _x( 'Hide Controls', 'label for hide controls button without length constraints' ),
'expandSidebar' => _x( 'Show Controls', 'label for hide controls button without length constraints' ),
'untitledBlogName' => __( '(Untitled)' ),
'serverSaveError' => __( 'Failed connecting to the server. Please try saving again.' ),
'unknownRequestFail' => __( 'Looks like something’s gone wrong. Wait a couple seconds, and then try again.' ),
'themeDownloading' => __( 'Downloading your new theme…' ),
'themePreviewWait' => __( 'Setting up your live preview. This may take a bit.' ),
'revertingChanges' => __( 'Reverting unpublished changes…' ),
'trashConfirm' => __( 'Are you sure you’d like to discard your unpublished changes?' ),
/* translators: %s: Display name of the user who has taken over the changeset in customizer. */
'takenOverMessage' => __( '%s has taken over and is currently customizing.' ),
/* translators: %s: URL to the Customizer to load the autosaved version */
'autosaveNotice' => __( 'There is a more recent autosave of your changes than the one you are previewing. <a href="%s">Restore the autosave</a>' ),
'videoHeaderNotice' => __( 'This theme doesn&#8217;t support video headers on this page. Navigate to the front page or another page that supports video headers.' ),